Commit | Line | Data |
---|---|---|
8dbf4a5b KT |
1 | /* |
2 | * Make a file system prototype. | |
3 | * usage: mkfs filsys proto/size [ m n ] | |
4 | */ | |
5 | #define NIPB (BSIZE/sizeof(struct dinode)) | |
6 | #define NINDIR (BSIZE/sizeof(daddr_t)) | |
7 | #define NDIRECT (BSIZE/sizeof(struct direct)) | |
8 | #define LADDR 10 | |
9 | #define MAXFN 500 | |
10 | #define itoo(x) (int)((x+15)&07) | |
11 | #ifndef STANDALONE | |
12 | #include <stdio.h> | |
13 | #include <a.out.h> | |
14 | #endif | |
15 | #include <sys/param.h> | |
16 | #include <sys/ino.h> | |
17 | #include <sys/inode.h> | |
18 | #include <sys/filsys.h> | |
19 | #include <sys/fblk.h> | |
20 | #include <sys/dir.h> | |
21 | time_t utime; | |
22 | #ifndef STANDALONE | |
23 | FILE *fin; | |
24 | #else | |
25 | int fin; | |
26 | #endif | |
27 | int fsi; | |
28 | int fso; | |
29 | char *charp; | |
30 | char buf[BSIZE]; | |
31 | union { | |
32 | struct fblk fb; | |
33 | char pad1[BSIZE]; | |
34 | } fbuf; | |
35 | #ifndef STANDALONE | |
36 | struct exec head; | |
37 | #endif | |
38 | char string[50]; | |
39 | union { | |
40 | struct filsys fs; | |
41 | char pad2[BSIZE]; | |
42 | } filsys; | |
43 | char *fsys; | |
44 | char *proto; | |
45 | int f_n = MAXFN; | |
46 | int f_m = 3; | |
47 | int error; | |
48 | ino_t ino; | |
49 | long getnum(); | |
50 | daddr_t alloc(); | |
51 | ||
52 | main(argc, argv) | |
53 | char *argv[]; | |
54 | { | |
55 | int f, c; | |
56 | long n; | |
57 | ||
58 | #ifndef STANDALONE | |
59 | time(&utime); | |
60 | if(argc < 3) { | |
61 | printf("usage: mkfs filsys proto/size [ m n ]\n"); | |
62 | exit(1); | |
63 | } | |
64 | fsys = argv[1]; | |
65 | proto = argv[2]; | |
66 | #else | |
67 | { | |
68 | static char protos[60]; | |
69 | ||
70 | printf("file sys size: "); | |
71 | gets(protos); | |
72 | proto = protos; | |
73 | } | |
74 | #endif | |
75 | #ifdef STANDALONE | |
76 | { | |
77 | char fsbuf[100]; | |
78 | ||
79 | do { | |
80 | printf("file system: "); | |
81 | gets(fsbuf); | |
82 | fso = open(fsbuf, 1); | |
83 | fsi = open(fsbuf, 0); | |
84 | } while (fso < 0 || fsi < 0); | |
85 | } | |
86 | fin = NULL; | |
87 | argc = 0; | |
88 | #else | |
89 | fso = creat(fsys, 0666); | |
90 | if(fso < 0) { | |
91 | printf("%s: cannot create\n", fsys); | |
92 | exit(1); | |
93 | } | |
94 | fsi = open(fsys, 0); | |
95 | if(fsi < 0) { | |
96 | printf("%s: cannot open\n", fsys); | |
97 | exit(1); | |
98 | } | |
99 | fin = fopen(proto, "r"); | |
100 | #endif | |
101 | if(fin == NULL) { | |
102 | n = 0; | |
103 | for(f=0; c=proto[f]; f++) { | |
104 | if(c<'0' || c>'9') { | |
105 | printf("%s: cannot open\n", proto); | |
106 | exit(1); | |
107 | } | |
108 | n = n*10 + (c-'0'); | |
109 | } | |
110 | filsys.s_fsize = n; | |
111 | n = n/25; | |
112 | if(n <= 0) | |
113 | n = 1; | |
114 | if(n > 65500/NIPB) | |
115 | n = 65500/NIPB; | |
116 | filsys.s_isize = n + 2; | |
117 | printf("isize = %D\n", n*NIPB); | |
118 | charp = "d--777 0 0 $ "; | |
119 | goto f3; | |
120 | } | |
121 | ||
122 | #ifndef STANDALONE | |
123 | /* | |
124 | * get name of boot load program | |
125 | * and read onto block 0 | |
126 | */ | |
127 | ||
128 | getstr(); | |
129 | f = open(string, 0); | |
130 | if(f < 0) { | |
131 | printf("%s: cannot open init\n", string); | |
132 | goto f2; | |
133 | } | |
134 | read(f, (char *)&head, sizeof head); | |
135 | if(head.a_magic != A_MAGIC1) { | |
136 | printf("%s: bad format\n", string); | |
137 | goto f1; | |
138 | } | |
139 | c = head.a_text + head.a_data; | |
140 | if(c > BSIZE) { | |
141 | printf("%s: too big\n", string); | |
142 | goto f1; | |
143 | } | |
144 | read(f, buf, c); | |
145 | wtfs((long)0, buf); | |
146 | ||
147 | f1: | |
148 | close(f); | |
149 | ||
150 | /* | |
151 | * get total disk size | |
152 | * and inode block size | |
153 | */ | |
154 | ||
155 | f2: | |
156 | filsys.s_fsize = getnum(); | |
157 | n = getnum(); | |
158 | n /= NIPB; | |
159 | filsys.s_isize = n + 3; | |
160 | ||
161 | #endif | |
162 | f3: | |
163 | if(argc >= 5) { | |
164 | f_m = atoi(argv[3]); | |
165 | f_n = atoi(argv[4]); | |
166 | if(f_n <= 0 || f_n >= MAXFN) | |
167 | f_n = MAXFN; | |
168 | if(f_m <= 0 || f_m > f_n) | |
169 | f_m = 3; | |
170 | } | |
171 | filsys.s_m = f_m; | |
172 | filsys.s_n = f_n; | |
173 | printf("m/n = %d %d\n", f_m, f_n); | |
174 | if(filsys.s_isize >= filsys.s_fsize) { | |
175 | printf("%ld/%ld: bad ratio\n", filsys.s_fsize, filsys.s_isize-2); | |
176 | exit(1); | |
177 | } | |
178 | filsys.s_tfree = 0; | |
179 | filsys.s_tinode = 0; | |
180 | for(c=0; c<BSIZE; c++) | |
181 | buf[c] = 0; | |
182 | for(n=2; n!=filsys.s_isize; n++) { | |
183 | wtfs(n, buf); | |
184 | filsys.s_tinode += NIPB; | |
185 | } | |
186 | ino = 0; | |
187 | ||
188 | bflist(); | |
189 | ||
190 | cfile((struct inode *)0); | |
191 | ||
192 | filsys.s_time = utime; | |
193 | wtfs((long)1, (char *)&filsys); | |
194 | exit(error); | |
195 | } | |
196 | ||
197 | cfile(par) | |
198 | struct inode *par; | |
199 | { | |
200 | struct inode in; | |
201 | int dbc, ibc; | |
202 | char db[BSIZE]; | |
203 | daddr_t ib[NINDIR]; | |
204 | int i, f, c; | |
205 | ||
206 | /* | |
207 | * get mode, uid and gid | |
208 | */ | |
209 | ||
210 | getstr(); | |
211 | in.i_mode = gmode(string[0], "-bcd", IFREG, IFBLK, IFCHR, IFDIR); | |
212 | in.i_mode |= gmode(string[1], "-u", 0, ISUID, 0, 0); | |
213 | in.i_mode |= gmode(string[2], "-g", 0, ISGID, 0, 0); | |
214 | for(i=3; i<6; i++) { | |
215 | c = string[i]; | |
216 | if(c<'0' || c>'7') { | |
217 | printf("%c/%s: bad octal mode digit\n", c, string); | |
218 | error = 1; | |
219 | c = 0; | |
220 | } | |
221 | in.i_mode |= (c-'0')<<(15-3*i); | |
222 | } | |
223 | in.i_uid = getnum(); | |
224 | in.i_gid = getnum(); | |
225 | ||
226 | /* | |
227 | * general initialization prior to | |
228 | * switching on format | |
229 | */ | |
230 | ||
231 | ino++; | |
232 | in.i_number = ino; | |
233 | for(i=0; i<BSIZE; i++) | |
234 | db[i] = 0; | |
235 | for(i=0; i<NINDIR; i++) | |
236 | ib[i] = (daddr_t)0; | |
237 | in.i_nlink = 1; | |
238 | in.i_size = 0; | |
239 | for(i=0; i<NADDR; i++) | |
240 | in.i_un.i_addr[i] = (daddr_t)0; | |
241 | if(par == (struct inode *)0) { | |
242 | par = ∈ | |
243 | in.i_nlink--; | |
244 | } | |
245 | dbc = 0; | |
246 | ibc = 0; | |
247 | switch(in.i_mode&IFMT) { | |
248 | ||
249 | case IFREG: | |
250 | /* | |
251 | * regular file | |
252 | * contents is a file name | |
253 | */ | |
254 | ||
255 | getstr(); | |
256 | f = open(string, 0); | |
257 | if(f < 0) { | |
258 | printf("%s: cannot open\n", string); | |
259 | error = 1; | |
260 | break; | |
261 | } | |
262 | while((i=read(f, db, BSIZE)) > 0) { | |
263 | in.i_size += i; | |
264 | newblk(&dbc, db, &ibc, ib); | |
265 | } | |
266 | close(f); | |
267 | break; | |
268 | ||
269 | case IFBLK: | |
270 | case IFCHR: | |
271 | /* | |
272 | * special file | |
273 | * content is maj/min types | |
274 | */ | |
275 | ||
276 | i = getnum() & 0377; | |
277 | f = getnum() & 0377; | |
278 | in.i_un.i_addr[0] = (i<<8) | f; | |
279 | break; | |
280 | ||
281 | case IFDIR: | |
282 | /* | |
283 | * directory | |
284 | * put in extra links | |
285 | * call recursively until | |
286 | * name of "$" found | |
287 | */ | |
288 | ||
289 | par->i_nlink++; | |
290 | in.i_nlink++; | |
291 | entry(in.i_number, ".", &dbc, db, &ibc, ib); | |
292 | entry(par->i_number, "..", &dbc, db, &ibc, ib); | |
293 | in.i_size = 2*sizeof(struct direct); | |
294 | for(;;) { | |
295 | getstr(); | |
296 | if(string[0]=='$' && string[1]=='\0') | |
297 | break; | |
298 | entry(ino+1, string, &dbc, db, &ibc, ib); | |
299 | in.i_size += sizeof(struct direct); | |
300 | cfile(&in); | |
301 | } | |
302 | break; | |
303 | } | |
304 | if(dbc != 0) | |
305 | newblk(&dbc, db, &ibc, ib); | |
306 | iput(&in, &ibc, ib); | |
307 | } | |
308 | ||
309 | gmode(c, s, m0, m1, m2, m3) | |
310 | char c, *s; | |
311 | { | |
312 | int i; | |
313 | ||
314 | for(i=0; s[i]; i++) | |
315 | if(c == s[i]) | |
316 | return((&m0)[i]); | |
317 | printf("%c/%s: bad mode\n", c, string); | |
318 | error = 1; | |
319 | return(0); | |
320 | } | |
321 | ||
322 | long | |
323 | getnum() | |
324 | { | |
325 | int i, c; | |
326 | long n; | |
327 | ||
328 | getstr(); | |
329 | n = 0; | |
330 | i = 0; | |
331 | for(i=0; c=string[i]; i++) { | |
332 | if(c<'0' || c>'9') { | |
333 | printf("%s: bad number\n", string); | |
334 | error = 1; | |
335 | return((long)0); | |
336 | } | |
337 | n = n*10 + (c-'0'); | |
338 | } | |
339 | return(n); | |
340 | } | |
341 | ||
342 | getstr() | |
343 | { | |
344 | int i, c; | |
345 | ||
346 | loop: | |
347 | switch(c=getch()) { | |
348 | ||
349 | case ' ': | |
350 | case '\t': | |
351 | case '\n': | |
352 | goto loop; | |
353 | ||
354 | case '\0': | |
355 | printf("EOF\n"); | |
356 | exit(1); | |
357 | ||
358 | case ':': | |
359 | while(getch() != '\n'); | |
360 | goto loop; | |
361 | ||
362 | } | |
363 | i = 0; | |
364 | ||
365 | do { | |
366 | string[i++] = c; | |
367 | c = getch(); | |
368 | } while(c!=' '&&c!='\t'&&c!='\n'&&c!='\0'); | |
369 | string[i] = '\0'; | |
370 | } | |
371 | ||
372 | rdfs(bno, bf) | |
373 | daddr_t bno; | |
374 | char *bf; | |
375 | { | |
376 | int n; | |
377 | ||
378 | lseek(fsi, bno*BSIZE, 0); | |
379 | n = read(fsi, bf, BSIZE); | |
380 | if(n != BSIZE) { | |
381 | printf("read error: %ld\n", bno); | |
382 | exit(1); | |
383 | } | |
384 | } | |
385 | ||
386 | wtfs(bno, bf) | |
387 | daddr_t bno; | |
388 | char *bf; | |
389 | { | |
390 | int n; | |
391 | ||
392 | lseek(fso, bno*BSIZE, 0); | |
393 | n = write(fso, bf, BSIZE); | |
394 | if(n != BSIZE) { | |
395 | printf("write error: %D\n", bno); | |
396 | exit(1); | |
397 | } | |
398 | } | |
399 | ||
400 | daddr_t | |
401 | alloc() | |
402 | { | |
403 | int i; | |
404 | daddr_t bno; | |
405 | ||
406 | filsys.s_tfree--; | |
407 | bno = filsys.s_free[--filsys.s_nfree]; | |
408 | if(bno == 0) { | |
409 | printf("out of free space\n"); | |
410 | exit(1); | |
411 | } | |
412 | if(filsys.s_nfree <= 0) { | |
413 | rdfs(bno, (char *)&fbuf); | |
414 | filsys.s_nfree = fbuf.df_nfree; | |
415 | for(i=0; i<NICFREE; i++) | |
416 | filsys.s_free[i] = fbuf.df_free[i]; | |
417 | } | |
418 | return(bno); | |
419 | } | |
420 | ||
421 | bfree(bno) | |
422 | daddr_t bno; | |
423 | { | |
424 | int i; | |
425 | ||
426 | filsys.s_tfree++; | |
427 | if(filsys.s_nfree >= NICFREE) { | |
428 | fbuf.df_nfree = filsys.s_nfree; | |
429 | for(i=0; i<NICFREE; i++) | |
430 | fbuf.df_free[i] = filsys.s_free[i]; | |
431 | wtfs(bno, (char *)&fbuf); | |
432 | filsys.s_nfree = 0; | |
433 | } | |
434 | filsys.s_free[filsys.s_nfree++] = bno; | |
435 | } | |
436 | ||
437 | entry(inum, str, adbc, db, aibc, ib) | |
438 | ino_t inum; | |
439 | char *str; | |
440 | int *adbc, *aibc; | |
441 | char *db; | |
442 | daddr_t *ib; | |
443 | { | |
444 | struct direct *dp; | |
445 | int i; | |
446 | ||
447 | dp = (struct direct *)db; | |
448 | dp += *adbc; | |
449 | (*adbc)++; | |
450 | dp->d_ino = inum; | |
451 | for(i=0; i<DIRSIZ; i++) | |
452 | dp->d_name[i] = 0; | |
453 | for(i=0; i<DIRSIZ; i++) | |
454 | if((dp->d_name[i] = str[i]) == 0) | |
455 | break; | |
456 | if(*adbc >= NDIRECT) | |
457 | newblk(adbc, db, aibc, ib); | |
458 | } | |
459 | ||
460 | newblk(adbc, db, aibc, ib) | |
461 | int *adbc, *aibc; | |
462 | char *db; | |
463 | daddr_t *ib; | |
464 | { | |
465 | int i; | |
466 | daddr_t bno; | |
467 | ||
468 | bno = alloc(); | |
469 | wtfs(bno, db); | |
470 | for(i=0; i<BSIZE; i++) | |
471 | db[i] = 0; | |
472 | *adbc = 0; | |
473 | ib[*aibc] = bno; | |
474 | (*aibc)++; | |
475 | if(*aibc >= NINDIR) { | |
476 | printf("indirect block full\n"); | |
477 | error = 1; | |
478 | *aibc = 0; | |
479 | } | |
480 | } | |
481 | ||
482 | getch() | |
483 | { | |
484 | ||
485 | #ifndef STANDALONE | |
486 | if(charp) | |
487 | #endif | |
488 | return(*charp++); | |
489 | #ifndef STANDALONE | |
490 | return(getc(fin)); | |
491 | #endif | |
492 | } | |
493 | ||
494 | bflist() | |
495 | { | |
496 | struct inode in; | |
497 | daddr_t ib[NINDIR]; | |
498 | int ibc; | |
499 | char flg[MAXFN]; | |
500 | int adr[MAXFN]; | |
501 | int i, j; | |
502 | daddr_t f, d; | |
503 | ||
504 | for(i=0; i<f_n; i++) | |
505 | flg[i] = 0; | |
506 | i = 0; | |
507 | for(j=0; j<f_n; j++) { | |
508 | while(flg[i]) | |
509 | i = (i+1)%f_n; | |
510 | adr[j] = i+1; | |
511 | flg[i]++; | |
512 | i = (i+f_m)%f_n; | |
513 | } | |
514 | ||
515 | ino++; | |
516 | in.i_number = ino; | |
517 | in.i_mode = IFREG; | |
518 | in.i_uid = 0; | |
519 | in.i_gid = 0; | |
520 | in.i_nlink = 0; | |
521 | in.i_size = 0; | |
522 | for(i=0; i<NADDR; i++) | |
523 | in.i_un.i_addr[i] = (daddr_t)0; | |
524 | ||
525 | for(i=0; i<NINDIR; i++) | |
526 | ib[i] = (daddr_t)0; | |
527 | ibc = 0; | |
528 | bfree((daddr_t)0); | |
529 | d = filsys.s_fsize-1; | |
530 | while(d%f_n) | |
531 | d++; | |
532 | for(; d > 0; d -= f_n) | |
533 | for(i=0; i<f_n; i++) { | |
534 | f = d - adr[i]; | |
535 | if(f < filsys.s_fsize && f >= filsys.s_isize) | |
536 | if(badblk(f)) { | |
537 | if(ibc >= NINDIR) { | |
538 | printf("too many bad blocks\n"); | |
539 | error = 1; | |
540 | ibc = 0; | |
541 | } | |
542 | ib[ibc] = f; | |
543 | ibc++; | |
544 | } else | |
545 | bfree(f); | |
546 | } | |
547 | iput(&in, &ibc, ib); | |
548 | } | |
549 | ||
550 | iput(ip, aibc, ib) | |
551 | struct inode *ip; | |
552 | int *aibc; | |
553 | daddr_t *ib; | |
554 | { | |
555 | struct dinode *dp; | |
556 | daddr_t d; | |
557 | int i; | |
558 | ||
559 | filsys.s_tinode--; | |
560 | d = itod(ip->i_number); | |
561 | if(d >= filsys.s_isize) { | |
562 | if(error == 0) | |
563 | printf("ilist too small\n"); | |
564 | error = 1; | |
565 | return; | |
566 | } | |
567 | rdfs(d, buf); | |
568 | dp = (struct dinode *)buf; | |
569 | dp += itoo(ip->i_number); | |
570 | ||
571 | dp->di_mode = ip->i_mode; | |
572 | dp->di_nlink = ip->i_nlink; | |
573 | dp->di_uid = ip->i_uid; | |
574 | dp->di_gid = ip->i_gid; | |
575 | dp->di_size = ip->i_size; | |
576 | dp->di_atime = utime; | |
577 | dp->di_mtime = utime; | |
578 | dp->di_ctime = utime; | |
579 | ||
580 | switch(ip->i_mode&IFMT) { | |
581 | ||
582 | case IFDIR: | |
583 | case IFREG: | |
584 | for(i=0; i<*aibc; i++) { | |
585 | if(i >= LADDR) | |
586 | break; | |
587 | ip->i_un.i_addr[i] = ib[i]; | |
588 | } | |
589 | if(*aibc >= LADDR) { | |
590 | ip->i_un.i_addr[LADDR] = alloc(); | |
591 | for(i=0; i<NINDIR-LADDR; i++) { | |
592 | ib[i] = ib[i+LADDR]; | |
593 | ib[i+LADDR] = (daddr_t)0; | |
594 | } | |
595 | wtfs(ip->i_un.i_addr[LADDR], (char *)ib); | |
596 | } | |
597 | ||
598 | case IFBLK: | |
599 | case IFCHR: | |
600 | ltol3(dp->di_addr, ip->i_un.i_addr, NADDR); | |
601 | break; | |
602 | ||
603 | default: | |
604 | printf("bad mode %o\n", ip->i_mode); | |
605 | exit(1); | |
606 | } | |
607 | wtfs(d, buf); | |
608 | } | |
609 | ||
610 | badblk(bno) | |
611 | daddr_t bno; | |
612 | { | |
613 | ||
614 | return(0); | |
615 | } |