/* * Data structures for 2.xBSD filesystem. * * Copyright (C) 2006-2014 Serge Vakulenko, * * Permission to use, copy, modify, and distribute this software * and its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice appear in all * copies and that both that the copyright notice and this * permission notice and warranty disclaimer appear in supporting * documentation, and that the name of the author not be used in * advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * * The author disclaim all warranties with regard to this * software, including all implied warranties of merchantability * and fitness. In no event shall the author be liable for any * special, indirect or consequential damages or any damages * whatsoever resulting from loss of use, data or profits, whether * in an action of contract, negligence or other tortious action, * 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 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 */ /* * 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 */ /* * 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 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 */ unsigned char part_type; unsigned part_offset; unsigned part_nsectors; 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 */ time_t 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 */ 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 */ /* * 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 */ /* * 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 */ time_t atime; /* time last accessed */ time_t mtime; /* time last modified */ time_t ctime; /* time created */ } fs_inode_t; typedef struct { 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); typedef struct { 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 */ } fs_op_t; int fs_seek (fs_t *fs, unsigned long offset); int fs_read8 (fs_t *fs, unsigned char *val); int fs_read16 (fs_t *fs, unsigned short *val); int fs_read32 (fs_t *fs, unsigned *val); int fs_write8 (fs_t *fs, unsigned char val); int fs_write16 (fs_t *fs, unsigned short val); int fs_write32 (fs_t *fs, unsigned val); int fs_read (fs_t *fs, unsigned char *data, int bytes); int fs_write (fs_t *fs, unsigned char *data, int bytes); int fs_open (fs_t *fs, const char *filename, int writable, unsigned pindex); void fs_close (fs_t *fs); int fs_set_partition (fs_t *fs, unsigned pindex); int fs_sync (fs_t *fs, int force); int fs_create (fs_t *fs, const char *filename, int kbytes, unsigned swap_kbytes); int fs_check (fs_t *fs); void fs_print (fs_t *fs, FILE *out); int fs_mount(fs_t *fs, char *dirname); int fs_inode_get (fs_t *fs, fs_inode_t *inode, unsigned inum); int fs_inode_save (fs_inode_t *inode, int force); 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); int fs_inode_write (fs_inode_t *inode, unsigned long offset, 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); int fs_inode_lookup (fs_t *fs, fs_inode_t *inode, const char *name); int fs_inode_create (fs_t *fs, fs_inode_t *inode, const char *name, int mode); int fs_inode_delete (fs_t *fs, fs_inode_t *inode, const char *name); int fs_inode_link (fs_t *fs, fs_inode_t *inode, const char *name, int mode); int inode_build_list (fs_t *fs); int fs_write_block (fs_t *fs, unsigned bnum, unsigned char *data); int fs_read_block (fs_t *fs, unsigned bnum, unsigned char *data); int fs_block_free (fs_t *fs, unsigned int bno); int fs_block_alloc (fs_t *fs, unsigned int *bno); 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_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); 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); int fs_file_write (fs_file_t *file, unsigned char *data, unsigned long bytes); int fs_file_close (fs_file_t *file);