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