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