diff --git a/tools/fsutil/block.c b/tools/fsutil/block.c index c1a880f..0606c58 100644 --- a/tools/fsutil/block.c +++ b/tools/fsutil/block.c @@ -28,29 +28,29 @@ extern int verbose; int fs_read_block (fs_t *fs, unsigned bnum, unsigned char *data) { - if (verbose > 3) - printf ("read block %d\n", bnum); - if (bnum < fs->isize) - return 0; - if (! fs_seek (fs, bnum * BSDFS_BSIZE)) - return 0; - if (! fs_read (fs, data, BSDFS_BSIZE)) - return 0; - return 1; + if (verbose > 3) + printf ("read block %d\n", bnum); + if (bnum < fs->isize) + return 0; + if (! fs_seek (fs, bnum * BSDFS_BSIZE)) + return 0; + if (! fs_read (fs, data, BSDFS_BSIZE)) + return 0; + return 1; } int fs_write_block (fs_t *fs, unsigned bnum, unsigned char *data) { - if (verbose > 3) - printf ("write block %d\n", bnum); - if (! fs->writable || bnum < fs->isize) - return 0; - if (! fs_seek (fs, bnum * BSDFS_BSIZE)) - return 0; - if (! fs_write (fs, data, BSDFS_BSIZE)) - return 0; - fs->modified = 1; - return 1; + if (verbose > 3) + printf ("write block %d\n", bnum); + if (! fs->writable || bnum < fs->isize) + return 0; + if (! fs_seek (fs, bnum * BSDFS_BSIZE)) + return 0; + if (! fs_write (fs, data, BSDFS_BSIZE)) + return 0; + fs->modified = 1; + return 1; } /* @@ -58,27 +58,27 @@ int fs_write_block (fs_t *fs, unsigned bnum, unsigned char *data) */ int fs_block_free (fs_t *fs, unsigned int bno) { - int i; - unsigned buf [BSDFS_BSIZE / 4]; + int i; + unsigned buf [BSDFS_BSIZE / 4]; - if (verbose > 1) - printf ("free block %d, total %d\n", bno, fs->nfree); - if (fs->nfree >= NICFREE) { - buf[0] = fs->nfree; - for (i=0; ifree[i]; - if (! fs_write_block (fs, bno, (unsigned char*) buf)) { - fprintf (stderr, "block_free: write error at block %d\n", bno); - return 0; - } - fs->nfree = 0; - } - fs->free [fs->nfree] = bno; - fs->nfree++; - fs->dirty = 1; - if (bno) /* Count total free blocks. */ - ++fs->tfree; - return 1; + if (verbose > 1) + printf ("free block %d, total %d\n", bno, fs->nfree); + if (fs->nfree >= NICFREE) { + buf[0] = fs->nfree; + for (i=0; ifree[i]; + if (! fs_write_block (fs, bno, (unsigned char*) buf)) { + fprintf (stderr, "block_free: write error at block %d\n", bno); + return 0; + } + fs->nfree = 0; + } + fs->free [fs->nfree] = bno; + fs->nfree++; + fs->dirty = 1; + if (bno) /* Count total free blocks. */ + ++fs->tfree; + return 1; } /* @@ -86,26 +86,26 @@ int fs_block_free (fs_t *fs, unsigned int bno) */ int fs_indirect_block_free (fs_t *fs, unsigned int bno, int nblk) { - unsigned nb; - unsigned char data [BSDFS_BSIZE]; - int i; + unsigned nb; + unsigned char data [BSDFS_BSIZE]; + int i; - if (! fs_read_block (fs, bno, data)) { - fprintf (stderr, "inode_clear: read error at block %d\n", bno); - return 0; - } - for (i=BSDFS_BSIZE-4; i>=0; i-=4) { - if (i/4 < nblk) { - /* Truncate up to required size. */ - return 0; - } - nb = data [i+3] << 24 | data [i+2] << 16 | - data [i+1] << 8 | data [i]; - if (nb) - fs_block_free (fs, nb); - } - fs_block_free (fs, bno); - return 1; + if (! fs_read_block (fs, bno, data)) { + fprintf (stderr, "inode_clear: read error at block %d\n", bno); + return 0; + } + for (i=BSDFS_BSIZE-4; i>=0; i-=4) { + if (i/4 < nblk) { + /* Truncate up to required size. */ + return 0; + } + nb = data [i+3] << 24 | data [i+2] << 16 | + data [i+1] << 8 | data [i]; + if (nb) + fs_block_free (fs, nb); + } + fs_block_free (fs, bno); + return 1; } /* @@ -113,27 +113,27 @@ int fs_indirect_block_free (fs_t *fs, unsigned int bno, int nblk) */ int fs_double_indirect_block_free (fs_t *fs, unsigned int bno, int nblk) { - unsigned nb; - unsigned char data [BSDFS_BSIZE]; - int i; + unsigned nb; + unsigned char data [BSDFS_BSIZE]; + int i; - if (! fs_read_block (fs, bno, data)) { - fprintf (stderr, "inode_clear: read error at block %d\n", bno); - return 0; - } - for (i=BSDFS_BSIZE-4; i>=0; i-=4) { - if (i/4 * BSDFS_BSIZE/4 < nblk) { - /* Truncate up to required size. */ - return 0; - } - nb = data [i+3] << 24 | data [i+2] << 16 | - data [i+1] << 8 | data [i]; - if (nb) - fs_indirect_block_free (fs, nb, - nblk - i/4 * BSDFS_BSIZE/4); - } - fs_block_free (fs, bno); - return 1; + if (! fs_read_block (fs, bno, data)) { + fprintf (stderr, "inode_clear: read error at block %d\n", bno); + return 0; + } + for (i=BSDFS_BSIZE-4; i>=0; i-=4) { + if (i/4 * BSDFS_BSIZE/4 < nblk) { + /* Truncate up to required size. */ + return 0; + } + nb = data [i+3] << 24 | data [i+2] << 16 | + data [i+1] << 8 | data [i]; + if (nb) + fs_indirect_block_free (fs, nb, + nblk - i/4 * BSDFS_BSIZE/4); + } + fs_block_free (fs, bno); + return 1; } /* @@ -141,27 +141,27 @@ int fs_double_indirect_block_free (fs_t *fs, unsigned int bno, int nblk) */ int fs_triple_indirect_block_free (fs_t *fs, unsigned int bno, int nblk) { - unsigned nb; - unsigned char data [BSDFS_BSIZE]; - int i; + unsigned nb; + unsigned char data [BSDFS_BSIZE]; + int i; - if (! fs_read_block (fs, bno, data)) { - fprintf (stderr, "inode_clear: read error at block %d\n", bno); - return 0; - } - for (i=BSDFS_BSIZE-4; i>=0; i-=4) { - if (i/4 * BSDFS_BSIZE/4 * BSDFS_BSIZE/4 < nblk) { - /* Truncate up to required size. */ - return 0; - } - nb = data [i+3] << 24 | data [i+2] << 16 | - data [i+1] << 8 | data [i]; - if (nb) - fs_double_indirect_block_free (fs, nb, - nblk - i/4 * BSDFS_BSIZE/4 * BSDFS_BSIZE/4); - } - fs_block_free (fs, bno); - return 1; + if (! fs_read_block (fs, bno, data)) { + fprintf (stderr, "inode_clear: read error at block %d\n", bno); + return 0; + } + for (i=BSDFS_BSIZE-4; i>=0; i-=4) { + if (i/4 * BSDFS_BSIZE/4 * BSDFS_BSIZE/4 < nblk) { + /* Truncate up to required size. */ + return 0; + } + nb = data [i+3] << 24 | data [i+2] << 16 | + data [i+1] << 8 | data [i]; + if (nb) + fs_double_indirect_block_free (fs, nb, + nblk - i/4 * BSDFS_BSIZE/4 * BSDFS_BSIZE/4); + } + fs_block_free (fs, bno); + return 1; } /* @@ -169,26 +169,26 @@ int fs_triple_indirect_block_free (fs_t *fs, unsigned int bno, int nblk) */ int fs_block_alloc (fs_t *fs, unsigned int *bno) { - int i; - unsigned buf [BSDFS_BSIZE / 4]; + int i; + unsigned buf [BSDFS_BSIZE / 4]; again: - if (fs->nfree == 0) - return 0; - fs->nfree--; - --fs->tfree; /* Count total free blocks. */ - *bno = fs->free [fs->nfree]; - if (verbose) - printf ("allocate new block %d from slot %d\n", *bno, fs->nfree); - fs->free [fs->nfree] = 0; - fs->dirty = 1; - if (fs->nfree <= 0) { - if (! fs_read_block (fs, *bno, (unsigned char*) buf)) - return 0; - fs->nfree = buf[0]; - for (i=0; ifree[i] = buf[i+1]; - } - if (*bno == 0) - goto again; - return 1; + if (fs->nfree == 0) + return 0; + fs->nfree--; + --fs->tfree; /* Count total free blocks. */ + *bno = fs->free [fs->nfree]; + if (verbose) + printf ("allocate new block %d from slot %d\n", *bno, fs->nfree); + fs->free [fs->nfree] = 0; + fs->dirty = 1; + if (fs->nfree <= 0) { + if (! fs_read_block (fs, *bno, (unsigned char*) buf)) + return 0; + fs->nfree = buf[0]; + for (i=0; ifree[i] = buf[i+1]; + } + if (*bno == 0) + goto again; + return 1; } diff --git a/tools/fsutil/bsdfs.h b/tools/fsutil/bsdfs.h index e2d77d5..bd54e8b 100644 --- a/tools/fsutil/bsdfs.h +++ b/tools/fsutil/bsdfs.h @@ -21,135 +21,135 @@ * arising out of or in connection with the use or performance of * this software. */ -#define BSDFS_BSIZE 1024 /* block size */ -#define BSDFS_ROOT_INODE 2 /* root directory in inode 2 */ -#define BSDFS_LOSTFOUND_INODE 3 /* lost+found directory in inode 3 */ -#define BSDFS_SWAP_INODE 4 /* swap file in inode 4 */ -#define BSDFS_INODES_PER_BLOCK 16 /* inodes per block */ +#define BSDFS_BSIZE 1024 /* block size */ +#define BSDFS_ROOT_INODE 2 /* root directory in inode 2 */ +#define BSDFS_LOSTFOUND_INODE 3 /* lost+found directory in inode 3 */ +#define BSDFS_SWAP_INODE 4 /* swap file in inode 4 */ +#define BSDFS_INODES_PER_BLOCK 16 /* inodes per block */ -#define NICINOD 32 /* number of superblock inodes */ -#define NICFREE 200 /* number of superblock free blocks */ +#define NICINOD 32 /* number of superblock inodes */ +#define NICFREE 200 /* number of superblock free blocks */ /* * 28 of the di_addr address bytes are used; 7 addresses of 4 * bytes each: 4 direct (4Kb directly accessible) and 3 indirect. */ -#define NDADDR 4 /* direct addresses in inode */ -#define NIADDR 3 /* indirect addresses in inode */ -#define NADDR (NDADDR + NIADDR) /* total addresses in inode */ +#define NDADDR 4 /* direct addresses in inode */ +#define NIADDR 3 /* indirect addresses in inode */ +#define NADDR (NDADDR + NIADDR) /* total addresses in inode */ /* * NINDIR is the number of indirects in a file system block. */ -#define NINDIR (DEV_BSIZE / sizeof(daddr_t)) -#define NSHIFT 8 /* log2(NINDIR) */ -#define NMASK 0377L /* NINDIR - 1 */ +#define NINDIR (DEV_BSIZE / sizeof(daddr_t)) +#define NSHIFT 8 /* log2(NINDIR) */ +#define NMASK 0377L /* NINDIR - 1 */ /* * The path name on which the file system is mounted is maintained * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in * the super block for this name. */ -#define MAXMNTLEN 28 +#define MAXMNTLEN 28 -#define FSMAGIC1 ('F' | 'S'<<8 | '<'<<16 | '<'<<24) -#define FSMAGIC2 ('>' | '>'<<8 | 'F'<<16 | 'S'<<24) +#define FSMAGIC1 ('F' | 'S'<<8 | '<'<<16 | '<'<<24) +#define FSMAGIC2 ('>' | '>'<<8 | 'F'<<16 | 'S'<<24) typedef struct { - const char *filename; - int fd; - unsigned long seek; - int writable; - int dirty; /* sync needed */ - int modified; /* write_block was called */ + const char *filename; + int fd; + unsigned long seek; + int writable; + int dirty; /* sync needed */ + int modified; /* write_block was called */ - unsigned isize; /* size in blocks of superblock + I list */ - unsigned fsize; /* size in blocks of entire volume */ - unsigned swapsz; /* size in blocks of swap area */ - unsigned nfree; /* number of in core free blocks (0-100) */ - unsigned free [NICFREE]; /* in core free blocks */ - unsigned ninode; /* number of in core I nodes (0-100) */ - unsigned inode [NICINOD]; /* in core free I nodes */ - unsigned flock; /* lock during free list manipulation */ - unsigned ilock; /* lock during I list manipulation */ - unsigned fmod; /* super block modified flag */ - unsigned ronly; /* mounted read-only flag */ - long utime; /* current date of last update */ - unsigned tfree; /* total free blocks */ - unsigned tinode; /* total free inodes */ - char fsmnt [MAXMNTLEN]; /* ordinary file mounted on */ - unsigned lasti; /* start place for circular search */ - unsigned nbehind; /* est # free inodes before s_lasti */ - unsigned flags; /* mount time flags */ + unsigned isize; /* size in blocks of superblock + I list */ + unsigned fsize; /* size in blocks of entire volume */ + unsigned swapsz; /* size in blocks of swap area */ + unsigned nfree; /* number of in core free blocks (0-100) */ + unsigned free [NICFREE]; /* in core free blocks */ + unsigned ninode; /* number of in core I nodes (0-100) */ + unsigned inode [NICINOD]; /* in core free I nodes */ + unsigned flock; /* lock during free list manipulation */ + unsigned ilock; /* lock during I list manipulation */ + unsigned fmod; /* super block modified flag */ + unsigned ronly; /* mounted read-only flag */ + long utime; /* current date of last update */ + unsigned tfree; /* total free blocks */ + unsigned tinode; /* total free inodes */ + char fsmnt [MAXMNTLEN]; /* ordinary file mounted on */ + unsigned lasti; /* start place for circular search */ + unsigned nbehind; /* est # free inodes before s_lasti */ + unsigned flags; /* mount time flags */ } fs_t; typedef struct { - fs_t *fs; - unsigned number; - int dirty; /* save needed */ + fs_t *fs; + unsigned number; + int dirty; /* save needed */ - unsigned short mode; /* file type and access mode */ -#define INODE_MODE_FMT 0170000 /* type of file */ -#define INODE_MODE_FCHR 020000 /* character special */ -#define INODE_MODE_FDIR 040000 /* directory */ -#define INODE_MODE_FBLK 060000 /* block special */ -#define INODE_MODE_FREG 0100000 /* regular */ -#define INODE_MODE_FLNK 0120000 /* symbolic link */ -#define INODE_MODE_FSOCK 0140000 /* socket */ -#define INODE_MODE_SUID 04000 /* set user id on execution */ -#define INODE_MODE_SGID 02000 /* set group id on execution */ -#define INODE_MODE_SVTX 01000 /* save swapped text even after use */ -#define INODE_MODE_READ 0400 /* read, write, execute permissions */ -#define INODE_MODE_WRITE 0200 -#define INODE_MODE_EXEC 0100 + unsigned short mode; /* file type and access mode */ +#define INODE_MODE_FMT 0170000 /* type of file */ +#define INODE_MODE_FCHR 020000 /* character special */ +#define INODE_MODE_FDIR 040000 /* directory */ +#define INODE_MODE_FBLK 060000 /* block special */ +#define INODE_MODE_FREG 0100000 /* regular */ +#define INODE_MODE_FLNK 0120000 /* symbolic link */ +#define INODE_MODE_FSOCK 0140000 /* socket */ +#define INODE_MODE_SUID 04000 /* set user id on execution */ +#define INODE_MODE_SGID 02000 /* set group id on execution */ +#define INODE_MODE_SVTX 01000 /* save swapped text even after use */ +#define INODE_MODE_READ 0400 /* read, write, execute permissions */ +#define INODE_MODE_WRITE 0200 +#define INODE_MODE_EXEC 0100 - unsigned short nlink; /* directory entries */ - unsigned uid; /* owner */ - unsigned gid; /* group */ - unsigned long size; /* size */ - unsigned addr [7]; /* device addresses constituting file */ - unsigned flags; /* user defined flags */ + unsigned short nlink; /* directory entries */ + unsigned uid; /* owner */ + unsigned gid; /* group */ + unsigned long size; /* size */ + unsigned addr [7]; /* device addresses constituting file */ + unsigned flags; /* user defined flags */ /* * Super-user and owner changeable flags. */ -#define USER_SETTABLE 0x00ff /* mask of owner changeable flags */ -#define USER_NODUMP 0x0001 /* do not dump file */ -#define USER_IMMUTABLE 0x0002 /* file may not be changed */ -#define USER_APPEND 0x0004 /* writes to file may only append */ +#define USER_SETTABLE 0x00ff /* mask of owner changeable flags */ +#define USER_NODUMP 0x0001 /* do not dump file */ +#define USER_IMMUTABLE 0x0002 /* file may not be changed */ +#define USER_APPEND 0x0004 /* writes to file may only append */ /* * Super-user changeable flags. */ -#define SYS_SETTABLE 0xff00 /* mask of superuser changeable flags */ -#define SYS_ARCHIVED 0x0100 /* file is archived */ -#define SYS_IMMUTABLE 0x0200 /* file may not be changed */ -#define SYS_APPEND 0x0400 /* writes to file may only append */ +#define SYS_SETTABLE 0xff00 /* mask of superuser changeable flags */ +#define SYS_ARCHIVED 0x0100 /* file is archived */ +#define SYS_IMMUTABLE 0x0200 /* file may not be changed */ +#define SYS_APPEND 0x0400 /* writes to file may only append */ - long atime; /* time last accessed */ - long mtime; /* time last modified */ - long ctime; /* time created */ + long atime; /* time last accessed */ + long mtime; /* time last modified */ + long ctime; /* time created */ } fs_inode_t; typedef struct { - unsigned ino; - unsigned reclen; - unsigned namlen; - char name [63+1]; + unsigned ino; + unsigned reclen; + unsigned namlen; + char name [63+1]; } fs_dirent_t; typedef void (*fs_directory_scanner_t) (fs_inode_t *dir, - fs_inode_t *file, char *dirname, char *filename, void *arg); + fs_inode_t *file, char *dirname, char *filename, void *arg); typedef struct { - fs_inode_t inode; - int writable; /* write allowed */ - unsigned long offset; /* current i/o offset */ + fs_inode_t inode; + int writable; /* write allowed */ + unsigned long offset; /* current i/o offset */ } fs_file_t; typedef enum { - INODE_OP_LOOKUP, /* lookup inode by name */ - INODE_OP_CREATE, /* create new file */ - INODE_OP_DELETE, /* delete file */ - INODE_OP_LINK, /* make a link to a file */ + INODE_OP_LOOKUP, /* lookup inode by name */ + INODE_OP_CREATE, /* create new file */ + INODE_OP_DELETE, /* delete file */ + INODE_OP_LINK, /* make a link to a file */ } fs_op_t; int fs_seek (fs_t *fs, unsigned long offset); @@ -167,7 +167,7 @@ int fs_open (fs_t *fs, const char *filename, int writable); void fs_close (fs_t *fs); int fs_sync (fs_t *fs, int force); int fs_create (fs_t *fs, const char *filename, unsigned kbytes, - unsigned swap_kbytes); + unsigned swap_kbytes); int fs_check (fs_t *fs); void fs_print (fs_t *fs, FILE *out); @@ -179,12 +179,12 @@ void fs_inode_clear (fs_inode_t *inode); void fs_inode_truncate (fs_inode_t *inode, unsigned long size); void fs_inode_print (fs_inode_t *inode, FILE *out); int fs_inode_read (fs_inode_t *inode, unsigned long offset, - unsigned char *data, unsigned long bytes); + unsigned char *data, unsigned long bytes); int fs_inode_write (fs_inode_t *inode, unsigned long offset, - unsigned char *data, unsigned long bytes); + unsigned char *data, unsigned long bytes); int fs_inode_alloc (fs_t *fs, fs_inode_t *inode); int fs_inode_by_name (fs_t *fs, fs_inode_t *inode, const char *name, - fs_op_t op, int mode); + fs_op_t op, int mode); int inode_build_list (fs_t *fs); int fs_write_block (fs_t *fs, unsigned bnum, unsigned char *data); @@ -196,14 +196,14 @@ int fs_double_indirect_block_free (fs_t *fs, unsigned int bno, int nblk); int fs_triple_indirect_block_free (fs_t *fs, unsigned int bno, int nblk); void fs_directory_scan (fs_inode_t *inode, char *dirname, - fs_directory_scanner_t scanner, void *arg); + fs_directory_scanner_t scanner, void *arg); void fs_dirent_pack (unsigned char *data, fs_dirent_t *dirent); void fs_dirent_unpack (fs_dirent_t *dirent, unsigned char *data); int fs_file_create (fs_t *fs, fs_file_t *file, const char *name, int mode); int fs_file_open (fs_t *fs, fs_file_t *file, const char *name, int wflag); int fs_file_read (fs_file_t *file, unsigned char *data, - unsigned long bytes); + unsigned long bytes); int fs_file_write (fs_file_t *file, unsigned char *data, - unsigned long bytes); + unsigned long bytes); int fs_file_close (fs_file_t *file); diff --git a/tools/fsutil/check.c b/tools/fsutil/check.c index 6240cde..2aa9e80 100644 --- a/tools/fsutil/check.c +++ b/tools/fsutil/check.c @@ -31,138 +31,138 @@ extern int verbose; -#define MAXDUP 10 /* limit on dup blks (per inode) */ -#define MAXBAD 10 /* limit on bad blks (per inode) */ -#define DUP_LIST_SIZE 100 /* num of dup blocks to remember */ -#define LINK_LIST_SIZE 20 /* num zero link cnts to remember */ +#define MAXDUP 10 /* limit on dup blks (per inode) */ +#define MAXBAD 10 /* limit on bad blks (per inode) */ +#define DUP_LIST_SIZE 100 /* num of dup blocks to remember */ +#define LINK_LIST_SIZE 20 /* num zero link cnts to remember */ -#define STATE_BITS 2 /* bits per inode state */ -#define STATE_MASK 3 /* mask for inode state */ -#define STATES_PER_BYTE 4 /* inode states per byte */ -#define USTATE 0 /* inode not allocated */ -#define FSTATE 1 /* inode is file */ -#define DSTATE 2 /* inode is directory */ -#define CLEAR 3 /* inode is to be cleared */ +#define STATE_BITS 2 /* bits per inode state */ +#define STATE_MASK 3 /* mask for inode state */ +#define STATES_PER_BYTE 4 /* inode states per byte */ +#define USTATE 0 /* inode not allocated */ +#define FSTATE 1 /* inode is file */ +#define DSTATE 2 /* inode is directory */ +#define CLEAR 3 /* inode is to be cleared */ -#define DATA 1 /* flags for scan_inode() */ -#define ADDR 0 +#define DATA 1 /* flags for scan_inode() */ +#define ADDR 0 -#define ALTERD 010 /* values returned by scan functions */ -#define KEEPON 004 -#define SKIP 002 -#define STOP 001 +#define ALTERD 010 /* values returned by scan functions */ +#define KEEPON 004 +#define SKIP 002 +#define STOP 001 -#define outrange(fs,x) ((x) < (fs)->isize || (x) >= (fs)->fsize) +#define outrange(fs,x) ((x) < (fs)->isize || (x) >= (fs)->fsize) /* block scan function, called by scan_inode for every file block */ typedef int scanner_t (fs_inode_t *inode, unsigned blk, void *arg); -static unsigned char buf_data [BSDFS_BSIZE]; /* buffer data for scan_directory */ -static unsigned buf_bno; /* buffer block number */ -static int buf_dirty; /* buffer data modified */ +static unsigned char buf_data [BSDFS_BSIZE]; /* buffer data for scan_directory */ +static unsigned buf_bno; /* buffer block number */ +static int buf_dirty; /* buffer data modified */ -static unsigned dup_list [DUP_LIST_SIZE]; /* dup block table */ -static unsigned *dup_end; /* next entry in dup table */ -static unsigned *dup_multi; /* multiple dups part of table */ +static unsigned dup_list [DUP_LIST_SIZE]; /* dup block table */ +static unsigned *dup_end; /* next entry in dup table */ +static unsigned *dup_multi; /* multiple dups part of table */ -static unsigned bad_link_list [LINK_LIST_SIZE]; /* inos with zero link cnts */ -static unsigned *bad_link_end; /* next entry in table */ +static unsigned bad_link_list [LINK_LIST_SIZE]; /* inos with zero link cnts */ +static unsigned *bad_link_end; /* next entry in table */ -static char *block_map; /* primary blk allocation map */ -static char *free_map; /* secondary blk allocation map */ -static char *state_map; /* inode state table */ -static int *link_count; /* link count table */ +static char *block_map; /* primary blk allocation map */ +static char *free_map; /* secondary blk allocation map */ +static char *state_map; /* inode state table */ +static int *link_count; /* link count table */ -static char pathname [256]; /* file path name for pass2 */ -static char *pathp; /* pointer to pathname position */ -static char *thisname; /* ptr to current pathname component */ +static char pathname [256]; /* file path name for pass2 */ +static char *pathp; /* pointer to pathname position */ +static char *thisname; /* ptr to current pathname component */ -static char *lost_found_name = "lost+found"; -static unsigned lost_found_inode; /* lost & found directory */ +static char *lost_found_name = "lost+found"; +static unsigned lost_found_inode; /* lost & found directory */ -static int free_list_corrupted; /* corrupted free list */ -static int bad_blocks; /* num of bad blks seen (per inode) */ -static int dup_blocks; /* num of dup blks seen (per inode) */ +static int free_list_corrupted; /* corrupted free list */ +static int bad_blocks; /* num of bad blks seen (per inode) */ +static int dup_blocks; /* num of dup blks seen (per inode) */ -static char *find_inode_name; /* searching for this name */ -static unsigned find_inode_result; /* result of inode search */ -static unsigned lost_inode; /* lost file to reconnect */ +static char *find_inode_name; /* searching for this name */ +static unsigned find_inode_result; /* result of inode search */ +static unsigned lost_inode; /* lost file to reconnect */ -static unsigned long scan_filesize; /* file size, decremented during scan */ -static unsigned total_files; /* number of files seen */ +static unsigned long scan_filesize; /* file size, decremented during scan */ +static unsigned total_files; /* number of files seen */ static void set_inode_state (unsigned inum, int s) { - unsigned int byte, shift; + unsigned int byte, shift; - byte = inum / STATES_PER_BYTE; - shift = inum % STATES_PER_BYTE * STATE_BITS; - state_map [byte] &= ~(STATE_MASK << shift); - state_map [byte] |= s << shift; + byte = inum / STATES_PER_BYTE; + shift = inum % STATES_PER_BYTE * STATE_BITS; + state_map [byte] &= ~(STATE_MASK << shift); + state_map [byte] |= s << shift; } static int inode_state (unsigned inum) { - unsigned int byte, shift; + unsigned int byte, shift; - byte = inum / STATES_PER_BYTE; - shift = inum % STATES_PER_BYTE * STATE_BITS; - return (state_map [byte] >> shift) & STATE_MASK; + byte = inum / STATES_PER_BYTE; + shift = inum % STATES_PER_BYTE * STATE_BITS; + return (state_map [byte] >> shift) & STATE_MASK; } static int block_is_busy (unsigned blk) { - return block_map [blk >> 3] & (1 << (blk & 7)); + return block_map [blk >> 3] & (1 << (blk & 7)); } static void mark_block_busy (unsigned blk) { - block_map [blk >> 3] |= 1 << (blk & 7); + block_map [blk >> 3] |= 1 << (blk & 7); } static void mark_block_free (unsigned blk) { - block_map [blk >> 3] &= ~(1 << (blk & 7)); + block_map [blk >> 3] &= ~(1 << (blk & 7)); } static void mark_free_list (unsigned blk) { - free_map [blk >> 3] |= 1 << (blk & 7); + free_map [blk >> 3] |= 1 << (blk & 7); } static int in_free_list (unsigned blk) { - return free_map [blk >> 3] & (1 << (blk & 7)); + return free_map [blk >> 3] & (1 << (blk & 7)); } static void print_io_error (char *s, unsigned blk) { - printf ("\nCAN NOT %s: BLK %d\n", s, blk); + printf ("\nCAN NOT %s: BLK %d\n", s, blk); } static void buf_flush (fs_t *fs) { - if (buf_dirty && fs->writable) { + if (buf_dirty && fs->writable) { /*printf ("WRITE blk %d\n", buf_bno);*/ - if (! fs_write_block (fs, buf_bno, buf_data)) - print_io_error ("WRITE", buf_bno); - } - buf_dirty = 0; + if (! fs_write_block (fs, buf_bno, buf_data)) + print_io_error ("WRITE", buf_bno); + } + buf_dirty = 0; } static int buf_get (fs_t *fs, unsigned blk) { - if (buf_bno == blk) - return 1; - buf_flush (fs); + if (buf_bno == blk) + return 1; + buf_flush (fs); /*printf ("read blk %d\n", blk);*/ - if (! fs_read_block (fs, blk, buf_data)) { - print_io_error ("READ", blk); - buf_bno = (unsigned)-1; - return 0; - } - buf_bno = blk; - return 1; + if (! fs_read_block (fs, blk, buf_data)) { + print_io_error ("READ", blk); + buf_bno = (unsigned)-1; + return 0; + } + buf_bno = blk; + return 1; } /* @@ -170,39 +170,39 @@ static int buf_get (fs_t *fs, unsigned blk) * and for every block call the given function. */ static int scan_indirect_block (fs_inode_t *inode, unsigned blk, - int double_indirect, int flg, scanner_t *func, void *arg) + int double_indirect, int flg, scanner_t *func, void *arg) { - unsigned nb; - int ret, i; - unsigned char data [BSDFS_BSIZE]; + unsigned nb; + int ret, i; + unsigned char data [BSDFS_BSIZE]; /*printf ("check %siblock %d: \n", double_indirect > 1 ? "triple " : double_indirect ? "double " : "", blk);*/ - if (flg == ADDR) { - ret = (*func) (inode, blk, arg); - if (! (ret & KEEPON)) - return ret; - } - if (outrange (inode->fs, blk)) /* protect thyself */ - return SKIP; + if (flg == ADDR) { + ret = (*func) (inode, blk, arg); + if (! (ret & KEEPON)) + return ret; + } + if (outrange (inode->fs, blk)) /* protect thyself */ + return SKIP; - if (! fs_read_block (inode->fs, blk, data)) { - print_io_error ("READ", blk); - return SKIP; - } - for (i = 0; i < BSDFS_BSIZE; i+=2) { - nb = data [i+1] << 8 | data [i]; - if (nb) { - if (double_indirect) - ret = scan_indirect_block (inode, nb, - double_indirect - 1, flg, func, arg); - else - ret = (*func) (inode, nb, arg); + if (! fs_read_block (inode->fs, blk, data)) { + print_io_error ("READ", blk); + return SKIP; + } + for (i = 0; i < BSDFS_BSIZE; i+=2) { + nb = data [i+1] << 8 | data [i]; + if (nb) { + if (double_indirect) + ret = scan_indirect_block (inode, nb, + double_indirect - 1, flg, func, arg); + else + ret = (*func) (inode, nb, arg); - if (ret & STOP) - return ret; - } - } - return KEEPON; + if (ret & STOP) + return ret; + } + } + return KEEPON; } /* @@ -214,50 +214,50 @@ static int scan_indirect_block (fs_inode_t *inode, unsigned blk, */ static int scan_inode (fs_inode_t *inode, int flg, scanner_t *func, void *arg) { - unsigned *ap; - int ret; + unsigned *ap; + int ret; /*printf ("check inode %d: %#o\n", inode->number, inode->mode);*/ - if (((inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK) || - ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FCHR)) - return KEEPON; - scan_filesize = inode->size; + if (((inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK) || + ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FCHR)) + return KEEPON; + scan_filesize = inode->size; - /* Check direct blocks. */ - for (ap = inode->addr; ap < &inode->addr[NDADDR]; ap++) { - if (*ap) { - ret = (*func) (inode, *ap, arg); - if (ret & STOP) - return ret; - } - } - if (inode->addr[NADDR-3]) { - /* Check the indirect block. */ - ret = scan_indirect_block (inode, inode->addr[NADDR-3], 0, - flg, func, arg); - if (ret & STOP) - return (ret); - } - if (inode->addr[NADDR-2]) { - /* Check the double indirect block. */ - ret = scan_indirect_block (inode, inode->addr[NADDR-2], 1, - flg, func, arg); - if (ret & STOP) - return (ret); - } - if (inode->addr[NADDR-1]) { - /* Check the last (triple indirect) block. */ - ret = scan_indirect_block (inode, inode->addr[NADDR-1], 2, - flg, func, arg); - if (ret & STOP) - return (ret); - } - return KEEPON; + /* Check direct blocks. */ + for (ap = inode->addr; ap < &inode->addr[NDADDR]; ap++) { + if (*ap) { + ret = (*func) (inode, *ap, arg); + if (ret & STOP) + return ret; + } + } + if (inode->addr[NADDR-3]) { + /* Check the indirect block. */ + ret = scan_indirect_block (inode, inode->addr[NADDR-3], 0, + flg, func, arg); + if (ret & STOP) + return (ret); + } + if (inode->addr[NADDR-2]) { + /* Check the double indirect block. */ + ret = scan_indirect_block (inode, inode->addr[NADDR-2], 1, + flg, func, arg); + if (ret & STOP) + return (ret); + } + if (inode->addr[NADDR-1]) { + /* Check the last (triple indirect) block. */ + ret = scan_indirect_block (inode, inode->addr[NADDR-1], 2, + flg, func, arg); + if (ret & STOP) + return (ret); + } + return KEEPON; } static void print_block_error (char *s, unsigned blk, unsigned inum) { - printf ("%u %s I=%u\n", blk, s, inum); + printf ("%u %s I=%u\n", blk, s, inum); } /* @@ -267,64 +267,64 @@ static void print_block_error (char *s, unsigned blk, unsigned inum) */ static int pass1 (fs_inode_t *inode, unsigned blk, void *arg) { - unsigned *dlp; - unsigned *blocks = arg; + unsigned *dlp; + unsigned *blocks = arg; /*printf ("pass1 inode %d block %d: \n", inode->number, blk);*/ - if (outrange (inode->fs, blk)) { - print_block_error ("BAD", blk, inode->number); - set_inode_state (inode->number, CLEAR); /* mark for possible clearing */ - if (++bad_blocks >= MAXBAD) { - printf ("EXCESSIVE BAD BLKS I=%u\n", inode->number); - return STOP; - } - return SKIP; - } - if (block_is_busy (blk)) { - print_block_error ("DUP", blk, inode->number); - set_inode_state (inode->number, CLEAR); /* mark for possible clearing */ - if (++dup_blocks >= MAXDUP) { - printf ("EXCESSIVE DUP BLKS I=%u\n", inode->number); - return STOP; - } - if (dup_end >= &dup_list[DUP_LIST_SIZE]) { - printf ("DUP TABLE OVERFLOW.\n"); - return STOP; - } - for (dlp = dup_list; dlp < dup_multi; dlp++) { - if (*dlp == blk) { - *dup_end++ = blk; - break; - } - } - if (dlp >= dup_multi) { - *dup_end++ = *dup_multi; - *dup_multi++ = blk; - } - } else { - if (blocks) - ++*blocks; - mark_block_busy (blk); - } - return KEEPON; + if (outrange (inode->fs, blk)) { + print_block_error ("BAD", blk, inode->number); + set_inode_state (inode->number, CLEAR); /* mark for possible clearing */ + if (++bad_blocks >= MAXBAD) { + printf ("EXCESSIVE BAD BLKS I=%u\n", inode->number); + return STOP; + } + return SKIP; + } + if (block_is_busy (blk)) { + print_block_error ("DUP", blk, inode->number); + set_inode_state (inode->number, CLEAR); /* mark for possible clearing */ + if (++dup_blocks >= MAXDUP) { + printf ("EXCESSIVE DUP BLKS I=%u\n", inode->number); + return STOP; + } + if (dup_end >= &dup_list[DUP_LIST_SIZE]) { + printf ("DUP TABLE OVERFLOW.\n"); + return STOP; + } + for (dlp = dup_list; dlp < dup_multi; dlp++) { + if (*dlp == blk) { + *dup_end++ = blk; + break; + } + } + if (dlp >= dup_multi) { + *dup_end++ = *dup_multi; + *dup_multi++ = blk; + } + } else { + if (blocks) + ++*blocks; + mark_block_busy (blk); + } + return KEEPON; } static int pass1b (fs_inode_t *inode, unsigned blk, void *arg) { - unsigned *dlp; + unsigned *dlp; - if (outrange (inode->fs, blk)) - return SKIP; - for (dlp = dup_list; dlp < dup_multi; dlp++) { - if (*dlp == blk) { - print_block_error ("DUP", blk, inode->number); - set_inode_state (inode->number, CLEAR); /* mark for possible clearing */ - *dlp = *--dup_multi; - *dup_multi = blk; - return (dup_multi == dup_list ? STOP : KEEPON); - } - } - return KEEPON; + if (outrange (inode->fs, blk)) + return SKIP; + for (dlp = dup_list; dlp < dup_multi; dlp++) { + if (*dlp == blk) { + print_block_error ("DUP", blk, inode->number); + set_inode_state (inode->number, CLEAR); /* mark for possible clearing */ + *dlp = *--dup_multi; + *dup_multi = blk; + return (dup_multi == dup_list ? STOP : KEEPON); + } + } + return KEEPON; } /* @@ -333,68 +333,68 @@ static int pass1b (fs_inode_t *inode, unsigned blk, void *arg) */ static int scan_directory (fs_inode_t *inode, unsigned blk, void *arg) { - fs_dirent_t direntry; - unsigned char *dirp; - int (*func) () = arg; - int n; + fs_dirent_t direntry; + unsigned char *dirp; + int (*func) () = arg; + int n; /*printf ("scan_directory: I=%d, blk=%d\n", inode->number, blk);*/ - if (outrange (inode->fs, blk)) { - scan_filesize -= BSDFS_BSIZE; - return SKIP; - } - dirp = buf_data; - while (dirp < &buf_data[BSDFS_BSIZE] && scan_filesize > 0) { - if (! buf_get (inode->fs, blk)) { - scan_filesize -= (&buf_data[BSDFS_BSIZE] - dirp); - return SKIP; - } - fs_dirent_unpack (&direntry, dirp); - if (direntry.reclen == 0) - break; + if (outrange (inode->fs, blk)) { + scan_filesize -= BSDFS_BSIZE; + return SKIP; + } + dirp = buf_data; + while (dirp < &buf_data[BSDFS_BSIZE] && scan_filesize > 0) { + if (! buf_get (inode->fs, blk)) { + scan_filesize -= (&buf_data[BSDFS_BSIZE] - dirp); + return SKIP; + } + fs_dirent_unpack (&direntry, dirp); + if (direntry.reclen == 0) + break; - /* For every directory entry, call handler. */ - n = (*func) (inode->fs, &direntry); + /* For every directory entry, call handler. */ + n = (*func) (inode->fs, &direntry); - if (n & ALTERD) { - if (buf_get (inode->fs, blk)) { - fs_dirent_pack (dirp, &direntry); - buf_dirty = 1; - } else - n &= ~ALTERD; - } - if (n & STOP) - return n; - dirp += direntry.reclen; - scan_filesize -= direntry.reclen; - } - return (scan_filesize > 0) ? KEEPON : STOP; + if (n & ALTERD) { + if (buf_get (inode->fs, blk)) { + fs_dirent_pack (dirp, &direntry); + buf_dirty = 1; + } else + n &= ~ALTERD; + } + if (n & STOP) + return n; + dirp += direntry.reclen; + scan_filesize -= direntry.reclen; + } + return (scan_filesize > 0) ? KEEPON : STOP; } static void print_inode (fs_inode_t *inode) { - char *p; + char *p; - printf (" I=%u ", inode->number); - printf (" OWNER=%d ", inode->uid); - printf ("MODE=%o\n", inode->mode); - printf ("SIZE=%ld ", inode->size); - p = ctime (&inode->mtime); - printf ("MTIME=%12.12s %4.4s\n", p+4, p+20); + printf (" I=%u ", inode->number); + printf (" OWNER=%d ", inode->uid); + printf ("MODE=%o\n", inode->mode); + printf ("SIZE=%ld ", inode->size); + p = ctime (&inode->mtime); + printf ("MTIME=%12.12s %4.4s\n", p+4, p+20); } static void print_dir_error (fs_t *fs, unsigned inum, char *s) { - fs_inode_t inode; + fs_inode_t inode; - if (! fs_inode_get (fs, &inode, inum)) { - printf ("%s I=%u\nNAME=%s\n", s, inum, pathname); - return; - } - printf ("%s ", s); - print_inode (&inode); - printf ("%s=%s\n", ((inode.mode & INODE_MODE_FMT) == - INODE_MODE_FDIR) ? "DIR" : "FILE", pathname); + if (! fs_inode_get (fs, &inode, inum)) { + printf ("%s I=%u\nNAME=%s\n", s, inum, pathname); + return; + } + printf ("%s ", s); + print_inode (&inode); + printf ("%s=%s\n", ((inode.mode & INODE_MODE_FMT) == + INODE_MODE_FDIR) ? "DIR" : "FILE", pathname); } static void scan_pass2 (fs_t *fs, unsigned inum); @@ -405,53 +405,53 @@ static void scan_pass2 (fs_t *fs, unsigned inum); */ static int pass2 (fs_t *fs, fs_dirent_t *dirp) { - int inum, ret = KEEPON; - fs_inode_t inode; + int inum, ret = KEEPON; + fs_inode_t inode; - inum = dirp->ino; - if (inum == 0) - return KEEPON; + inum = dirp->ino; + if (inum == 0) + return KEEPON; - /* Copy file name from dirp to pathp */ - thisname = pathp; - strcpy (pathp, dirp->name); - pathp += strlen (pathp); + /* Copy file name from dirp to pathp */ + thisname = pathp; + strcpy (pathp, dirp->name); + pathp += strlen (pathp); /*printf ("%s %d\n", pathname, inum);*/ - if (inum > (fs->isize - 1) * BSDFS_INODES_PER_BLOCK || - inum < BSDFS_ROOT_INODE) - print_dir_error (fs, inum, "I OUT OF RANGE"); - else { -again: switch (inode_state (inum)) { - case USTATE: - print_dir_error (fs, inum, "UNALLOCATED"); - if (fs->writable) { - dirp->ino = 0; - ret |= ALTERD; - break; - } - break; - case CLEAR: - print_dir_error (fs, inum, "DUP/BAD"); - if (fs->writable) { - dirp->ino = 0; - ret |= ALTERD; - break; - } - if (! fs_inode_get (fs, &inode, inum)) - break; - set_inode_state (inum, ((inode.mode & INODE_MODE_FMT) == - INODE_MODE_FDIR) ? DSTATE : FSTATE); - goto again; - case FSTATE: - --link_count [inum]; - break; - case DSTATE: - --link_count [inum]; - scan_pass2 (fs, inum); - } - } - pathp = thisname; - return ret; + if (inum > (fs->isize - 1) * BSDFS_INODES_PER_BLOCK || + inum < BSDFS_ROOT_INODE) + print_dir_error (fs, inum, "I OUT OF RANGE"); + else { +again: switch (inode_state (inum)) { + case USTATE: + print_dir_error (fs, inum, "UNALLOCATED"); + if (fs->writable) { + dirp->ino = 0; + ret |= ALTERD; + break; + } + break; + case CLEAR: + print_dir_error (fs, inum, "DUP/BAD"); + if (fs->writable) { + dirp->ino = 0; + ret |= ALTERD; + break; + } + if (! fs_inode_get (fs, &inode, inum)) + break; + set_inode_state (inum, ((inode.mode & INODE_MODE_FMT) == + INODE_MODE_FDIR) ? DSTATE : FSTATE); + goto again; + case FSTATE: + --link_count [inum]; + break; + case DSTATE: + --link_count [inum]; + scan_pass2 (fs, inum); + } + } + pathp = thisname; + return ret; } /* @@ -460,20 +460,20 @@ again: switch (inode_state (inum)) { */ static void scan_pass2 (fs_t *fs, unsigned inum) { - fs_inode_t inode; - char *savname; - unsigned long savsize; + fs_inode_t inode; + char *savname; + unsigned long savsize; - set_inode_state (inum, FSTATE); - if (! fs_inode_get (fs, &inode, inum)) - return; - *pathp++ = '/'; - savname = thisname; - savsize = scan_filesize; - scan_inode (&inode, DATA, scan_directory, pass2); - scan_filesize = savsize; - thisname = savname; - *--pathp = 0; + set_inode_state (inum, FSTATE); + if (! fs_inode_get (fs, &inode, inum)) + return; + *pathp++ = '/'; + savname = thisname; + savsize = scan_filesize; + scan_inode (&inode, DATA, scan_directory, pass2); + scan_filesize = savsize; + thisname = savname; + *--pathp = 0; } /* @@ -483,15 +483,15 @@ static void scan_pass2 (fs_t *fs, unsigned inum) */ static int find_inode (fs_t *fs, fs_dirent_t *dirp) { - if (dirp->ino == 0) - return KEEPON; - if (strcmp (find_inode_name, dirp->name) == 0) { - if (dirp->ino >= BSDFS_ROOT_INODE && - dirp->ino < (fs->isize-1) * BSDFS_INODES_PER_BLOCK) - find_inode_result = dirp->ino; - return STOP; - } - return KEEPON; + if (dirp->ino == 0) + return KEEPON; + if (strcmp (find_inode_name, dirp->name) == 0) { + if (dirp->ino >= BSDFS_ROOT_INODE && + dirp->ino < (fs->isize-1) * BSDFS_INODES_PER_BLOCK) + find_inode_result = dirp->ino; + return STOP; + } + return KEEPON; } /* @@ -500,11 +500,11 @@ static int find_inode (fs_t *fs, fs_dirent_t *dirp) */ static int make_lost_entry (fs_t *fs, fs_dirent_t *dirp) { - if (dirp->ino) - return KEEPON; - dirp->ino = lost_inode; - sprintf (dirp->name, "#%05d", dirp->ino); - return ALTERD | STOP; + if (dirp->ino) + return KEEPON; + dirp->ino = lost_inode; + sprintf (dirp->name, "#%05d", dirp->ino); + return ALTERD | STOP; } /* @@ -512,12 +512,12 @@ static int make_lost_entry (fs_t *fs, fs_dirent_t *dirp) */ static int dotdot_to_lost_found (fs_t *fs, fs_dirent_t *dirp) { - if (dirp->name[0] == '.' && dirp->name[1] == '.' && - dirp->name[2] == 0) { - dirp->ino = lost_found_inode; - return ALTERD | STOP; - } - return KEEPON; + if (dirp->name[0] == '.' && dirp->name[1] == '.' && + dirp->name[2] == 0) { + dirp->ino = lost_found_inode; + return ALTERD | STOP; + } + return KEEPON; } /* @@ -526,15 +526,15 @@ static int dotdot_to_lost_found (fs_t *fs, fs_dirent_t *dirp) */ static unsigned find_lost_found (fs_t *fs) { - fs_inode_t root; + fs_inode_t root; - /* Find lost_found directory inode number. */ - if (! fs_inode_get (fs, &root, BSDFS_ROOT_INODE)) - return 0; - find_inode_name = lost_found_name; - find_inode_result = 0; - scan_inode (&root, DATA, scan_directory, find_inode); - return find_inode_result; + /* Find lost_found directory inode number. */ + if (! fs_inode_get (fs, &root, BSDFS_ROOT_INODE)) + return 0; + find_inode_name = lost_found_name; + find_inode_result = 0; + scan_inode (&root, DATA, scan_directory, find_inode); + return find_inode_result; } /* @@ -542,61 +542,61 @@ static unsigned find_lost_found (fs_t *fs) */ static int move_to_lost_found (fs_inode_t *inode) { - fs_inode_t lost_found; + fs_inode_t lost_found; - printf ("UNREF %s ", ((inode->mode & INODE_MODE_FMT) == - INODE_MODE_FDIR) ? "DIR" : "FILE"); - print_inode (inode); - if (! inode->fs->writable) - return 0; + printf ("UNREF %s ", ((inode->mode & INODE_MODE_FMT) == + INODE_MODE_FDIR) ? "DIR" : "FILE"); + print_inode (inode); + if (! inode->fs->writable) + return 0; - /* Get lost+found inode. */ - if (lost_found_inode == 0) { - /* Find lost_found directory inode number. */ - lost_found_inode = find_lost_found (inode->fs); - if (! lost_found_inode) { - printf ("SORRY. NO lost+found DIRECTORY\n\n"); - return 0; - } - } - if (! fs_inode_get (inode->fs, &lost_found, lost_found_inode) || - ((lost_found.mode & INODE_MODE_FMT) != INODE_MODE_FDIR) || - inode_state (lost_found_inode) != FSTATE) { - printf ("SORRY. NO lost+found DIRECTORY\n\n"); - return 0; - } - if (lost_found.size % BSDFS_BSIZE) { - lost_found.size = (lost_found.size + BSDFS_BSIZE - 1) / - BSDFS_BSIZE * BSDFS_BSIZE; - if (! fs_inode_save (&lost_found, 1)) { - printf ("SORRY. ERROR WRITING lost+found I-NODE\n\n"); - return 0; - } - } + /* Get lost+found inode. */ + if (lost_found_inode == 0) { + /* Find lost_found directory inode number. */ + lost_found_inode = find_lost_found (inode->fs); + if (! lost_found_inode) { + printf ("SORRY. NO lost+found DIRECTORY\n\n"); + return 0; + } + } + if (! fs_inode_get (inode->fs, &lost_found, lost_found_inode) || + ((lost_found.mode & INODE_MODE_FMT) != INODE_MODE_FDIR) || + inode_state (lost_found_inode) != FSTATE) { + printf ("SORRY. NO lost+found DIRECTORY\n\n"); + return 0; + } + if (lost_found.size % BSDFS_BSIZE) { + lost_found.size = (lost_found.size + BSDFS_BSIZE - 1) / + BSDFS_BSIZE * BSDFS_BSIZE; + if (! fs_inode_save (&lost_found, 1)) { + printf ("SORRY. ERROR WRITING lost+found I-NODE\n\n"); + return 0; + } + } - /* Put a file to lost+found. */ - lost_inode = inode->number; - if ((scan_inode (&lost_found, DATA, scan_directory, make_lost_entry) & - ALTERD) == 0) { - printf ("SORRY. NO SPACE IN lost+found DIRECTORY\n\n"); - return 0; - } - --link_count [inode->number]; + /* Put a file to lost+found. */ + lost_inode = inode->number; + if ((scan_inode (&lost_found, DATA, scan_directory, make_lost_entry) & + ALTERD) == 0) { + printf ("SORRY. NO SPACE IN lost+found DIRECTORY\n\n"); + return 0; + } + --link_count [inode->number]; - if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { - /* For ".." set inode number to lost_found_inode. */ - scan_inode (inode, DATA, scan_directory, dotdot_to_lost_found); - if (fs_inode_get (inode->fs, &lost_found, lost_found_inode)) { - lost_found.nlink++; - ++link_count [lost_found.number]; - if (! fs_inode_save (&lost_found, 1)) { - printf ("SORRY. ERROR WRITING lost+found I-NODE\n\n"); - return 0; - } - } - printf ("DIR I=%u CONNECTED.\n\n", inode->number); - } - return 1; + if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { + /* For ".." set inode number to lost_found_inode. */ + scan_inode (inode, DATA, scan_directory, dotdot_to_lost_found); + if (fs_inode_get (inode->fs, &lost_found, lost_found_inode)) { + lost_found.nlink++; + ++link_count [lost_found.number]; + if (! fs_inode_save (&lost_found, 1)) { + printf ("SORRY. ERROR WRITING lost+found I-NODE\n\n"); + return 0; + } + } + printf ("DIR I=%u CONNECTED.\n\n", inode->number); + } + return 1; } /* @@ -604,23 +604,23 @@ static int move_to_lost_found (fs_inode_t *inode) */ static int pass4 (fs_inode_t *inode, unsigned blk, void *arg) { - unsigned *dlp; - unsigned *blocks = arg; + unsigned *dlp; + unsigned *blocks = arg; - if (outrange (inode->fs, blk)) - return SKIP; - if (block_is_busy (blk)) { - /* Free block. */ - for (dlp = dup_list; dlp < dup_end; dlp++) - if (*dlp == blk) { - *dlp = *--dup_end; - return KEEPON; - } - mark_block_free (blk); - if (blocks) - --*blocks; - } - return KEEPON; + if (outrange (inode->fs, blk)) + return SKIP; + if (block_is_busy (blk)) { + /* Free block. */ + for (dlp = dup_list; dlp < dup_end; dlp++) + if (*dlp == blk) { + *dlp = *--dup_end; + return KEEPON; + } + mark_block_free (blk); + if (blocks) + --*blocks; + } + return KEEPON; } /* @@ -628,21 +628,21 @@ static int pass4 (fs_inode_t *inode, unsigned blk, void *arg) */ static void clear_inode (fs_t *fs, unsigned inum, char *msg) { - fs_inode_t inode; + fs_inode_t inode; - if (! fs_inode_get (fs, &inode, inum)) - return; - if (msg) { - printf ("%s %s", msg, ((inode.mode & INODE_MODE_FMT) == - INODE_MODE_FDIR) ? "DIR" : "FILE"); - print_inode (&inode); - } - if (fs->writable) { - total_files--; - scan_inode (&inode, ADDR, pass4, 0); - fs_inode_clear (&inode); - fs_inode_save (&inode, 1); - } + if (! fs_inode_get (fs, &inode, inum)) + return; + if (msg) { + printf ("%s %s", msg, ((inode.mode & INODE_MODE_FMT) == + INODE_MODE_FDIR) ? "DIR" : "FILE"); + print_inode (&inode); + } + if (fs->writable) { + total_files--; + scan_inode (&inode, ADDR, pass4, 0); + fs_inode_clear (&inode); + fs_inode_save (&inode, 1); + } } /* @@ -651,26 +651,26 @@ static void clear_inode (fs_t *fs, unsigned inum, char *msg) */ static void adjust_link_count (fs_t *fs, unsigned inum, unsigned lcnt) { - fs_inode_t inode; + fs_inode_t inode; - if (! fs_inode_get (fs, &inode, inum)) - return; - if (inode.nlink == lcnt) { - /* No links to file - move to lost+found. */ - if (! move_to_lost_found (&inode)) - clear_inode (fs, inum, 0); - } else { - printf ("LINK COUNT %s", (lost_found_inode==inum) ? lost_found_name : - (((inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) ? - "DIR" : "FILE")); - print_inode (&inode); - printf ("COUNT %d SHOULD BE %d\n", - inode.nlink, inode.nlink - lcnt); - if (fs->writable) { - inode.nlink -= lcnt; - fs_inode_save (&inode, 1); - } - } + if (! fs_inode_get (fs, &inode, inum)) + return; + if (inode.nlink == lcnt) { + /* No links to file - move to lost+found. */ + if (! move_to_lost_found (&inode)) + clear_inode (fs, inum, 0); + } else { + printf ("LINK COUNT %s", (lost_found_inode==inum) ? lost_found_name : + (((inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) ? + "DIR" : "FILE")); + print_inode (&inode); + printf ("COUNT %d SHOULD BE %d\n", + inode.nlink, inode.nlink - lcnt); + if (fs->writable) { + inode.nlink -= lcnt; + fs_inode_save (&inode, 1); + } + } } /* @@ -679,25 +679,25 @@ static void adjust_link_count (fs_t *fs, unsigned inum, unsigned lcnt) */ static int pass5 (fs_t *fs, unsigned blk, unsigned *free_blocks) { - if (outrange (fs, blk)) { - free_list_corrupted = 1; - if (++bad_blocks >= MAXBAD) { - printf ("EXCESSIVE BAD BLKS IN FREE LIST.\n"); - return STOP; - } - return SKIP; - } - if (in_free_list (blk)) { - free_list_corrupted = 1; - if (++dup_blocks >= DUP_LIST_SIZE) { - printf ("EXCESSIVE DUP BLKS IN FREE LIST.\n"); - return STOP; - } - } else { - ++*free_blocks; - mark_free_list (blk); - } - return KEEPON; + if (outrange (fs, blk)) { + free_list_corrupted = 1; + if (++bad_blocks >= MAXBAD) { + printf ("EXCESSIVE BAD BLKS IN FREE LIST.\n"); + return STOP; + } + return SKIP; + } + if (in_free_list (blk)) { + free_list_corrupted = 1; + if (++dup_blocks >= DUP_LIST_SIZE) { + printf ("EXCESSIVE DUP BLKS IN FREE LIST.\n"); + return STOP; + } + } else { + ++*free_blocks; + mark_free_list (blk); + } + return KEEPON; } /* @@ -706,40 +706,40 @@ static int pass5 (fs_t *fs, unsigned blk, unsigned *free_blocks) */ static unsigned check_free_list (fs_t *fs) { - unsigned *ap, *base; - unsigned free_blocks, nfree; - unsigned data [BSDFS_BSIZE / 4]; - unsigned list [NICFREE]; - int i; + unsigned *ap, *base; + unsigned free_blocks, nfree; + unsigned data [BSDFS_BSIZE / 4]; + unsigned list [NICFREE]; + int i; - if (fs->nfree == 0) - return 0; - free_blocks = 0; - nfree = fs->nfree; - base = fs->free; - for (;;) { - if (nfree <= 0 || nfree > NICFREE) { - printf ("BAD FREEBLK COUNT\n"); - free_list_corrupted = 1; - break; - } - ap = base + nfree; - while (--ap > base) { - if (pass5 (fs, *ap, &free_blocks) == STOP) - return free_blocks; - } - if (*ap == 0 || pass5 (fs, *ap, &free_blocks) != KEEPON) - break; - if (! fs_read_block (fs, *ap, (unsigned char*) data)) { - print_io_error ("READ", *ap); - break; - } - nfree = data[0]; - for (i=0; infree == 0) + return 0; + free_blocks = 0; + nfree = fs->nfree; + base = fs->free; + for (;;) { + if (nfree <= 0 || nfree > NICFREE) { + printf ("BAD FREEBLK COUNT\n"); + free_list_corrupted = 1; + break; + } + ap = base + nfree; + while (--ap > base) { + if (pass5 (fs, *ap, &free_blocks) == STOP) + return free_blocks; + } + if (*ap == 0 || pass5 (fs, *ap, &free_blocks) != KEEPON) + break; + if (! fs_read_block (fs, *ap, (unsigned char*) data)) { + print_io_error ("READ", *ap); + break; + } + nfree = data[0]; + for (i=0; ininode; i++) { - inum = fs->inode[i]; - if (inode_state (inum) != USTATE) { - printf ("ALLOCATED INODE(S) IN IFREE LIST\n"); - if (fs->writable) { - fs->ninode = i - 1; - while (i < NICINOD) - fs->inode [i++] = 0; - fs->dirty = 1; - } - return; - } - } + for (i=0; ininode; i++) { + inum = fs->inode[i]; + if (inode_state (inum) != USTATE) { + printf ("ALLOCATED INODE(S) IN IFREE LIST\n"); + if (fs->writable) { + fs->ninode = i - 1; + while (i < NICINOD) + fs->inode [i++] = 0; + fs->dirty = 1; + } + return; + } + } } /* @@ -770,26 +770,26 @@ static void check_free_inode_list (fs_t *fs) */ static unsigned make_free_list (fs_t *fs) { - unsigned free_blocks, n; + unsigned free_blocks, n; - fs->nfree = 0; - fs->flock = 0; - fs->fmod = 0; - fs->ilock = 0; - fs->ronly = 0; - fs->dirty = 1; - free_blocks = 0; + fs->nfree = 0; + fs->flock = 0; + fs->fmod = 0; + fs->ilock = 0; + fs->ronly = 0; + fs->dirty = 1; + free_blocks = 0; - /* Build a list of free blocks */ - fs_block_free (fs, 0); - for (n = fs->fsize - 1; n >= fs->isize; n--) { - if (block_is_busy (n)) - continue; - ++free_blocks; - if (! fs_block_free (fs, n)) - return 0; - } - return free_blocks; + /* Build a list of free blocks */ + fs_block_free (fs, 0); + for (n = fs->fsize - 1; n >= fs->isize; n--) { + if (block_is_busy (n)) + continue; + ++free_blocks; + if (! fs_block_free (fs, n)) + return 0; + } + return free_blocks; } /* @@ -799,220 +799,220 @@ static unsigned make_free_list (fs_t *fs) */ int fs_check (fs_t *fs) { - fs_inode_t inode; - int n; - unsigned inum; - unsigned block_map_size; /* number of free blocks */ - unsigned free_blocks; /* number of free blocks */ - unsigned used_blocks; /* number of blocks used */ - unsigned last_allocated_inode; /* hiwater mark of inodes */ + fs_inode_t inode; + int n; + unsigned inum; + unsigned block_map_size; /* number of free blocks */ + unsigned free_blocks; /* number of free blocks */ + unsigned used_blocks; /* number of blocks used */ + unsigned last_allocated_inode; /* hiwater mark of inodes */ - if (fs->isize >= fs->fsize) { - printf ("Bad filesystem size: total %d blocks with %d inode blocks\n", - fs->fsize, fs->isize); - return 0; - } - free_list_corrupted = 0; - total_files = 0; - used_blocks = 0; - dup_multi = dup_end = &dup_list[0]; - bad_link_end = &bad_link_list[0]; - lost_found_inode = 0; - buf_dirty = 0; - buf_bno = (unsigned) -1; + if (fs->isize >= fs->fsize) { + printf ("Bad filesystem size: total %d blocks with %d inode blocks\n", + fs->fsize, fs->isize); + return 0; + } + free_list_corrupted = 0; + total_files = 0; + used_blocks = 0; + dup_multi = dup_end = &dup_list[0]; + bad_link_end = &bad_link_list[0]; + lost_found_inode = 0; + buf_dirty = 0; + buf_bno = (unsigned) -1; - /* Allocate memory. */ - block_map_size = (fs->fsize + 7) / 8; - block_map = calloc (block_map_size, sizeof (*block_map)); - state_map = calloc (((fs->isize-1) * BSDFS_INODES_PER_BLOCK + - STATES_PER_BYTE) / STATES_PER_BYTE, sizeof (*state_map)); - link_count = calloc ((fs->isize-1) * BSDFS_INODES_PER_BLOCK + 1, - sizeof (*link_count)); - if (! block_map || ! state_map || ! link_count) { - printf ("Cannot allocate memory\n"); -fatal: if (block_map) - free (block_map); - if (state_map) - free (state_map); - if (link_count) - free (link_count); - return 0; - } + /* Allocate memory. */ + block_map_size = (fs->fsize + 7) / 8; + block_map = calloc (block_map_size, sizeof (*block_map)); + state_map = calloc (((fs->isize-1) * BSDFS_INODES_PER_BLOCK + + STATES_PER_BYTE) / STATES_PER_BYTE, sizeof (*state_map)); + link_count = calloc ((fs->isize-1) * BSDFS_INODES_PER_BLOCK + 1, + sizeof (*link_count)); + if (! block_map || ! state_map || ! link_count) { + printf ("Cannot allocate memory\n"); +fatal: if (block_map) + free (block_map); + if (state_map) + free (state_map); + if (link_count) + free (link_count); + return 0; + } - printf ("** Phase 1 - Check Blocks and Sizes\n"); - last_allocated_inode = 0; - for (inum = 1; inum <= (fs->isize-1) * BSDFS_INODES_PER_BLOCK; inum++) { - if (! fs_inode_get (fs, &inode, inum)) - continue; - if (inode.mode & INODE_MODE_FMT) { + printf ("** Phase 1 - Check Blocks and Sizes\n"); + last_allocated_inode = 0; + for (inum = 1; inum <= (fs->isize-1) * BSDFS_INODES_PER_BLOCK; inum++) { + if (! fs_inode_get (fs, &inode, inum)) + continue; + if (inode.mode & INODE_MODE_FMT) { /*printf ("inode %d: %#o\n", inode.number, inode.mode);*/ - last_allocated_inode = inum; - total_files++; - link_count[inum] = inode.nlink; - if (link_count[inum] <= 0) { - if (bad_link_end < &bad_link_list[LINK_LIST_SIZE]) - *bad_link_end++ = inum; - else { - printf ("LINK COUNT TABLE OVERFLOW\n"); - } - } - set_inode_state (inum, ((inode.mode & INODE_MODE_FMT) == - INODE_MODE_FDIR) ? DSTATE : FSTATE); - bad_blocks = dup_blocks = 0; - scan_inode (&inode, ADDR, pass1, &used_blocks); - n = inode_state (inum); - if (n == DSTATE || n == FSTATE) { - if ((inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR && - (inode.size % 4) != 0) { - printf ("DIRECTORY MISALIGNED I=%u\n\n", - inode.number); - } - } - } - else if (inode.mode != 0) { - printf ("PARTIALLY ALLOCATED INODE I=%u\n", inum); - if (fs->writable) - fs_inode_clear (&inode); - } - fs_inode_save (&inode, 0); - } - if (dup_end != &dup_list[0]) { - printf ("** Phase 1b - Rescan For More DUPS\n"); - for (inum = 1; inum <= last_allocated_inode; inum++) { - if (inode_state (inum) == USTATE) - continue; - if (! fs_inode_get (fs, &inode, inum)) - continue; - if (scan_inode (&inode, ADDR, pass1b, 0) & STOP) - break; - } - } + last_allocated_inode = inum; + total_files++; + link_count[inum] = inode.nlink; + if (link_count[inum] <= 0) { + if (bad_link_end < &bad_link_list[LINK_LIST_SIZE]) + *bad_link_end++ = inum; + else { + printf ("LINK COUNT TABLE OVERFLOW\n"); + } + } + set_inode_state (inum, ((inode.mode & INODE_MODE_FMT) == + INODE_MODE_FDIR) ? DSTATE : FSTATE); + bad_blocks = dup_blocks = 0; + scan_inode (&inode, ADDR, pass1, &used_blocks); + n = inode_state (inum); + if (n == DSTATE || n == FSTATE) { + if ((inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR && + (inode.size % 4) != 0) { + printf ("DIRECTORY MISALIGNED I=%u\n\n", + inode.number); + } + } + } + else if (inode.mode != 0) { + printf ("PARTIALLY ALLOCATED INODE I=%u\n", inum); + if (fs->writable) + fs_inode_clear (&inode); + } + fs_inode_save (&inode, 0); + } + if (dup_end != &dup_list[0]) { + printf ("** Phase 1b - Rescan For More DUPS\n"); + for (inum = 1; inum <= last_allocated_inode; inum++) { + if (inode_state (inum) == USTATE) + continue; + if (! fs_inode_get (fs, &inode, inum)) + continue; + if (scan_inode (&inode, ADDR, pass1b, 0) & STOP) + break; + } + } - printf ("** Phase 2 - Check Pathnames\n"); - thisname = pathp = pathname; - switch (inode_state (BSDFS_ROOT_INODE)) { - case USTATE: - printf ("ROOT INODE UNALLOCATED. TERMINATING.\n"); - goto fatal; - case FSTATE: - printf ("ROOT INODE NOT DIRECTORY\n"); - if (! fs->writable) - goto fatal; - if (! fs_inode_get (fs, &inode, BSDFS_ROOT_INODE)) - goto fatal; - inode.mode &= ~INODE_MODE_FMT; - inode.mode |= INODE_MODE_FDIR; - fs_inode_save (&inode, 1); - set_inode_state (BSDFS_ROOT_INODE, DSTATE); - case DSTATE: - scan_pass2 (fs, BSDFS_ROOT_INODE); - break; - case CLEAR: - printf ("DUPS/BAD IN ROOT INODE\n"); - set_inode_state (BSDFS_ROOT_INODE, DSTATE); - scan_pass2 (fs, BSDFS_ROOT_INODE); - } + printf ("** Phase 2 - Check Pathnames\n"); + thisname = pathp = pathname; + switch (inode_state (BSDFS_ROOT_INODE)) { + case USTATE: + printf ("ROOT INODE UNALLOCATED. TERMINATING.\n"); + goto fatal; + case FSTATE: + printf ("ROOT INODE NOT DIRECTORY\n"); + if (! fs->writable) + goto fatal; + if (! fs_inode_get (fs, &inode, BSDFS_ROOT_INODE)) + goto fatal; + inode.mode &= ~INODE_MODE_FMT; + inode.mode |= INODE_MODE_FDIR; + fs_inode_save (&inode, 1); + set_inode_state (BSDFS_ROOT_INODE, DSTATE); + case DSTATE: + scan_pass2 (fs, BSDFS_ROOT_INODE); + break; + case CLEAR: + printf ("DUPS/BAD IN ROOT INODE\n"); + set_inode_state (BSDFS_ROOT_INODE, DSTATE); + scan_pass2 (fs, BSDFS_ROOT_INODE); + } - printf ("** Phase 3 - Check Connectivity\n"); - for (inum = BSDFS_ROOT_INODE; inum <= last_allocated_inode; inum++) { - if (inode_state (inum) == DSTATE) { - unsigned ino; + printf ("** Phase 3 - Check Connectivity\n"); + for (inum = BSDFS_ROOT_INODE; inum <= last_allocated_inode; inum++) { + if (inode_state (inum) == DSTATE) { + unsigned ino; - find_inode_name = ".."; - ino = inum; - do { - if (! fs_inode_get (fs, &inode, ino)) - break; - find_inode_result = 0; - scan_inode (&inode, DATA, scan_directory, find_inode); - if (find_inode_result == 0) { - /* Parent link lost. */ - if (move_to_lost_found (&inode)) { - thisname = pathp = pathname; - *pathp++ = '?'; - scan_pass2 (fs, ino); - } - break; - } - ino = find_inode_result; - } while (inode_state (ino) == DSTATE); - } - } + find_inode_name = ".."; + ino = inum; + do { + if (! fs_inode_get (fs, &inode, ino)) + break; + find_inode_result = 0; + scan_inode (&inode, DATA, scan_directory, find_inode); + if (find_inode_result == 0) { + /* Parent link lost. */ + if (move_to_lost_found (&inode)) { + thisname = pathp = pathname; + *pathp++ = '?'; + scan_pass2 (fs, ino); + } + break; + } + ino = find_inode_result; + } while (inode_state (ino) == DSTATE); + } + } - printf ("** Phase 4 - Check Reference Counts\n"); - for (inum = BSDFS_ROOT_INODE; inum <= last_allocated_inode; inum++) { - switch (inode_state (inum)) { - case FSTATE: - n = link_count [inum]; - if (n) - adjust_link_count (fs, inum, n); - else { - unsigned *blp; + printf ("** Phase 4 - Check Reference Counts\n"); + for (inum = BSDFS_ROOT_INODE; inum <= last_allocated_inode; inum++) { + switch (inode_state (inum)) { + case FSTATE: + n = link_count [inum]; + if (n) + adjust_link_count (fs, inum, n); + else { + unsigned *blp; - for (blp = bad_link_list; blp < bad_link_end; blp++) - if (*blp == inum) { - clear_inode (fs, inum, "UNREF"); - break; - } - } - break; - case DSTATE: - clear_inode (fs, inum, "UNREF"); - break; - case CLEAR: - clear_inode (fs, inum, "BAD/DUP"); - } - } - buf_flush (fs); + for (blp = bad_link_list; blp < bad_link_end; blp++) + if (*blp == inum) { + clear_inode (fs, inum, "UNREF"); + break; + } + } + break; + case DSTATE: + clear_inode (fs, inum, "UNREF"); + break; + case CLEAR: + clear_inode (fs, inum, "BAD/DUP"); + } + } + buf_flush (fs); - printf ("** Phase 5 - Check Free List\n"); - free (link_count); - check_free_inode_list (fs); - free (state_map); - bad_blocks = dup_blocks = 0; - free_map = calloc (block_map_size, sizeof (*free_map)); - if (! free_map) { - printf ("NO MEMORY TO CHECK FREE LIST\n"); - free_list_corrupted = 1; - free_blocks = 0; - } else { - memcpy (free_map, block_map, block_map_size); - free_blocks = check_free_list (fs); - free (free_map); - } - if (bad_blocks) - printf ("%d BAD BLKS IN FREE LIST\n", bad_blocks); - if (dup_blocks) - printf ("%d DUP BLKS IN FREE LIST\n", dup_blocks); - if (free_list_corrupted == 0) { - if (used_blocks + free_blocks != fs->fsize - fs->isize) { - printf ("%d BLK(S) MISSING\n", fs->fsize - - fs->isize - used_blocks - free_blocks); - free_list_corrupted = 1; - } - } - if (free_list_corrupted) { - printf ("BAD FREE LIST\n"); - if (! fs->writable) - free_list_corrupted = 0; - } + printf ("** Phase 5 - Check Free List\n"); + free (link_count); + check_free_inode_list (fs); + free (state_map); + bad_blocks = dup_blocks = 0; + free_map = calloc (block_map_size, sizeof (*free_map)); + if (! free_map) { + printf ("NO MEMORY TO CHECK FREE LIST\n"); + free_list_corrupted = 1; + free_blocks = 0; + } else { + memcpy (free_map, block_map, block_map_size); + free_blocks = check_free_list (fs); + free (free_map); + } + if (bad_blocks) + printf ("%d BAD BLKS IN FREE LIST\n", bad_blocks); + if (dup_blocks) + printf ("%d DUP BLKS IN FREE LIST\n", dup_blocks); + if (free_list_corrupted == 0) { + if (used_blocks + free_blocks != fs->fsize - fs->isize) { + printf ("%d BLK(S) MISSING\n", fs->fsize - + fs->isize - used_blocks - free_blocks); + free_list_corrupted = 1; + } + } + if (free_list_corrupted) { + printf ("BAD FREE LIST\n"); + if (! fs->writable) + free_list_corrupted = 0; + } - if (free_list_corrupted) { - printf ("** Phase 6 - Salvage Free List\n"); - free_blocks = make_free_list (fs); - } + if (free_list_corrupted) { + printf ("** Phase 6 - Salvage Free List\n"); + free_blocks = make_free_list (fs); + } - printf ("%d files %d blocks %d free\n", - total_files, used_blocks, free_blocks); - if (fs->modified) { - time (&fs->utime); - fs->dirty = 1; - } - buf_flush (fs); - fs_sync (fs, 0); - if (fs->modified) - printf ("\n***** FILE SYSTEM WAS MODIFIED *****\n"); + printf ("%d files %d blocks %d free\n", + total_files, used_blocks, free_blocks); + if (fs->modified) { + time (&fs->utime); + fs->dirty = 1; + } + buf_flush (fs); + fs_sync (fs, 0); + if (fs->modified) + printf ("\n***** FILE SYSTEM WAS MODIFIED *****\n"); - free (block_map); - return 1; + free (block_map); + return 1; } diff --git a/tools/fsutil/create.c b/tools/fsutil/create.c index 28e8b43..66ef485 100644 --- a/tools/fsutil/create.c +++ b/tools/fsutil/create.c @@ -33,368 +33,370 @@ extern int verbose; int inode_build_list (fs_t *fs) { - fs_inode_t inode; - unsigned int inum, total_inodes; + fs_inode_t inode; + unsigned int inum, total_inodes; - total_inodes = (fs->isize - 1) * BSDFS_INODES_PER_BLOCK; - for (inum = 1; inum <= total_inodes; inum++) { - if (! fs_inode_get (fs, &inode, inum)) - return 0; - if (inode.mode == 0) { - fs->inode [fs->ninode++] = inum; - if (fs->ninode >= NICINOD) - break; - } - } - return 1; + total_inodes = (fs->isize - 1) * BSDFS_INODES_PER_BLOCK; + for (inum = 1; inum <= total_inodes; inum++) { + if (! fs_inode_get (fs, &inode, inum)) + return 0; + if (inode.mode == 0) { + fs->inode [fs->ninode++] = inum; + if (fs->ninode >= NICINOD) + break; + } + } + return 1; } static int create_inode1 (fs_t *fs) { - fs_inode_t inode; + fs_inode_t inode; - memset (&inode, 0, sizeof(inode)); - inode.mode = INODE_MODE_FREG; - inode.fs = fs; - inode.number = 1; - if (! fs_inode_save (&inode, 1)) - return 0; - fs->tinode--; - return 1; + memset (&inode, 0, sizeof(inode)); + inode.mode = INODE_MODE_FREG; + inode.fs = fs; + inode.number = 1; + if (! fs_inode_save (&inode, 1)) + return 0; + fs->tinode--; + return 1; } static int create_root_directory (fs_t *fs) { - fs_inode_t inode; - unsigned char buf [BSDFS_BSIZE]; - unsigned int bno; + fs_inode_t inode; + unsigned char buf [BSDFS_BSIZE]; + unsigned int bno; - memset (&inode, 0, sizeof(inode)); - inode.mode = INODE_MODE_FDIR | 0777; - inode.fs = fs; - inode.number = BSDFS_ROOT_INODE; - inode.size = BSDFS_BSIZE; - inode.flags = 0; + memset (&inode, 0, sizeof(inode)); + inode.mode = INODE_MODE_FDIR | 0777; + inode.fs = fs; + inode.number = BSDFS_ROOT_INODE; + inode.size = BSDFS_BSIZE; + inode.flags = 0; - time (&inode.ctime); - time (&inode.atime); - time (&inode.mtime); + time (&inode.ctime); + time (&inode.atime); + time (&inode.mtime); - /* directory - put in extra links */ - memset (buf, 0, sizeof(buf)); - buf[0] = inode.number; - buf[1] = inode.number >> 8; - buf[2] = inode.number >> 16; - buf[3] = inode.number >> 24; - buf[4] = 12; - buf[5] = 12 >> 8; - buf[6] = 1; - buf[7] = 1 >> 8; - buf[8] = '.'; - buf[9] = 0; - buf[10] = 0; - buf[11] = 0; + /* directory - put in extra links */ + memset (buf, 0, sizeof(buf)); + buf[0] = inode.number; + buf[1] = inode.number >> 8; + buf[2] = inode.number >> 16; + buf[3] = inode.number >> 24; + buf[4] = 12; + buf[5] = 12 >> 8; + buf[6] = 1; + buf[7] = 1 >> 8; + buf[8] = '.'; + buf[9] = 0; + buf[10] = 0; + buf[11] = 0; - buf[12+0] = BSDFS_ROOT_INODE; - buf[12+1] = BSDFS_ROOT_INODE >> 8; - buf[12+2] = BSDFS_ROOT_INODE >> 16; - buf[12+3] = BSDFS_ROOT_INODE >> 24; - buf[12+4] = 12; - buf[12+5] = 12 >> 8; - buf[12+6] = 2; - buf[12+7] = 2 >> 8; - buf[12+8] = '.'; - buf[12+9] = '.'; - buf[12+10] = 0; - buf[12+11] = 0; + buf[12+0] = BSDFS_ROOT_INODE; + buf[12+1] = BSDFS_ROOT_INODE >> 8; + buf[12+2] = BSDFS_ROOT_INODE >> 16; + buf[12+3] = BSDFS_ROOT_INODE >> 24; + buf[12+4] = 12; + buf[12+5] = 12 >> 8; + buf[12+6] = 2; + buf[12+7] = 2 >> 8; + buf[12+8] = '.'; + buf[12+9] = '.'; + buf[12+10] = 0; + buf[12+11] = 0; - buf[24+0] = BSDFS_LOSTFOUND_INODE; - buf[24+1] = BSDFS_LOSTFOUND_INODE >> 8; - buf[24+2] = BSDFS_LOSTFOUND_INODE >> 16; - buf[24+3] = BSDFS_LOSTFOUND_INODE >> 24; - buf[24+4] = (unsigned char) (BSDFS_BSIZE - 12 - 12); - buf[24+5] = (BSDFS_BSIZE - 12 - 12) >> 8; - buf[24+6] = 10; - buf[24+7] = 10 >> 8; - memcpy (&buf[24+8], "lost+found\0\0", 12); + buf[24+0] = BSDFS_LOSTFOUND_INODE; + buf[24+1] = BSDFS_LOSTFOUND_INODE >> 8; + buf[24+2] = BSDFS_LOSTFOUND_INODE >> 16; + buf[24+3] = BSDFS_LOSTFOUND_INODE >> 24; + buf[24+4] = (unsigned char) (BSDFS_BSIZE - 12 - 12); + buf[24+5] = (BSDFS_BSIZE - 12 - 12) >> 8; + buf[24+6] = 10; + buf[24+7] = 10 >> 8; + memcpy (&buf[24+8], "lost+found\0\0", 12); - if (fs->swapsz != 0) { - buf[24+4] = 20; - buf[24+5] = 20 >> 8; - buf[44+0] = BSDFS_SWAP_INODE; - buf[44+1] = BSDFS_SWAP_INODE >> 8; - buf[44+2] = BSDFS_SWAP_INODE >> 16; - buf[44+3] = BSDFS_SWAP_INODE >> 24; - buf[44+4] = (unsigned char) (BSDFS_BSIZE - 12 - 12 - 20); - buf[44+5] = (BSDFS_BSIZE - 12 - 12 - 20) >> 8; - buf[44+6] = 4; - buf[44+7] = 4 >> 8; - memcpy (&buf[44+8], "swap\0\0\0\0", 8); - } - inode.nlink = 3; + if (fs->swapsz != 0) { + buf[24+4] = 20; + buf[24+5] = 20 >> 8; + buf[44+0] = BSDFS_SWAP_INODE; + buf[44+1] = BSDFS_SWAP_INODE >> 8; + buf[44+2] = BSDFS_SWAP_INODE >> 16; + buf[44+3] = BSDFS_SWAP_INODE >> 24; + buf[44+4] = (unsigned char) (BSDFS_BSIZE - 12 - 12 - 20); + buf[44+5] = (BSDFS_BSIZE - 12 - 12 - 20) >> 8; + buf[44+6] = 4; + buf[44+7] = 4 >> 8; + memcpy (&buf[44+8], "swap\0\0\0\0", 8); + } + inode.nlink = 3; - if (! fs_block_alloc (fs, &bno)) - return 0; - if (! fs_write_block (fs, bno, buf)) - return 0; - inode.addr[0] = bno; + if (! fs_block_alloc (fs, &bno)) + return 0; + if (! fs_write_block (fs, bno, buf)) + return 0; + inode.addr[0] = bno; - if (! fs_inode_save (&inode, 1)) - return 0; - fs->tinode--; - return 1; + if (! fs_inode_save (&inode, 1)) + return 0; + fs->tinode--; + return 1; } static int create_lost_found_directory (fs_t *fs) { - fs_inode_t inode; - unsigned char buf [BSDFS_BSIZE]; - unsigned int bno; + fs_inode_t inode; + unsigned char buf [BSDFS_BSIZE]; + unsigned int bno; - memset (&inode, 0, sizeof(inode)); - inode.mode = INODE_MODE_FDIR | 0777; - inode.fs = fs; - inode.number = BSDFS_LOSTFOUND_INODE; - inode.size = BSDFS_BSIZE; - inode.flags = 0; + memset (&inode, 0, sizeof(inode)); + inode.mode = INODE_MODE_FDIR | 0777; + inode.fs = fs; + inode.number = BSDFS_LOSTFOUND_INODE; + inode.size = BSDFS_BSIZE; + inode.flags = 0; - time (&inode.ctime); - time (&inode.atime); - time (&inode.mtime); + time (&inode.ctime); + time (&inode.atime); + time (&inode.mtime); - /* directory - put in extra links */ - memset (buf, 0, sizeof(buf)); - buf[0] = inode.number; - buf[1] = inode.number >> 8; - buf[2] = inode.number >> 16; - buf[3] = inode.number >> 24; - buf[4] = 12; - buf[5] = 12 >> 8; - buf[6] = 1; - buf[7] = 1 >> 8; - buf[8] = '.'; - buf[9] = 0; - buf[10] = 0; - buf[11] = 0; + /* directory - put in extra links */ + memset (buf, 0, sizeof(buf)); + buf[0] = inode.number; + buf[1] = inode.number >> 8; + buf[2] = inode.number >> 16; + buf[3] = inode.number >> 24; + buf[4] = 12; + buf[5] = 12 >> 8; + buf[6] = 1; + buf[7] = 1 >> 8; + buf[8] = '.'; + buf[9] = 0; + buf[10] = 0; + buf[11] = 0; - buf[12+0] = BSDFS_ROOT_INODE; - buf[12+1] = BSDFS_ROOT_INODE >> 8; - buf[12+2] = BSDFS_ROOT_INODE >> 16; - buf[12+3] = BSDFS_ROOT_INODE >> 24; - buf[12+4] = (unsigned char) (BSDFS_BSIZE - 12); - buf[12+5] = (BSDFS_BSIZE - 12) >> 8; - buf[12+6] = 2; - buf[12+7] = 2 >> 8; - buf[12+8] = '.'; - buf[12+9] = '.'; - buf[12+10] = 0; - buf[12+11] = 0; + buf[12+0] = BSDFS_ROOT_INODE; + buf[12+1] = BSDFS_ROOT_INODE >> 8; + buf[12+2] = BSDFS_ROOT_INODE >> 16; + buf[12+3] = BSDFS_ROOT_INODE >> 24; + buf[12+4] = (unsigned char) (BSDFS_BSIZE - 12); + buf[12+5] = (BSDFS_BSIZE - 12) >> 8; + buf[12+6] = 2; + buf[12+7] = 2 >> 8; + buf[12+8] = '.'; + buf[12+9] = '.'; + buf[12+10] = 0; + buf[12+11] = 0; - inode.nlink = 2; + inode.nlink = 2; - if (! fs_block_alloc (fs, &bno)) - return 0; - if (! fs_write_block (fs, bno, buf)) - return 0; - inode.addr[0] = bno; + if (! fs_block_alloc (fs, &bno)) + return 0; + if (! fs_write_block (fs, bno, buf)) + return 0; + inode.addr[0] = bno; - if (! fs_inode_save (&inode, 1)) - return 0; - fs->tinode--; - return 1; + if (! fs_inode_save (&inode, 1)) + return 0; + fs->tinode--; + return 1; } static void map_block_swap (fs_inode_t *inode, unsigned lbn) { - unsigned block [BSDFS_BSIZE / 4]; - unsigned int bn, indir, newb, shift, i, j; + unsigned block [BSDFS_BSIZE / 4]; + unsigned int bn, indir, newb, shift, i, j; - /* - * Blocks 0..NADDR-3 are direct blocks. - */ - if (lbn < NADDR-3) { - /* small file algorithm */ - inode->addr[lbn] = inode->fs->isize + lbn; - return; - } + /* + * Blocks 0..NADDR-3 are direct blocks. + */ + if (lbn < NADDR-3) { + /* small file algorithm */ + inode->addr[lbn] = inode->fs->isize + lbn; + return; + } - /* - * Addresses NADDR-3, NADDR-2, and NADDR-1 - * have single, double, triple indirect blocks. - * The first step is to determine - * how many levels of indirection. - */ - shift = 0; - i = 1; - bn = lbn - (NADDR-3); - for (j=3; ; j--) { - if (j == 0) { - fprintf (stderr, "swap: too large size\n"); - exit (-1); - } - shift += NSHIFT; - i <<= NSHIFT; - if (bn < i) - break; - bn -= i; - } + /* + * Addresses NADDR-3, NADDR-2, and NADDR-1 + * have single, double, triple indirect blocks. + * The first step is to determine + * how many levels of indirection. + */ + shift = 0; + i = 1; + bn = lbn - (NADDR-3); + for (j=3; ; j--) { + if (j == 0) { + fprintf (stderr, "swap: too large size\n"); + exit (-1); + } + shift += NSHIFT; + i <<= NSHIFT; + if (bn < i) + break; + bn -= i; + } - /* - * Fetch the first indirect block. - */ - indir = inode->addr [NADDR-j]; - if (indir == 0) { - if (! fs_block_alloc (inode->fs, &indir)) { -alloc_error: fprintf (stderr, "swap: cannot allocate indirect block\n"); - exit (-1); - } - if (verbose) - printf ("swap: allocate indirect block %d (j=%d)\n", indir, j); - memset (block, 0, BSDFS_BSIZE); - if (! fs_write_block (inode->fs, indir, (unsigned char*) block)) { -write_error: fprintf (stderr, "swap: cannot write indirect block %d\n", indir); - exit (-1); - } - inode->addr [NADDR-j] = indir; - } + /* + * Fetch the first indirect block. + */ + indir = inode->addr [NADDR-j]; + if (indir == 0) { + if (! fs_block_alloc (inode->fs, &indir)) { +alloc_error: + fprintf (stderr, "swap: cannot allocate indirect block\n"); + exit (-1); + } + if (verbose) + printf ("swap: allocate indirect block %d (j=%d)\n", indir, j); + memset (block, 0, BSDFS_BSIZE); + if (! fs_write_block (inode->fs, indir, (unsigned char*) block)) { +write_error: + fprintf (stderr, "swap: cannot write indirect block %d\n", indir); + exit (-1); + } + inode->addr [NADDR-j] = indir; + } - /* - * Fetch through the indirect blocks - */ - for (; ; j++) { - if (! fs_read_block (inode->fs, indir, (unsigned char*) block)) { - fprintf (stderr, "swap: cannot read indirect block %d\n", indir); - exit (-1); - } - shift -= NSHIFT; - i = (bn >> shift) & NMASK; - if (j == 3) { - block[i] = inode->fs->isize + lbn; - if (! fs_write_block (inode->fs, indir, (unsigned char*) block)) - goto write_error; - return; - } - if (block[i] != 0) { - indir = block [i]; - continue; - } - /* Allocate new indirect block. */ - if (! fs_block_alloc (inode->fs, &newb)) - goto alloc_error; - if (verbose) - printf ("swap: allocate new block %d (j=%d)\n", newb, j); - block[i] = newb; - if (! fs_write_block (inode->fs, indir, (unsigned char*) block)) - goto write_error; - memset (block, 0, BSDFS_BSIZE); - if (! fs_write_block (inode->fs, newb, (unsigned char*) block)) { - fprintf (stderr, "swap: cannot write block %d\n", newb); - exit (-1); - } - indir = newb; - } + /* + * Fetch through the indirect blocks + */ + for (; ; j++) { + if (! fs_read_block (inode->fs, indir, (unsigned char*) block)) { + fprintf (stderr, "swap: cannot read indirect block %d\n", indir); + exit (-1); + } + shift -= NSHIFT; + i = (bn >> shift) & NMASK; + if (j == 3) { + block[i] = inode->fs->isize + lbn; + if (! fs_write_block (inode->fs, indir, (unsigned char*) block)) + goto write_error; + return; + } + if (block[i] != 0) { + indir = block [i]; + continue; + } + /* Allocate new indirect block. */ + if (! fs_block_alloc (inode->fs, &newb)) + goto alloc_error; + if (verbose) + printf ("swap: allocate new block %d (j=%d)\n", newb, j); + block[i] = newb; + if (! fs_write_block (inode->fs, indir, (unsigned char*) block)) + goto write_error; + memset (block, 0, BSDFS_BSIZE); + if (! fs_write_block (inode->fs, newb, (unsigned char*) block)) { + fprintf (stderr, "swap: cannot write block %d\n", newb); + exit (-1); + } + indir = newb; + } } static int create_swap_file (fs_t *fs) { - fs_inode_t inode; - unsigned lbn; + fs_inode_t inode; + unsigned lbn; - memset (&inode, 0, sizeof(inode)); - inode.mode = INODE_MODE_FREG | 0400; - inode.fs = fs; - inode.number = BSDFS_SWAP_INODE; - inode.size = fs->swapsz * BSDFS_BSIZE; - inode.flags = /*SYS_IMMUTABLE |*/ USER_IMMUTABLE | USER_NODUMP; - inode.nlink = 1; - inode.dirty = 1; + memset (&inode, 0, sizeof(inode)); + inode.mode = INODE_MODE_FREG | 0400; + inode.fs = fs; + inode.number = BSDFS_SWAP_INODE; + inode.size = fs->swapsz * BSDFS_BSIZE; + inode.flags = /*SYS_IMMUTABLE |*/ USER_IMMUTABLE | USER_NODUMP; + inode.nlink = 1; + inode.dirty = 1; - time (&inode.ctime); - time (&inode.atime); - time (&inode.mtime); + time (&inode.ctime); + time (&inode.atime); + time (&inode.mtime); - for (lbn=0; lbnswapsz; lbn++) - map_block_swap (&inode, lbn); + for (lbn=0; lbnswapsz; lbn++) + map_block_swap (&inode, lbn); - if (! fs_inode_save (&inode, 0)) { - fprintf (stderr, "swap: cannot save file inode\n"); - return 0; - } - return 1; + if (! fs_inode_save (&inode, 0)) { + fprintf (stderr, "swap: cannot save file inode\n"); + return 0; + } + return 1; } int fs_create (fs_t *fs, const char *filename, unsigned kbytes, - unsigned swap_kbytes) + unsigned swap_kbytes) { - int n; - unsigned char buf [BSDFS_BSIZE]; - off_t bytes, offset; + int n; + unsigned char buf [BSDFS_BSIZE]; + off_t bytes, offset; - memset (fs, 0, sizeof (*fs)); - fs->filename = filename; - fs->seek = 0; + memset (fs, 0, sizeof (*fs)); + fs->filename = filename; + fs->seek = 0; - fs->fd = open (fs->filename, O_CREAT | O_RDWR, 0666); - if (fs->fd < 0) - return 0; - fs->writable = 1; + fs->fd = open (fs->filename, O_CREAT | O_RDWR, 0666); + if (fs->fd < 0) + return 0; + fs->writable = 1; - /* get total disk size - * and inode block size */ - bytes = (off_t) kbytes * 1024ULL; - fs->fsize = bytes / BSDFS_BSIZE; - fs->isize = 1 + (fs->fsize / 16 + BSDFS_INODES_PER_BLOCK - 1) / - BSDFS_INODES_PER_BLOCK; - if (fs->isize < 2) - return 0; + /* get total disk size + * and inode block size */ + bytes = (off_t) kbytes * 1024ULL; + fs->fsize = bytes / BSDFS_BSIZE; + fs->isize = 1 + (fs->fsize / 16 + BSDFS_INODES_PER_BLOCK - 1) / + BSDFS_INODES_PER_BLOCK; + if (fs->isize < 2) + return 0; - /* make sure the file is of proper size */ - offset = lseek (fs->fd, bytes-1, SEEK_SET); - if (offset != bytes-1) - return 0; - if (write (fs->fd, "", 1) != 1) { - perror ("write"); - return 0; - } - lseek (fs->fd, 0, SEEK_SET); + /* make sure the file is of proper size */ + offset = lseek (fs->fd, bytes-1, SEEK_SET); + if (offset != bytes-1) + return 0; + if (write (fs->fd, "", 1) != 1) { + perror ("write"); + return 0; + } + lseek (fs->fd, 0, SEEK_SET); - /* build a list of free blocks */ - fs->swapsz = swap_kbytes * 1024 / BSDFS_BSIZE; - fs_block_free (fs, 0); - for (n = fs->fsize - 1; n >= fs->isize + fs->swapsz; n--) - if (! fs_block_free (fs, n)) - return 0; + /* build a list of free blocks */ + fs->swapsz = swap_kbytes * 1024 / BSDFS_BSIZE; + fs_block_free (fs, 0); + for (n = fs->fsize - 1; n >= fs->isize + fs->swapsz; n--) + if (! fs_block_free (fs, n)) + return 0; - /* initialize inodes */ - memset (buf, 0, BSDFS_BSIZE); - if (! fs_seek (fs, BSDFS_BSIZE)) - return 0; - for (n=1; n < fs->isize; n++) { - if (! fs_write (fs, buf, BSDFS_BSIZE)) - return 0; - fs->tinode += BSDFS_INODES_PER_BLOCK; - } + /* initialize inodes */ + memset (buf, 0, BSDFS_BSIZE); + if (! fs_seek (fs, BSDFS_BSIZE)) + return 0; + for (n=1; n < fs->isize; n++) { + if (! fs_write (fs, buf, BSDFS_BSIZE)) + return 0; + fs->tinode += BSDFS_INODES_PER_BLOCK; + } - /* legacy empty inode 1 */ - if (! create_inode1 (fs)) - return 0; + /* legacy empty inode 1 */ + if (! create_inode1 (fs)) + return 0; - /* lost+found directory */ - if (! create_lost_found_directory (fs)) - return 0; + /* lost+found directory */ + if (! create_lost_found_directory (fs)) + return 0; - /* root directory */ - if (! create_root_directory (fs)) - return 0; + /* root directory */ + if (! create_root_directory (fs)) + return 0; - /* swap file */ - if (fs->swapsz != 0 && ! create_swap_file (fs)) - return 0; + /* swap file */ + if (fs->swapsz != 0 && ! create_swap_file (fs)) + return 0; - /* build a list of free inodes */ - if (! inode_build_list (fs)) - return 0; + /* build a list of free inodes */ + if (! inode_build_list (fs)) + return 0; - /* write out super block */ - return fs_sync (fs, 1); + /* write out super block */ + return fs_sync (fs, 1); } diff --git a/tools/fsutil/file.c b/tools/fsutil/file.c index 8218edb..13d650c 100644 --- a/tools/fsutil/file.c +++ b/tools/fsutil/file.c @@ -29,68 +29,68 @@ extern int verbose; int fs_file_create (fs_t *fs, fs_file_t *file, const char *name, int mode) { - if (! fs_inode_by_name (fs, &file->inode, name, INODE_OP_CREATE, mode)) { - fprintf (stderr, "%s: inode open failed\n", name); - return 0; - } - if ((file->inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { - /* Cannot open directory on write. */ - return 0; - } - fs_inode_truncate (&file->inode, 0); - fs_inode_save (&file->inode, 0); - file->writable = 1; - file->offset = 0; - return 1; + if (! fs_inode_by_name (fs, &file->inode, name, INODE_OP_CREATE, mode)) { + fprintf (stderr, "%s: inode open failed\n", name); + return 0; + } + if ((file->inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { + /* Cannot open directory on write. */ + return 0; + } + fs_inode_truncate (&file->inode, 0); + fs_inode_save (&file->inode, 0); + file->writable = 1; + file->offset = 0; + return 1; } int fs_file_open (fs_t *fs, fs_file_t *file, const char *name, int wflag) { - if (! fs_inode_by_name (fs, &file->inode, name, INODE_OP_LOOKUP, 0)) { - fprintf (stderr, "%s: inode open failed\n", name); - return 0; - } - if (wflag && (file->inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { - /* Cannot open directory on write. */ - return 0; - } - file->writable = wflag; - file->offset = 0; - return 1; + if (! fs_inode_by_name (fs, &file->inode, name, INODE_OP_LOOKUP, 0)) { + fprintf (stderr, "%s: inode open failed\n", name); + return 0; + } + if (wflag && (file->inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { + /* Cannot open directory on write. */ + return 0; + } + file->writable = wflag; + file->offset = 0; + return 1; } int fs_file_read (fs_file_t *file, unsigned char *data, unsigned long bytes) { - if (! fs_inode_read (&file->inode, file->offset, data, bytes)) { - fprintf (stderr, "inode %d: file read failed, %lu bytes at offset %lu\n", - file->inode.number, bytes, file->offset); - return 0; - } - file->offset += bytes; - return 1; + if (! fs_inode_read (&file->inode, file->offset, data, bytes)) { + fprintf (stderr, "inode %d: file read failed, %lu bytes at offset %lu\n", + file->inode.number, bytes, file->offset); + return 0; + } + file->offset += bytes; + return 1; } int fs_file_write (fs_file_t *file, unsigned char *data, unsigned long bytes) { - if (! file->writable) - return 0; - if (! fs_inode_write (&file->inode, file->offset, data, bytes)) { - fprintf (stderr, "inode %d: file write failed, %lu bytes at offset %lu\n", - file->inode.number, bytes, file->offset); - return 0; - } - file->offset += bytes; - return 1; + if (! file->writable) + return 0; + if (! fs_inode_write (&file->inode, file->offset, data, bytes)) { + fprintf (stderr, "inode %d: file write failed, %lu bytes at offset %lu\n", + file->inode.number, bytes, file->offset); + return 0; + } + file->offset += bytes; + return 1; } int fs_file_close (fs_file_t *file) { - if (file->writable) { - if (! fs_inode_save (&file->inode, 0)) { - fprintf (stderr, "inode %d: file close failed\n", - file->inode.number); - return 0; - } - } - return 1; + if (file->writable) { + if (! fs_inode_save (&file->inode, 0)) { + fprintf (stderr, "inode %d: file close failed\n", + file->inode.number); + return 0; + } + } + return 1; } diff --git a/tools/fsutil/fsutil.c b/tools/fsutil/fsutil.c index 7fdfb8c..627b366 100644 --- a/tools/fsutil/fsutil.c +++ b/tools/fsutil/fsutil.c @@ -43,249 +43,249 @@ unsigned kbytes; unsigned swap_kbytes; static const char *program_version = - "BSD 2.x file system utility, version 1.1\n" - "Copyright (C) 2011-2014 Serge Vakulenko"; + "BSD 2.x file system utility, version 1.1\n" + "Copyright (C) 2011-2014 Serge Vakulenko"; static const char *program_bug_address = ""; static struct option program_options[] = { - { "help", no_argument, 0, 'h' }, - { "version", no_argument, 0, 'V' }, - { "verbose", no_argument, 0, 'v' }, - { "add", no_argument, 0, 'a' }, - { "extract", no_argument, 0, 'x' }, - { "check", no_argument, 0, 'c' }, - { "fix", no_argument, 0, 'f' }, - { "mount", no_argument, 0, 'm' }, - { "new", required_argument, 0, 'n' }, - { "swap", required_argument, 0, 's' }, - { "manifest", required_argument, 0, 'M' }, - { 0 } + { "help", no_argument, 0, 'h' }, + { "version", no_argument, 0, 'V' }, + { "verbose", no_argument, 0, 'v' }, + { "add", no_argument, 0, 'a' }, + { "extract", no_argument, 0, 'x' }, + { "check", no_argument, 0, 'c' }, + { "fix", no_argument, 0, 'f' }, + { "mount", no_argument, 0, 'm' }, + { "new", required_argument, 0, 'n' }, + { "swap", required_argument, 0, 's' }, + { "manifest", required_argument, 0, 'M' }, + { 0 } }; static void print_help (char *progname) { - char *p = strrchr (progname, '/'); - if (p) - progname = p+1; + char *p = strrchr (progname, '/'); + if (p) + progname = p+1; - printf ("%s\n", program_version); - printf ("This program is free software; it comes with ABSOLUTELY NO WARRANTY;\n" - "see the GNU General Public License for more details.\n"); - printf ("\n"); - printf ("Usage:\n"); - printf (" %s [--verbose] filesys.img\n", progname); - printf (" %s --add filesys.img files...\n", progname); - printf (" %s --extract filesys.img\n", progname); - printf (" %s --check [--fix] filesys.img\n", progname); - printf (" %s --new=kbytes [--swap=kbytes] [--manifest=file] filesys.img [dir]\n", progname); - printf (" %s --mount filesys.img dir\n", progname); - printf ("\n"); - printf ("Options:\n"); - printf (" -a, --add Add files to filesystem.\n"); - printf (" -x, --extract Extract all files.\n"); - printf (" -c, --check Check filesystem, use -c -f to fix.\n"); - printf (" -f, --fix Fix bugs in filesystem.\n"); - printf (" -n NUM, --new=NUM Create new filesystem, size in kbytes.\n"); - printf (" Add files from specified directory (optional)\n"); - printf (" -s NUM, --swap=NUM Size of swap area in kbytes.\n"); - printf (" -M file, --manifest=file List of files and attributes to create.\n"); - printf (" -m, --mount Mount the filesystem.\n"); - printf (" -v, --verbose Be verbose.\n"); - printf (" -V, --version Print version information and then exit.\n"); - printf (" -h, --help Print this message.\n"); - printf ("\n"); - printf ("Report bugs to \"%s\".\n", program_bug_address); + printf ("%s\n", program_version); + printf ("This program is free software; it comes with ABSOLUTELY NO WARRANTY;\n" + "see the GNU General Public License for more details.\n"); + printf ("\n"); + printf ("Usage:\n"); + printf (" %s [--verbose] filesys.img\n", progname); + printf (" %s --add filesys.img files...\n", progname); + printf (" %s --extract filesys.img\n", progname); + printf (" %s --check [--fix] filesys.img\n", progname); + printf (" %s --new=kbytes [--swap=kbytes] [--manifest=file] filesys.img [dir]\n", progname); + printf (" %s --mount filesys.img dir\n", progname); + printf ("\n"); + printf ("Options:\n"); + printf (" -a, --add Add files to filesystem.\n"); + printf (" -x, --extract Extract all files.\n"); + printf (" -c, --check Check filesystem, use -c -f to fix.\n"); + printf (" -f, --fix Fix bugs in filesystem.\n"); + printf (" -n NUM, --new=NUM Create new filesystem, size in kbytes.\n"); + printf (" Add files from specified directory (optional)\n"); + printf (" -s NUM, --swap=NUM Size of swap area in kbytes.\n"); + printf (" -M file, --manifest=file List of files and attributes to create.\n"); + printf (" -m, --mount Mount the filesystem.\n"); + printf (" -v, --verbose Be verbose.\n"); + printf (" -V, --version Print version information and then exit.\n"); + printf (" -h, --help Print this message.\n"); + printf ("\n"); + printf ("Report bugs to \"%s\".\n", program_bug_address); } void print_inode (fs_inode_t *inode, - char *dirname, char *filename, FILE *out) + char *dirname, char *filename, FILE *out) { - fprintf (out, "%s/%s", dirname, filename); - switch (inode->mode & INODE_MODE_FMT) { - case INODE_MODE_FDIR: - if (filename[0] != 0) - fprintf (out, "/"); - break; - case INODE_MODE_FCHR: - fprintf (out, " - char %d %d", - inode->addr[1] >> 8, inode->addr[1] & 0xff); - break; - case INODE_MODE_FBLK: - fprintf (out, " - block %d %d", - inode->addr[1] >> 8, inode->addr[1] & 0xff); - break; - default: - fprintf (out, " - %lu bytes", inode->size); - break; - } - fprintf (out, "\n"); + fprintf (out, "%s/%s", dirname, filename); + switch (inode->mode & INODE_MODE_FMT) { + case INODE_MODE_FDIR: + if (filename[0] != 0) + fprintf (out, "/"); + break; + case INODE_MODE_FCHR: + fprintf (out, " - char %d %d", + inode->addr[1] >> 8, inode->addr[1] & 0xff); + break; + case INODE_MODE_FBLK: + fprintf (out, " - block %d %d", + inode->addr[1] >> 8, inode->addr[1] & 0xff); + break; + default: + fprintf (out, " - %lu bytes", inode->size); + break; + } + fprintf (out, "\n"); } void print_indirect_block (fs_t *fs, unsigned int bno, FILE *out) { - unsigned short nb; - unsigned char data [BSDFS_BSIZE]; - int i; + unsigned short nb; + unsigned char data [BSDFS_BSIZE]; + int i; - fprintf (out, " [%d]", bno); - if (! fs_read_block (fs, bno, data)) { - fprintf (stderr, "read error at block %d\n", bno); - return; - } - for (i=0; imode & INODE_MODE_FMT) == INODE_MODE_FCHR || - (inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK) - return; + if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FCHR || + (inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK) + return; - fprintf (out, " "); - for (i=0; iaddr[i] == 0) - continue; - fprintf (out, " %d", inode->addr[i]); - } - if (inode->addr[NDADDR] != 0) - print_indirect_block (inode->fs, inode->addr[NDADDR], out); - if (inode->addr[NDADDR+1] != 0) - print_double_indirect_block (inode->fs, - inode->addr[NDADDR+1], out); - if (inode->addr[NDADDR+2] != 0) - print_triple_indirect_block (inode->fs, - inode->addr[NDADDR+2], out); - fprintf (out, "\n"); + fprintf (out, " "); + for (i=0; iaddr[i] == 0) + continue; + fprintf (out, " %d", inode->addr[i]); + } + if (inode->addr[NDADDR] != 0) + print_indirect_block (inode->fs, inode->addr[NDADDR], out); + if (inode->addr[NDADDR+1] != 0) + print_double_indirect_block (inode->fs, + inode->addr[NDADDR+1], out); + if (inode->addr[NDADDR+2] != 0) + print_triple_indirect_block (inode->fs, + inode->addr[NDADDR+2], out); + fprintf (out, "\n"); } void extract_inode (fs_inode_t *inode, char *path) { - int fd, n, mode; - unsigned long offset; - unsigned char data [BSDFS_BSIZE]; + int fd, n, mode; + unsigned long offset; + unsigned char data [BSDFS_BSIZE]; - /* Allow read/write for user. */ - mode = (inode->mode & 0777) | 0600; - fd = open (path, O_CREAT | O_RDWR, mode); - if (fd < 0) { - perror (path); - return; - } - for (offset = 0; offset < inode->size; offset += BSDFS_BSIZE) { - n = inode->size - offset; - if (n > BSDFS_BSIZE) - n = BSDFS_BSIZE; - if (! fs_inode_read (inode, offset, data, n)) { - fprintf (stderr, "%s: read error at offset %ld\n", - path, offset); - break; - } - if (write (fd, data, n) != n) { - fprintf (stderr, "%s: write error\n", path); - break; - } - } - close (fd); + /* Allow read/write for user. */ + mode = (inode->mode & 0777) | 0600; + fd = open (path, O_CREAT | O_RDWR, mode); + if (fd < 0) { + perror (path); + return; + } + for (offset = 0; offset < inode->size; offset += BSDFS_BSIZE) { + n = inode->size - offset; + if (n > BSDFS_BSIZE) + n = BSDFS_BSIZE; + if (! fs_inode_read (inode, offset, data, n)) { + fprintf (stderr, "%s: read error at offset %ld\n", + path, offset); + break; + } + if (write (fd, data, n) != n) { + fprintf (stderr, "%s: write error\n", path); + break; + } + } + close (fd); } void extractor (fs_inode_t *dir, fs_inode_t *inode, - char *dirname, char *filename, void *arg) + char *dirname, char *filename, void *arg) { - FILE *out = arg; - char *path, *relpath; + FILE *out = arg; + char *path, *relpath; - if (verbose) - print_inode (inode, dirname, filename, out); + if (verbose) + print_inode (inode, dirname, filename, out); - if ((inode->mode & INODE_MODE_FMT) != INODE_MODE_FDIR && - (inode->mode & INODE_MODE_FMT) != INODE_MODE_FREG) - return; + if ((inode->mode & INODE_MODE_FMT) != INODE_MODE_FDIR && + (inode->mode & INODE_MODE_FMT) != INODE_MODE_FREG) + return; - path = alloca (strlen (dirname) + strlen (filename) + 2); - strcpy (path, dirname); - strcat (path, "/"); - strcat (path, filename); - for (relpath=path; *relpath == '/'; relpath++) - continue; + path = alloca (strlen (dirname) + strlen (filename) + 2); + strcpy (path, dirname); + strcat (path, "/"); + strcat (path, filename); + for (relpath=path; *relpath == '/'; relpath++) + continue; - if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { - if (mkdir (relpath, 0775) < 0 && errno != EEXIST) - perror (relpath); - /* Scan subdirectory. */ - fs_directory_scan (inode, path, extractor, arg); - } else { - extract_inode (inode, relpath); - } + if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { + if (mkdir (relpath, 0775) < 0 && errno != EEXIST) + perror (relpath); + /* Scan subdirectory. */ + fs_directory_scan (inode, path, extractor, arg); + } else { + extract_inode (inode, relpath); + } } void scanner (fs_inode_t *dir, fs_inode_t *inode, - char *dirname, char *filename, void *arg) + char *dirname, char *filename, void *arg) { - FILE *out = arg; - char *path; + FILE *out = arg; + char *path; - print_inode (inode, dirname, filename, out); + print_inode (inode, dirname, filename, out); - if (verbose > 1) { - /* Print a list of blocks. */ - print_inode_blocks (inode, out); - if (verbose > 2) { - fs_inode_print (inode, out); - printf ("--------\n"); - } - } - if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR && - inode->number != BSDFS_ROOT_INODE) { - /* Scan subdirectory. */ - path = alloca (strlen (dirname) + strlen (filename) + 2); - strcpy (path, dirname); - strcat (path, "/"); - strcat (path, filename); - fs_directory_scan (inode, path, scanner, arg); - } + if (verbose > 1) { + /* Print a list of blocks. */ + print_inode_blocks (inode, out); + if (verbose > 2) { + fs_inode_print (inode, out); + printf ("--------\n"); + } + } + if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR && + inode->number != BSDFS_ROOT_INODE) { + /* Scan subdirectory. */ + path = alloca (strlen (dirname) + strlen (filename) + 2); + strcpy (path, dirname); + strcat (path, "/"); + strcat (path, filename); + fs_directory_scan (inode, path, scanner, arg); + } } /* @@ -293,46 +293,46 @@ void scanner (fs_inode_t *dir, fs_inode_t *inode, */ void add_directory (fs_t *fs, char *name) { - fs_inode_t dir, parent; - char buf [BSDFS_BSIZE], *p; + fs_inode_t dir, parent; + char buf [BSDFS_BSIZE], *p; - /* Open parent directory. */ - strcpy (buf, name); - p = strrchr (buf, '/'); - if (p) - *p = 0; - else - *buf = 0; - if (! fs_inode_by_name (fs, &parent, buf, INODE_OP_LOOKUP, 0)) { - fprintf (stderr, "%s: cannot open directory\n", buf); - return; - } + /* Open parent directory. */ + strcpy (buf, name); + p = strrchr (buf, '/'); + if (p) + *p = 0; + else + *buf = 0; + if (! fs_inode_by_name (fs, &parent, buf, INODE_OP_LOOKUP, 0)) { + fprintf (stderr, "%s: cannot open directory\n", buf); + return; + } - /* Create directory. */ - int done = fs_inode_by_name (fs, &dir, name, INODE_OP_CREATE, INODE_MODE_FDIR | 0777); - if (! done) { - fprintf (stderr, "%s: directory inode create failed\n", name); - return; - } - if (done == 1) { - /* The directory already existed. */ - return; - } - fs_inode_save (&dir, 0); + /* Create directory. */ + int done = fs_inode_by_name (fs, &dir, name, INODE_OP_CREATE, INODE_MODE_FDIR | 0777); + if (! done) { + fprintf (stderr, "%s: directory inode create failed\n", name); + return; + } + if (done == 1) { + /* The directory already existed. */ + return; + } + fs_inode_save (&dir, 0); - /* Make parent link '..' */ - strcpy (buf, name); - strcat (buf, "/.."); - if (! fs_inode_by_name (fs, &dir, buf, INODE_OP_LINK, parent.number)) { - fprintf (stderr, "%s: dotdot link failed\n", name); - return; - } - if (! fs_inode_get (fs, &parent, parent.number)) { - fprintf (stderr, "inode %d: cannot open parent\n", parent.number); - return; - } - ++parent.nlink; - fs_inode_save (&parent, 1); + /* Make parent link '..' */ + strcpy (buf, name); + strcat (buf, "/.."); + if (! fs_inode_by_name (fs, &dir, buf, INODE_OP_LINK, parent.number)) { + fprintf (stderr, "%s: dotdot link failed\n", name); + return; + } + if (! fs_inode_get (fs, &parent, parent.number)) { + fprintf (stderr, "inode %d: cannot open parent\n", parent.number); + return; + } + ++parent.nlink; + fs_inode_save (&parent, 1); /*printf ("*** inode %d: increment link counter to %d\n", parent.number, parent.nlink);*/ } @@ -341,25 +341,25 @@ void add_directory (fs_t *fs, char *name) */ void add_device (fs_t *fs, char *name, char *spec) { - fs_inode_t dev; - int majr, minr; - char type; + fs_inode_t dev; + int majr, minr; + char type; - if (sscanf (spec, "%c%d:%d", &type, &majr, &minr) != 3 || - (type != 'c' && type != 'b') || - majr < 0 || majr > 255 || minr < 0 || minr > 255) { - fprintf (stderr, "%s: invalid device specification\n", spec); - fprintf (stderr, "expected c: or b:\n"); - return; - } - if (! fs_inode_by_name (fs, &dev, name, INODE_OP_CREATE, 0666 | - ((type == 'b') ? INODE_MODE_FBLK : INODE_MODE_FCHR))) { - fprintf (stderr, "%s: device inode create failed\n", name); - return; - } - dev.addr[1] = majr << 8 | minr; - time (&dev.mtime); - fs_inode_save (&dev, 1); + if (sscanf (spec, "%c%d:%d", &type, &majr, &minr) != 3 || + (type != 'c' && type != 'b') || + majr < 0 || majr > 255 || minr < 0 || minr > 255) { + fprintf (stderr, "%s: invalid device specification\n", spec); + fprintf (stderr, "expected c: or b:\n"); + return; + } + if (! fs_inode_by_name (fs, &dev, name, INODE_OP_CREATE, 0666 | + ((type == 'b') ? INODE_MODE_FBLK : INODE_MODE_FCHR))) { + fprintf (stderr, "%s: device inode create failed\n", name); + return; + } + dev.addr[1] = majr << 8 | minr; + time (&dev.mtime); + fs_inode_save (&dev, 1); } /* @@ -368,54 +368,54 @@ void add_device (fs_t *fs, char *name, char *spec) */ void add_file (fs_t *fs, char *name) { - fs_file_t file; - FILE *fd; - unsigned char data [BSDFS_BSIZE]; - struct stat st; - char *p; - int len; + fs_file_t file; + FILE *fd; + unsigned char data [BSDFS_BSIZE]; + struct stat st; + char *p; + int len; - if (verbose) { - printf ("%s\n", name); - } - p = strrchr (name, '/'); - if (p && p[1] == 0) { - *p = 0; - add_directory (fs, name); - return; - } - p = strrchr (name, '!'); - if (p) { - *p++ = 0; - add_device (fs, name, p); - return; - } - fd = fopen (name, "r"); - if (! fd) { - perror (name); - return; - } - stat (name, &st); - if (! fs_file_create (fs, &file, name, st.st_mode)) { - fprintf (stderr, "%s: cannot create\n", name); - return; - } - for (;;) { - len = fread (data, 1, sizeof (data), fd); -/* printf ("read %d bytes from %s\n", len, name);*/ - if (len < 0) - perror (name); - if (len <= 0) - break; - if (! fs_file_write (&file, data, len)) { - fprintf (stderr, "%s: write error\n", name); - break; - } - } - file.inode.mtime = st.st_mtime; - file.inode.dirty = 1; - fs_file_close (&file); - fclose (fd); + if (verbose) { + printf ("%s\n", name); + } + p = strrchr (name, '/'); + if (p && p[1] == 0) { + *p = 0; + add_directory (fs, name); + return; + } + p = strrchr (name, '!'); + if (p) { + *p++ = 0; + add_device (fs, name, p); + return; + } + fd = fopen (name, "r"); + if (! fd) { + perror (name); + return; + } + stat (name, &st); + if (! fs_file_create (fs, &file, name, st.st_mode)) { + fprintf (stderr, "%s: cannot create\n", name); + return; + } + for (;;) { + len = fread (data, 1, sizeof (data), fd); +/* printf ("read %d bytes from %s\n", len, name);*/ + if (len < 0) + perror (name); + if (len <= 0) + break; + if (! fs_file_write (&file, data, len)) { + fprintf (stderr, "%s: write error\n", name); + break; + } + } + file.inode.mtime = st.st_mtime; + file.inode.dirty = 1; + fs_file_close (&file); + fclose (fd); } /* @@ -424,156 +424,157 @@ void add_file (fs_t *fs, char *name) */ void add_contents (fs_t *fs, const char *dirname, const char *manifest) { - printf ("TODO: add contents from directory '%s'\n", dirname); - if (manifest) - printf ("TODO: use manifest '%s'\n", manifest); + printf ("TODO: add contents from directory '%s'\n", dirname); + if (manifest) + printf ("TODO: use manifest '%s'\n", manifest); } int main (int argc, char **argv) { - int i, key; - fs_t fs; - fs_inode_t inode; - const char *manifest = 0; + int i, key; + fs_t fs; + fs_inode_t inode; + const char *manifest = 0; - for (;;) { - key = getopt_long (argc, argv, "vaxmMn:cfs:", - program_options, 0); - if (key == -1) - break; - switch (key) { - case 'v': - ++verbose; - break; - case 'a': - ++add; - break; - case 'x': - ++extract; - break; - case 'n': - ++newfs; - kbytes = strtol (optarg, 0, 0); - break; - case 'c': - ++check; - break; - case 'f': - ++fix; - break; - case 'm': - ++mount; - break; - case 's': - swap_kbytes = strtol (optarg, 0, 0); - break; - case 'M': - manifest = optarg; - break; - case 'V': - printf ("%s\n", program_version); - return 0; - case 'h': - print_help (argv[0]); - return 0; - default: - print_help (argv[0]); - return -1; - } - } - i = optind; - if ((! add && ! mount && ! newfs && i != argc-1) || - (add && i >= argc) || - (newfs && i != argc-1 && i != argc-2) || - (mount && i != argc-2) || - (extract + newfs + check + add + mount > 1) || - (newfs && kbytes < BSDFS_BSIZE * 10 / 1024)) { - print_help (argv[0]); - return -1; - } + for (;;) { + key = getopt_long (argc, argv, "vaxmMn:cfs:", + program_options, 0); + if (key == -1) + break; + switch (key) { + case 'v': + ++verbose; + break; + case 'a': + ++add; + break; + case 'x': + ++extract; + break; + case 'n': + ++newfs; + kbytes = strtol (optarg, 0, 0); + break; + case 'c': + ++check; + break; + case 'f': + ++fix; + break; + case 'm': + ++mount; + break; + case 's': + swap_kbytes = strtol (optarg, 0, 0); + break; + case 'M': + manifest = optarg; + break; + case 'V': + printf ("%s\n", program_version); + return 0; + case 'h': + print_help (argv[0]); + return 0; + default: + print_help (argv[0]); + return -1; + } + } + i = optind; + if ((! add && ! mount && ! newfs && i != argc-1) || + (add && i >= argc) || + (newfs && i != argc-1 && i != argc-2) || + (mount && i != argc-2) || + (extract + newfs + check + add + mount > 1) || + (newfs && kbytes < BSDFS_BSIZE * 10 / 1024)) + { + print_help (argv[0]); + return -1; + } - if (newfs) { - /* Create new filesystem. */ - if (! fs_create (&fs, argv[i], kbytes, swap_kbytes)) { - fprintf (stderr, "%s: cannot create filesystem\n", argv[i]); - return -1; - } - printf ("Created filesystem %s - %u kbytes\n", argv[i], kbytes); + if (newfs) { + /* Create new filesystem. */ + if (! fs_create (&fs, argv[i], kbytes, swap_kbytes)) { + fprintf (stderr, "%s: cannot create filesystem\n", argv[i]); + return -1; + } + printf ("Created filesystem %s - %u kbytes\n", argv[i], kbytes); - if (i == argc-2) { - /* Add the contents from the specified directory. - * Use the optional manifest file. */ - add_contents (&fs, argv[i+1], manifest); - } - fs_close (&fs); - return 0; - } + if (i == argc-2) { + /* Add the contents from the specified directory. + * Use the optional manifest file. */ + add_contents (&fs, argv[i+1], manifest); + } + fs_close (&fs); + return 0; + } - if (check) { - /* Check filesystem for errors, and optionally fix them. */ - if (! fs_open (&fs, argv[i], fix)) { - fprintf (stderr, "%s: cannot open\n", argv[i]); - return -1; - } - fs_check (&fs); - fs_close (&fs); - return 0; - } + if (check) { + /* Check filesystem for errors, and optionally fix them. */ + if (! fs_open (&fs, argv[i], fix)) { + fprintf (stderr, "%s: cannot open\n", argv[i]); + return -1; + } + fs_check (&fs); + fs_close (&fs); + return 0; + } - /* Add or extract or info. */ - if (! fs_open (&fs, argv[i], (add + mount != 0))) { - fprintf (stderr, "%s: cannot open\n", argv[i]); - return -1; - } + /* Add or extract or info. */ + if (! fs_open (&fs, argv[i], (add + mount != 0))) { + fprintf (stderr, "%s: cannot open\n", argv[i]); + return -1; + } - if (extract) { - /* Extract all files to current directory. */ - if (! fs_inode_get (&fs, &inode, BSDFS_ROOT_INODE)) { - fprintf (stderr, "%s: cannot get inode 1\n", argv[i]); - return -1; - } - fs_directory_scan (&inode, "", extractor, (void*) stdout); - fs_close (&fs); - return 0; - } + if (extract) { + /* Extract all files to current directory. */ + if (! fs_inode_get (&fs, &inode, BSDFS_ROOT_INODE)) { + fprintf (stderr, "%s: cannot get inode 1\n", argv[i]); + return -1; + } + fs_directory_scan (&inode, "", extractor, (void*) stdout); + fs_close (&fs); + return 0; + } - if (add) { - /* Add files i+1..argc-1 to filesystem. */ - while (++i < argc) - add_file (&fs, argv[i]); - fs_sync (&fs, 0); - fs_close (&fs); - return 0; - } + if (add) { + /* Add files i+1..argc-1 to filesystem. */ + while (++i < argc) + add_file (&fs, argv[i]); + fs_sync (&fs, 0); + fs_close (&fs); + return 0; + } - if (mount) { - /* Mount the filesystem. */ - if (++i >= argc) { - print_help (argv[0]); - return -1; - } - return fs_mount(&fs, argv[i]); - } + if (mount) { + /* Mount the filesystem. */ + if (++i >= argc) { + print_help (argv[0]); + return -1; + } + return fs_mount(&fs, argv[i]); + } - /* Print the structure of flesystem. */ - fs_print (&fs, stdout); - if (verbose) { - printf ("--------\n"); - if (! fs_inode_get (&fs, &inode, BSDFS_ROOT_INODE)) { - fprintf (stderr, "%s: cannot get inode 1\n", argv[i]); - return -1; - } - printf ("/\n"); - if (verbose > 1) { - /* Print a list of blocks. */ - print_inode_blocks (&inode, stdout); - if (verbose > 2) { - fs_inode_print (&inode, stdout); - printf ("--------\n"); - } - } - fs_directory_scan (&inode, "", scanner, (void*) stdout); - } - fs_close (&fs); - return 0; + /* Print the structure of flesystem. */ + fs_print (&fs, stdout); + if (verbose) { + printf ("--------\n"); + if (! fs_inode_get (&fs, &inode, BSDFS_ROOT_INODE)) { + fprintf (stderr, "%s: cannot get inode 1\n", argv[i]); + return -1; + } + printf ("/\n"); + if (verbose > 1) { + /* Print a list of blocks. */ + print_inode_blocks (&inode, stdout); + if (verbose > 2) { + fs_inode_print (&inode, stdout); + printf ("--------\n"); + } + } + fs_directory_scan (&inode, "", scanner, (void*) stdout); + } + fs_close (&fs); + return 0; } diff --git a/tools/fsutil/inode.c b/tools/fsutil/inode.c index ec9d88b..a07a1c5 100644 --- a/tools/fsutil/inode.c +++ b/tools/fsutil/inode.c @@ -32,53 +32,53 @@ extern int verbose; int fs_inode_get (fs_t *fs, fs_inode_t *inode, unsigned inum) { - unsigned long offset; - int i, reserved; + unsigned long offset; + int i, reserved; - memset (inode, 0, sizeof (*inode)); - inode->fs = fs; - inode->number = inum; + memset (inode, 0, sizeof (*inode)); + inode->fs = fs; + inode->number = inum; - /* Inodes are numbered starting from 1. - * 64 bytes per inode, 16 inodes per block. - * Skip first block. */ - if (inum == 0 || inum > (fs->isize-1) * BSDFS_INODES_PER_BLOCK) - return 0; - offset = (inode->number + BSDFS_INODES_PER_BLOCK - 1) * - BSDFS_BSIZE / BSDFS_INODES_PER_BLOCK; + /* Inodes are numbered starting from 1. + * 64 bytes per inode, 16 inodes per block. + * Skip first block. */ + if (inum == 0 || inum > (fs->isize-1) * BSDFS_INODES_PER_BLOCK) + return 0; + offset = (inode->number + BSDFS_INODES_PER_BLOCK - 1) * + BSDFS_BSIZE / BSDFS_INODES_PER_BLOCK; - if (! fs_seek (fs, offset)) - return 0; + if (! fs_seek (fs, offset)) + return 0; - if (! fs_read16 (fs, &inode->mode)) /* file type and access mode */ - return 0; - if (! fs_read16 (fs, &inode->nlink)) /* directory entries */ - return 0; - if (! fs_read32 (fs, &inode->uid)) /* owner */ - return 0; - if (! fs_read32 (fs, &inode->gid)) /* group */ - return 0; - if (! fs_read32 (fs, (unsigned*) &inode->size)) /* size */ - return 0; + if (! fs_read16 (fs, &inode->mode)) /* file type and access mode */ + return 0; + if (! fs_read16 (fs, &inode->nlink)) /* directory entries */ + return 0; + if (! fs_read32 (fs, &inode->uid)) /* owner */ + return 0; + if (! fs_read32 (fs, &inode->gid)) /* group */ + return 0; + if (! fs_read32 (fs, (unsigned*) &inode->size)) /* size */ + return 0; - for (i=0; iaddr[i])) - return 0; - } - if (! fs_read32 (fs, (unsigned*) &reserved)) - return 0; - if (! fs_read32 (fs, (unsigned*) &inode->flags)) - return 0; - if (! fs_read32 (fs, (unsigned*) &inode->atime)) - return 0; /* last access time */ - if (! fs_read32 (fs, (unsigned*) &inode->mtime)) - return 0; /* last modification time */ - if (! fs_read32 (fs, (unsigned*) &inode->ctime)) - return 0; /* creation time */ + for (i=0; iaddr[i])) + return 0; + } + if (! fs_read32 (fs, (unsigned*) &reserved)) + return 0; + if (! fs_read32 (fs, (unsigned*) &inode->flags)) + return 0; + if (! fs_read32 (fs, (unsigned*) &inode->atime)) + return 0; /* last access time */ + if (! fs_read32 (fs, (unsigned*) &inode->mtime)) + return 0; /* last modification time */ + if (! fs_read32 (fs, (unsigned*) &inode->ctime)) + return 0; /* creation time */ /*if (inode->mode) { fs_inode_print (inode, stdout); printf ("---\n"); }*/ - if (verbose > 3) - printf ("get inode %u\n", inode->number); - return 1; + if (verbose > 3) + printf ("get inode %u\n", inode->number); + return 1; } /* @@ -92,187 +92,187 @@ int fs_inode_get (fs_t *fs, fs_inode_t *inode, unsigned inum) */ void fs_inode_truncate (fs_inode_t *inode, unsigned long size) { - int i, nblk; - unsigned *blk; + int i, nblk; + unsigned *blk; - if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FCHR || - (inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK) - return; + if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FCHR || + (inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK) + return; -#define SINGLE NDADDR /* index of single indirect block */ -#define DOUBLE (SINGLE+1) /* index of double indirect block */ -#define TRIPLE (DOUBLE+1) /* index of triple indirect block */ +#define SINGLE NDADDR /* index of single indirect block */ +#define DOUBLE (SINGLE+1) /* index of double indirect block */ +#define TRIPLE (DOUBLE+1) /* index of triple indirect block */ - nblk = (size + BSDFS_BSIZE - 1) / BSDFS_BSIZE; - for (i=TRIPLE; i>=0; --i) { - blk = &inode->addr[i]; - if (*blk == 0) - continue; + nblk = (size + BSDFS_BSIZE - 1) / BSDFS_BSIZE; + for (i=TRIPLE; i>=0; --i) { + blk = &inode->addr[i]; + if (*blk == 0) + continue; - if (i == TRIPLE) { - if (! fs_triple_indirect_block_free (inode->fs, *blk, - nblk - (NDADDR + BSDFS_BSIZE/4 + BSDFS_BSIZE/4*BSDFS_BSIZE/4))) - break; - } else if (i == DOUBLE) { - if (! fs_double_indirect_block_free (inode->fs, *blk, - nblk - (NDADDR + BSDFS_BSIZE/4))) - break; - } else if (i == SINGLE) { - if (! fs_indirect_block_free (inode->fs, *blk, nblk - NDADDR)) - break; - } else { - if (i * BSDFS_BSIZE < size) - break; - fs_block_free (inode->fs, *blk); - } + if (i == TRIPLE) { + if (! fs_triple_indirect_block_free (inode->fs, *blk, + nblk - (NDADDR + BSDFS_BSIZE/4 + BSDFS_BSIZE/4*BSDFS_BSIZE/4))) + break; + } else if (i == DOUBLE) { + if (! fs_double_indirect_block_free (inode->fs, *blk, + nblk - (NDADDR + BSDFS_BSIZE/4))) + break; + } else if (i == SINGLE) { + if (! fs_indirect_block_free (inode->fs, *blk, nblk - NDADDR)) + break; + } else { + if (i * BSDFS_BSIZE < size) + break; + fs_block_free (inode->fs, *blk); + } - *blk = 0; - } + *blk = 0; + } - inode->size = size; - inode->dirty = 1; + inode->size = size; + inode->dirty = 1; } void fs_inode_clear (fs_inode_t *inode) { - inode->dirty = 1; - inode->mode = 0; - inode->nlink = 0; - inode->uid = 0; - inode->size = 0; - memset (inode->addr, 0, sizeof(inode->addr)); - inode->atime = 0; - inode->mtime = 0; + inode->dirty = 1; + inode->mode = 0; + inode->nlink = 0; + inode->uid = 0; + inode->size = 0; + memset (inode->addr, 0, sizeof(inode->addr)); + inode->atime = 0; + inode->mtime = 0; } int fs_inode_save (fs_inode_t *inode, int force) { - unsigned long offset; - int i; + unsigned long offset; + int i; - if (! inode->fs->writable) - return 0; - if (! force && ! inode->dirty) - return 1; - if (inode->number == 0 || - inode->number > (inode->fs->isize-1) * BSDFS_INODES_PER_BLOCK) - return 0; - offset = (inode->number + BSDFS_INODES_PER_BLOCK - 1) * - BSDFS_BSIZE / BSDFS_INODES_PER_BLOCK; + if (! inode->fs->writable) + return 0; + if (! force && ! inode->dirty) + return 1; + if (inode->number == 0 || + inode->number > (inode->fs->isize-1) * BSDFS_INODES_PER_BLOCK) + return 0; + offset = (inode->number + BSDFS_INODES_PER_BLOCK - 1) * + BSDFS_BSIZE / BSDFS_INODES_PER_BLOCK; - time (&inode->atime); + time (&inode->atime); - if (! fs_seek (inode->fs, offset)) - return 0; + if (! fs_seek (inode->fs, offset)) + return 0; - if (! fs_write16 (inode->fs, inode->mode)) /* file type and access mode */ - return 0; - if (! fs_write16 (inode->fs, inode->nlink)) /* directory entries */ - return 0; - if (! fs_write32 (inode->fs, inode->uid)) /* owner */ - return 0; - if (! fs_write32 (inode->fs, inode->gid)) /* group */ - return 0; - if (! fs_write32 (inode->fs, inode->size)) /* size */ - return 0; + if (! fs_write16 (inode->fs, inode->mode)) /* file type and access mode */ + return 0; + if (! fs_write16 (inode->fs, inode->nlink)) /* directory entries */ + return 0; + if (! fs_write32 (inode->fs, inode->uid)) /* owner */ + return 0; + if (! fs_write32 (inode->fs, inode->gid)) /* group */ + return 0; + if (! fs_write32 (inode->fs, inode->size)) /* size */ + return 0; - for (i=0; ifs, inode->addr[i])) - return 0; - } - if (! fs_write32 (inode->fs, 0)) /* reserved */ - return 0; - if (! fs_write32 (inode->fs, inode->flags)) /* flags */ - return 0; - if (! fs_write32 (inode->fs, inode->atime)) /* last access time */ - return 0; - if (! fs_write32 (inode->fs, inode->mtime)) /* last modification time */ - return 0; - if (! fs_write32 (inode->fs, inode->ctime)) /* creation time */ - return 0; + for (i=0; ifs, inode->addr[i])) + return 0; + } + if (! fs_write32 (inode->fs, 0)) /* reserved */ + return 0; + if (! fs_write32 (inode->fs, inode->flags)) /* flags */ + return 0; + if (! fs_write32 (inode->fs, inode->atime)) /* last access time */ + return 0; + if (! fs_write32 (inode->fs, inode->mtime)) /* last modification time */ + return 0; + if (! fs_write32 (inode->fs, inode->ctime)) /* creation time */ + return 0; - inode->dirty = 0; - if (verbose > 3) - printf ("save inode %u\n", inode->number); - return 1; + inode->dirty = 0; + if (verbose > 3) + printf ("save inode %u\n", inode->number); + return 1; } void fs_inode_print (fs_inode_t *inode, FILE *out) { - int i; + int i; - fprintf (out, " I-node: %u\n", inode->number); - fprintf (out, " Type: %s\n", - (inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR ? "Directory" : - (inode->mode & INODE_MODE_FMT) == INODE_MODE_FCHR ? "Character device" : - (inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK ? "Block device" : - (inode->mode & INODE_MODE_FMT) == INODE_MODE_FREG ? "File" : - (inode->mode & INODE_MODE_FMT) == INODE_MODE_FLNK ? "Symbolic link" : - (inode->mode & INODE_MODE_FMT) == INODE_MODE_FSOCK? "Socket" : - "Unknown"); - fprintf (out, " Size: %lu bytes\n", inode->size); - fprintf (out, " Mode: %#o\n", inode->mode); + fprintf (out, " I-node: %u\n", inode->number); + fprintf (out, " Type: %s\n", + (inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR ? "Directory" : + (inode->mode & INODE_MODE_FMT) == INODE_MODE_FCHR ? "Character device" : + (inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK ? "Block device" : + (inode->mode & INODE_MODE_FMT) == INODE_MODE_FREG ? "File" : + (inode->mode & INODE_MODE_FMT) == INODE_MODE_FLNK ? "Symbolic link" : + (inode->mode & INODE_MODE_FMT) == INODE_MODE_FSOCK? "Socket" : + "Unknown"); + fprintf (out, " Size: %lu bytes\n", inode->size); + fprintf (out, " Mode: %#o\n", inode->mode); - fprintf (out, " "); - if (inode->mode & INODE_MODE_SUID) fprintf (out, " SUID"); - if (inode->mode & INODE_MODE_SGID) fprintf (out, " SGID"); - if (inode->mode & INODE_MODE_SVTX) fprintf (out, " SVTX"); - if (inode->mode & INODE_MODE_READ) fprintf (out, " READ"); - if (inode->mode & INODE_MODE_WRITE) fprintf (out, " WRITE"); - if (inode->mode & INODE_MODE_EXEC) fprintf (out, " EXEC"); - fprintf (out, "\n"); + fprintf (out, " "); + if (inode->mode & INODE_MODE_SUID) fprintf (out, " SUID"); + if (inode->mode & INODE_MODE_SGID) fprintf (out, " SGID"); + if (inode->mode & INODE_MODE_SVTX) fprintf (out, " SVTX"); + if (inode->mode & INODE_MODE_READ) fprintf (out, " READ"); + if (inode->mode & INODE_MODE_WRITE) fprintf (out, " WRITE"); + if (inode->mode & INODE_MODE_EXEC) fprintf (out, " EXEC"); + fprintf (out, "\n"); - fprintf (out, " Links: %u\n", inode->nlink); - fprintf (out, " Owner id: %u\n", inode->uid); + fprintf (out, " Links: %u\n", inode->nlink); + fprintf (out, " Owner id: %u\n", inode->uid); - fprintf (out, " Blocks:"); - for (i=0; iaddr[i]); - } - fprintf (out, "\n"); + fprintf (out, " Blocks:"); + for (i=0; iaddr[i]); + } + fprintf (out, "\n"); - fprintf (out, " Created: %s", ctime (&inode->ctime)); - fprintf (out, " Modified: %s", ctime (&inode->mtime)); - fprintf (out, "Last access: %s", ctime (&inode->atime)); + fprintf (out, " Created: %s", ctime (&inode->ctime)); + fprintf (out, " Modified: %s", ctime (&inode->mtime)); + fprintf (out, "Last access: %s", ctime (&inode->atime)); } void fs_directory_scan (fs_inode_t *dir, char *dirname, - fs_directory_scanner_t scanner, void *arg) + fs_directory_scanner_t scanner, void *arg) { - fs_inode_t file; - unsigned long offset; - unsigned char name [BSDFS_BSIZE - 12]; - struct { - unsigned int inum; - unsigned short reclen; - unsigned short namlen; - } dirent; + fs_inode_t file; + unsigned long offset; + unsigned char name [BSDFS_BSIZE - 12]; + struct { + unsigned int inum; + unsigned short reclen; + unsigned short namlen; + } dirent; - /* Variable record per file */ - for (offset = 0; offset < dir->size; offset += dirent.reclen) { - if (! fs_inode_read (dir, offset, (unsigned char*) &dirent, sizeof(dirent))) { - fprintf (stderr, "%s: read error at offset %ld\n", - dirname[0] ? dirname : "/", offset); - return; - } + /* Variable record per file */ + for (offset = 0; offset < dir->size; offset += dirent.reclen) { + if (! fs_inode_read (dir, offset, (unsigned char*) &dirent, sizeof(dirent))) { + fprintf (stderr, "%s: read error at offset %ld\n", + dirname[0] ? dirname : "/", offset); + return; + } /*printf ("scan offset %lu: inum=%u, reclen=%u, namlen=%u\n", offset, dirent.inum, dirent.reclen, dirent.namlen);*/ - if (! fs_inode_read (dir, offset+sizeof(dirent), name, (dirent.namlen + 4) / 4 * 4)) { - fprintf (stderr, "%s: name read error at offset %ld\n", - dirname[0] ? dirname : "/", offset); - return; - } + if (! fs_inode_read (dir, offset+sizeof(dirent), name, (dirent.namlen + 4) / 4 * 4)) { + fprintf (stderr, "%s: name read error at offset %ld\n", + dirname[0] ? dirname : "/", offset); + return; + } /*printf ("scan offset %lu: name='%s'\n", offset, name);*/ - if (dirent.inum == 0 || (name[0]=='.' && name[1]==0) || - (name[0]=='.' && name[1]=='.' && name[2]==0)) - continue; + if (dirent.inum == 0 || (name[0]=='.' && name[1]==0) || + (name[0]=='.' && name[1]=='.' && name[2]==0)) + continue; - if (! fs_inode_get (dir->fs, &file, dirent.inum)) { - fprintf (stderr, "cannot scan inode %d\n", dirent.inum); - continue; - } - scanner (dir, &file, dirname, (char*) name, arg); - } + if (! fs_inode_get (dir->fs, &file, dirent.inum)) { + fprintf (stderr, "cannot scan inode %d\n", dirent.inum); + continue; + } + scanner (dir, &file, dirname, (char*) name, arg); + } } /* @@ -281,57 +281,57 @@ void fs_directory_scan (fs_inode_t *dir, char *dirname, */ static unsigned map_block (fs_inode_t *inode, unsigned lbn) { - unsigned block [BSDFS_BSIZE / 4]; - unsigned int nb, i, j, sh; + unsigned block [BSDFS_BSIZE / 4]; + unsigned int nb, i, j, sh; - /* - * Blocks 0..NADDR-4 are direct blocks. - */ - if (lbn < NADDR-3) { - /* small file algorithm */ - return inode->addr [lbn]; - } + /* + * Blocks 0..NADDR-4 are direct blocks. + */ + if (lbn < NADDR-3) { + /* small file algorithm */ + return inode->addr [lbn]; + } - /* - * Addresses NADDR-3, NADDR-2, and NADDR-1 - * have single, double, triple indirect blocks. - * The first step is to determine - * how many levels of indirection. - */ - sh = 0; - nb = 1; - lbn -= NADDR-3; - for (j=3; ; j--) { - if (j == 0) - return 0; - sh += NSHIFT; - nb <<= NSHIFT; - if (lbn < nb) - break; - lbn -= nb; - } + /* + * Addresses NADDR-3, NADDR-2, and NADDR-1 + * have single, double, triple indirect blocks. + * The first step is to determine + * how many levels of indirection. + */ + sh = 0; + nb = 1; + lbn -= NADDR-3; + for (j=3; ; j--) { + if (j == 0) + return 0; + sh += NSHIFT; + nb <<= NSHIFT; + if (lbn < nb) + break; + lbn -= nb; + } - /* - * Fetch the first indirect block. - */ - nb = inode->addr [NADDR-j]; - if (nb == 0) - return 0; + /* + * Fetch the first indirect block. + */ + nb = inode->addr [NADDR-j]; + if (nb == 0) + return 0; - /* - * Fetch through the indirect blocks. - */ - for(; j <= 3; j++) { - if (! fs_read_block (inode->fs, nb, (unsigned char*) block)) - return 0; + /* + * Fetch through the indirect blocks. + */ + for(; j <= 3; j++) { + if (! fs_read_block (inode->fs, nb, (unsigned char*) block)) + return 0; - sh -= NSHIFT; - i = (lbn >> sh) & NMASK; - nb = block [i]; - if (nb == 0) - return 0; - } - return nb; + sh -= NSHIFT; + i = (lbn >> sh) & NMASK; + nb = block [i]; + if (nb == 0) + return 0; + } + return nb; } /* @@ -341,163 +341,163 @@ static unsigned map_block (fs_inode_t *inode, unsigned lbn) */ static unsigned map_block_write (fs_inode_t *inode, unsigned lbn) { - unsigned block [BSDFS_BSIZE / 4]; - unsigned int nb, newb, sh, i, j; + unsigned block [BSDFS_BSIZE / 4]; + unsigned int nb, newb, sh, i, j; - /* - * Blocks 0..NADDR-3 are direct blocks. - */ - if (lbn < NADDR-3) { - /* small file algorithm */ - nb = inode->addr [lbn]; - if (nb != 0) { - if (verbose) - printf ("map logical block %d to physical %d\n", lbn, nb); - return nb; - } + /* + * Blocks 0..NADDR-3 are direct blocks. + */ + if (lbn < NADDR-3) { + /* small file algorithm */ + nb = inode->addr [lbn]; + if (nb != 0) { + if (verbose) + printf ("map logical block %d to physical %d\n", lbn, nb); + return nb; + } - /* allocate new block */ - if (! fs_block_alloc (inode->fs, &nb)) - return 0; - inode->addr[lbn] = nb; - inode->dirty = 1; - return nb; - } + /* allocate new block */ + if (! fs_block_alloc (inode->fs, &nb)) + return 0; + inode->addr[lbn] = nb; + inode->dirty = 1; + return nb; + } - /* - * Addresses NADDR-3, NADDR-2, and NADDR-1 - * have single, double, triple indirect blocks. - * The first step is to determine - * how many levels of indirection. - */ - sh = 0; - nb = 1; - lbn -= NADDR-3; - for (j=3; ; j--) { - if (j == 0) - return 0; - sh += NSHIFT; - nb <<= NSHIFT; - if (lbn < nb) - break; - lbn -= nb; - } + /* + * Addresses NADDR-3, NADDR-2, and NADDR-1 + * have single, double, triple indirect blocks. + * The first step is to determine + * how many levels of indirection. + */ + sh = 0; + nb = 1; + lbn -= NADDR-3; + for (j=3; ; j--) { + if (j == 0) + return 0; + sh += NSHIFT; + nb <<= NSHIFT; + if (lbn < nb) + break; + lbn -= nb; + } - /* - * Fetch the first indirect block. - */ - nb = inode->addr [NADDR-j]; - if (nb == 0) { - if (! fs_block_alloc (inode->fs, &nb)) - return 0; - if (verbose) - printf ("inode %d: allocate new block %d\n", inode->number, nb); - memset (block, 0, BSDFS_BSIZE); - if (! fs_write_block (inode->fs, nb, (unsigned char*) block)) - return 0; - inode->addr [NADDR-j] = nb; - inode->dirty = 1; - } + /* + * Fetch the first indirect block. + */ + nb = inode->addr [NADDR-j]; + if (nb == 0) { + if (! fs_block_alloc (inode->fs, &nb)) + return 0; + if (verbose) + printf ("inode %d: allocate new block %d\n", inode->number, nb); + memset (block, 0, BSDFS_BSIZE); + if (! fs_write_block (inode->fs, nb, (unsigned char*) block)) + return 0; + inode->addr [NADDR-j] = nb; + inode->dirty = 1; + } - /* - * Fetch through the indirect blocks - */ - for(; j <= 3; j++) { - if (! fs_read_block (inode->fs, nb, (unsigned char*) block)) - return 0; + /* + * Fetch through the indirect blocks + */ + for(; j <= 3; j++) { + if (! fs_read_block (inode->fs, nb, (unsigned char*) block)) + return 0; - sh -= NSHIFT; - i = (lbn >> sh) & NMASK; - if (block [i] != 0) - nb = block [i]; - else { - /* Allocate new block. */ - if (! fs_block_alloc (inode->fs, &newb)) - return 0; - if (verbose) - printf ("inode %d: allocate new block %d\n", inode->number, newb); - block[i] = newb; - if (! fs_write_block (inode->fs, nb, (unsigned char*) block)) - return 0; - memset (block, 0, BSDFS_BSIZE); - if (! fs_write_block (inode->fs, newb, (unsigned char*) block)) - return 0; - nb = newb; - } - } - return nb; + sh -= NSHIFT; + i = (lbn >> sh) & NMASK; + if (block [i] != 0) + nb = block [i]; + else { + /* Allocate new block. */ + if (! fs_block_alloc (inode->fs, &newb)) + return 0; + if (verbose) + printf ("inode %d: allocate new block %d\n", inode->number, newb); + block[i] = newb; + if (! fs_write_block (inode->fs, nb, (unsigned char*) block)) + return 0; + memset (block, 0, BSDFS_BSIZE); + if (! fs_write_block (inode->fs, newb, (unsigned char*) block)) + return 0; + nb = newb; + } + } + return nb; } int fs_inode_read (fs_inode_t *inode, unsigned long offset, - unsigned char *data, unsigned long bytes) + unsigned char *data, unsigned long bytes) { - unsigned char block [BSDFS_BSIZE]; - unsigned long n; - unsigned int bn, inblock_offset; + unsigned char block [BSDFS_BSIZE]; + unsigned long n; + unsigned int bn, inblock_offset; - if (bytes + offset > inode->size) - return 0; - while (bytes != 0) { - inblock_offset = offset % BSDFS_BSIZE; - n = BSDFS_BSIZE - inblock_offset; - if (n > bytes) - n = bytes; + if (bytes + offset > inode->size) + return 0; + while (bytes != 0) { + inblock_offset = offset % BSDFS_BSIZE; + n = BSDFS_BSIZE - inblock_offset; + if (n > bytes) + n = bytes; - bn = map_block (inode, offset / BSDFS_BSIZE); - if (bn == 0) - return 0; + bn = map_block (inode, offset / BSDFS_BSIZE); + if (bn == 0) + return 0; - if (! fs_read_block (inode->fs, bn, block)) - return 0; - memcpy (data, block + inblock_offset, n); - data += n; - offset += n; - bytes -= n; - } - return 1; + if (! fs_read_block (inode->fs, bn, block)) + return 0; + memcpy (data, block + inblock_offset, n); + data += n; + offset += n; + bytes -= n; + } + return 1; } int fs_inode_write (fs_inode_t *inode, unsigned long offset, - unsigned char *data, unsigned long bytes) + unsigned char *data, unsigned long bytes) { - unsigned char block [BSDFS_BSIZE]; - unsigned long n; - unsigned int bn, inblock_offset; + unsigned char block [BSDFS_BSIZE]; + unsigned long n; + unsigned int bn, inblock_offset; - time (&inode->mtime); - while (bytes != 0) { - inblock_offset = offset % BSDFS_BSIZE; - n = BSDFS_BSIZE - inblock_offset; - if (n > bytes) - n = bytes; + time (&inode->mtime); + while (bytes != 0) { + inblock_offset = offset % BSDFS_BSIZE; + n = BSDFS_BSIZE - inblock_offset; + if (n > bytes) + n = bytes; - bn = map_block_write (inode, offset / BSDFS_BSIZE); - if (bn == 0) - return 0; - if (inode->size < offset + n) { - /* Increase file size. */ - inode->size = offset + n; - inode->dirty = 1; - } - if (verbose) - printf ("inode %d offset %ld: write %ld bytes to block %d\n", - inode->number, offset, n, bn); + bn = map_block_write (inode, offset / BSDFS_BSIZE); + if (bn == 0) + return 0; + if (inode->size < offset + n) { + /* Increase file size. */ + inode->size = offset + n; + inode->dirty = 1; + } + if (verbose) + printf ("inode %d offset %ld: write %ld bytes to block %d\n", + inode->number, offset, n, bn); - if (n == BSDFS_BSIZE) { - if (! fs_write_block (inode->fs, bn, data)) - return 0; - } else { - if (! fs_read_block (inode->fs, bn, block)) - return 0; - memcpy (block + inblock_offset, data, n); - if (! fs_write_block (inode->fs, bn, block)) - return 0; - } - data += n; - offset += n; - bytes -= n; - } - return 1; + if (n == BSDFS_BSIZE) { + if (! fs_write_block (inode->fs, bn, data)) + return 0; + } else { + if (! fs_read_block (inode->fs, bn, block)) + return 0; + memcpy (block + inblock_offset, data, n); + if (! fs_write_block (inode->fs, bn, block)) + return 0; + } + data += n; + offset += n; + bytes -= n; + } + return 1; } /* @@ -505,20 +505,20 @@ int fs_inode_write (fs_inode_t *inode, unsigned long offset, */ void fs_dirent_pack (unsigned char *data, fs_dirent_t *dirent) { - int i; + int i; - *data++ = dirent->ino; - *data++ = dirent->ino >> 8; - *data++ = dirent->ino >> 16; - *data++ = dirent->ino >> 24; - *data++ = dirent->reclen; - *data++ = dirent->reclen >> 8; - *data++ = dirent->namlen; - *data++ = dirent->namlen >> 8; - for (i=0; dirent->name[i]; ++i) - *data++ = dirent->name[i]; - for (; i & 3; ++i) - *data++ = 0; + *data++ = dirent->ino; + *data++ = dirent->ino >> 8; + *data++ = dirent->ino >> 16; + *data++ = dirent->ino >> 24; + *data++ = dirent->reclen; + *data++ = dirent->reclen >> 8; + *data++ = dirent->namlen; + *data++ = dirent->namlen >> 8; + for (i=0; dirent->name[i]; ++i) + *data++ = dirent->name[i]; + for (; i & 3; ++i) + *data++ = 0; } /* @@ -526,16 +526,16 @@ void fs_dirent_pack (unsigned char *data, fs_dirent_t *dirent) */ void fs_dirent_unpack (fs_dirent_t *dirent, unsigned char *data) { - dirent->ino = *data++; - dirent->ino |= *data++ << 8; - dirent->ino |= *data++ << 16; - dirent->ino |= *data++ << 24; - dirent->reclen = *data++; - dirent->reclen |= *data++ << 8; - dirent->namlen = *data++; - dirent->namlen |= *data++ << 8; - memset (dirent->name, 0, sizeof (dirent->name)); - memcpy (dirent->name, data, dirent->namlen); + dirent->ino = *data++; + dirent->ino |= *data++ << 8; + dirent->ino |= *data++ << 16; + dirent->ino |= *data++ << 24; + dirent->reclen = *data++; + dirent->reclen |= *data++ << 8; + dirent->namlen = *data++; + dirent->namlen |= *data++ << 8; + memset (dirent->name, 0, sizeof (dirent->name)); + memcpy (dirent->name, data, dirent->namlen); } /* @@ -543,276 +543,276 @@ void fs_dirent_unpack (fs_dirent_t *dirent, unsigned char *data) * an inode. Note that the inode is locked. * * op = 0 if name is saught - * 1 if name is to be created, mode is given - * 2 if name is to be deleted - * 3 if name is to be linked, mode contains inode number + * 1 if name is to be created, mode is given + * 2 if name is to be deleted + * 3 if name is to be linked, mode contains inode number * * Return 0 on any error. * Return 1 when the inode was found. * Return 2 when the inode was created/deleted/linked. */ int fs_inode_by_name (fs_t *fs, fs_inode_t *inode, const char *name, - fs_op_t op, int mode) + fs_op_t op, int mode) { - fs_inode_t dir; - int c, namlen, reclen; - const char *namptr; - unsigned long offset, last_offset; - struct { + fs_inode_t dir; + int c, namlen, reclen; + const char *namptr; + unsigned long offset, last_offset; + struct { + unsigned int inum; + unsigned short reclen; + unsigned short namlen; + } dirent; + + /* Start from root. */ + if (! fs_inode_get (fs, &dir, BSDFS_ROOT_INODE)) { + fprintf (stderr, "inode_open(): cannot get root\n"); + return 0; + } + c = *name++; + while (c == '/') + c = *name++; + if (! c && op != INODE_OP_LOOKUP) { + /* Cannot write or delete root directory. */ + return 0; + } +cloop: + /* Here inode contains pointer + * to last component matched. */ + if (! c) { + *inode = dir; + return 1; + } + + /* If there is another component, + * inode must be a directory. */ + if ((dir.mode & INODE_MODE_FMT) != INODE_MODE_FDIR) { + return 0; + } + + /* Gather up dir name into buffer. */ + namptr = name - 1; + while (c && c != '/') { + c = *name++; + } + namlen = name - namptr - 1; + while (c == '/') + c = *name++; + + /* Search a directory, variable record per file */ + if (verbose > 2) + printf ("scan for '%.*s', %d bytes\n", namlen, namptr, namlen); + last_offset = 0; + for (offset = 0; offset < dir.size; last_offset = offset, offset += dirent.reclen) { + unsigned char fname [BSDFS_BSIZE - 12]; + + if (! fs_inode_read (&dir, offset, (unsigned char*) &dirent, sizeof(dirent))) { + fprintf (stderr, "inode %d: read error at offset %ld\n", + dir.number, offset); + return 0; + } + if (verbose > 2) + printf ("scan offset %lu: inum=%u, reclen=%u, namlen=%u\n", offset, dirent.inum, dirent.reclen, dirent.namlen); + if (dirent.inum == 0 || dirent.namlen != namlen) + continue; + if (! fs_inode_read (&dir, offset+sizeof(dirent), fname, namlen)) { + fprintf (stderr, "inode %d: name read error at offset %ld\n", + dir.number, offset); + return 0; + } + if (verbose > 2) + printf ("scan offset %lu: name='%.*s'\n", offset, namlen, fname); + if (strncmp (namptr, (char*) fname, namlen) == 0) { + /* Here a component matched in a directory. + * If there is more pathname, go back to + * cloop, otherwise return. */ + if (op == INODE_OP_DELETE && ! c) { + goto delete_file; + } + if (! fs_inode_get (fs, &dir, dirent.inum)) { + fprintf (stderr, "inode_open(): cannot get inode %d\n", dirent.inum); + return 0; + } + goto cloop; + } + } + /* If at the end of the directory, the search failed. + * Report what is appropriate as per flag. */ + if (op == INODE_OP_CREATE && ! c) + goto create_file; + if (op == INODE_OP_LINK && ! c) + goto create_link; + return 0; + + /* + * Make a new file, and return it's inode. + */ +create_file: + if (! fs_inode_alloc (fs, inode)) { + fprintf (stderr, "%s: cannot allocate inode\n", namptr); + return 0; + } + inode->dirty = 1; + inode->mode = mode & (07777 | INODE_MODE_FMT); + if ((inode->mode & INODE_MODE_FMT) == 0) + inode->mode |= INODE_MODE_FREG; + inode->nlink = 1; + inode->uid = 0; + inode->flags = 0; + time (&inode->ctime); + if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { + /* Make link '.' */ + struct { unsigned int inum; unsigned short reclen; unsigned short namlen; - } dirent; - - /* Start from root. */ - if (! fs_inode_get (fs, &dir, BSDFS_ROOT_INODE)) { - fprintf (stderr, "inode_open(): cannot get root\n"); - return 0; - } - c = *name++; - while (c == '/') - c = *name++; - if (! c && op != INODE_OP_LOOKUP) { - /* Cannot write or delete root directory. */ - return 0; - } -cloop: - /* Here inode contains pointer - * to last component matched. */ - if (! c) { - *inode = dir; - return 1; - } - - /* If there is another component, - * inode must be a directory. */ - if ((dir.mode & INODE_MODE_FMT) != INODE_MODE_FDIR) { - return 0; - } - - /* Gather up dir name into buffer. */ - namptr = name - 1; - while (c && c != '/') { - c = *name++; - } - namlen = name - namptr - 1; - while (c == '/') - c = *name++; - - /* Search a directory, variable record per file */ - if (verbose > 2) - printf ("scan for '%.*s', %d bytes\n", namlen, namptr, namlen); - last_offset = 0; - for (offset = 0; offset < dir.size; last_offset = offset, offset += dirent.reclen) { - unsigned char fname [BSDFS_BSIZE - 12]; - - if (! fs_inode_read (&dir, offset, (unsigned char*) &dirent, sizeof(dirent))) { - fprintf (stderr, "inode %d: read error at offset %ld\n", - dir.number, offset); - return 0; - } - if (verbose > 2) - printf ("scan offset %lu: inum=%u, reclen=%u, namlen=%u\n", offset, dirent.inum, dirent.reclen, dirent.namlen); - if (dirent.inum == 0 || dirent.namlen != namlen) - continue; - if (! fs_inode_read (&dir, offset+sizeof(dirent), fname, namlen)) { - fprintf (stderr, "inode %d: name read error at offset %ld\n", - dir.number, offset); - return 0; - } - if (verbose > 2) - printf ("scan offset %lu: name='%.*s'\n", offset, namlen, fname); - if (strncmp (namptr, (char*) fname, namlen) == 0) { - /* Here a component matched in a directory. - * If there is more pathname, go back to - * cloop, otherwise return. */ - if (op == INODE_OP_DELETE && ! c) { - goto delete_file; - } - if (! fs_inode_get (fs, &dir, dirent.inum)) { - fprintf (stderr, "inode_open(): cannot get inode %d\n", dirent.inum); - return 0; - } - goto cloop; - } - } - /* If at the end of the directory, the search failed. - * Report what is appropriate as per flag. */ - if (op == INODE_OP_CREATE && ! c) - goto create_file; - if (op == INODE_OP_LINK && ! c) - goto create_link; - return 0; - - /* - * Make a new file, and return it's inode. - */ -create_file: - if (! fs_inode_alloc (fs, inode)) { - fprintf (stderr, "%s: cannot allocate inode\n", namptr); - return 0; - } - inode->dirty = 1; - inode->mode = mode & (07777 | INODE_MODE_FMT); - if ((inode->mode & INODE_MODE_FMT) == 0) - inode->mode |= INODE_MODE_FREG; - inode->nlink = 1; - inode->uid = 0; - inode->flags = 0; - time (&inode->ctime); - if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { - /* Make link '.' */ - struct { - unsigned int inum; - unsigned short reclen; - unsigned short namlen; - char name [4]; - } dotent; - dotent.inum = inode->number; - dotent.reclen = BSDFS_BSIZE; - dotent.namlen = 1; - memcpy (dotent.name, ".\0\0\0", 4); - if (! fs_inode_write (inode, 0, (unsigned char*) &dotent, sizeof(dotent))) { - fprintf (stderr, "inode %d: write error at offset %ld\n", - inode->number, 0L); - return 0; - } - /* Increase file size. */ - inode->size = BSDFS_BSIZE; - ++inode->nlink; + char name [4]; + } dotent; + dotent.inum = inode->number; + dotent.reclen = BSDFS_BSIZE; + dotent.namlen = 1; + memcpy (dotent.name, ".\0\0\0", 4); + if (! fs_inode_write (inode, 0, (unsigned char*) &dotent, sizeof(dotent))) { + fprintf (stderr, "inode %d: write error at offset %ld\n", + inode->number, 0L); + return 0; } - if (! fs_inode_save (inode, 0)) { - fprintf (stderr, "%s: cannot save file inode\n", namptr); - return 0; - } + /* Increase file size. */ + inode->size = BSDFS_BSIZE; + ++inode->nlink; + } + if (! fs_inode_save (inode, 0)) { + fprintf (stderr, "%s: cannot save file inode\n", namptr); + return 0; + } - /* Write a directory entry. */ - if (verbose > 2) - printf ("*** create file '%.*s', inode %d\n", namlen, namptr, inode->number); - reclen = dirent.reclen - 8 - (dirent.namlen + 4) / 4 * 4; - c = 8 + (namlen + 4) / 4 * 4; - if (reclen >= c) { - /* Enough space */ - dirent.reclen -= reclen; - if (verbose > 2) - printf ("*** previous entry %u-%u-%u at offset %lu\n", - dirent.inum, dirent.reclen, dirent.namlen, last_offset); - if (! fs_inode_write (&dir, last_offset, (unsigned char*) &dirent, sizeof(dirent))) { - fprintf (stderr, "inode %d: write error at offset %ld\n", - dir.number, last_offset); - return 0; - } - } else { - /* No space, extend directory. */ - if (verbose > 2) - printf ("*** extend dir, previous entry %u-%u-%u at offset %lu\n", - dirent.inum, dirent.reclen, dirent.namlen, last_offset); - reclen = BSDFS_BSIZE; - } - offset = last_offset + dirent.reclen; - dirent.inum = inode->number; - dirent.reclen = reclen; - dirent.namlen = namlen; - if (verbose > 2) - printf ("*** new entry %u-%u-%u at offset %lu\n", dirent.inum, dirent.reclen, dirent.namlen, offset); - if (! fs_inode_write (&dir, offset, (unsigned char*) &dirent, sizeof(dirent))) { - fprintf (stderr, "inode %d: write error at offset %ld\n", - dir.number, offset); - return 0; - } - if (verbose > 2) - printf ("*** name '%.*s' at offset %lu\n", namlen, namptr, offset+sizeof(dirent)); - if (! fs_inode_write (&dir, offset+sizeof(dirent), (unsigned char*) namptr, namlen)) { - fprintf (stderr, "inode %d: write error at offset %ld\n", - dir.number, offset+sizeof(dirent)); - return 0; - } - /* Align directory size. */ - dir.size = (dir.size + BSDFS_BSIZE - 1) / BSDFS_BSIZE * BSDFS_BSIZE; - if (! fs_inode_save (&dir, 0)) { - fprintf (stderr, "%s: cannot save directory inode\n", namptr); - return 0; - } - return 2; - - /* - * Delete file. Return inode of deleted file. - */ -delete_file: - if (verbose > 2) - printf ("*** delete inode %d\n", dirent.inum); - if (! fs_inode_get (fs, inode, dirent.inum)) { - fprintf (stderr, "%s: cannot get inode %d\n", namptr, dirent.inum); - return 0; - } - inode->dirty = 1; - inode->nlink--; - if (inode->nlink <= 0) { - fs_inode_truncate (inode, 0); - fs_inode_clear (inode); - if (inode->fs->ninode < NICINOD) { - inode->fs->inode [inode->fs->ninode++] = dirent.inum; - inode->fs->dirty = 1; - } - } - /* Extend previous entry to cover the empty space. */ - reclen = dirent.reclen; - if (! fs_inode_read (&dir, last_offset, (unsigned char*) &dirent, sizeof(dirent))) { - fprintf (stderr, "inode %d: read error at offset %ld\n", - dir.number, last_offset); - return 0; - } - dirent.reclen += reclen; - if (! fs_inode_write (&dir, last_offset, (unsigned char*) &dirent, sizeof(dirent))) { - fprintf (stderr, "inode %d: write error at offset %ld\n", - dir.number, last_offset); - return 0; - } - if (! fs_inode_save (&dir, 0)) { - fprintf (stderr, "%s: cannot save directory inode\n", namptr); - return 0; - } - return 2; - - /* - * Make a link. Return a directory inode. - */ -create_link: - if (verbose > 2) - printf ("*** link inode %d to '%.*s', directory %d\n", mode, namlen, namptr, dir.number); - reclen = dirent.reclen - 8 - (dirent.namlen + 4) / 4 * 4; + /* Write a directory entry. */ + if (verbose > 2) + printf ("*** create file '%.*s', inode %d\n", namlen, namptr, inode->number); + reclen = dirent.reclen - 8 - (dirent.namlen + 4) / 4 * 4; + c = 8 + (namlen + 4) / 4 * 4; + if (reclen >= c) { + /* Enough space */ dirent.reclen -= reclen; if (verbose > 2) - printf ("*** previous entry %u-%u-%u at offset %lu\n", dirent.inum, dirent.reclen, dirent.namlen, last_offset); - if (! fs_inode_write (&dir, last_offset, (unsigned char*) &dirent, sizeof(dirent))) { - fprintf (stderr, "inode %d: write error at offset %ld\n", - dir.number, last_offset); - return 0; - } - offset = last_offset + dirent.reclen; - dirent.inum = mode; - dirent.reclen = reclen; - dirent.namlen = namlen; + printf ("*** previous entry %u-%u-%u at offset %lu\n", + dirent.inum, dirent.reclen, dirent.namlen, last_offset); + if (! fs_inode_write (&dir, last_offset, (unsigned char*) &dirent, sizeof(dirent))) { + fprintf (stderr, "inode %d: write error at offset %ld\n", + dir.number, last_offset); + return 0; + } + } else { + /* No space, extend directory. */ if (verbose > 2) - printf ("*** new entry %u-%u-%u at offset %lu\n", dirent.inum, dirent.reclen, dirent.namlen, offset); - if (! fs_inode_write (&dir, offset, (unsigned char*) &dirent, sizeof(dirent))) { - fprintf (stderr, "inode %d: write error at offset %ld\n", - dir.number, offset); - return 0; - } - if (verbose > 2) - printf ("*** name '%.*s' at offset %lu\n", namlen, namptr, offset+sizeof(dirent)); - if (! fs_inode_write (&dir, offset+sizeof(dirent), (unsigned char*) namptr, namlen)) { - fprintf (stderr, "inode %d: write error at offset %ld\n", - dir.number, offset+sizeof(dirent)); - return 0; - } - if (! fs_inode_save (&dir, 0)) { - fprintf (stderr, "%s: cannot save directory inode\n", namptr); - return 0; - } - *inode = dir; - return 2; + printf ("*** extend dir, previous entry %u-%u-%u at offset %lu\n", + dirent.inum, dirent.reclen, dirent.namlen, last_offset); + reclen = BSDFS_BSIZE; + } + offset = last_offset + dirent.reclen; + dirent.inum = inode->number; + dirent.reclen = reclen; + dirent.namlen = namlen; + if (verbose > 2) + printf ("*** new entry %u-%u-%u at offset %lu\n", dirent.inum, dirent.reclen, dirent.namlen, offset); + if (! fs_inode_write (&dir, offset, (unsigned char*) &dirent, sizeof(dirent))) { + fprintf (stderr, "inode %d: write error at offset %ld\n", + dir.number, offset); + return 0; + } + if (verbose > 2) + printf ("*** name '%.*s' at offset %lu\n", namlen, namptr, offset+sizeof(dirent)); + if (! fs_inode_write (&dir, offset+sizeof(dirent), (unsigned char*) namptr, namlen)) { + fprintf (stderr, "inode %d: write error at offset %ld\n", + dir.number, offset+sizeof(dirent)); + return 0; + } + /* Align directory size. */ + dir.size = (dir.size + BSDFS_BSIZE - 1) / BSDFS_BSIZE * BSDFS_BSIZE; + if (! fs_inode_save (&dir, 0)) { + fprintf (stderr, "%s: cannot save directory inode\n", namptr); + return 0; + } + return 2; + + /* + * Delete file. Return inode of deleted file. + */ +delete_file: + if (verbose > 2) + printf ("*** delete inode %d\n", dirent.inum); + if (! fs_inode_get (fs, inode, dirent.inum)) { + fprintf (stderr, "%s: cannot get inode %d\n", namptr, dirent.inum); + return 0; + } + inode->dirty = 1; + inode->nlink--; + if (inode->nlink <= 0) { + fs_inode_truncate (inode, 0); + fs_inode_clear (inode); + if (inode->fs->ninode < NICINOD) { + inode->fs->inode [inode->fs->ninode++] = dirent.inum; + inode->fs->dirty = 1; + } + } + /* Extend previous entry to cover the empty space. */ + reclen = dirent.reclen; + if (! fs_inode_read (&dir, last_offset, (unsigned char*) &dirent, sizeof(dirent))) { + fprintf (stderr, "inode %d: read error at offset %ld\n", + dir.number, last_offset); + return 0; + } + dirent.reclen += reclen; + if (! fs_inode_write (&dir, last_offset, (unsigned char*) &dirent, sizeof(dirent))) { + fprintf (stderr, "inode %d: write error at offset %ld\n", + dir.number, last_offset); + return 0; + } + if (! fs_inode_save (&dir, 0)) { + fprintf (stderr, "%s: cannot save directory inode\n", namptr); + return 0; + } + return 2; + + /* + * Make a link. Return a directory inode. + */ +create_link: + if (verbose > 2) + printf ("*** link inode %d to '%.*s', directory %d\n", mode, namlen, namptr, dir.number); + reclen = dirent.reclen - 8 - (dirent.namlen + 4) / 4 * 4; + dirent.reclen -= reclen; + if (verbose > 2) + printf ("*** previous entry %u-%u-%u at offset %lu\n", dirent.inum, dirent.reclen, dirent.namlen, last_offset); + if (! fs_inode_write (&dir, last_offset, (unsigned char*) &dirent, sizeof(dirent))) { + fprintf (stderr, "inode %d: write error at offset %ld\n", + dir.number, last_offset); + return 0; + } + offset = last_offset + dirent.reclen; + dirent.inum = mode; + dirent.reclen = reclen; + dirent.namlen = namlen; + if (verbose > 2) + printf ("*** new entry %u-%u-%u at offset %lu\n", dirent.inum, dirent.reclen, dirent.namlen, offset); + if (! fs_inode_write (&dir, offset, (unsigned char*) &dirent, sizeof(dirent))) { + fprintf (stderr, "inode %d: write error at offset %ld\n", + dir.number, offset); + return 0; + } + if (verbose > 2) + printf ("*** name '%.*s' at offset %lu\n", namlen, namptr, offset+sizeof(dirent)); + if (! fs_inode_write (&dir, offset+sizeof(dirent), (unsigned char*) namptr, namlen)) { + fprintf (stderr, "inode %d: write error at offset %ld\n", + dir.number, offset+sizeof(dirent)); + return 0; + } + if (! fs_inode_save (&dir, 0)) { + fprintf (stderr, "%s: cannot save directory inode\n", namptr); + return 0; + } + *inode = dir; + return 2; } /* @@ -824,30 +824,30 @@ create_link: */ int fs_inode_alloc (fs_t *fs, fs_inode_t *inode) { - int ino; + int ino; - for (;;) { - if (fs->ninode <= 0) { - /* Build a list of free inodes. */ - if (! inode_build_list (fs)) { - fprintf (stderr, "inode_alloc: cannot build inode list\n"); - return 0; - } - if (fs->ninode <= 0) { - fprintf (stderr, "inode_alloc: out of in-core inodes\n"); - return 0; - } - } - ino = fs->inode[--fs->ninode]; - fs->dirty = 1; - fs->tinode--; - if (! fs_inode_get (fs, inode, ino)) { - fprintf (stderr, "inode_alloc: cannot get inode %d\n", ino); - return 0; - } - if (inode->mode == 0) { - fs_inode_clear (inode); - return 1; - } - } + for (;;) { + if (fs->ninode <= 0) { + /* Build a list of free inodes. */ + if (! inode_build_list (fs)) { + fprintf (stderr, "inode_alloc: cannot build inode list\n"); + return 0; + } + if (fs->ninode <= 0) { + fprintf (stderr, "inode_alloc: out of in-core inodes\n"); + return 0; + } + } + ino = fs->inode[--fs->ninode]; + fs->dirty = 1; + fs->tinode--; + if (! fs_inode_get (fs, inode, ino)) { + fprintf (stderr, "inode_alloc: cannot get inode %d\n", ino); + return 0; + } + if (inode->mode == 0) { + fs_inode_clear (inode); + return 1; + } + } } diff --git a/tools/fsutil/superblock.c b/tools/fsutil/superblock.c index aa1d373..cc96ef7 100644 --- a/tools/fsutil/superblock.c +++ b/tools/fsutil/superblock.c @@ -32,298 +32,300 @@ extern int verbose; int fs_seek (fs_t *fs, unsigned long offset) { -/* printf ("seek %ld, block %ld\n", offset, offset / BSDFS_BSIZE);*/ - if (lseek (fs->fd, offset, 0) < 0) { - if (verbose) - printf ("error seeking %ld, block %ld\n", - offset, offset / BSDFS_BSIZE); - return 0; - } - fs->seek = offset; - return 1; +/* printf ("seek %ld, block %ld\n", offset, offset / BSDFS_BSIZE);*/ + if (lseek (fs->fd, offset, 0) < 0) { + if (verbose) + printf ("error seeking %ld, block %ld\n", + offset, offset / BSDFS_BSIZE); + return 0; + } + fs->seek = offset; + return 1; } int fs_read8 (fs_t *fs, unsigned char *val) { - if (read (fs->fd, val, 1) != 1) { - if (verbose) - printf ("error read8, seek %ld block %ld\n", fs->seek, fs->seek / BSDFS_BSIZE); - return 0; - } - return 1; + if (read (fs->fd, val, 1) != 1) { + if (verbose) + printf ("error read8, seek %ld block %ld\n", fs->seek, fs->seek / BSDFS_BSIZE); + return 0; + } + return 1; } int fs_read16 (fs_t *fs, unsigned short *val) { - unsigned char data [2]; + unsigned char data [2]; - if (read (fs->fd, data, 2) != 2) { - if (verbose) - printf ("error read16, seek %ld block %ld\n", fs->seek, fs->seek / BSDFS_BSIZE); - return 0; - } - *val = data[1] << 8 | data[0]; - return 1; + if (read (fs->fd, data, 2) != 2) { + if (verbose) + printf ("error read16, seek %ld block %ld\n", fs->seek, fs->seek / BSDFS_BSIZE); + return 0; + } + *val = data[1] << 8 | data[0]; + return 1; } int fs_read32 (fs_t *fs, unsigned *val) { - unsigned char data [4]; + unsigned char data [4]; - if (read (fs->fd, data, 4) != 4) { - if (verbose) - printf ("error read32, seek %ld block %ld\n", fs->seek, fs->seek / BSDFS_BSIZE); - return 0; - } - *val = (unsigned long) data[0] | (unsigned long) data[1] << 8 | - data[2] << 16 | data[3] << 24; - return 1; + if (read (fs->fd, data, 4) != 4) { + if (verbose) + printf ("error read32, seek %ld block %ld\n", fs->seek, fs->seek / BSDFS_BSIZE); + return 0; + } + *val = (unsigned long) data[0] | (unsigned long) data[1] << 8 | + data[2] << 16 | data[3] << 24; + return 1; } int fs_write8 (fs_t *fs, unsigned char val) { - if (write (fs->fd, &val, 1) != 1) - return 0; - return 1; + if (write (fs->fd, &val, 1) != 1) + return 0; + return 1; } int fs_write16 (fs_t *fs, unsigned short val) { - unsigned char data [2]; + unsigned char data [2]; - data[0] = val; - data[1] = val >> 8; - if (write (fs->fd, data, 2) != 2) - return 0; - return 1; + data[0] = val; + data[1] = val >> 8; + if (write (fs->fd, data, 2) != 2) + return 0; + return 1; } int fs_write32 (fs_t *fs, unsigned val) { - unsigned char data [4]; + unsigned char data [4]; - data[0] = val; - data[1] = val >> 8; - data[2] = val >> 16; - data[3] = val >> 24; - if (write (fs->fd, data, 4) != 4) - return 0; - return 1; + data[0] = val; + data[1] = val >> 8; + data[2] = val >> 16; + data[3] = val >> 24; + if (write (fs->fd, data, 4) != 4) + return 0; + return 1; } int fs_read (fs_t *fs, unsigned char *data, int bytes) { - int len; + int len; - while (bytes > 0) { - len = bytes; - if (len > 16*BSDFS_BSIZE) - len = 16*BSDFS_BSIZE; - if (read (fs->fd, data, len) != len) - return 0; - data += len; - bytes -= len; - } - return 1; + while (bytes > 0) { + len = bytes; + if (len > 16*BSDFS_BSIZE) + len = 16*BSDFS_BSIZE; + if (read (fs->fd, data, len) != len) + return 0; + data += len; + bytes -= len; + } + return 1; } int fs_write (fs_t *fs, unsigned char *data, int bytes) { - int len; + int len; - if (! fs->writable) - return 0; - while (bytes > 0) { - len = bytes; - if (len > 16*BSDFS_BSIZE) - len = 16*BSDFS_BSIZE; - if (write (fs->fd, data, len) != len) - return 0; - data += len; - bytes -= len; - } - return 1; + if (! fs->writable) + return 0; + while (bytes > 0) { + len = bytes; + if (len > 16*BSDFS_BSIZE) + len = 16*BSDFS_BSIZE; + if (write (fs->fd, data, len) != len) + return 0; + data += len; + bytes -= len; + } + return 1; } int fs_open (fs_t *fs, const char *filename, int writable) { - int i; - unsigned magic; + int i; + unsigned magic; - memset (fs, 0, sizeof (*fs)); - fs->filename = filename; - fs->seek = 0; + memset (fs, 0, sizeof (*fs)); + fs->filename = filename; + fs->seek = 0; - fs->fd = open (fs->filename, writable ? O_RDWR : O_RDONLY); - if (fs->fd < 0) - return 0; - fs->writable = writable; + fs->fd = open (fs->filename, writable ? O_RDWR : O_RDONLY); + if (fs->fd < 0) + return 0; + fs->writable = writable; - if (! fs_read32 (fs, &magic) || /* magic word */ - magic != FSMAGIC1) { - if (verbose) - printf ("fs_open: bad magic1 = %08x, expected %08x\n", - magic, FSMAGIC1); - return 0; - } - if (! fs_read32 (fs, &fs->isize)) /* size in blocks of I list */ - return 0; - if (! fs_read32 (fs, &fs->fsize)) /* size in blocks of entire volume */ - return 0; - if (! fs_read32 (fs, &fs->swapsz)) /* size in blocks of swap area */ - return 0; - if (! fs_read32 (fs, &fs->nfree)) /* number of in core free blocks */ - return 0; - for (i=0; ifree[i])) - return 0; - } - if (! fs_read32 (fs, &fs->ninode)) /* number of in core I nodes */ - return 0; - for (i=0; iinode[i])) - return 0; - } - if (! fs_read32 (fs, &fs->flock)) - return 0; - if (! fs_read32 (fs, &fs->fmod)) - return 0; - if (! fs_read32 (fs, &fs->ilock)) - return 0; - if (! fs_read32 (fs, &fs->ronly)) - return 0; - if (! fs_read32 (fs, (unsigned*) &fs->utime)) - return 0; /* current date of last update */ - if (! fs_read32 (fs, &fs->tfree)) /* total free blocks */ - return 0; - if (! fs_read32 (fs, &fs->tinode)) /* total free inodes */ - return 0; - if (! fs_read (fs, (unsigned char*) fs->fsmnt, MAXMNTLEN)) - return 0; /* ordinary file mounted on */ - if (! fs_read32 (fs, &fs->lasti)) /* start place for circular search */ - return 0; - if (! fs_read32 (fs, &fs->nbehind)) /* est # free inodes before s_lasti */ - return 0; - if (! fs_read32 (fs, &fs->flags)) /* mount time flags */ - return 0; - if (! fs_read32 (fs, &magic) || /* magic word */ - magic != FSMAGIC2) { - if (verbose) - printf ("fs_open: bad magic2 = %08x, expected %08x\n", - magic, FSMAGIC2); - return 0; - } - return 1; + if (! fs_read32 (fs, &magic) || /* magic word */ + magic != FSMAGIC1) { + if (verbose) + printf ("fs_open: bad magic1 = %08x, expected %08x\n", + magic, FSMAGIC1); + return 0; + } + if (! fs_read32 (fs, &fs->isize)) /* size in blocks of I list */ + return 0; + if (! fs_read32 (fs, &fs->fsize)) /* size in blocks of entire volume */ + return 0; + if (! fs_read32 (fs, &fs->swapsz)) /* size in blocks of swap area */ + return 0; + if (! fs_read32 (fs, &fs->nfree)) /* number of in core free blocks */ + return 0; + for (i=0; ifree[i])) + return 0; + } + if (! fs_read32 (fs, &fs->ninode)) /* number of in core I nodes */ + return 0; + for (i=0; iinode[i])) + return 0; + } + if (! fs_read32 (fs, &fs->flock)) + return 0; + if (! fs_read32 (fs, &fs->fmod)) + return 0; + if (! fs_read32 (fs, &fs->ilock)) + return 0; + if (! fs_read32 (fs, &fs->ronly)) + return 0; + if (! fs_read32 (fs, (unsigned*) &fs->utime)) + return 0; /* current date of last update */ + if (! fs_read32 (fs, &fs->tfree)) /* total free blocks */ + return 0; + if (! fs_read32 (fs, &fs->tinode)) /* total free inodes */ + return 0; + if (! fs_read (fs, (unsigned char*) fs->fsmnt, MAXMNTLEN)) + return 0; /* ordinary file mounted on */ + if (! fs_read32 (fs, &fs->lasti)) /* start place for circular search */ + return 0; + if (! fs_read32 (fs, &fs->nbehind)) /* est # free inodes before s_lasti */ + return 0; + if (! fs_read32 (fs, &fs->flags)) /* mount time flags */ + return 0; + if (! fs_read32 (fs, &magic) || /* magic word */ + magic != FSMAGIC2) { + if (verbose) + printf ("fs_open: bad magic2 = %08x, expected %08x\n", + magic, FSMAGIC2); + return 0; + } + return 1; } int fs_sync (fs_t *fs, int force) { - int i; + int i; - if (! fs->writable) - return 0; - if (! force && ! fs->dirty) - return 1; + if (! fs->writable) + return 0; + if (! force && ! fs->dirty) + return 1; - time (&fs->utime); - if (! fs_seek (fs, 0)) - return 0; + time (&fs->utime); + if (! fs_seek (fs, 0)) + return 0; - if (! fs_write32 (fs, FSMAGIC1)) /* magic word */ - return 0; - if (! fs_write32 (fs, fs->isize)) /* size in blocks of I list */ - return 0; - if (! fs_write32 (fs, fs->fsize)) /* size in blocks of entire volume */ - return 0; - if (! fs_write32 (fs, fs->swapsz)) /* size in blocks of swap area */ - return 0; - if (! fs_write32 (fs, fs->nfree)) /* number of in core free blocks */ - return 0; - for (i=0; ifree[i])) - return 0; - } - if (! fs_write32 (fs, fs->ninode)) /* number of in core I nodes */ - return 0; - for (i=0; iinode[i])) - return 0; - } - if (! fs_write32 (fs, fs->flock)) - return 0; - if (! fs_write32 (fs, fs->fmod)) - return 0; - if (! fs_write32 (fs, fs->ilock)) - return 0; - if (! fs_write32 (fs, fs->ronly)) - return 0; - if (! fs_write32 (fs, fs->utime)) /* current date of last update */ - return 0; - if (! fs_write32 (fs, fs->tfree)) /* total free blocks */ - return 0; - if (! fs_write32 (fs, fs->tinode)) /* total free inodes */ - return 0; - if (! fs_write (fs, (unsigned char*) fs->fsmnt, MAXMNTLEN)) - return 0; /* ordinary file mounted on */ - if (! fs_write32 (fs, 0)) /* lasti*/ - return 0; - if (! fs_write32 (fs, 0)) /* nbehind */ - return 0; - if (! fs_write32 (fs, 0)) /* flags */ - return 0; - if (! fs_write32 (fs, FSMAGIC2)) /* magic word */ - return 0; - fs->dirty = 0; - return 1; + if (! fs_write32 (fs, FSMAGIC1)) /* magic word */ + return 0; + if (! fs_write32 (fs, fs->isize)) /* size in blocks of I list */ + return 0; + if (! fs_write32 (fs, fs->fsize)) /* size in blocks of entire volume */ + return 0; + if (! fs_write32 (fs, fs->swapsz)) /* size in blocks of swap area */ + return 0; + if (! fs_write32 (fs, fs->nfree)) /* number of in core free blocks */ + return 0; + for (i=0; ifree[i])) + return 0; + } + if (! fs_write32 (fs, fs->ninode)) /* number of in core I nodes */ + return 0; + for (i=0; iinode[i])) + return 0; + } + if (! fs_write32 (fs, fs->flock)) + return 0; + if (! fs_write32 (fs, fs->fmod)) + return 0; + if (! fs_write32 (fs, fs->ilock)) + return 0; + if (! fs_write32 (fs, fs->ronly)) + return 0; + if (! fs_write32 (fs, fs->utime)) /* current date of last update */ + return 0; + if (! fs_write32 (fs, fs->tfree)) /* total free blocks */ + return 0; + if (! fs_write32 (fs, fs->tinode)) /* total free inodes */ + return 0; + if (! fs_write (fs, (unsigned char*) fs->fsmnt, MAXMNTLEN)) + return 0; /* ordinary file mounted on */ + if (! fs_write32 (fs, 0)) /* lasti*/ + return 0; + if (! fs_write32 (fs, 0)) /* nbehind */ + return 0; + if (! fs_write32 (fs, 0)) /* flags */ + return 0; + if (! fs_write32 (fs, FSMAGIC2)) /* magic word */ + return 0; + fs->dirty = 0; + return 1; } void fs_print (fs_t *fs, FILE *out) { - int i; + int i; - fprintf (out, " File: %s\n", fs->filename); - fprintf (out, " Volume size: %u blocks\n", fs->fsize); - fprintf (out, " Inode list size: %u blocks\n", fs->isize); - fprintf (out, " Swap size: %u blocks\n", fs->swapsz); - fprintf (out, " Total free blocks: %u blocks\n", fs->tfree); - fprintf (out, " Total free inodes: %u inodes\n", fs->tinode); - fprintf (out, " Last mounted on: %.*s\n", MAXMNTLEN, - fs->fsmnt[0] ? fs->fsmnt : "(none)"); - fprintf (out, " In-core free list: %u blocks", fs->nfree); - if (verbose) - for (i=0; i < NICFREE && i < fs->nfree; ++i) { - if (i % 10 == 0) - fprintf (out, "\n "); - fprintf (out, " %u", fs->free[i]); - } - fprintf (out, "\n"); + fprintf (out, " File: %s\n", fs->filename); + fprintf (out, " Volume size: %u blocks\n", fs->fsize); + fprintf (out, " Inode list size: %u blocks\n", fs->isize); + fprintf (out, " Swap size: %u blocks\n", fs->swapsz); + fprintf (out, " Total free blocks: %u blocks\n", fs->tfree); + fprintf (out, " Total free inodes: %u inodes\n", fs->tinode); + fprintf (out, " Last mounted on: %.*s\n", MAXMNTLEN, + fs->fsmnt[0] ? fs->fsmnt : "(none)"); + fprintf (out, " In-core free list: %u blocks", fs->nfree); + if (verbose) { + for (i=0; i < NICFREE && i < fs->nfree; ++i) { + if (i % 10 == 0) + fprintf (out, "\n "); + fprintf (out, " %u", fs->free[i]); + } + } + fprintf (out, "\n"); - fprintf (out, " In-core free inodes: %u inodes", fs->ninode); - if (verbose) - for (i=0; i < NICINOD && i < fs->ninode; ++i) { - if (i % 10 == 0) - fprintf (out, "\n "); - fprintf (out, " %u", fs->inode[i]); - } - fprintf (out, "\n"); - if (verbose) { -// fprintf (out, " Free list lock: %u\n", fs->flock); -// fprintf (out, " Inode list lock: %u\n", fs->ilock); -// fprintf (out, "Super block modified: %u\n", fs->fmod); -// fprintf (out, " Mounted read-only: %u\n", fs->ronly); -// fprintf (out, " Circ.search start: %u\n", fs->lasti); -// fprintf (out, " Circ.search behind: %u\n", fs->nbehind); -// fprintf (out, " Mount flags: 0x%x\n", fs->flags); - } + fprintf (out, " In-core free inodes: %u inodes", fs->ninode); + if (verbose) { + for (i=0; i < NICINOD && i < fs->ninode; ++i) { + if (i % 10 == 0) + fprintf (out, "\n "); + fprintf (out, " %u", fs->inode[i]); + } + } + fprintf (out, "\n"); + if (verbose) { +// fprintf (out, " Free list lock: %u\n", fs->flock); +// fprintf (out, " Inode list lock: %u\n", fs->ilock); +// fprintf (out, "Super block modified: %u\n", fs->fmod); +// fprintf (out, " Mounted read-only: %u\n", fs->ronly); +// fprintf (out, " Circ.search start: %u\n", fs->lasti); +// fprintf (out, " Circ.search behind: %u\n", fs->nbehind); +// fprintf (out, " Mount flags: 0x%x\n", fs->flags); + } - fprintf (out, " Last update time: %s", ctime (&fs->utime)); + fprintf (out, " Last update time: %s", ctime (&fs->utime)); } void fs_close (fs_t *fs) { - if (fs->fd < 0) - return; + if (fs->fd < 0) + return; - close (fs->fd); - fs->fd = -1; + close (fs->fd); + fs->fd = -1; }