/* * An FFS file system is a sequence of cylinder groups. * * Each cylinder group is laid out as follows: * * fs superblock (Fsblk) * cylinder group block (Cgblk) * inodes * data * * The location of the fs superblock in the first cylinder * group is known. The rest of the info about cylinder group * layout can be derived from the super block. */ #define daddr_t u32int#define time_t u32int typedef struct Cgblk Cgblk;typedef struct Cylgrp Cylgrp;typedef struct Cylsum Cylsum;typedef struct Cylsumtotal Cylsumtotal;typedef struct Ffs Ffs;typedef struct Fsblk Fsblk;typedef struct Inode1 Inode1;typedef struct Inode Inode;typedef struct Dirent Dirent; enum{ BYTESPERSEC = 512, /* constants for Fsblk */ FSMAXMNTLEN = 512, FSMAXMNTLEN2 = 468, FSMAXVOLLEN = 32, /* UFS2 */ FSNOCSPTRSLEN = 128-12, FSNOCSPTRSLEN2 = 128-16, /* UFS2 */ FSMAXSNAP = 20, FSMAGIC = 0x011954, FSMAGIC2 = 0x19540119, FSCHECKSUM = 0x7c269d38, /* Fsblk.inodefmt */ FS42INODEFMT = -1, FS44INODEFMT = 2, /* offset and size of first boot block */ BBOFF = 0, BBSIZE = 8192, /* offset and size of first super block */ SBOFF = BBOFF+BBSIZE, SBOFF2 = BBOFF+65536, /* UFS2 */ SBOFFPIGGY = BBOFF+262144, /* UFS2 */ SBSIZE = 8192, /* minimum block size */ MINBSIZE = 4096, /* maximum fragments per block */ MAXFRAG = 8, /* constants for Cgblk */ CGMAGIC = 0x090255, /* inode-related */ ROOTINODE = 2, WHITEOUT = 1, NXADDR = 2, /* UFS2 */ NDADDR = 12, NIADDR = 3, /* permissions in Inode.mode */ IEXEC = 00100, IWRITE = 0200, IREAD = 0400, ISVTX = 01000, ISGID = 02000, ISUID = 04000, /* type in Inode.mode */ IFMT = 0170000, IFIFO = 0010000, IFCHR = 0020000, IFDIR = 0040000, IFBLK = 0060000, IFREG = 0100000, IFLNK = 0120000, IFSOCK = 0140000, IFWHT = 0160000, /* type in Dirent.type */ DTUNKNOWN = 0, DTFIFO = 1, DTCHR = 2, DTDIR = 4, DTBLK = 6, DTREG = 8, DTLNK = 10, DTSOCK = 12, DTWHT = 14}; struct Cylsum{ u32int ndir; u32int nbfree; u32int nifree; u32int nffree;}; struct Cylsumtotal{ u64int ndir; u64int nbfree; u64int nifree; u64int nffree; u64int numclusters; u64int unused[3];}; /* Fields beginning with underscore are deprecated in UFS2 */struct Fsblk{ u32int unused0; u32int unused1; daddr_t sfragno; /* fragment address of super block in file system */ daddr_t cfragno; /* fragment address if cylinder block in file system */ daddr_t ifragno; /* fragment offset of inode blocks in file system */ daddr_t dfragno; /* fragment offset of data blocks in cg */ u32int _cgoffset; /* block (maybe fragment?) offset of Cgblk in cylinder */ u32int _cgmask; time_t _time; u32int _nfrag; /* number of blocks in fs * fragsperblock */ u32int _ndfrag; u32int ncg; /* number of cylinder groups in fs */ u32int blocksize; /* block size in fs */ u32int fragsize; /* frag size in fs */ u32int fragsperblock; /* fragments per block: blocksize / fragsize */ u32int minfree; /* ignored by us */ u32int rotdelay; /* ... */ u32int rps; u32int bmask; u32int fmask; u32int bshift; u32int fshift; u32int maxcontig; u32int maxbpg; u32int fragshift; u32int fsbtodbshift; u32int sbsize; /* size of super block */ u32int unused2; /* more stuff we don't use ... */ u32int unused3; u32int nindir; u32int inosperblock; /* inodes per block */ u32int _nspf; u32int optim; u32int _npsect; u32int _interleave; u32int _trackskew; u32int id[2]; daddr_t _csaddr; /* blk addr of cyl grp summary area */ u32int cssize; /* size of cyl grp summary area */ u32int cgsize; /* cylinder group size */ u32int _trackspercyl; /* tracks per cylinder */ u32int _secspertrack; /* sectors per track */ u32int _secspercyl; /* sectors per cylinder */ u32int _ncyl; /* cylinders in fs */ u32int _cylspergroup; /* cylinders per group */ u32int inospergroup; /* inodes per group */ u32int fragspergroup; /* data blocks per group * fragperblock */ Cylsum _cstotal; /* more unused... */ u8int fmod; u8int clean; u8int ronly; u8int _flags; /* char fsmnt[512]; in UFS1 */ char fsmnt[FSMAXMNTLEN2]; char volname[FSMAXVOLLEN]; u64int swuid; u32int pad; u32int cgrotor; uchar ocsp[FSNOCSPTRSLEN]; /* last 4 bytes is contigdirs in UFS2 */ u32int contigdirs; /* csp in UFS2 */ u32int csp; /* maxcluster in UFS2 */ u32int maxcluster; /* active in UFS2 */ u32int _cpc; /* u16int opostbl[16][8]; in UFS1 */ u32int maxbsize; u64int spare64[17]; u64int sblockloc; Cylsumtotal cstotal; u64int time; u64int nfrag; u64int ndfrag; u64int csaddr; u64int pendingblocks; u32int pendinginodes; u32int snapinum[FSMAXSNAP]; u32int avgfilesize; u32int avgfpdir; /* u32int sparecon[26], pendingblocks, pendinginodes; in UFS1 */ u32int savecgsize; u32int sparecon[26]; u32int flags; u32int contigsumsize; u32int maxsymlinklen; u32int _inodefmt; /* format of on-disk inodes */ u64int maxfilesize; /* maximum representable file size */ u64int qbmask; u64int qfmask; u32int state; u32int _postblformat; u32int _nrpos; u32int _postbloff; u32int _rotbloff; u32int magic; /* FSMAGIC or FSMAGIC2 */}; /* * Cylinder group block for a file system. */struct Cgblk{ u32int unused0; u32int magic; /* CGMAGIC */ u32int time; /* time last written */ u32int num; /* we are cg #cgnum */ u16int ncyl; /* number of cylinders in gp */ u16int nino; /* number of inodes */ u32int nfrag; /* number of fragments */ Cylsum csum; u32int rotor; u32int frotor; u32int irotor; u32int frsum[MAXFRAG]; /* counts of available frags */ u32int btotoff; u32int boff; u32int imapoff; /* offset to used inode map */ u32int fmapoff; /* offset to free fragment map */ u32int nextfrag; /* next free fragment */ u32int csumoff; u32int clusteroff; u32int ncluster; u32int sparecon[13];}; struct Cylgrp{ /* these are block numbers not fragment numbers */ u64int bno; /* disk block address of start of cg */ u64int ibno; /* disk block address of first inode */ u64int dbno; /* disk block address of first data */ u64int cgblkno;}; /* * this is the on-disk structure */struct Inode1{ u16int mode; u16int nlink; u32int unused; u64int size; u32int atime; u32int atimensec; u32int mtime; u32int mtimensec; u32int ctime; u32int ctimensec; /* rdev is db[0] */ u32int db[NDADDR]; u32int ib[NIADDR]; u32int flags; u32int nblock; u32int gen; u32int uid; u32int gid; u32int spare[2];}; struct Inode{ u16int mode; u16int nlink; u32int uid; u32int gid; u32int blksize; u64int size; u64int nblock; u64int atime; u64int mtime; u64int ctime; u64int btime; u32int atimensec; u32int mtimensec; u32int ctimensec; u32int btimensec; u32int gen; u32int kernflags; u32int flags; u32int extsize; u64int ext[NXADDR]; u64int db[NDADDR]; u64int ib[NIADDR]; u64int spare[3];}; struct Dirent{ u32int ino; u16int reclen; u8int type; u8int namlen; char name[1];}; /* * main file system structure */struct Ffs{ int ufs; int blocksize; u64int nblock; int fragsize; int fragsperblock; int inosperblock; u64int blockspergroup; u64int fragspergroup; int inospergroup; u64int nfrag; u64int ndfrag; int ncg; Cylgrp *cg; Disk *disk;};
/*
* An FFS file system is a sequence of cylinder groups.
*
* Each cylinder group is laid out as follows:
*
* fs superblock (Fsblk)
* cylinder group block (Cgblk)
* inodes
* data
*
* The location of the fs superblock in the first cylinder
* group is known. The rest of the info about cylinder group
* layout can be derived from the super block.
*/
#define daddr_t u32int
#define time_t u32int
typedef struct Cgblk Cgblk;
typedef struct Cylgrp Cylgrp;
typedef struct Cylsum Cylsum;
typedef struct Cylsumtotal Cylsumtotal;
typedef struct Ffs Ffs;
typedef struct Fsblk Fsblk;
typedef struct Inode1 Inode1;
typedef struct Inode Inode;
typedef struct Dirent Dirent;
enum
{
BYTESPERSEC = 512,
/* constants for Fsblk */
FSMAXMNTLEN = 512,
FSMAXMNTLEN2 = 468,
FSMAXVOLLEN = 32, /* UFS2 */
FSNOCSPTRSLEN = 128-12,
FSNOCSPTRSLEN2 = 128-16, /* UFS2 */
FSMAXSNAP = 20,
FSMAGIC = 0x011954,
FSMAGIC2 = 0x19540119,
FSCHECKSUM = 0x7c269d38,
/* Fsblk.inodefmt */
FS42INODEFMT = -1,
FS44INODEFMT = 2,
/* offset and size of first boot block */
BBOFF = 0,
BBSIZE = 8192,
/* offset and size of first super block */
SBOFF = BBOFF+BBSIZE,
SBOFF2 = BBOFF+65536, /* UFS2 */
SBOFFPIGGY = BBOFF+262144, /* UFS2 */
SBSIZE = 8192,
/* minimum block size */
MINBSIZE = 4096,
/* maximum fragments per block */
MAXFRAG = 8,
/* constants for Cgblk */
CGMAGIC = 0x090255,
/* inode-related */
ROOTINODE = 2,
WHITEOUT = 1,
NXADDR = 2, /* UFS2 */
NDADDR = 12,
NIADDR = 3,
/* permissions in Inode.mode */
IEXEC = 00100,
IWRITE = 0200,
IREAD = 0400,
ISVTX = 01000,
ISGID = 02000,
ISUID = 04000,
/* type in Inode.mode */
IFMT = 0170000,
IFIFO = 0010000,
IFCHR = 0020000,
IFDIR = 0040000,
IFBLK = 0060000,
IFREG = 0100000,
IFLNK = 0120000,
IFSOCK = 0140000,
IFWHT = 0160000,
/* type in Dirent.type */
DTUNKNOWN = 0,
DTFIFO = 1,
DTCHR = 2,
DTDIR = 4,
DTBLK = 6,
DTREG = 8,
DTLNK = 10,
DTSOCK = 12,
DTWHT = 14
};
struct Cylsum
{
u32int ndir;
u32int nbfree;
u32int nifree;
u32int nffree;
};
struct Cylsumtotal
{
u64int ndir;
u64int nbfree;
u64int nifree;
u64int nffree;
u64int numclusters;
u64int unused[3];
};
/* Fields beginning with underscore are deprecated in UFS2 */
struct Fsblk
{
u32int unused0;
u32int unused1;
daddr_t sfragno; /* fragment address of super block in file system */
daddr_t cfragno; /* fragment address if cylinder block in file system */
daddr_t ifragno; /* fragment offset of inode blocks in file system */
daddr_t dfragno; /* fragment offset of data blocks in cg */
u32int _cgoffset; /* block (maybe fragment?) offset of Cgblk in cylinder */
u32int _cgmask;
time_t _time;
u32int _nfrag; /* number of blocks in fs * fragsperblock */
u32int _ndfrag;
u32int ncg; /* number of cylinder groups in fs */
u32int blocksize; /* block size in fs */
u32int fragsize; /* frag size in fs */
u32int fragsperblock; /* fragments per block: blocksize / fragsize */
u32int minfree; /* ignored by us */
u32int rotdelay; /* ... */
u32int rps;
u32int bmask;
u32int fmask;
u32int bshift;
u32int fshift;
u32int maxcontig;
u32int maxbpg;
u32int fragshift;
u32int fsbtodbshift;
u32int sbsize; /* size of super block */
u32int unused2; /* more stuff we don't use ... */
u32int unused3;
u32int nindir;
u32int inosperblock; /* inodes per block */
u32int _nspf;
u32int optim;
u32int _npsect;
u32int _interleave;
u32int _trackskew;
u32int id[2];
daddr_t _csaddr; /* blk addr of cyl grp summary area */
u32int cssize; /* size of cyl grp summary area */
u32int cgsize; /* cylinder group size */
u32int _trackspercyl; /* tracks per cylinder */
u32int _secspertrack; /* sectors per track */
u32int _secspercyl; /* sectors per cylinder */
u32int _ncyl; /* cylinders in fs */
u32int _cylspergroup; /* cylinders per group */
u32int inospergroup; /* inodes per group */
u32int fragspergroup; /* data blocks per group * fragperblock */
Cylsum _cstotal; /* more unused... */
u8int fmod;
u8int clean;
u8int ronly;
u8int _flags;
/* char fsmnt[512]; in UFS1 */
char fsmnt[FSMAXMNTLEN2];
char volname[FSMAXVOLLEN];
u64int swuid;
u32int pad;
u32int cgrotor;
uchar ocsp[FSNOCSPTRSLEN]; /* last 4 bytes is contigdirs in UFS2 */
u32int contigdirs; /* csp in UFS2 */
u32int csp; /* maxcluster in UFS2 */
u32int maxcluster; /* active in UFS2 */
u32int _cpc;
/* u16int opostbl[16][8]; in UFS1 */
u32int maxbsize;
u64int spare64[17];
u64int sblockloc;
Cylsumtotal cstotal;
u64int time;
u64int nfrag;
u64int ndfrag;
u64int csaddr;
u64int pendingblocks;
u32int pendinginodes;
u32int snapinum[FSMAXSNAP];
u32int avgfilesize;
u32int avgfpdir;
/* u32int sparecon[26], pendingblocks, pendinginodes; in UFS1 */
u32int savecgsize;
u32int sparecon[26];
u32int flags;
u32int contigsumsize;
u32int maxsymlinklen;
u32int _inodefmt; /* format of on-disk inodes */
u64int maxfilesize; /* maximum representable file size */
u64int qbmask;
u64int qfmask;
u32int state;
u32int _postblformat;
u32int _nrpos;
u32int _postbloff;
u32int _rotbloff;
u32int magic; /* FSMAGIC or FSMAGIC2 */
};
/*
* Cylinder group block for a file system.
*/
struct Cgblk
{
u32int unused0;
u32int magic; /* CGMAGIC */
u32int time; /* time last written */
u32int num; /* we are cg #cgnum */
u16int ncyl; /* number of cylinders in gp */
u16int nino; /* number of inodes */
u32int nfrag; /* number of fragments */
Cylsum csum;
u32int rotor;
u32int frotor;
u32int irotor;
u32int frsum[MAXFRAG]; /* counts of available frags */
u32int btotoff;
u32int boff;
u32int imapoff; /* offset to used inode map */
u32int fmapoff; /* offset to free fragment map */
u32int nextfrag; /* next free fragment */
u32int csumoff;
u32int clusteroff;
u32int ncluster;
u32int sparecon[13];
};
struct Cylgrp
{
/* these are block numbers not fragment numbers */
u64int bno; /* disk block address of start of cg */
u64int ibno; /* disk block address of first inode */
u64int dbno; /* disk block address of first data */
u64int cgblkno;
};
/*
* this is the on-disk structure
*/
struct Inode1
{
u16int mode;
u16int nlink;
u32int unused;
u64int size;
u32int atime;
u32int atimensec;
u32int mtime;
u32int mtimensec;
u32int ctime;
u32int ctimensec;
/* rdev is db[0] */
u32int db[NDADDR];
u32int ib[NIADDR];
u32int flags;
u32int nblock;
u32int gen;
u32int uid;
u32int gid;
u32int spare[2];
};
struct Inode
{
u16int mode;
u16int nlink;
u32int uid;
u32int gid;
u32int blksize;
u64int size;
u64int nblock;
u64int atime;
u64int mtime;
u64int ctime;
u64int btime;
u32int atimensec;
u32int mtimensec;
u32int ctimensec;
u32int btimensec;
u32int gen;
u32int kernflags;
u32int flags;
u32int extsize;
u64int ext[NXADDR];
u64int db[NDADDR];
u64int ib[NIADDR];
u64int spare[3];
};
struct Dirent
{
u32int ino;
u16int reclen;
u8int type;
u8int namlen;
char name[1];
};
/*
* main file system structure
*/
struct Ffs
{
int ufs;
int blocksize;
u64int nblock;
int fragsize;
int fragsperblock;
int inosperblock;
u64int blockspergroup;
u64int fragspergroup;
int inospergroup;
u64int nfrag;
u64int ndfrag;
int ncg;
Cylgrp *cg;
Disk *disk;
};