aboutsummaryrefslogtreecommitdiff
path: root/src/libdiskfs/ffs.h
blob: 479ff65f71bd28b3bcf35e83edde26c111893d3a (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
/*
 * 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;
};