1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
|
/*
* 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 Ffs Ffs;
typedef struct Fsblk Fsblk;
typedef struct Inode Inode;
typedef struct Dirent Dirent;
enum
{
BYTESPERSEC = 512,
/* constants for Fsblk */
FSMAXMNTLEN = 512,
FSNOCSPTRS = 128 / sizeof(void*) - 3,
FSMAXSNAP = 20,
FSMAGIC = 0x011954,
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,
SBSIZE = 8192,
/* minimum block size */
MINBSIZE = 4096,
/* maximum fragments per block */
MAXFRAG = 8,
/* constants for Cgblk */
CGMAGIC = 0x090255,
/* inode-related */
ROOTINODE = 2,
WHITEOUT = 1,
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 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[FSMAXMNTLEN];
u32int cgrotor;
void* ocsp[FSNOCSPTRS];
u8int* contigdirs;
Cylsum* csp;
u32int* maxcluster;
u32int cpc;
u16int opostbl[16][8];
u32int snapinum[FSMAXSNAP];
u32int avgfilesize;
u32int avgfpdir;
u32int sparecon[26];
u32int pendingblocks;
u32int pendinginodes;
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; /* FS_MAGIC */
};
/*
* 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 */
u32int bno; /* disk block address of start of cg */
u32int ibno; /* disk block address of first inode */
u32int dbno; /* disk block address of first data */
u32int cgblkno;
};
/*
* this is the on-disk structure
*/
struct Inode
{
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 Dirent
{
u32int ino;
u16int reclen;
u8int type;
u8int namlen;
char name[1];
};
/*
* main file system structure
*/
struct Ffs
{
int blocksize;
int nblock;
int fragsize;
int fragsperblock;
int inosperblock;
int blockspergroup;
int fragspergroup;
int inospergroup;
u32int nfrag;
u32int ndfrag;
int ncg;
Cylgrp *cg;
Disk *disk;
};
|