Fsutil: sources reformatted to 4-space indents.

This commit is contained in:
Serge Vakulenko
2014-07-31 18:37:15 -07:00
parent 4d8233582a
commit c2b3647d5e
8 changed files with 2609 additions and 2604 deletions

View File

@@ -28,29 +28,29 @@ extern int verbose;
int fs_read_block (fs_t *fs, unsigned bnum, unsigned char *data) int fs_read_block (fs_t *fs, unsigned bnum, unsigned char *data)
{ {
if (verbose > 3) if (verbose > 3)
printf ("read block %d\n", bnum); printf ("read block %d\n", bnum);
if (bnum < fs->isize) if (bnum < fs->isize)
return 0; return 0;
if (! fs_seek (fs, bnum * BSDFS_BSIZE)) if (! fs_seek (fs, bnum * BSDFS_BSIZE))
return 0; return 0;
if (! fs_read (fs, data, BSDFS_BSIZE)) if (! fs_read (fs, data, BSDFS_BSIZE))
return 0; return 0;
return 1; return 1;
} }
int fs_write_block (fs_t *fs, unsigned bnum, unsigned char *data) int fs_write_block (fs_t *fs, unsigned bnum, unsigned char *data)
{ {
if (verbose > 3) if (verbose > 3)
printf ("write block %d\n", bnum); printf ("write block %d\n", bnum);
if (! fs->writable || bnum < fs->isize) if (! fs->writable || bnum < fs->isize)
return 0; return 0;
if (! fs_seek (fs, bnum * BSDFS_BSIZE)) if (! fs_seek (fs, bnum * BSDFS_BSIZE))
return 0; return 0;
if (! fs_write (fs, data, BSDFS_BSIZE)) if (! fs_write (fs, data, BSDFS_BSIZE))
return 0; return 0;
fs->modified = 1; fs->modified = 1;
return 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 fs_block_free (fs_t *fs, unsigned int bno)
{ {
int i; int i;
unsigned buf [BSDFS_BSIZE / 4]; unsigned buf [BSDFS_BSIZE / 4];
if (verbose > 1) if (verbose > 1)
printf ("free block %d, total %d\n", bno, fs->nfree); printf ("free block %d, total %d\n", bno, fs->nfree);
if (fs->nfree >= NICFREE) { if (fs->nfree >= NICFREE) {
buf[0] = fs->nfree; buf[0] = fs->nfree;
for (i=0; i<NICFREE; i++) for (i=0; i<NICFREE; i++)
buf[i+1] = fs->free[i]; buf[i+1] = fs->free[i];
if (! fs_write_block (fs, bno, (unsigned char*) buf)) { if (! fs_write_block (fs, bno, (unsigned char*) buf)) {
fprintf (stderr, "block_free: write error at block %d\n", bno); fprintf (stderr, "block_free: write error at block %d\n", bno);
return 0; return 0;
} }
fs->nfree = 0; fs->nfree = 0;
} }
fs->free [fs->nfree] = bno; fs->free [fs->nfree] = bno;
fs->nfree++; fs->nfree++;
fs->dirty = 1; fs->dirty = 1;
if (bno) /* Count total free blocks. */ if (bno) /* Count total free blocks. */
++fs->tfree; ++fs->tfree;
return 1; 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) int fs_indirect_block_free (fs_t *fs, unsigned int bno, int nblk)
{ {
unsigned nb; unsigned nb;
unsigned char data [BSDFS_BSIZE]; unsigned char data [BSDFS_BSIZE];
int i; int i;
if (! fs_read_block (fs, bno, data)) { if (! fs_read_block (fs, bno, data)) {
fprintf (stderr, "inode_clear: read error at block %d\n", bno); fprintf (stderr, "inode_clear: read error at block %d\n", bno);
return 0; return 0;
} }
for (i=BSDFS_BSIZE-4; i>=0; i-=4) { for (i=BSDFS_BSIZE-4; i>=0; i-=4) {
if (i/4 < nblk) { if (i/4 < nblk) {
/* Truncate up to required size. */ /* Truncate up to required size. */
return 0; return 0;
} }
nb = data [i+3] << 24 | data [i+2] << 16 | nb = data [i+3] << 24 | data [i+2] << 16 |
data [i+1] << 8 | data [i]; data [i+1] << 8 | data [i];
if (nb) if (nb)
fs_block_free (fs, nb); fs_block_free (fs, nb);
} }
fs_block_free (fs, bno); fs_block_free (fs, bno);
return 1; 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) int fs_double_indirect_block_free (fs_t *fs, unsigned int bno, int nblk)
{ {
unsigned nb; unsigned nb;
unsigned char data [BSDFS_BSIZE]; unsigned char data [BSDFS_BSIZE];
int i; int i;
if (! fs_read_block (fs, bno, data)) { if (! fs_read_block (fs, bno, data)) {
fprintf (stderr, "inode_clear: read error at block %d\n", bno); fprintf (stderr, "inode_clear: read error at block %d\n", bno);
return 0; return 0;
} }
for (i=BSDFS_BSIZE-4; i>=0; i-=4) { for (i=BSDFS_BSIZE-4; i>=0; i-=4) {
if (i/4 * BSDFS_BSIZE/4 < nblk) { if (i/4 * BSDFS_BSIZE/4 < nblk) {
/* Truncate up to required size. */ /* Truncate up to required size. */
return 0; return 0;
} }
nb = data [i+3] << 24 | data [i+2] << 16 | nb = data [i+3] << 24 | data [i+2] << 16 |
data [i+1] << 8 | data [i]; data [i+1] << 8 | data [i];
if (nb) if (nb)
fs_indirect_block_free (fs, nb, fs_indirect_block_free (fs, nb,
nblk - i/4 * BSDFS_BSIZE/4); nblk - i/4 * BSDFS_BSIZE/4);
} }
fs_block_free (fs, bno); fs_block_free (fs, bno);
return 1; 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) int fs_triple_indirect_block_free (fs_t *fs, unsigned int bno, int nblk)
{ {
unsigned nb; unsigned nb;
unsigned char data [BSDFS_BSIZE]; unsigned char data [BSDFS_BSIZE];
int i; int i;
if (! fs_read_block (fs, bno, data)) { if (! fs_read_block (fs, bno, data)) {
fprintf (stderr, "inode_clear: read error at block %d\n", bno); fprintf (stderr, "inode_clear: read error at block %d\n", bno);
return 0; return 0;
} }
for (i=BSDFS_BSIZE-4; i>=0; i-=4) { for (i=BSDFS_BSIZE-4; i>=0; i-=4) {
if (i/4 * BSDFS_BSIZE/4 * BSDFS_BSIZE/4 < nblk) { if (i/4 * BSDFS_BSIZE/4 * BSDFS_BSIZE/4 < nblk) {
/* Truncate up to required size. */ /* Truncate up to required size. */
return 0; return 0;
} }
nb = data [i+3] << 24 | data [i+2] << 16 | nb = data [i+3] << 24 | data [i+2] << 16 |
data [i+1] << 8 | data [i]; data [i+1] << 8 | data [i];
if (nb) if (nb)
fs_double_indirect_block_free (fs, nb, fs_double_indirect_block_free (fs, nb,
nblk - i/4 * BSDFS_BSIZE/4 * BSDFS_BSIZE/4); nblk - i/4 * BSDFS_BSIZE/4 * BSDFS_BSIZE/4);
} }
fs_block_free (fs, bno); fs_block_free (fs, bno);
return 1; 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 fs_block_alloc (fs_t *fs, unsigned int *bno)
{ {
int i; int i;
unsigned buf [BSDFS_BSIZE / 4]; unsigned buf [BSDFS_BSIZE / 4];
again: again:
if (fs->nfree == 0) if (fs->nfree == 0)
return 0; return 0;
fs->nfree--; fs->nfree--;
--fs->tfree; /* Count total free blocks. */ --fs->tfree; /* Count total free blocks. */
*bno = fs->free [fs->nfree]; *bno = fs->free [fs->nfree];
if (verbose) if (verbose)
printf ("allocate new block %d from slot %d\n", *bno, fs->nfree); printf ("allocate new block %d from slot %d\n", *bno, fs->nfree);
fs->free [fs->nfree] = 0; fs->free [fs->nfree] = 0;
fs->dirty = 1; fs->dirty = 1;
if (fs->nfree <= 0) { if (fs->nfree <= 0) {
if (! fs_read_block (fs, *bno, (unsigned char*) buf)) if (! fs_read_block (fs, *bno, (unsigned char*) buf))
return 0; return 0;
fs->nfree = buf[0]; fs->nfree = buf[0];
for (i=0; i<NICFREE; i++) for (i=0; i<NICFREE; i++)
fs->free[i] = buf[i+1]; fs->free[i] = buf[i+1];
} }
if (*bno == 0) if (*bno == 0)
goto again; goto again;
return 1; return 1;
} }

View File

@@ -21,135 +21,135 @@
* arising out of or in connection with the use or performance of * arising out of or in connection with the use or performance of
* this software. * this software.
*/ */
#define BSDFS_BSIZE 1024 /* block size */ #define BSDFS_BSIZE 1024 /* block size */
#define BSDFS_ROOT_INODE 2 /* root directory in inode 2 */ #define BSDFS_ROOT_INODE 2 /* root directory in inode 2 */
#define BSDFS_LOSTFOUND_INODE 3 /* lost+found directory in inode 3 */ #define BSDFS_LOSTFOUND_INODE 3 /* lost+found directory in inode 3 */
#define BSDFS_SWAP_INODE 4 /* swap file in inode 4 */ #define BSDFS_SWAP_INODE 4 /* swap file in inode 4 */
#define BSDFS_INODES_PER_BLOCK 16 /* inodes per block */ #define BSDFS_INODES_PER_BLOCK 16 /* inodes per block */
#define NICINOD 32 /* number of superblock inodes */ #define NICINOD 32 /* number of superblock inodes */
#define NICFREE 200 /* number of superblock free blocks */ #define NICFREE 200 /* number of superblock free blocks */
/* /*
* 28 of the di_addr address bytes are used; 7 addresses of 4 * 28 of the di_addr address bytes are used; 7 addresses of 4
* bytes each: 4 direct (4Kb directly accessible) and 3 indirect. * bytes each: 4 direct (4Kb directly accessible) and 3 indirect.
*/ */
#define NDADDR 4 /* direct addresses in inode */ #define NDADDR 4 /* direct addresses in inode */
#define NIADDR 3 /* indirect addresses in inode */ #define NIADDR 3 /* indirect addresses in inode */
#define NADDR (NDADDR + NIADDR) /* total addresses in inode */ #define NADDR (NDADDR + NIADDR) /* total addresses in inode */
/* /*
* NINDIR is the number of indirects in a file system block. * NINDIR is the number of indirects in a file system block.
*/ */
#define NINDIR (DEV_BSIZE / sizeof(daddr_t)) #define NINDIR (DEV_BSIZE / sizeof(daddr_t))
#define NSHIFT 8 /* log2(NINDIR) */ #define NSHIFT 8 /* log2(NINDIR) */
#define NMASK 0377L /* NINDIR - 1 */ #define NMASK 0377L /* NINDIR - 1 */
/* /*
* The path name on which the file system is mounted is maintained * The path name on which the file system is mounted is maintained
* in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in
* the super block for this name. * the super block for this name.
*/ */
#define MAXMNTLEN 28 #define MAXMNTLEN 28
#define FSMAGIC1 ('F' | 'S'<<8 | '<'<<16 | '<'<<24) #define FSMAGIC1 ('F' | 'S'<<8 | '<'<<16 | '<'<<24)
#define FSMAGIC2 ('>' | '>'<<8 | 'F'<<16 | 'S'<<24) #define FSMAGIC2 ('>' | '>'<<8 | 'F'<<16 | 'S'<<24)
typedef struct { typedef struct {
const char *filename; const char *filename;
int fd; int fd;
unsigned long seek; unsigned long seek;
int writable; int writable;
int dirty; /* sync needed */ int dirty; /* sync needed */
int modified; /* write_block was called */ int modified; /* write_block was called */
unsigned isize; /* size in blocks of superblock + I list */ unsigned isize; /* size in blocks of superblock + I list */
unsigned fsize; /* size in blocks of entire volume */ unsigned fsize; /* size in blocks of entire volume */
unsigned swapsz; /* size in blocks of swap area */ unsigned swapsz; /* size in blocks of swap area */
unsigned nfree; /* number of in core free blocks (0-100) */ unsigned nfree; /* number of in core free blocks (0-100) */
unsigned free [NICFREE]; /* in core free blocks */ unsigned free [NICFREE]; /* in core free blocks */
unsigned ninode; /* number of in core I nodes (0-100) */ unsigned ninode; /* number of in core I nodes (0-100) */
unsigned inode [NICINOD]; /* in core free I nodes */ unsigned inode [NICINOD]; /* in core free I nodes */
unsigned flock; /* lock during free list manipulation */ unsigned flock; /* lock during free list manipulation */
unsigned ilock; /* lock during I list manipulation */ unsigned ilock; /* lock during I list manipulation */
unsigned fmod; /* super block modified flag */ unsigned fmod; /* super block modified flag */
unsigned ronly; /* mounted read-only flag */ unsigned ronly; /* mounted read-only flag */
long utime; /* current date of last update */ long utime; /* current date of last update */
unsigned tfree; /* total free blocks */ unsigned tfree; /* total free blocks */
unsigned tinode; /* total free inodes */ unsigned tinode; /* total free inodes */
char fsmnt [MAXMNTLEN]; /* ordinary file mounted on */ char fsmnt [MAXMNTLEN]; /* ordinary file mounted on */
unsigned lasti; /* start place for circular search */ unsigned lasti; /* start place for circular search */
unsigned nbehind; /* est # free inodes before s_lasti */ unsigned nbehind; /* est # free inodes before s_lasti */
unsigned flags; /* mount time flags */ unsigned flags; /* mount time flags */
} fs_t; } fs_t;
typedef struct { typedef struct {
fs_t *fs; fs_t *fs;
unsigned number; unsigned number;
int dirty; /* save needed */ int dirty; /* save needed */
unsigned short mode; /* file type and access mode */ unsigned short mode; /* file type and access mode */
#define INODE_MODE_FMT 0170000 /* type of file */ #define INODE_MODE_FMT 0170000 /* type of file */
#define INODE_MODE_FCHR 020000 /* character special */ #define INODE_MODE_FCHR 020000 /* character special */
#define INODE_MODE_FDIR 040000 /* directory */ #define INODE_MODE_FDIR 040000 /* directory */
#define INODE_MODE_FBLK 060000 /* block special */ #define INODE_MODE_FBLK 060000 /* block special */
#define INODE_MODE_FREG 0100000 /* regular */ #define INODE_MODE_FREG 0100000 /* regular */
#define INODE_MODE_FLNK 0120000 /* symbolic link */ #define INODE_MODE_FLNK 0120000 /* symbolic link */
#define INODE_MODE_FSOCK 0140000 /* socket */ #define INODE_MODE_FSOCK 0140000 /* socket */
#define INODE_MODE_SUID 04000 /* set user id on execution */ #define INODE_MODE_SUID 04000 /* set user id on execution */
#define INODE_MODE_SGID 02000 /* set group 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_SVTX 01000 /* save swapped text even after use */
#define INODE_MODE_READ 0400 /* read, write, execute permissions */ #define INODE_MODE_READ 0400 /* read, write, execute permissions */
#define INODE_MODE_WRITE 0200 #define INODE_MODE_WRITE 0200
#define INODE_MODE_EXEC 0100 #define INODE_MODE_EXEC 0100
unsigned short nlink; /* directory entries */ unsigned short nlink; /* directory entries */
unsigned uid; /* owner */ unsigned uid; /* owner */
unsigned gid; /* group */ unsigned gid; /* group */
unsigned long size; /* size */ unsigned long size; /* size */
unsigned addr [7]; /* device addresses constituting file */ unsigned addr [7]; /* device addresses constituting file */
unsigned flags; /* user defined flags */ unsigned flags; /* user defined flags */
/* /*
* Super-user and owner changeable flags. * Super-user and owner changeable flags.
*/ */
#define USER_SETTABLE 0x00ff /* mask of owner changeable flags */ #define USER_SETTABLE 0x00ff /* mask of owner changeable flags */
#define USER_NODUMP 0x0001 /* do not dump file */ #define USER_NODUMP 0x0001 /* do not dump file */
#define USER_IMMUTABLE 0x0002 /* file may not be changed */ #define USER_IMMUTABLE 0x0002 /* file may not be changed */
#define USER_APPEND 0x0004 /* writes to file may only append */ #define USER_APPEND 0x0004 /* writes to file may only append */
/* /*
* Super-user changeable flags. * Super-user changeable flags.
*/ */
#define SYS_SETTABLE 0xff00 /* mask of superuser changeable flags */ #define SYS_SETTABLE 0xff00 /* mask of superuser changeable flags */
#define SYS_ARCHIVED 0x0100 /* file is archived */ #define SYS_ARCHIVED 0x0100 /* file is archived */
#define SYS_IMMUTABLE 0x0200 /* file may not be changed */ #define SYS_IMMUTABLE 0x0200 /* file may not be changed */
#define SYS_APPEND 0x0400 /* writes to file may only append */ #define SYS_APPEND 0x0400 /* writes to file may only append */
long atime; /* time last accessed */ long atime; /* time last accessed */
long mtime; /* time last modified */ long mtime; /* time last modified */
long ctime; /* time created */ long ctime; /* time created */
} fs_inode_t; } fs_inode_t;
typedef struct { typedef struct {
unsigned ino; unsigned ino;
unsigned reclen; unsigned reclen;
unsigned namlen; unsigned namlen;
char name [63+1]; char name [63+1];
} fs_dirent_t; } fs_dirent_t;
typedef void (*fs_directory_scanner_t) (fs_inode_t *dir, 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 { typedef struct {
fs_inode_t inode; fs_inode_t inode;
int writable; /* write allowed */ int writable; /* write allowed */
unsigned long offset; /* current i/o offset */ unsigned long offset; /* current i/o offset */
} fs_file_t; } fs_file_t;
typedef enum { typedef enum {
INODE_OP_LOOKUP, /* lookup inode by name */ INODE_OP_LOOKUP, /* lookup inode by name */
INODE_OP_CREATE, /* create new file */ INODE_OP_CREATE, /* create new file */
INODE_OP_DELETE, /* delete file */ INODE_OP_DELETE, /* delete file */
INODE_OP_LINK, /* make a link to a file */ INODE_OP_LINK, /* make a link to a file */
} fs_op_t; } fs_op_t;
int fs_seek (fs_t *fs, unsigned long offset); 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); void fs_close (fs_t *fs);
int fs_sync (fs_t *fs, int force); int fs_sync (fs_t *fs, int force);
int fs_create (fs_t *fs, const char *filename, unsigned kbytes, int fs_create (fs_t *fs, const char *filename, unsigned kbytes,
unsigned swap_kbytes); unsigned swap_kbytes);
int fs_check (fs_t *fs); int fs_check (fs_t *fs);
void fs_print (fs_t *fs, FILE *out); 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_truncate (fs_inode_t *inode, unsigned long size);
void fs_inode_print (fs_inode_t *inode, FILE *out); void fs_inode_print (fs_inode_t *inode, FILE *out);
int fs_inode_read (fs_inode_t *inode, unsigned long offset, 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, 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_alloc (fs_t *fs, fs_inode_t *inode);
int fs_inode_by_name (fs_t *fs, fs_inode_t *inode, const char *name, 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 inode_build_list (fs_t *fs);
int fs_write_block (fs_t *fs, unsigned bnum, unsigned char *data); 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); int fs_triple_indirect_block_free (fs_t *fs, unsigned int bno, int nblk);
void fs_directory_scan (fs_inode_t *inode, char *dirname, 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_pack (unsigned char *data, fs_dirent_t *dirent);
void fs_dirent_unpack (fs_dirent_t *dirent, unsigned char *data); 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_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_open (fs_t *fs, fs_file_t *file, const char *name, int wflag);
int fs_file_read (fs_file_t *file, unsigned char *data, 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, 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); int fs_file_close (fs_file_t *file);

File diff suppressed because it is too large Load Diff

View File

@@ -33,368 +33,370 @@ extern int verbose;
int inode_build_list (fs_t *fs) int inode_build_list (fs_t *fs)
{ {
fs_inode_t inode; fs_inode_t inode;
unsigned int inum, total_inodes; unsigned int inum, total_inodes;
total_inodes = (fs->isize - 1) * BSDFS_INODES_PER_BLOCK; total_inodes = (fs->isize - 1) * BSDFS_INODES_PER_BLOCK;
for (inum = 1; inum <= total_inodes; inum++) { for (inum = 1; inum <= total_inodes; inum++) {
if (! fs_inode_get (fs, &inode, inum)) if (! fs_inode_get (fs, &inode, inum))
return 0; return 0;
if (inode.mode == 0) { if (inode.mode == 0) {
fs->inode [fs->ninode++] = inum; fs->inode [fs->ninode++] = inum;
if (fs->ninode >= NICINOD) if (fs->ninode >= NICINOD)
break; break;
} }
} }
return 1; return 1;
} }
static int create_inode1 (fs_t *fs) static int create_inode1 (fs_t *fs)
{ {
fs_inode_t inode; fs_inode_t inode;
memset (&inode, 0, sizeof(inode)); memset (&inode, 0, sizeof(inode));
inode.mode = INODE_MODE_FREG; inode.mode = INODE_MODE_FREG;
inode.fs = fs; inode.fs = fs;
inode.number = 1; inode.number = 1;
if (! fs_inode_save (&inode, 1)) if (! fs_inode_save (&inode, 1))
return 0; return 0;
fs->tinode--; fs->tinode--;
return 1; return 1;
} }
static int create_root_directory (fs_t *fs) static int create_root_directory (fs_t *fs)
{ {
fs_inode_t inode; fs_inode_t inode;
unsigned char buf [BSDFS_BSIZE]; unsigned char buf [BSDFS_BSIZE];
unsigned int bno; unsigned int bno;
memset (&inode, 0, sizeof(inode)); memset (&inode, 0, sizeof(inode));
inode.mode = INODE_MODE_FDIR | 0777; inode.mode = INODE_MODE_FDIR | 0777;
inode.fs = fs; inode.fs = fs;
inode.number = BSDFS_ROOT_INODE; inode.number = BSDFS_ROOT_INODE;
inode.size = BSDFS_BSIZE; inode.size = BSDFS_BSIZE;
inode.flags = 0; inode.flags = 0;
time (&inode.ctime); time (&inode.ctime);
time (&inode.atime); time (&inode.atime);
time (&inode.mtime); time (&inode.mtime);
/* directory - put in extra links */ /* directory - put in extra links */
memset (buf, 0, sizeof(buf)); memset (buf, 0, sizeof(buf));
buf[0] = inode.number; buf[0] = inode.number;
buf[1] = inode.number >> 8; buf[1] = inode.number >> 8;
buf[2] = inode.number >> 16; buf[2] = inode.number >> 16;
buf[3] = inode.number >> 24; buf[3] = inode.number >> 24;
buf[4] = 12; buf[4] = 12;
buf[5] = 12 >> 8; buf[5] = 12 >> 8;
buf[6] = 1; buf[6] = 1;
buf[7] = 1 >> 8; buf[7] = 1 >> 8;
buf[8] = '.'; buf[8] = '.';
buf[9] = 0; buf[9] = 0;
buf[10] = 0; buf[10] = 0;
buf[11] = 0; buf[11] = 0;
buf[12+0] = BSDFS_ROOT_INODE; buf[12+0] = BSDFS_ROOT_INODE;
buf[12+1] = BSDFS_ROOT_INODE >> 8; buf[12+1] = BSDFS_ROOT_INODE >> 8;
buf[12+2] = BSDFS_ROOT_INODE >> 16; buf[12+2] = BSDFS_ROOT_INODE >> 16;
buf[12+3] = BSDFS_ROOT_INODE >> 24; buf[12+3] = BSDFS_ROOT_INODE >> 24;
buf[12+4] = 12; buf[12+4] = 12;
buf[12+5] = 12 >> 8; buf[12+5] = 12 >> 8;
buf[12+6] = 2; buf[12+6] = 2;
buf[12+7] = 2 >> 8; buf[12+7] = 2 >> 8;
buf[12+8] = '.'; buf[12+8] = '.';
buf[12+9] = '.'; buf[12+9] = '.';
buf[12+10] = 0; buf[12+10] = 0;
buf[12+11] = 0; buf[12+11] = 0;
buf[24+0] = BSDFS_LOSTFOUND_INODE; buf[24+0] = BSDFS_LOSTFOUND_INODE;
buf[24+1] = BSDFS_LOSTFOUND_INODE >> 8; buf[24+1] = BSDFS_LOSTFOUND_INODE >> 8;
buf[24+2] = BSDFS_LOSTFOUND_INODE >> 16; buf[24+2] = BSDFS_LOSTFOUND_INODE >> 16;
buf[24+3] = BSDFS_LOSTFOUND_INODE >> 24; buf[24+3] = BSDFS_LOSTFOUND_INODE >> 24;
buf[24+4] = (unsigned char) (BSDFS_BSIZE - 12 - 12); buf[24+4] = (unsigned char) (BSDFS_BSIZE - 12 - 12);
buf[24+5] = (BSDFS_BSIZE - 12 - 12) >> 8; buf[24+5] = (BSDFS_BSIZE - 12 - 12) >> 8;
buf[24+6] = 10; buf[24+6] = 10;
buf[24+7] = 10 >> 8; buf[24+7] = 10 >> 8;
memcpy (&buf[24+8], "lost+found\0\0", 12); memcpy (&buf[24+8], "lost+found\0\0", 12);
if (fs->swapsz != 0) { if (fs->swapsz != 0) {
buf[24+4] = 20; buf[24+4] = 20;
buf[24+5] = 20 >> 8; buf[24+5] = 20 >> 8;
buf[44+0] = BSDFS_SWAP_INODE; buf[44+0] = BSDFS_SWAP_INODE;
buf[44+1] = BSDFS_SWAP_INODE >> 8; buf[44+1] = BSDFS_SWAP_INODE >> 8;
buf[44+2] = BSDFS_SWAP_INODE >> 16; buf[44+2] = BSDFS_SWAP_INODE >> 16;
buf[44+3] = BSDFS_SWAP_INODE >> 24; buf[44+3] = BSDFS_SWAP_INODE >> 24;
buf[44+4] = (unsigned char) (BSDFS_BSIZE - 12 - 12 - 20); buf[44+4] = (unsigned char) (BSDFS_BSIZE - 12 - 12 - 20);
buf[44+5] = (BSDFS_BSIZE - 12 - 12 - 20) >> 8; buf[44+5] = (BSDFS_BSIZE - 12 - 12 - 20) >> 8;
buf[44+6] = 4; buf[44+6] = 4;
buf[44+7] = 4 >> 8; buf[44+7] = 4 >> 8;
memcpy (&buf[44+8], "swap\0\0\0\0", 8); memcpy (&buf[44+8], "swap\0\0\0\0", 8);
} }
inode.nlink = 3; inode.nlink = 3;
if (! fs_block_alloc (fs, &bno)) if (! fs_block_alloc (fs, &bno))
return 0; return 0;
if (! fs_write_block (fs, bno, buf)) if (! fs_write_block (fs, bno, buf))
return 0; return 0;
inode.addr[0] = bno; inode.addr[0] = bno;
if (! fs_inode_save (&inode, 1)) if (! fs_inode_save (&inode, 1))
return 0; return 0;
fs->tinode--; fs->tinode--;
return 1; return 1;
} }
static int create_lost_found_directory (fs_t *fs) static int create_lost_found_directory (fs_t *fs)
{ {
fs_inode_t inode; fs_inode_t inode;
unsigned char buf [BSDFS_BSIZE]; unsigned char buf [BSDFS_BSIZE];
unsigned int bno; unsigned int bno;
memset (&inode, 0, sizeof(inode)); memset (&inode, 0, sizeof(inode));
inode.mode = INODE_MODE_FDIR | 0777; inode.mode = INODE_MODE_FDIR | 0777;
inode.fs = fs; inode.fs = fs;
inode.number = BSDFS_LOSTFOUND_INODE; inode.number = BSDFS_LOSTFOUND_INODE;
inode.size = BSDFS_BSIZE; inode.size = BSDFS_BSIZE;
inode.flags = 0; inode.flags = 0;
time (&inode.ctime); time (&inode.ctime);
time (&inode.atime); time (&inode.atime);
time (&inode.mtime); time (&inode.mtime);
/* directory - put in extra links */ /* directory - put in extra links */
memset (buf, 0, sizeof(buf)); memset (buf, 0, sizeof(buf));
buf[0] = inode.number; buf[0] = inode.number;
buf[1] = inode.number >> 8; buf[1] = inode.number >> 8;
buf[2] = inode.number >> 16; buf[2] = inode.number >> 16;
buf[3] = inode.number >> 24; buf[3] = inode.number >> 24;
buf[4] = 12; buf[4] = 12;
buf[5] = 12 >> 8; buf[5] = 12 >> 8;
buf[6] = 1; buf[6] = 1;
buf[7] = 1 >> 8; buf[7] = 1 >> 8;
buf[8] = '.'; buf[8] = '.';
buf[9] = 0; buf[9] = 0;
buf[10] = 0; buf[10] = 0;
buf[11] = 0; buf[11] = 0;
buf[12+0] = BSDFS_ROOT_INODE; buf[12+0] = BSDFS_ROOT_INODE;
buf[12+1] = BSDFS_ROOT_INODE >> 8; buf[12+1] = BSDFS_ROOT_INODE >> 8;
buf[12+2] = BSDFS_ROOT_INODE >> 16; buf[12+2] = BSDFS_ROOT_INODE >> 16;
buf[12+3] = BSDFS_ROOT_INODE >> 24; buf[12+3] = BSDFS_ROOT_INODE >> 24;
buf[12+4] = (unsigned char) (BSDFS_BSIZE - 12); buf[12+4] = (unsigned char) (BSDFS_BSIZE - 12);
buf[12+5] = (BSDFS_BSIZE - 12) >> 8; buf[12+5] = (BSDFS_BSIZE - 12) >> 8;
buf[12+6] = 2; buf[12+6] = 2;
buf[12+7] = 2 >> 8; buf[12+7] = 2 >> 8;
buf[12+8] = '.'; buf[12+8] = '.';
buf[12+9] = '.'; buf[12+9] = '.';
buf[12+10] = 0; buf[12+10] = 0;
buf[12+11] = 0; buf[12+11] = 0;
inode.nlink = 2; inode.nlink = 2;
if (! fs_block_alloc (fs, &bno)) if (! fs_block_alloc (fs, &bno))
return 0; return 0;
if (! fs_write_block (fs, bno, buf)) if (! fs_write_block (fs, bno, buf))
return 0; return 0;
inode.addr[0] = bno; inode.addr[0] = bno;
if (! fs_inode_save (&inode, 1)) if (! fs_inode_save (&inode, 1))
return 0; return 0;
fs->tinode--; fs->tinode--;
return 1; return 1;
} }
static void map_block_swap (fs_inode_t *inode, unsigned lbn) static void map_block_swap (fs_inode_t *inode, unsigned lbn)
{ {
unsigned block [BSDFS_BSIZE / 4]; unsigned block [BSDFS_BSIZE / 4];
unsigned int bn, indir, newb, shift, i, j; unsigned int bn, indir, newb, shift, i, j;
/* /*
* Blocks 0..NADDR-3 are direct blocks. * Blocks 0..NADDR-3 are direct blocks.
*/ */
if (lbn < NADDR-3) { if (lbn < NADDR-3) {
/* small file algorithm */ /* small file algorithm */
inode->addr[lbn] = inode->fs->isize + lbn; inode->addr[lbn] = inode->fs->isize + lbn;
return; return;
} }
/* /*
* Addresses NADDR-3, NADDR-2, and NADDR-1 * Addresses NADDR-3, NADDR-2, and NADDR-1
* have single, double, triple indirect blocks. * have single, double, triple indirect blocks.
* The first step is to determine * The first step is to determine
* how many levels of indirection. * how many levels of indirection.
*/ */
shift = 0; shift = 0;
i = 1; i = 1;
bn = lbn - (NADDR-3); bn = lbn - (NADDR-3);
for (j=3; ; j--) { for (j=3; ; j--) {
if (j == 0) { if (j == 0) {
fprintf (stderr, "swap: too large size\n"); fprintf (stderr, "swap: too large size\n");
exit (-1); exit (-1);
} }
shift += NSHIFT; shift += NSHIFT;
i <<= NSHIFT; i <<= NSHIFT;
if (bn < i) if (bn < i)
break; break;
bn -= i; bn -= i;
} }
/* /*
* Fetch the first indirect block. * Fetch the first indirect block.
*/ */
indir = inode->addr [NADDR-j]; indir = inode->addr [NADDR-j];
if (indir == 0) { if (indir == 0) {
if (! fs_block_alloc (inode->fs, &indir)) { if (! fs_block_alloc (inode->fs, &indir)) {
alloc_error: fprintf (stderr, "swap: cannot allocate indirect block\n"); alloc_error:
exit (-1); fprintf (stderr, "swap: cannot allocate indirect block\n");
} exit (-1);
if (verbose) }
printf ("swap: allocate indirect block %d (j=%d)\n", indir, j); if (verbose)
memset (block, 0, BSDFS_BSIZE); printf ("swap: allocate indirect block %d (j=%d)\n", indir, j);
if (! fs_write_block (inode->fs, indir, (unsigned char*) block)) { memset (block, 0, BSDFS_BSIZE);
write_error: fprintf (stderr, "swap: cannot write indirect block %d\n", indir); if (! fs_write_block (inode->fs, indir, (unsigned char*) block)) {
exit (-1); write_error:
} fprintf (stderr, "swap: cannot write indirect block %d\n", indir);
inode->addr [NADDR-j] = indir; exit (-1);
} }
inode->addr [NADDR-j] = indir;
}
/* /*
* Fetch through the indirect blocks * Fetch through the indirect blocks
*/ */
for (; ; j++) { for (; ; j++) {
if (! fs_read_block (inode->fs, indir, (unsigned char*) block)) { if (! fs_read_block (inode->fs, indir, (unsigned char*) block)) {
fprintf (stderr, "swap: cannot read indirect block %d\n", indir); fprintf (stderr, "swap: cannot read indirect block %d\n", indir);
exit (-1); exit (-1);
} }
shift -= NSHIFT; shift -= NSHIFT;
i = (bn >> shift) & NMASK; i = (bn >> shift) & NMASK;
if (j == 3) { if (j == 3) {
block[i] = inode->fs->isize + lbn; block[i] = inode->fs->isize + lbn;
if (! fs_write_block (inode->fs, indir, (unsigned char*) block)) if (! fs_write_block (inode->fs, indir, (unsigned char*) block))
goto write_error; goto write_error;
return; return;
} }
if (block[i] != 0) { if (block[i] != 0) {
indir = block [i]; indir = block [i];
continue; continue;
} }
/* Allocate new indirect block. */ /* Allocate new indirect block. */
if (! fs_block_alloc (inode->fs, &newb)) if (! fs_block_alloc (inode->fs, &newb))
goto alloc_error; goto alloc_error;
if (verbose) if (verbose)
printf ("swap: allocate new block %d (j=%d)\n", newb, j); printf ("swap: allocate new block %d (j=%d)\n", newb, j);
block[i] = newb; block[i] = newb;
if (! fs_write_block (inode->fs, indir, (unsigned char*) block)) if (! fs_write_block (inode->fs, indir, (unsigned char*) block))
goto write_error; goto write_error;
memset (block, 0, BSDFS_BSIZE); memset (block, 0, BSDFS_BSIZE);
if (! fs_write_block (inode->fs, newb, (unsigned char*) block)) { if (! fs_write_block (inode->fs, newb, (unsigned char*) block)) {
fprintf (stderr, "swap: cannot write block %d\n", newb); fprintf (stderr, "swap: cannot write block %d\n", newb);
exit (-1); exit (-1);
} }
indir = newb; indir = newb;
} }
} }
static int create_swap_file (fs_t *fs) static int create_swap_file (fs_t *fs)
{ {
fs_inode_t inode; fs_inode_t inode;
unsigned lbn; unsigned lbn;
memset (&inode, 0, sizeof(inode)); memset (&inode, 0, sizeof(inode));
inode.mode = INODE_MODE_FREG | 0400; inode.mode = INODE_MODE_FREG | 0400;
inode.fs = fs; inode.fs = fs;
inode.number = BSDFS_SWAP_INODE; inode.number = BSDFS_SWAP_INODE;
inode.size = fs->swapsz * BSDFS_BSIZE; inode.size = fs->swapsz * BSDFS_BSIZE;
inode.flags = /*SYS_IMMUTABLE |*/ USER_IMMUTABLE | USER_NODUMP; inode.flags = /*SYS_IMMUTABLE |*/ USER_IMMUTABLE | USER_NODUMP;
inode.nlink = 1; inode.nlink = 1;
inode.dirty = 1; inode.dirty = 1;
time (&inode.ctime); time (&inode.ctime);
time (&inode.atime); time (&inode.atime);
time (&inode.mtime); time (&inode.mtime);
for (lbn=0; lbn<fs->swapsz; lbn++) for (lbn=0; lbn<fs->swapsz; lbn++)
map_block_swap (&inode, lbn); map_block_swap (&inode, lbn);
if (! fs_inode_save (&inode, 0)) { if (! fs_inode_save (&inode, 0)) {
fprintf (stderr, "swap: cannot save file inode\n"); fprintf (stderr, "swap: cannot save file inode\n");
return 0; return 0;
} }
return 1; return 1;
} }
int fs_create (fs_t *fs, const char *filename, unsigned kbytes, int fs_create (fs_t *fs, const char *filename, unsigned kbytes,
unsigned swap_kbytes) unsigned swap_kbytes)
{ {
int n; int n;
unsigned char buf [BSDFS_BSIZE]; unsigned char buf [BSDFS_BSIZE];
off_t bytes, offset; off_t bytes, offset;
memset (fs, 0, sizeof (*fs)); memset (fs, 0, sizeof (*fs));
fs->filename = filename; fs->filename = filename;
fs->seek = 0; fs->seek = 0;
fs->fd = open (fs->filename, O_CREAT | O_RDWR, 0666); fs->fd = open (fs->filename, O_CREAT | O_RDWR, 0666);
if (fs->fd < 0) if (fs->fd < 0)
return 0; return 0;
fs->writable = 1; fs->writable = 1;
/* get total disk size /* get total disk size
* and inode block size */ * and inode block size */
bytes = (off_t) kbytes * 1024ULL; bytes = (off_t) kbytes * 1024ULL;
fs->fsize = bytes / BSDFS_BSIZE; fs->fsize = bytes / BSDFS_BSIZE;
fs->isize = 1 + (fs->fsize / 16 + BSDFS_INODES_PER_BLOCK - 1) / fs->isize = 1 + (fs->fsize / 16 + BSDFS_INODES_PER_BLOCK - 1) /
BSDFS_INODES_PER_BLOCK; BSDFS_INODES_PER_BLOCK;
if (fs->isize < 2) if (fs->isize < 2)
return 0; return 0;
/* make sure the file is of proper size */ /* make sure the file is of proper size */
offset = lseek (fs->fd, bytes-1, SEEK_SET); offset = lseek (fs->fd, bytes-1, SEEK_SET);
if (offset != bytes-1) if (offset != bytes-1)
return 0; return 0;
if (write (fs->fd, "", 1) != 1) { if (write (fs->fd, "", 1) != 1) {
perror ("write"); perror ("write");
return 0; return 0;
} }
lseek (fs->fd, 0, SEEK_SET); lseek (fs->fd, 0, SEEK_SET);
/* build a list of free blocks */ /* build a list of free blocks */
fs->swapsz = swap_kbytes * 1024 / BSDFS_BSIZE; fs->swapsz = swap_kbytes * 1024 / BSDFS_BSIZE;
fs_block_free (fs, 0); fs_block_free (fs, 0);
for (n = fs->fsize - 1; n >= fs->isize + fs->swapsz; n--) for (n = fs->fsize - 1; n >= fs->isize + fs->swapsz; n--)
if (! fs_block_free (fs, n)) if (! fs_block_free (fs, n))
return 0; return 0;
/* initialize inodes */ /* initialize inodes */
memset (buf, 0, BSDFS_BSIZE); memset (buf, 0, BSDFS_BSIZE);
if (! fs_seek (fs, BSDFS_BSIZE)) if (! fs_seek (fs, BSDFS_BSIZE))
return 0; return 0;
for (n=1; n < fs->isize; n++) { for (n=1; n < fs->isize; n++) {
if (! fs_write (fs, buf, BSDFS_BSIZE)) if (! fs_write (fs, buf, BSDFS_BSIZE))
return 0; return 0;
fs->tinode += BSDFS_INODES_PER_BLOCK; fs->tinode += BSDFS_INODES_PER_BLOCK;
} }
/* legacy empty inode 1 */ /* legacy empty inode 1 */
if (! create_inode1 (fs)) if (! create_inode1 (fs))
return 0; return 0;
/* lost+found directory */ /* lost+found directory */
if (! create_lost_found_directory (fs)) if (! create_lost_found_directory (fs))
return 0; return 0;
/* root directory */ /* root directory */
if (! create_root_directory (fs)) if (! create_root_directory (fs))
return 0; return 0;
/* swap file */ /* swap file */
if (fs->swapsz != 0 && ! create_swap_file (fs)) if (fs->swapsz != 0 && ! create_swap_file (fs))
return 0; return 0;
/* build a list of free inodes */ /* build a list of free inodes */
if (! inode_build_list (fs)) if (! inode_build_list (fs))
return 0; return 0;
/* write out super block */ /* write out super block */
return fs_sync (fs, 1); return fs_sync (fs, 1);
} }

View File

@@ -29,68 +29,68 @@ extern int verbose;
int fs_file_create (fs_t *fs, fs_file_t *file, const char *name, int mode) 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)) { if (! fs_inode_by_name (fs, &file->inode, name, INODE_OP_CREATE, mode)) {
fprintf (stderr, "%s: inode open failed\n", name); fprintf (stderr, "%s: inode open failed\n", name);
return 0; return 0;
} }
if ((file->inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { if ((file->inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) {
/* Cannot open directory on write. */ /* Cannot open directory on write. */
return 0; return 0;
} }
fs_inode_truncate (&file->inode, 0); fs_inode_truncate (&file->inode, 0);
fs_inode_save (&file->inode, 0); fs_inode_save (&file->inode, 0);
file->writable = 1; file->writable = 1;
file->offset = 0; file->offset = 0;
return 1; return 1;
} }
int fs_file_open (fs_t *fs, fs_file_t *file, const char *name, int wflag) 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)) { if (! fs_inode_by_name (fs, &file->inode, name, INODE_OP_LOOKUP, 0)) {
fprintf (stderr, "%s: inode open failed\n", name); fprintf (stderr, "%s: inode open failed\n", name);
return 0; return 0;
} }
if (wflag && (file->inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { if (wflag && (file->inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) {
/* Cannot open directory on write. */ /* Cannot open directory on write. */
return 0; return 0;
} }
file->writable = wflag; file->writable = wflag;
file->offset = 0; file->offset = 0;
return 1; return 1;
} }
int fs_file_read (fs_file_t *file, unsigned char *data, unsigned long bytes) int fs_file_read (fs_file_t *file, unsigned char *data, unsigned long bytes)
{ {
if (! fs_inode_read (&file->inode, file->offset, data, bytes)) { if (! fs_inode_read (&file->inode, file->offset, data, bytes)) {
fprintf (stderr, "inode %d: file read failed, %lu bytes at offset %lu\n", fprintf (stderr, "inode %d: file read failed, %lu bytes at offset %lu\n",
file->inode.number, bytes, file->offset); file->inode.number, bytes, file->offset);
return 0; return 0;
} }
file->offset += bytes; file->offset += bytes;
return 1; return 1;
} }
int fs_file_write (fs_file_t *file, unsigned char *data, unsigned long bytes) int fs_file_write (fs_file_t *file, unsigned char *data, unsigned long bytes)
{ {
if (! file->writable) if (! file->writable)
return 0; return 0;
if (! fs_inode_write (&file->inode, file->offset, data, bytes)) { if (! fs_inode_write (&file->inode, file->offset, data, bytes)) {
fprintf (stderr, "inode %d: file write failed, %lu bytes at offset %lu\n", fprintf (stderr, "inode %d: file write failed, %lu bytes at offset %lu\n",
file->inode.number, bytes, file->offset); file->inode.number, bytes, file->offset);
return 0; return 0;
} }
file->offset += bytes; file->offset += bytes;
return 1; return 1;
} }
int fs_file_close (fs_file_t *file) int fs_file_close (fs_file_t *file)
{ {
if (file->writable) { if (file->writable) {
if (! fs_inode_save (&file->inode, 0)) { if (! fs_inode_save (&file->inode, 0)) {
fprintf (stderr, "inode %d: file close failed\n", fprintf (stderr, "inode %d: file close failed\n",
file->inode.number); file->inode.number);
return 0; return 0;
} }
} }
return 1; return 1;
} }

View File

@@ -43,249 +43,249 @@ unsigned kbytes;
unsigned swap_kbytes; unsigned swap_kbytes;
static const char *program_version = static const char *program_version =
"BSD 2.x file system utility, version 1.1\n" "BSD 2.x file system utility, version 1.1\n"
"Copyright (C) 2011-2014 Serge Vakulenko"; "Copyright (C) 2011-2014 Serge Vakulenko";
static const char *program_bug_address = "<serge@vak.ru>"; static const char *program_bug_address = "<serge@vak.ru>";
static struct option program_options[] = { static struct option program_options[] = {
{ "help", no_argument, 0, 'h' }, { "help", no_argument, 0, 'h' },
{ "version", no_argument, 0, 'V' }, { "version", no_argument, 0, 'V' },
{ "verbose", no_argument, 0, 'v' }, { "verbose", no_argument, 0, 'v' },
{ "add", no_argument, 0, 'a' }, { "add", no_argument, 0, 'a' },
{ "extract", no_argument, 0, 'x' }, { "extract", no_argument, 0, 'x' },
{ "check", no_argument, 0, 'c' }, { "check", no_argument, 0, 'c' },
{ "fix", no_argument, 0, 'f' }, { "fix", no_argument, 0, 'f' },
{ "mount", no_argument, 0, 'm' }, { "mount", no_argument, 0, 'm' },
{ "new", required_argument, 0, 'n' }, { "new", required_argument, 0, 'n' },
{ "swap", required_argument, 0, 's' }, { "swap", required_argument, 0, 's' },
{ "manifest", required_argument, 0, 'M' }, { "manifest", required_argument, 0, 'M' },
{ 0 } { 0 }
}; };
static void print_help (char *progname) static void print_help (char *progname)
{ {
char *p = strrchr (progname, '/'); char *p = strrchr (progname, '/');
if (p) if (p)
progname = p+1; progname = p+1;
printf ("%s\n", program_version); printf ("%s\n", program_version);
printf ("This program is free software; it comes with ABSOLUTELY NO WARRANTY;\n" printf ("This program is free software; it comes with ABSOLUTELY NO WARRANTY;\n"
"see the GNU General Public License for more details.\n"); "see the GNU General Public License for more details.\n");
printf ("\n"); printf ("\n");
printf ("Usage:\n"); printf ("Usage:\n");
printf (" %s [--verbose] filesys.img\n", progname); printf (" %s [--verbose] filesys.img\n", progname);
printf (" %s --add filesys.img files...\n", progname); printf (" %s --add filesys.img files...\n", progname);
printf (" %s --extract filesys.img\n", progname); printf (" %s --extract filesys.img\n", progname);
printf (" %s --check [--fix] 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 --new=kbytes [--swap=kbytes] [--manifest=file] filesys.img [dir]\n", progname);
printf (" %s --mount filesys.img dir\n", progname); printf (" %s --mount filesys.img dir\n", progname);
printf ("\n"); printf ("\n");
printf ("Options:\n"); printf ("Options:\n");
printf (" -a, --add Add files to filesystem.\n"); printf (" -a, --add Add files to filesystem.\n");
printf (" -x, --extract Extract all files.\n"); printf (" -x, --extract Extract all files.\n");
printf (" -c, --check Check filesystem, use -c -f to fix.\n"); printf (" -c, --check Check filesystem, use -c -f to fix.\n");
printf (" -f, --fix Fix bugs in filesystem.\n"); printf (" -f, --fix Fix bugs in filesystem.\n");
printf (" -n NUM, --new=NUM Create new filesystem, size in kbytes.\n"); printf (" -n NUM, --new=NUM Create new filesystem, size in kbytes.\n");
printf (" Add files from specified directory (optional)\n"); printf (" Add files from specified directory (optional)\n");
printf (" -s NUM, --swap=NUM Size of swap area in kbytes.\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 file, --manifest=file List of files and attributes to create.\n");
printf (" -m, --mount Mount the filesystem.\n"); printf (" -m, --mount Mount the filesystem.\n");
printf (" -v, --verbose Be verbose.\n"); printf (" -v, --verbose Be verbose.\n");
printf (" -V, --version Print version information and then exit.\n"); printf (" -V, --version Print version information and then exit.\n");
printf (" -h, --help Print this message.\n"); printf (" -h, --help Print this message.\n");
printf ("\n"); printf ("\n");
printf ("Report bugs to \"%s\".\n", program_bug_address); printf ("Report bugs to \"%s\".\n", program_bug_address);
} }
void print_inode (fs_inode_t *inode, 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); fprintf (out, "%s/%s", dirname, filename);
switch (inode->mode & INODE_MODE_FMT) { switch (inode->mode & INODE_MODE_FMT) {
case INODE_MODE_FDIR: case INODE_MODE_FDIR:
if (filename[0] != 0) if (filename[0] != 0)
fprintf (out, "/"); fprintf (out, "/");
break; break;
case INODE_MODE_FCHR: case INODE_MODE_FCHR:
fprintf (out, " - char %d %d", fprintf (out, " - char %d %d",
inode->addr[1] >> 8, inode->addr[1] & 0xff); inode->addr[1] >> 8, inode->addr[1] & 0xff);
break; break;
case INODE_MODE_FBLK: case INODE_MODE_FBLK:
fprintf (out, " - block %d %d", fprintf (out, " - block %d %d",
inode->addr[1] >> 8, inode->addr[1] & 0xff); inode->addr[1] >> 8, inode->addr[1] & 0xff);
break; break;
default: default:
fprintf (out, " - %lu bytes", inode->size); fprintf (out, " - %lu bytes", inode->size);
break; break;
} }
fprintf (out, "\n"); fprintf (out, "\n");
} }
void print_indirect_block (fs_t *fs, unsigned int bno, FILE *out) void print_indirect_block (fs_t *fs, unsigned int bno, FILE *out)
{ {
unsigned short nb; unsigned short nb;
unsigned char data [BSDFS_BSIZE]; unsigned char data [BSDFS_BSIZE];
int i; int i;
fprintf (out, " [%d]", bno); fprintf (out, " [%d]", bno);
if (! fs_read_block (fs, bno, data)) { if (! fs_read_block (fs, bno, data)) {
fprintf (stderr, "read error at block %d\n", bno); fprintf (stderr, "read error at block %d\n", bno);
return; return;
} }
for (i=0; i<BSDFS_BSIZE-2; i+=2) { for (i=0; i<BSDFS_BSIZE-2; i+=2) {
nb = data [i+1] << 8 | data [i]; nb = data [i+1] << 8 | data [i];
if (nb) if (nb)
fprintf (out, " %d", nb); fprintf (out, " %d", nb);
} }
} }
void print_double_indirect_block (fs_t *fs, unsigned int bno, FILE *out) void print_double_indirect_block (fs_t *fs, unsigned int bno, FILE *out)
{ {
unsigned short nb; unsigned short nb;
unsigned char data [BSDFS_BSIZE]; unsigned char data [BSDFS_BSIZE];
int i; int i;
fprintf (out, " [%d]", bno); fprintf (out, " [%d]", bno);
if (! fs_read_block (fs, bno, data)) { if (! fs_read_block (fs, bno, data)) {
fprintf (stderr, "read error at block %d\n", bno); fprintf (stderr, "read error at block %d\n", bno);
return; return;
} }
for (i=0; i<BSDFS_BSIZE-2; i+=2) { for (i=0; i<BSDFS_BSIZE-2; i+=2) {
nb = data [i+1] << 8 | data [i]; nb = data [i+1] << 8 | data [i];
if (nb) if (nb)
print_indirect_block (fs, nb, out); print_indirect_block (fs, nb, out);
} }
} }
void print_triple_indirect_block (fs_t *fs, unsigned int bno, FILE *out) void print_triple_indirect_block (fs_t *fs, unsigned int bno, FILE *out)
{ {
unsigned short nb; unsigned short nb;
unsigned char data [BSDFS_BSIZE]; unsigned char data [BSDFS_BSIZE];
int i; int i;
fprintf (out, " [%d]", bno); fprintf (out, " [%d]", bno);
if (! fs_read_block (fs, bno, data)) { if (! fs_read_block (fs, bno, data)) {
fprintf (stderr, "read error at block %d\n", bno); fprintf (stderr, "read error at block %d\n", bno);
return; return;
} }
for (i=0; i<BSDFS_BSIZE-2; i+=2) { for (i=0; i<BSDFS_BSIZE-2; i+=2) {
nb = data [i+1] << 8 | data [i]; nb = data [i+1] << 8 | data [i];
if (nb) if (nb)
print_indirect_block (fs, nb, out); print_indirect_block (fs, nb, out);
} }
} }
void print_inode_blocks (fs_inode_t *inode, FILE *out) void print_inode_blocks (fs_inode_t *inode, FILE *out)
{ {
int i; int i;
if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FCHR || if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FCHR ||
(inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK) (inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK)
return; return;
fprintf (out, " "); fprintf (out, " ");
for (i=0; i<NDADDR; ++i) { for (i=0; i<NDADDR; ++i) {
if (inode->addr[i] == 0) if (inode->addr[i] == 0)
continue; continue;
fprintf (out, " %d", inode->addr[i]); fprintf (out, " %d", inode->addr[i]);
} }
if (inode->addr[NDADDR] != 0) if (inode->addr[NDADDR] != 0)
print_indirect_block (inode->fs, inode->addr[NDADDR], out); print_indirect_block (inode->fs, inode->addr[NDADDR], out);
if (inode->addr[NDADDR+1] != 0) if (inode->addr[NDADDR+1] != 0)
print_double_indirect_block (inode->fs, print_double_indirect_block (inode->fs,
inode->addr[NDADDR+1], out); inode->addr[NDADDR+1], out);
if (inode->addr[NDADDR+2] != 0) if (inode->addr[NDADDR+2] != 0)
print_triple_indirect_block (inode->fs, print_triple_indirect_block (inode->fs,
inode->addr[NDADDR+2], out); inode->addr[NDADDR+2], out);
fprintf (out, "\n"); fprintf (out, "\n");
} }
void extract_inode (fs_inode_t *inode, char *path) void extract_inode (fs_inode_t *inode, char *path)
{ {
int fd, n, mode; int fd, n, mode;
unsigned long offset; unsigned long offset;
unsigned char data [BSDFS_BSIZE]; unsigned char data [BSDFS_BSIZE];
/* Allow read/write for user. */ /* Allow read/write for user. */
mode = (inode->mode & 0777) | 0600; mode = (inode->mode & 0777) | 0600;
fd = open (path, O_CREAT | O_RDWR, mode); fd = open (path, O_CREAT | O_RDWR, mode);
if (fd < 0) { if (fd < 0) {
perror (path); perror (path);
return; return;
} }
for (offset = 0; offset < inode->size; offset += BSDFS_BSIZE) { for (offset = 0; offset < inode->size; offset += BSDFS_BSIZE) {
n = inode->size - offset; n = inode->size - offset;
if (n > BSDFS_BSIZE) if (n > BSDFS_BSIZE)
n = BSDFS_BSIZE; n = BSDFS_BSIZE;
if (! fs_inode_read (inode, offset, data, n)) { if (! fs_inode_read (inode, offset, data, n)) {
fprintf (stderr, "%s: read error at offset %ld\n", fprintf (stderr, "%s: read error at offset %ld\n",
path, offset); path, offset);
break; break;
} }
if (write (fd, data, n) != n) { if (write (fd, data, n) != n) {
fprintf (stderr, "%s: write error\n", path); fprintf (stderr, "%s: write error\n", path);
break; break;
} }
} }
close (fd); close (fd);
} }
void extractor (fs_inode_t *dir, fs_inode_t *inode, 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; FILE *out = arg;
char *path, *relpath; char *path, *relpath;
if (verbose) if (verbose)
print_inode (inode, dirname, filename, out); print_inode (inode, dirname, filename, out);
if ((inode->mode & INODE_MODE_FMT) != INODE_MODE_FDIR && if ((inode->mode & INODE_MODE_FMT) != INODE_MODE_FDIR &&
(inode->mode & INODE_MODE_FMT) != INODE_MODE_FREG) (inode->mode & INODE_MODE_FMT) != INODE_MODE_FREG)
return; return;
path = alloca (strlen (dirname) + strlen (filename) + 2); path = alloca (strlen (dirname) + strlen (filename) + 2);
strcpy (path, dirname); strcpy (path, dirname);
strcat (path, "/"); strcat (path, "/");
strcat (path, filename); strcat (path, filename);
for (relpath=path; *relpath == '/'; relpath++) for (relpath=path; *relpath == '/'; relpath++)
continue; continue;
if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR) {
if (mkdir (relpath, 0775) < 0 && errno != EEXIST) if (mkdir (relpath, 0775) < 0 && errno != EEXIST)
perror (relpath); perror (relpath);
/* Scan subdirectory. */ /* Scan subdirectory. */
fs_directory_scan (inode, path, extractor, arg); fs_directory_scan (inode, path, extractor, arg);
} else { } else {
extract_inode (inode, relpath); extract_inode (inode, relpath);
} }
} }
void scanner (fs_inode_t *dir, fs_inode_t *inode, 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; FILE *out = arg;
char *path; char *path;
print_inode (inode, dirname, filename, out); print_inode (inode, dirname, filename, out);
if (verbose > 1) { if (verbose > 1) {
/* Print a list of blocks. */ /* Print a list of blocks. */
print_inode_blocks (inode, out); print_inode_blocks (inode, out);
if (verbose > 2) { if (verbose > 2) {
fs_inode_print (inode, out); fs_inode_print (inode, out);
printf ("--------\n"); printf ("--------\n");
} }
} }
if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR && if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR &&
inode->number != BSDFS_ROOT_INODE) { inode->number != BSDFS_ROOT_INODE) {
/* Scan subdirectory. */ /* Scan subdirectory. */
path = alloca (strlen (dirname) + strlen (filename) + 2); path = alloca (strlen (dirname) + strlen (filename) + 2);
strcpy (path, dirname); strcpy (path, dirname);
strcat (path, "/"); strcat (path, "/");
strcat (path, filename); strcat (path, filename);
fs_directory_scan (inode, path, scanner, arg); 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) void add_directory (fs_t *fs, char *name)
{ {
fs_inode_t dir, parent; fs_inode_t dir, parent;
char buf [BSDFS_BSIZE], *p; char buf [BSDFS_BSIZE], *p;
/* Open parent directory. */ /* Open parent directory. */
strcpy (buf, name); strcpy (buf, name);
p = strrchr (buf, '/'); p = strrchr (buf, '/');
if (p) if (p)
*p = 0; *p = 0;
else else
*buf = 0; *buf = 0;
if (! fs_inode_by_name (fs, &parent, buf, INODE_OP_LOOKUP, 0)) { if (! fs_inode_by_name (fs, &parent, buf, INODE_OP_LOOKUP, 0)) {
fprintf (stderr, "%s: cannot open directory\n", buf); fprintf (stderr, "%s: cannot open directory\n", buf);
return; return;
} }
/* Create directory. */ /* Create directory. */
int done = fs_inode_by_name (fs, &dir, name, INODE_OP_CREATE, INODE_MODE_FDIR | 0777); int done = fs_inode_by_name (fs, &dir, name, INODE_OP_CREATE, INODE_MODE_FDIR | 0777);
if (! done) { if (! done) {
fprintf (stderr, "%s: directory inode create failed\n", name); fprintf (stderr, "%s: directory inode create failed\n", name);
return; return;
} }
if (done == 1) { if (done == 1) {
/* The directory already existed. */ /* The directory already existed. */
return; return;
} }
fs_inode_save (&dir, 0); fs_inode_save (&dir, 0);
/* Make parent link '..' */ /* Make parent link '..' */
strcpy (buf, name); strcpy (buf, name);
strcat (buf, "/.."); strcat (buf, "/..");
if (! fs_inode_by_name (fs, &dir, buf, INODE_OP_LINK, parent.number)) { if (! fs_inode_by_name (fs, &dir, buf, INODE_OP_LINK, parent.number)) {
fprintf (stderr, "%s: dotdot link failed\n", name); fprintf (stderr, "%s: dotdot link failed\n", name);
return; return;
} }
if (! fs_inode_get (fs, &parent, parent.number)) { if (! fs_inode_get (fs, &parent, parent.number)) {
fprintf (stderr, "inode %d: cannot open parent\n", parent.number); fprintf (stderr, "inode %d: cannot open parent\n", parent.number);
return; return;
} }
++parent.nlink; ++parent.nlink;
fs_inode_save (&parent, 1); fs_inode_save (&parent, 1);
/*printf ("*** inode %d: increment link counter to %d\n", parent.number, parent.nlink);*/ /*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) void add_device (fs_t *fs, char *name, char *spec)
{ {
fs_inode_t dev; fs_inode_t dev;
int majr, minr; int majr, minr;
char type; char type;
if (sscanf (spec, "%c%d:%d", &type, &majr, &minr) != 3 || if (sscanf (spec, "%c%d:%d", &type, &majr, &minr) != 3 ||
(type != 'c' && type != 'b') || (type != 'c' && type != 'b') ||
majr < 0 || majr > 255 || minr < 0 || minr > 255) { majr < 0 || majr > 255 || minr < 0 || minr > 255) {
fprintf (stderr, "%s: invalid device specification\n", spec); fprintf (stderr, "%s: invalid device specification\n", spec);
fprintf (stderr, "expected c<major>:<minor> or b<major>:<minor>\n"); fprintf (stderr, "expected c<major>:<minor> or b<major>:<minor>\n");
return; return;
} }
if (! fs_inode_by_name (fs, &dev, name, INODE_OP_CREATE, 0666 | if (! fs_inode_by_name (fs, &dev, name, INODE_OP_CREATE, 0666 |
((type == 'b') ? INODE_MODE_FBLK : INODE_MODE_FCHR))) { ((type == 'b') ? INODE_MODE_FBLK : INODE_MODE_FCHR))) {
fprintf (stderr, "%s: device inode create failed\n", name); fprintf (stderr, "%s: device inode create failed\n", name);
return; return;
} }
dev.addr[1] = majr << 8 | minr; dev.addr[1] = majr << 8 | minr;
time (&dev.mtime); time (&dev.mtime);
fs_inode_save (&dev, 1); 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) void add_file (fs_t *fs, char *name)
{ {
fs_file_t file; fs_file_t file;
FILE *fd; FILE *fd;
unsigned char data [BSDFS_BSIZE]; unsigned char data [BSDFS_BSIZE];
struct stat st; struct stat st;
char *p; char *p;
int len; int len;
if (verbose) { if (verbose) {
printf ("%s\n", name); printf ("%s\n", name);
} }
p = strrchr (name, '/'); p = strrchr (name, '/');
if (p && p[1] == 0) { if (p && p[1] == 0) {
*p = 0; *p = 0;
add_directory (fs, name); add_directory (fs, name);
return; return;
} }
p = strrchr (name, '!'); p = strrchr (name, '!');
if (p) { if (p) {
*p++ = 0; *p++ = 0;
add_device (fs, name, p); add_device (fs, name, p);
return; return;
} }
fd = fopen (name, "r"); fd = fopen (name, "r");
if (! fd) { if (! fd) {
perror (name); perror (name);
return; return;
} }
stat (name, &st); stat (name, &st);
if (! fs_file_create (fs, &file, name, st.st_mode)) { if (! fs_file_create (fs, &file, name, st.st_mode)) {
fprintf (stderr, "%s: cannot create\n", name); fprintf (stderr, "%s: cannot create\n", name);
return; return;
} }
for (;;) { for (;;) {
len = fread (data, 1, sizeof (data), fd); len = fread (data, 1, sizeof (data), fd);
/* printf ("read %d bytes from %s\n", len, name);*/ /* printf ("read %d bytes from %s\n", len, name);*/
if (len < 0) if (len < 0)
perror (name); perror (name);
if (len <= 0) if (len <= 0)
break; break;
if (! fs_file_write (&file, data, len)) { if (! fs_file_write (&file, data, len)) {
fprintf (stderr, "%s: write error\n", name); fprintf (stderr, "%s: write error\n", name);
break; break;
} }
} }
file.inode.mtime = st.st_mtime; file.inode.mtime = st.st_mtime;
file.inode.dirty = 1; file.inode.dirty = 1;
fs_file_close (&file); fs_file_close (&file);
fclose (fd); 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) void add_contents (fs_t *fs, const char *dirname, const char *manifest)
{ {
printf ("TODO: add contents from directory '%s'\n", dirname); printf ("TODO: add contents from directory '%s'\n", dirname);
if (manifest) if (manifest)
printf ("TODO: use manifest '%s'\n", manifest); printf ("TODO: use manifest '%s'\n", manifest);
} }
int main (int argc, char **argv) int main (int argc, char **argv)
{ {
int i, key; int i, key;
fs_t fs; fs_t fs;
fs_inode_t inode; fs_inode_t inode;
const char *manifest = 0; const char *manifest = 0;
for (;;) { for (;;) {
key = getopt_long (argc, argv, "vaxmMn:cfs:", key = getopt_long (argc, argv, "vaxmMn:cfs:",
program_options, 0); program_options, 0);
if (key == -1) if (key == -1)
break; break;
switch (key) { switch (key) {
case 'v': case 'v':
++verbose; ++verbose;
break; break;
case 'a': case 'a':
++add; ++add;
break; break;
case 'x': case 'x':
++extract; ++extract;
break; break;
case 'n': case 'n':
++newfs; ++newfs;
kbytes = strtol (optarg, 0, 0); kbytes = strtol (optarg, 0, 0);
break; break;
case 'c': case 'c':
++check; ++check;
break; break;
case 'f': case 'f':
++fix; ++fix;
break; break;
case 'm': case 'm':
++mount; ++mount;
break; break;
case 's': case 's':
swap_kbytes = strtol (optarg, 0, 0); swap_kbytes = strtol (optarg, 0, 0);
break; break;
case 'M': case 'M':
manifest = optarg; manifest = optarg;
break; break;
case 'V': case 'V':
printf ("%s\n", program_version); printf ("%s\n", program_version);
return 0; return 0;
case 'h': case 'h':
print_help (argv[0]); print_help (argv[0]);
return 0; return 0;
default: default:
print_help (argv[0]); print_help (argv[0]);
return -1; return -1;
} }
} }
i = optind; i = optind;
if ((! add && ! mount && ! newfs && i != argc-1) || if ((! add && ! mount && ! newfs && i != argc-1) ||
(add && i >= argc) || (add && i >= argc) ||
(newfs && i != argc-1 && i != argc-2) || (newfs && i != argc-1 && i != argc-2) ||
(mount && i != argc-2) || (mount && i != argc-2) ||
(extract + newfs + check + add + mount > 1) || (extract + newfs + check + add + mount > 1) ||
(newfs && kbytes < BSDFS_BSIZE * 10 / 1024)) { (newfs && kbytes < BSDFS_BSIZE * 10 / 1024))
print_help (argv[0]); {
return -1; print_help (argv[0]);
} return -1;
}
if (newfs) { if (newfs) {
/* Create new filesystem. */ /* Create new filesystem. */
if (! fs_create (&fs, argv[i], kbytes, swap_kbytes)) { if (! fs_create (&fs, argv[i], kbytes, swap_kbytes)) {
fprintf (stderr, "%s: cannot create filesystem\n", argv[i]); fprintf (stderr, "%s: cannot create filesystem\n", argv[i]);
return -1; return -1;
} }
printf ("Created filesystem %s - %u kbytes\n", argv[i], kbytes); printf ("Created filesystem %s - %u kbytes\n", argv[i], kbytes);
if (i == argc-2) { if (i == argc-2) {
/* Add the contents from the specified directory. /* Add the contents from the specified directory.
* Use the optional manifest file. */ * Use the optional manifest file. */
add_contents (&fs, argv[i+1], manifest); add_contents (&fs, argv[i+1], manifest);
} }
fs_close (&fs); fs_close (&fs);
return 0; return 0;
} }
if (check) { if (check) {
/* Check filesystem for errors, and optionally fix them. */ /* Check filesystem for errors, and optionally fix them. */
if (! fs_open (&fs, argv[i], fix)) { if (! fs_open (&fs, argv[i], fix)) {
fprintf (stderr, "%s: cannot open\n", argv[i]); fprintf (stderr, "%s: cannot open\n", argv[i]);
return -1; return -1;
} }
fs_check (&fs); fs_check (&fs);
fs_close (&fs); fs_close (&fs);
return 0; return 0;
} }
/* Add or extract or info. */ /* Add or extract or info. */
if (! fs_open (&fs, argv[i], (add + mount != 0))) { if (! fs_open (&fs, argv[i], (add + mount != 0))) {
fprintf (stderr, "%s: cannot open\n", argv[i]); fprintf (stderr, "%s: cannot open\n", argv[i]);
return -1; return -1;
} }
if (extract) { if (extract) {
/* Extract all files to current directory. */ /* Extract all files to current directory. */
if (! fs_inode_get (&fs, &inode, BSDFS_ROOT_INODE)) { if (! fs_inode_get (&fs, &inode, BSDFS_ROOT_INODE)) {
fprintf (stderr, "%s: cannot get inode 1\n", argv[i]); fprintf (stderr, "%s: cannot get inode 1\n", argv[i]);
return -1; return -1;
} }
fs_directory_scan (&inode, "", extractor, (void*) stdout); fs_directory_scan (&inode, "", extractor, (void*) stdout);
fs_close (&fs); fs_close (&fs);
return 0; return 0;
} }
if (add) { if (add) {
/* Add files i+1..argc-1 to filesystem. */ /* Add files i+1..argc-1 to filesystem. */
while (++i < argc) while (++i < argc)
add_file (&fs, argv[i]); add_file (&fs, argv[i]);
fs_sync (&fs, 0); fs_sync (&fs, 0);
fs_close (&fs); fs_close (&fs);
return 0; return 0;
} }
if (mount) { if (mount) {
/* Mount the filesystem. */ /* Mount the filesystem. */
if (++i >= argc) { if (++i >= argc) {
print_help (argv[0]); print_help (argv[0]);
return -1; return -1;
} }
return fs_mount(&fs, argv[i]); return fs_mount(&fs, argv[i]);
} }
/* Print the structure of flesystem. */ /* Print the structure of flesystem. */
fs_print (&fs, stdout); fs_print (&fs, stdout);
if (verbose) { if (verbose) {
printf ("--------\n"); printf ("--------\n");
if (! fs_inode_get (&fs, &inode, BSDFS_ROOT_INODE)) { if (! fs_inode_get (&fs, &inode, BSDFS_ROOT_INODE)) {
fprintf (stderr, "%s: cannot get inode 1\n", argv[i]); fprintf (stderr, "%s: cannot get inode 1\n", argv[i]);
return -1; return -1;
} }
printf ("/\n"); printf ("/\n");
if (verbose > 1) { if (verbose > 1) {
/* Print a list of blocks. */ /* Print a list of blocks. */
print_inode_blocks (&inode, stdout); print_inode_blocks (&inode, stdout);
if (verbose > 2) { if (verbose > 2) {
fs_inode_print (&inode, stdout); fs_inode_print (&inode, stdout);
printf ("--------\n"); printf ("--------\n");
} }
} }
fs_directory_scan (&inode, "", scanner, (void*) stdout); fs_directory_scan (&inode, "", scanner, (void*) stdout);
} }
fs_close (&fs); fs_close (&fs);
return 0; return 0;
} }

File diff suppressed because it is too large Load Diff

View File

@@ -32,298 +32,300 @@ extern int verbose;
int fs_seek (fs_t *fs, unsigned long offset) int fs_seek (fs_t *fs, unsigned long offset)
{ {
/* printf ("seek %ld, block %ld\n", offset, offset / BSDFS_BSIZE);*/ /* printf ("seek %ld, block %ld\n", offset, offset / BSDFS_BSIZE);*/
if (lseek (fs->fd, offset, 0) < 0) { if (lseek (fs->fd, offset, 0) < 0) {
if (verbose) if (verbose)
printf ("error seeking %ld, block %ld\n", printf ("error seeking %ld, block %ld\n",
offset, offset / BSDFS_BSIZE); offset, offset / BSDFS_BSIZE);
return 0; return 0;
} }
fs->seek = offset; fs->seek = offset;
return 1; return 1;
} }
int fs_read8 (fs_t *fs, unsigned char *val) int fs_read8 (fs_t *fs, unsigned char *val)
{ {
if (read (fs->fd, val, 1) != 1) { if (read (fs->fd, val, 1) != 1) {
if (verbose) if (verbose)
printf ("error read8, seek %ld block %ld\n", fs->seek, fs->seek / BSDFS_BSIZE); printf ("error read8, seek %ld block %ld\n", fs->seek, fs->seek / BSDFS_BSIZE);
return 0; return 0;
} }
return 1; return 1;
} }
int fs_read16 (fs_t *fs, unsigned short *val) 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 (read (fs->fd, data, 2) != 2) {
if (verbose) if (verbose)
printf ("error read16, seek %ld block %ld\n", fs->seek, fs->seek / BSDFS_BSIZE); printf ("error read16, seek %ld block %ld\n", fs->seek, fs->seek / BSDFS_BSIZE);
return 0; return 0;
} }
*val = data[1] << 8 | data[0]; *val = data[1] << 8 | data[0];
return 1; return 1;
} }
int fs_read32 (fs_t *fs, unsigned *val) int fs_read32 (fs_t *fs, unsigned *val)
{ {
unsigned char data [4]; unsigned char data [4];
if (read (fs->fd, data, 4) != 4) { if (read (fs->fd, data, 4) != 4) {
if (verbose) if (verbose)
printf ("error read32, seek %ld block %ld\n", fs->seek, fs->seek / BSDFS_BSIZE); printf ("error read32, seek %ld block %ld\n", fs->seek, fs->seek / BSDFS_BSIZE);
return 0; return 0;
} }
*val = (unsigned long) data[0] | (unsigned long) data[1] << 8 | *val = (unsigned long) data[0] | (unsigned long) data[1] << 8 |
data[2] << 16 | data[3] << 24; data[2] << 16 | data[3] << 24;
return 1; return 1;
} }
int fs_write8 (fs_t *fs, unsigned char val) int fs_write8 (fs_t *fs, unsigned char val)
{ {
if (write (fs->fd, &val, 1) != 1) if (write (fs->fd, &val, 1) != 1)
return 0; return 0;
return 1; return 1;
} }
int fs_write16 (fs_t *fs, unsigned short val) int fs_write16 (fs_t *fs, unsigned short val)
{ {
unsigned char data [2]; unsigned char data [2];
data[0] = val; data[0] = val;
data[1] = val >> 8; data[1] = val >> 8;
if (write (fs->fd, data, 2) != 2) if (write (fs->fd, data, 2) != 2)
return 0; return 0;
return 1; return 1;
} }
int fs_write32 (fs_t *fs, unsigned val) int fs_write32 (fs_t *fs, unsigned val)
{ {
unsigned char data [4]; unsigned char data [4];
data[0] = val; data[0] = val;
data[1] = val >> 8; data[1] = val >> 8;
data[2] = val >> 16; data[2] = val >> 16;
data[3] = val >> 24; data[3] = val >> 24;
if (write (fs->fd, data, 4) != 4) if (write (fs->fd, data, 4) != 4)
return 0; return 0;
return 1; return 1;
} }
int fs_read (fs_t *fs, unsigned char *data, int bytes) int fs_read (fs_t *fs, unsigned char *data, int bytes)
{ {
int len; int len;
while (bytes > 0) { while (bytes > 0) {
len = bytes; len = bytes;
if (len > 16*BSDFS_BSIZE) if (len > 16*BSDFS_BSIZE)
len = 16*BSDFS_BSIZE; len = 16*BSDFS_BSIZE;
if (read (fs->fd, data, len) != len) if (read (fs->fd, data, len) != len)
return 0; return 0;
data += len; data += len;
bytes -= len; bytes -= len;
} }
return 1; return 1;
} }
int fs_write (fs_t *fs, unsigned char *data, int bytes) int fs_write (fs_t *fs, unsigned char *data, int bytes)
{ {
int len; int len;
if (! fs->writable) if (! fs->writable)
return 0; return 0;
while (bytes > 0) { while (bytes > 0) {
len = bytes; len = bytes;
if (len > 16*BSDFS_BSIZE) if (len > 16*BSDFS_BSIZE)
len = 16*BSDFS_BSIZE; len = 16*BSDFS_BSIZE;
if (write (fs->fd, data, len) != len) if (write (fs->fd, data, len) != len)
return 0; return 0;
data += len; data += len;
bytes -= len; bytes -= len;
} }
return 1; return 1;
} }
int fs_open (fs_t *fs, const char *filename, int writable) int fs_open (fs_t *fs, const char *filename, int writable)
{ {
int i; int i;
unsigned magic; unsigned magic;
memset (fs, 0, sizeof (*fs)); memset (fs, 0, sizeof (*fs));
fs->filename = filename; fs->filename = filename;
fs->seek = 0; fs->seek = 0;
fs->fd = open (fs->filename, writable ? O_RDWR : O_RDONLY); fs->fd = open (fs->filename, writable ? O_RDWR : O_RDONLY);
if (fs->fd < 0) if (fs->fd < 0)
return 0; return 0;
fs->writable = writable; fs->writable = writable;
if (! fs_read32 (fs, &magic) || /* magic word */ if (! fs_read32 (fs, &magic) || /* magic word */
magic != FSMAGIC1) { magic != FSMAGIC1) {
if (verbose) if (verbose)
printf ("fs_open: bad magic1 = %08x, expected %08x\n", printf ("fs_open: bad magic1 = %08x, expected %08x\n",
magic, FSMAGIC1); magic, FSMAGIC1);
return 0; return 0;
} }
if (! fs_read32 (fs, &fs->isize)) /* size in blocks of I list */ if (! fs_read32 (fs, &fs->isize)) /* size in blocks of I list */
return 0; return 0;
if (! fs_read32 (fs, &fs->fsize)) /* size in blocks of entire volume */ if (! fs_read32 (fs, &fs->fsize)) /* size in blocks of entire volume */
return 0; return 0;
if (! fs_read32 (fs, &fs->swapsz)) /* size in blocks of swap area */ if (! fs_read32 (fs, &fs->swapsz)) /* size in blocks of swap area */
return 0; return 0;
if (! fs_read32 (fs, &fs->nfree)) /* number of in core free blocks */ if (! fs_read32 (fs, &fs->nfree)) /* number of in core free blocks */
return 0; return 0;
for (i=0; i<NICFREE; ++i) { /* in core free blocks */ for (i=0; i<NICFREE; ++i) { /* in core free blocks */
if (! fs_read32 (fs, &fs->free[i])) if (! fs_read32 (fs, &fs->free[i]))
return 0; return 0;
} }
if (! fs_read32 (fs, &fs->ninode)) /* number of in core I nodes */ if (! fs_read32 (fs, &fs->ninode)) /* number of in core I nodes */
return 0; return 0;
for (i=0; i<NICINOD; ++i) { /* in core free I nodes */ for (i=0; i<NICINOD; ++i) { /* in core free I nodes */
if (! fs_read32 (fs, &fs->inode[i])) if (! fs_read32 (fs, &fs->inode[i]))
return 0; return 0;
} }
if (! fs_read32 (fs, &fs->flock)) if (! fs_read32 (fs, &fs->flock))
return 0; return 0;
if (! fs_read32 (fs, &fs->fmod)) if (! fs_read32 (fs, &fs->fmod))
return 0; return 0;
if (! fs_read32 (fs, &fs->ilock)) if (! fs_read32 (fs, &fs->ilock))
return 0; return 0;
if (! fs_read32 (fs, &fs->ronly)) if (! fs_read32 (fs, &fs->ronly))
return 0; return 0;
if (! fs_read32 (fs, (unsigned*) &fs->utime)) if (! fs_read32 (fs, (unsigned*) &fs->utime))
return 0; /* current date of last update */ return 0; /* current date of last update */
if (! fs_read32 (fs, &fs->tfree)) /* total free blocks */ if (! fs_read32 (fs, &fs->tfree)) /* total free blocks */
return 0; return 0;
if (! fs_read32 (fs, &fs->tinode)) /* total free inodes */ if (! fs_read32 (fs, &fs->tinode)) /* total free inodes */
return 0; return 0;
if (! fs_read (fs, (unsigned char*) fs->fsmnt, MAXMNTLEN)) if (! fs_read (fs, (unsigned char*) fs->fsmnt, MAXMNTLEN))
return 0; /* ordinary file mounted on */ return 0; /* ordinary file mounted on */
if (! fs_read32 (fs, &fs->lasti)) /* start place for circular search */ if (! fs_read32 (fs, &fs->lasti)) /* start place for circular search */
return 0; return 0;
if (! fs_read32 (fs, &fs->nbehind)) /* est # free inodes before s_lasti */ if (! fs_read32 (fs, &fs->nbehind)) /* est # free inodes before s_lasti */
return 0; return 0;
if (! fs_read32 (fs, &fs->flags)) /* mount time flags */ if (! fs_read32 (fs, &fs->flags)) /* mount time flags */
return 0; return 0;
if (! fs_read32 (fs, &magic) || /* magic word */ if (! fs_read32 (fs, &magic) || /* magic word */
magic != FSMAGIC2) { magic != FSMAGIC2) {
if (verbose) if (verbose)
printf ("fs_open: bad magic2 = %08x, expected %08x\n", printf ("fs_open: bad magic2 = %08x, expected %08x\n",
magic, FSMAGIC2); magic, FSMAGIC2);
return 0; return 0;
} }
return 1; return 1;
} }
int fs_sync (fs_t *fs, int force) int fs_sync (fs_t *fs, int force)
{ {
int i; int i;
if (! fs->writable) if (! fs->writable)
return 0; return 0;
if (! force && ! fs->dirty) if (! force && ! fs->dirty)
return 1; return 1;
time (&fs->utime); time (&fs->utime);
if (! fs_seek (fs, 0)) if (! fs_seek (fs, 0))
return 0; return 0;
if (! fs_write32 (fs, FSMAGIC1)) /* magic word */ if (! fs_write32 (fs, FSMAGIC1)) /* magic word */
return 0; return 0;
if (! fs_write32 (fs, fs->isize)) /* size in blocks of I list */ if (! fs_write32 (fs, fs->isize)) /* size in blocks of I list */
return 0; return 0;
if (! fs_write32 (fs, fs->fsize)) /* size in blocks of entire volume */ if (! fs_write32 (fs, fs->fsize)) /* size in blocks of entire volume */
return 0; return 0;
if (! fs_write32 (fs, fs->swapsz)) /* size in blocks of swap area */ if (! fs_write32 (fs, fs->swapsz)) /* size in blocks of swap area */
return 0; return 0;
if (! fs_write32 (fs, fs->nfree)) /* number of in core free blocks */ if (! fs_write32 (fs, fs->nfree)) /* number of in core free blocks */
return 0; return 0;
for (i=0; i<NICFREE; ++i) { /* in core free blocks */ for (i=0; i<NICFREE; ++i) { /* in core free blocks */
if (! fs_write32 (fs, fs->free[i])) if (! fs_write32 (fs, fs->free[i]))
return 0; return 0;
} }
if (! fs_write32 (fs, fs->ninode)) /* number of in core I nodes */ if (! fs_write32 (fs, fs->ninode)) /* number of in core I nodes */
return 0; return 0;
for (i=0; i<NICINOD; ++i) { /* in core free I nodes */ for (i=0; i<NICINOD; ++i) { /* in core free I nodes */
if (! fs_write32 (fs, fs->inode[i])) if (! fs_write32 (fs, fs->inode[i]))
return 0; return 0;
} }
if (! fs_write32 (fs, fs->flock)) if (! fs_write32 (fs, fs->flock))
return 0; return 0;
if (! fs_write32 (fs, fs->fmod)) if (! fs_write32 (fs, fs->fmod))
return 0; return 0;
if (! fs_write32 (fs, fs->ilock)) if (! fs_write32 (fs, fs->ilock))
return 0; return 0;
if (! fs_write32 (fs, fs->ronly)) if (! fs_write32 (fs, fs->ronly))
return 0; return 0;
if (! fs_write32 (fs, fs->utime)) /* current date of last update */ if (! fs_write32 (fs, fs->utime)) /* current date of last update */
return 0; return 0;
if (! fs_write32 (fs, fs->tfree)) /* total free blocks */ if (! fs_write32 (fs, fs->tfree)) /* total free blocks */
return 0; return 0;
if (! fs_write32 (fs, fs->tinode)) /* total free inodes */ if (! fs_write32 (fs, fs->tinode)) /* total free inodes */
return 0; return 0;
if (! fs_write (fs, (unsigned char*) fs->fsmnt, MAXMNTLEN)) if (! fs_write (fs, (unsigned char*) fs->fsmnt, MAXMNTLEN))
return 0; /* ordinary file mounted on */ return 0; /* ordinary file mounted on */
if (! fs_write32 (fs, 0)) /* lasti*/ if (! fs_write32 (fs, 0)) /* lasti*/
return 0; return 0;
if (! fs_write32 (fs, 0)) /* nbehind */ if (! fs_write32 (fs, 0)) /* nbehind */
return 0; return 0;
if (! fs_write32 (fs, 0)) /* flags */ if (! fs_write32 (fs, 0)) /* flags */
return 0; return 0;
if (! fs_write32 (fs, FSMAGIC2)) /* magic word */ if (! fs_write32 (fs, FSMAGIC2)) /* magic word */
return 0; return 0;
fs->dirty = 0; fs->dirty = 0;
return 1; return 1;
} }
void fs_print (fs_t *fs, FILE *out) void fs_print (fs_t *fs, FILE *out)
{ {
int i; int i;
fprintf (out, " File: %s\n", fs->filename); fprintf (out, " File: %s\n", fs->filename);
fprintf (out, " Volume size: %u blocks\n", fs->fsize); fprintf (out, " Volume size: %u blocks\n", fs->fsize);
fprintf (out, " Inode list size: %u blocks\n", fs->isize); fprintf (out, " Inode list size: %u blocks\n", fs->isize);
fprintf (out, " Swap size: %u blocks\n", fs->swapsz); fprintf (out, " Swap size: %u blocks\n", fs->swapsz);
fprintf (out, " Total free blocks: %u blocks\n", fs->tfree); fprintf (out, " Total free blocks: %u blocks\n", fs->tfree);
fprintf (out, " Total free inodes: %u inodes\n", fs->tinode); fprintf (out, " Total free inodes: %u inodes\n", fs->tinode);
fprintf (out, " Last mounted on: %.*s\n", MAXMNTLEN, fprintf (out, " Last mounted on: %.*s\n", MAXMNTLEN,
fs->fsmnt[0] ? fs->fsmnt : "(none)"); fs->fsmnt[0] ? fs->fsmnt : "(none)");
fprintf (out, " In-core free list: %u blocks", fs->nfree); fprintf (out, " In-core free list: %u blocks", fs->nfree);
if (verbose) if (verbose) {
for (i=0; i < NICFREE && i < fs->nfree; ++i) { for (i=0; i < NICFREE && i < fs->nfree; ++i) {
if (i % 10 == 0) if (i % 10 == 0)
fprintf (out, "\n "); fprintf (out, "\n ");
fprintf (out, " %u", fs->free[i]); fprintf (out, " %u", fs->free[i]);
} }
fprintf (out, "\n"); }
fprintf (out, "\n");
fprintf (out, " In-core free inodes: %u inodes", fs->ninode); fprintf (out, " In-core free inodes: %u inodes", fs->ninode);
if (verbose) if (verbose) {
for (i=0; i < NICINOD && i < fs->ninode; ++i) { for (i=0; i < NICINOD && i < fs->ninode; ++i) {
if (i % 10 == 0) if (i % 10 == 0)
fprintf (out, "\n "); fprintf (out, "\n ");
fprintf (out, " %u", fs->inode[i]); fprintf (out, " %u", fs->inode[i]);
} }
fprintf (out, "\n"); }
if (verbose) { fprintf (out, "\n");
// fprintf (out, " Free list lock: %u\n", fs->flock); if (verbose) {
// fprintf (out, " Inode list lock: %u\n", fs->ilock); // fprintf (out, " Free list lock: %u\n", fs->flock);
// fprintf (out, "Super block modified: %u\n", fs->fmod); // fprintf (out, " Inode list lock: %u\n", fs->ilock);
// fprintf (out, " Mounted read-only: %u\n", fs->ronly); // fprintf (out, "Super block modified: %u\n", fs->fmod);
// fprintf (out, " Circ.search start: %u\n", fs->lasti); // fprintf (out, " Mounted read-only: %u\n", fs->ronly);
// fprintf (out, " Circ.search behind: %u\n", fs->nbehind); // fprintf (out, " Circ.search start: %u\n", fs->lasti);
// fprintf (out, " Mount flags: 0x%x\n", fs->flags); // 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) void fs_close (fs_t *fs)
{ {
if (fs->fd < 0) if (fs->fd < 0)
return; return;
close (fs->fd); close (fs->fd);
fs->fd = -1; fs->fd = -1;
} }