This source file includes following definitions.
- xshort
- xint
- main
- wsect
- winode
- rinode
- rsect
- ialloc
- balloc
- iappend
- die
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <fcntl.h>
6 #include <assert.h>
7
8 #define stat xv6_stat
9 #include "kernel/types.h"
10 #include "kernel/fs.h"
11 #include "kernel/stat.h"
12 #include "kernel/param.h"
13
14 #ifndef static_assert
15 #define static_assert(a, b) \
16 do { \
17 switch (0) \
18 case 0: \
19 case (a):; \
20 } while (0)
21 #endif
22
23 #define NINODES 200
24
25
26
27
28 int nbitmap = FSSIZE / BPB + 1;
29 int ninodeblocks = NINODES / IPB + 1;
30 int nlog = LOGBLOCKS + 1;
31 int nmeta;
32 int nblocks;
33
34 int fsfd;
35 struct superblock sb;
36 char zeroes[BSIZE];
37 uint freeinode = 1;
38 uint freeblock;
39
40 void balloc(int);
41 void wsect(uint, void *);
42 void winode(uint, struct dinode *);
43 void rinode(uint inum, struct dinode *ip);
44 void rsect(uint sec, void *buf);
45 uint ialloc(ushort type);
46 void iappend(uint inum, void *p, int n);
47 void die(const char *);
48
49
50 ushort
51 xshort(ushort x)
52 {
53 ushort y;
54 uchar *a = (uchar *)&y;
55 a[0] = x;
56 a[1] = x >> 8;
57 return y;
58 }
59
60 uint
61 xint(uint x)
62 {
63 uint y;
64 uchar *a = (uchar *)&y;
65 a[0] = x;
66 a[1] = x >> 8;
67 a[2] = x >> 16;
68 a[3] = x >> 24;
69 return y;
70 }
71
72 int
73 main(int argc, char *argv[])
74 {
75 int i, cc, fd;
76 uint rootino, inum, off;
77 struct dirent de;
78 char buf[BSIZE];
79 struct dinode din;
80
81 static_assert(sizeof(int) == 4, "Integers must be 4 bytes!");
82
83 if (argc < 2) {
84 fprintf(stderr, "Usage: mkfs fs.img files...\n");
85 exit(1);
86 }
87
88 assert((BSIZE % sizeof(struct dinode)) == 0);
89 assert((BSIZE % sizeof(struct dirent)) == 0);
90
91 fsfd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC, 0666);
92 if (fsfd < 0)
93 die(argv[1]);
94
95
96 nmeta = 2 + nlog + ninodeblocks + nbitmap;
97 nblocks = FSSIZE - nmeta;
98
99 sb.magic = FSMAGIC;
100 sb.size = xint(FSSIZE);
101 sb.nblocks = xint(nblocks);
102 sb.ninodes = xint(NINODES);
103 sb.nlog = xint(nlog);
104 sb.logstart = xint(2);
105 sb.inodestart = xint(2 + nlog);
106 sb.bmapstart = xint(2 + nlog + ninodeblocks);
107
108 printf(
109 "nmeta %d (boot, super, log blocks %u, inode blocks %u, bitmap blocks %u) blocks %d total %d\n",
110 nmeta, nlog, ninodeblocks, nbitmap, nblocks, FSSIZE);
111
112 freeblock = nmeta;
113
114 for (i = 0; i < FSSIZE; i++)
115 wsect(i, zeroes);
116
117 memset(buf, 0, sizeof(buf));
118 memmove(buf, &sb, sizeof(sb));
119 wsect(1, buf);
120
121 rootino = ialloc(T_DIR);
122 assert(rootino == ROOTINO);
123
124 bzero(&de, sizeof(de));
125 de.inum = xshort(rootino);
126 strcpy(de.name, ".");
127 iappend(rootino, &de, sizeof(de));
128
129 bzero(&de, sizeof(de));
130 de.inum = xshort(rootino);
131 strcpy(de.name, "..");
132 iappend(rootino, &de, sizeof(de));
133
134 for (i = 2; i < argc; i++) {
135
136 char *shortname;
137 if (strncmp(argv[i], "user/", 5) == 0)
138 shortname = argv[i] + 5;
139 else
140 shortname = argv[i];
141
142 assert(index(shortname, '/') == 0);
143
144 if ((fd = open(argv[i], 0)) < 0)
145 die(argv[i]);
146
147
148
149
150
151 if (shortname[0] == '_')
152 shortname += 1;
153
154 assert(strlen(shortname) <= DIRSIZ);
155
156 inum = ialloc(T_FILE);
157
158 bzero(&de, sizeof(de));
159 de.inum = xshort(inum);
160 strncpy(de.name, shortname, DIRSIZ);
161 iappend(rootino, &de, sizeof(de));
162
163 while ((cc = read(fd, buf, sizeof(buf))) > 0)
164 iappend(inum, buf, cc);
165
166 close(fd);
167 }
168
169
170 rinode(rootino, &din);
171 off = xint(din.size);
172 off = ((off / BSIZE) + 1) * BSIZE;
173 din.size = xint(off);
174 winode(rootino, &din);
175
176 balloc(freeblock);
177
178 exit(0);
179 }
180
181 void
182 wsect(uint sec, void *buf)
183 {
184 if (lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE)
185 die("lseek");
186 if (write(fsfd, buf, BSIZE) != BSIZE)
187 die("write");
188 }
189
190 void
191 winode(uint inum, struct dinode *ip)
192 {
193 char buf[BSIZE];
194 uint bn;
195 struct dinode *dip;
196
197 bn = IBLOCK(inum, sb);
198 rsect(bn, buf);
199 dip = ((struct dinode *)buf) + (inum % IPB);
200 *dip = *ip;
201 wsect(bn, buf);
202 }
203
204 void
205 rinode(uint inum, struct dinode *ip)
206 {
207 char buf[BSIZE];
208 uint bn;
209 struct dinode *dip;
210
211 bn = IBLOCK(inum, sb);
212 rsect(bn, buf);
213 dip = ((struct dinode *)buf) + (inum % IPB);
214 *ip = *dip;
215 }
216
217 void
218 rsect(uint sec, void *buf)
219 {
220 if (lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE)
221 die("lseek");
222 if (read(fsfd, buf, BSIZE) != BSIZE)
223 die("read");
224 }
225
226 uint
227 ialloc(ushort type)
228 {
229 uint inum = freeinode++;
230 struct dinode din;
231
232 bzero(&din, sizeof(din));
233 din.type = xshort(type);
234 din.nlink = xshort(1);
235 din.size = xint(0);
236 winode(inum, &din);
237 return inum;
238 }
239
240 void
241 balloc(int used)
242 {
243 uchar buf[BSIZE];
244 int i;
245
246 printf("balloc: first %d blocks have been allocated\n", used);
247 assert(used < BPB);
248 bzero(buf, BSIZE);
249 for (i = 0; i < used; i++) {
250 buf[i / 8] = buf[i / 8] | (0x1 << (i % 8));
251 }
252 printf("balloc: write bitmap block at sector %d\n", sb.bmapstart);
253 wsect(sb.bmapstart, buf);
254 }
255
256 #define min(a, b) ((a) < (b) ? (a) : (b))
257
258 void
259 iappend(uint inum, void *xp, int n)
260 {
261 char *p = (char *)xp;
262 uint fbn, off, n1;
263 struct dinode din;
264 char buf[BSIZE];
265 uint indirect[NINDIRECT];
266 uint x;
267
268 rinode(inum, &din);
269 off = xint(din.size);
270
271 while (n > 0) {
272 fbn = off / BSIZE;
273 assert(fbn < MAXFILE);
274 if (fbn < NDIRECT) {
275 if (xint(din.addrs[fbn]) == 0) {
276 din.addrs[fbn] = xint(freeblock++);
277 }
278 x = xint(din.addrs[fbn]);
279 } else {
280 if (xint(din.addrs[NDIRECT]) == 0) {
281 din.addrs[NDIRECT] = xint(freeblock++);
282 }
283 rsect(xint(din.addrs[NDIRECT]), (char *)indirect);
284 if (indirect[fbn - NDIRECT] == 0) {
285 indirect[fbn - NDIRECT] = xint(freeblock++);
286 wsect(xint(din.addrs[NDIRECT]), (char *)indirect);
287 }
288 x = xint(indirect[fbn - NDIRECT]);
289 }
290 n1 = min(n, (fbn + 1) * BSIZE - off);
291 rsect(x, buf);
292 bcopy(p, buf + off - (fbn * BSIZE), n1);
293 wsect(x, buf);
294 n -= n1;
295 off += n1;
296 p += n1;
297 }
298 din.size = xint(off);
299 winode(inum, &din);
300 }
301
302 void
303 die(const char *s)
304 {
305 perror(s);
306 exit(1);
307 }