BSD inodes vs. SYSV inodes?

BSD inodes vs. SYSV inodes?

Post by Guy Harr » Fri, 20 Dec 1991 04:13:55



Quote:>In fslook.c, posted yesterday, people on big-endian machines (680x0,
>etc) should change the line:

Or, alternatively, people on big-endian, little-endian, or other-endian
machines should change the program to use the "l3tol()" routine, which
should be in the C library on any UNIX system that supports the V7 file
system or derivatives of same (such as the SV file system), and which
should even be documented.
 
 
 

BSD inodes vs. SYSV inodes?

Post by Steven M. Schul » Sat, 28 Dec 1991 18:26:39



>Or, alternatively, people on big-endian, little-endian, or other-endian
>machines should change the program to use the "l3tol()" routine, which...

        Or, alternatively, with access to the sources, change the
        kernel&filesystem to get rid of the weird 3byte block number
        packing scheme.  I know I breathed a sigh of relief when 3byte
        block numbers were obviated in the 2.11BSD system.

        Steven M. Schultz


 
 
 

BSD inodes vs. SYSV inodes?

Post by Bruce Momji » Wed, 01 Jan 1992 12:49:42


[Note:  I am cross-posting to comp.unix.admin because this program may
be useful in restoring files from corrupted System V file systems. ]

Two weeks ago, I posted a program that generated a file's contents from
an inode number and file system device file, using the block numbers
stored in the inode.  Unfortunately, I have discovered a bug in the
handling of the 2nd and 3rd indirect blocks.  I am reposting the entire
program.  I don't have a copy of the original posted source code.

I have now tested the program on every file on my system, as well as
one sparse file to test triple indirection.  The new program uses
l3tol, as recommended by several posters.  It now allows the start byte
and length to be optional, and if they are not provided, the entire
file is piped to the standard output.

The program was designed on AT&T 386 Unix SVr3.1, but should work on
SVr3.2 or earlier System V(?).  To test it on your /usr file system,
try this:

cd /usr
ncheck -a /dev/usr | grep -v 'FIFO' | grep -v '/dev/' | while read LINE
do
        echo "$LINE"
        fslook /dev/usr `echo "$LINE" | cut -d\         -f1` | \
                cmp -s - /usr/`echo "$LINE" | cut -d\  -f2`
        [ "$?" -ne 0 ] && echo "$LINE" >>/tmp/usr.bad
done

It will display each file as it tests it, and put the bad ones in the
file /tmp/usr.bad.

For administrators, this program could be used to recover files from a
file system whose super block is trashed, or whose directory structure
is messed up.  For best recovery, you should have a copy of a recent
"ncheck" for each file system, as well as an "ls -liR" for file
ownership and file modes.  Obviously, if you keep those files only on
the file system that was trashed, you will not be able to get at them
easily.

My apologies for initially submitting a buggy program.  I should have
checked it better.  Also, my apologies for those of you in
comp.unix.internals who are tired of hearing about this trivial program
I wrote. :-)

I have assumed this program is too trivial to be posted to a source
group.  I figured, if it was generally useful, someone would have
already posted it.  Please e-mail your opinions of this decision.

------------- cut here -----------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#       fslook.c
# This archive created: Mon Dec 30 22:44:53 1991
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'fslook.c'" '(5525 characters)'
if test -f 'fslook.c'
then
        echo shar: "will not over-write existing file 'fslook.c'"
else
cat << \SHAR_EOF > 'fslook.c'
/*************************************************************************
**
** fslook.c - displays data from a file given it's inode
**      by Bruce Momjian ( root%candle.u...@ls.com )
**
**************************************************************************/

#include <stdio.h>
#include <malloc.h>
#include <unistd.h>
#include <signal.h>
#include <ctype.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/fs/s5param.h>               /* for INOPB */
#include <sys/ino.h>                      /* for dinode structure */
#include <errno.h>

#define USAGE           fprintf(stderr,\
                                                        "Usage: %s file_system_device inode_number [start_byte] [length]\n",argv[0]);

                                                /* assumes 3 bytes per disk block address in inode */
#define INOBLOCK(b,n)   ( l3block( (b) + (n) * 3 ) )
                                                /* assumes 4 bytes per disk block address in inode */
#define INDBLOCK(b,n)   ( *(long *)((b) + (n) * 4) )    

#ifndef BSIZE
#define BSIZE   1024    /* block size in bytes */
#endif

#ifndef INOPB
#define INOPB   (BSIZE / sizeof(dinode))
#endif

long l3block();

int main(argc,argv)
int argc;
char *argv[];
{
        int curquit(),
                offset,
                infd;

        unsigned inode_num;

        unsigned long start,
                 length;

        unsigned char   *buf;
        char                    *badchar;

        struct dinode *ino;

        if ( argc < 3 || argc > 5 )
        {
                USAGE;
                exit(1);
        }

        if ( (infd = open(argv[1],O_RDONLY)) == -1)
        {
                perror("Can not open device file");
                exit(1);
        }

        buf = (unsigned char *) malloc(BSIZE);
        if ( buf == NULL)
        {
                fputs("No memory\n", stderr);
                exit(1);
        }

        inode_num = strtol(argv[2],&badchar, 0);
        if (*badchar != '\0')
        {
                fputs("Invalid inode number.\n", stderr);
                USAGE;
                exit(1);
        }

        if (argc >=4)
        {
                start = strtol(argv[3],&badchar, 0);
                if (*badchar != '\0')
                {
                        fputs("Invalid start byte.\n", stderr);
                        USAGE;
                        exit(1);
                }
        }
        else
                start = 0;

        if (argc >=5)
        {
                length = strtol(argv[4],&badchar, 0);
                if (*badchar != '\0')
                {
                        fputs("Invalid length byte.\n", stderr);
                        USAGE;
                        exit(1);
                }
        }
        else
        {
                get_inode(infd, inode_num, &ino, buf);
                length = ino->di_size;
        }              

        signal(SIGINT, curquit);

        while (length > 0)
        {
                if (start / BSIZE == (start + length - 1) / BSIZE)
                        offset = length;
                else
                        offset = BSIZE - start % BSIZE;
                index_block(infd, inode_num, start, buf);
                print_block(buf, start, offset);
                length -= offset;
                start += offset;
        }
        return(0);

}

/************************************************************************
**
**      index_block
**
*************************************************************************/

index_block(infd, inode_num, start, buf)
int infd;
unsigned inode_num;
unsigned long start;
unsigned char *buf;
{
        struct dinode *ino;
        get_inode(infd, inode_num, &ino, buf);

        if (start / BSIZE < 10)              /* 10 DIRECT BLOCKS */
                get_block(infd, INOBLOCK(ino->di_addr,start / BSIZE), buf);
        else
        {
                start -= BSIZE * 10;
                if ( start < BSIZE * (BSIZE / 4) )   /* INDIRECT BLOCKS */
                {
                        get_block(infd, INOBLOCK(ino->di_addr, 10), buf);
                        get_block(infd, INDBLOCK(buf, start / BSIZE), buf);
                }                      
                else
                {
                        start -= BSIZE * (BSIZE / 4);
                        if (start < BSIZE * (BSIZE / 4) * (BSIZE / 4) )/* DOUBLE INDIRECT*/
                        {
                                get_block(infd, INOBLOCK(ino->di_addr, 11), buf);
                                get_block(infd, INDBLOCK(buf, start / (BSIZE/4*BSIZE)), buf);
                                start %= BSIZE / 4 * BSIZE;
                                get_block(infd, INDBLOCK(buf, start /  BSIZE), buf);
                        }      
                        else
                        {                                                               /* TRIPLE INDIRECT */
                                start -= BSIZE * (BSIZE / 4) * ( BSIZE / 4 );
                                get_block(infd, INOBLOCK(ino->di_addr, 12), buf);
                                get_block(infd, INDBLOCK(buf, start / (BSIZE/4*BSIZE/4*BSIZE)),buf);
                                start %= BSIZE / 4 * BSIZE / 4 * BSIZE;
                                get_block(infd, INDBLOCK(buf, start / (BSIZE/4*BSIZE)), buf);
                                start %= BSIZE / 4 * BSIZE;
                                get_block(infd, INDBLOCK(buf, start /  BSIZE), buf);

                        }
                }
        }

}

/************************************************************************
**
**      get_inode
**
*************************************************************************/

get_inode(infd, inode_num, ino, buf )
int infd;
unsigned inode_num;
struct dinode **ino;
unsigned char *buf;
{
        inode_num--;                    /* inodes start at num - 1 */
        get_block(infd, (daddr_t)(inode_num / INOPB + 2), buf);
        *ino = (struct dinode *)buf + (inode_num % INOPB);

}

/*************************************************************************
**
**      print_block
**
**************************************************************************/

print_block( buf, start, offset)
int offset;
unsigned long start;
unsigned char *buf;
{
int cnt = 0;

        while (cnt < offset )
                printf("%c", buf[start % BSIZE + cnt++]);

}

/***************************************************************************
**
**      get_block
**
****************************************************************************/
get_block(infd, block, buf)
int infd;
long block;
unsigned char *buf;
{
        int bufsize;    
        if (lseek(infd, block * BSIZE, SEEK_SET) == -1)
        {
                perror("Can not seek in file");
                exit(1);
        }

        if( (bufsize = read(infd, buf, BSIZE )) == -1 || bufsize != BSIZE)
        {
                perror("Can not read from file");
                exit(1);
        }

}

/****************************************************************************
**
**      l3block
**
*****************************************************************************/
long l3block(blockptr)
char *blockptr;
{
        long ret;

        l3tol(&ret, blockptr, 1);
        return ret;

}

/****************************************************************************
**
**      cur_quit
**
*****************************************************************************/
int curquit()
{
        exit(0);

}

SHAR_EOF
fi
exit 0
#       End of shell archive

--
Bruce Momjian           | 830 Blythe Avenue               | home: (215)853-3000
root%candle.u...@ls.com | Drexel Hill, Pennsylvania 19026 | work: (215)353-9879

 
 
 

BSD inodes vs. SYSV inodes?

Post by Bob Anken » Thu, 02 Jan 1992 06:07:54


     I'm afraid I missed the thread on this, but it looks like someone did
a SYSV file recovery program.  Some time back, I posted a pair of programs
called fssal and fsls which are used to salvage or show a directory list of
files on a BSD filesystem given a superblock number and a directory inode.
This program will work on an unmounted filesystem.  It assumes that there
is an existing superblock (or alternate), and can do recursive restores.
It's also a potential security problem for the machines around with world-
readable /dev/drives!  Anyway, if someone is interested, it could be
potentially modified to work with SYSV filesystems.  I don't have access
to one or I would do it myself.

        Robert Ankeney

--
----------------------------------------------------------------------
Robert Ankeney                 | "Yield and overcome.                |
...!tektronix!reed!bob         |  Bend and be straight.              |

 
 
 

1. I have filled up with inodes on /usr, can I change inode withour reinstall?

I have FreeBSD 4.5, a recent install. When trying to install Pine, and a couple of small apps, I
ran into inode trouble.
I am full of inodes in /usr and have searched everywhere for information about it.
The best so far is http://www.freebsddiary.org/inodes.php
However, I do not know if it is possible to change inode on /usr without corrupting what's there
already? Is it, and if so how?
Furthermore, if it isn't possible, how do I change the inode during sysinstall? I don't think I
have seen it anywhere.

Another inode question. when using the pc, will the inodes slowly increase until I have filled it
again?
I am concerned that after xx months of use, I decide to install another application, and i run
into the same problem again.
If I delete an application, will the inodes connected with that app. disappear, and will it be
available for the next app?

So many questions and hopefully so many answers.
Please cc: me if replying.
Thanks in advance for all help.

kolsen
a fresh, and interested new FreeBSD user

2. INVESTMENTS ASSISTANCE

3. grow inodes: inode-max limit reached error.

4. Solaris SW list: More program info needed

5. Bad blocks, inodes and .badblocks -> Make root inode 2

6. can ssh-agent work between ssh-2.3 and ssh-3.5

7. Question about deleting inode / drop inode

8. Max Swap size?

9. directory inode from file inode?

10. grow-inodes: inode-max limit reached

11. how to access inode structure based on inode number ?

12. fs/inode.c sync fix and fs/ext2/inode.c tidy

13. SysV.3.2 Inode contents