aboutsummaryrefslogtreecommitdiff
path: root/src/libdiskfs/ffs.h
blob: d7881f15f8d03d6537286fdc2bd7a218ff75dccb (plain)
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
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
/*
 * 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;
};