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