Research V7 development
[unix-history] / usr / src / cmd / mkfs.c
CommitLineData
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>
21time_t utime;
22#ifndef STANDALONE
23FILE *fin;
24#else
25int fin;
26#endif
27int fsi;
28int fso;
29char *charp;
30char buf[BSIZE];
31union {
32 struct fblk fb;
33 char pad1[BSIZE];
34} fbuf;
35#ifndef STANDALONE
36struct exec head;
37#endif
38char string[50];
39union {
40 struct filsys fs;
41 char pad2[BSIZE];
42} filsys;
43char *fsys;
44char *proto;
45int f_n = MAXFN;
46int f_m = 3;
47int error;
48ino_t ino;
49long getnum();
50daddr_t alloc();
51
52main(argc, argv)
53char *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
147f1:
148 close(f);
149
150 /*
151 * get total disk size
152 * and inode block size
153 */
154
155f2:
156 filsys.s_fsize = getnum();
157 n = getnum();
158 n /= NIPB;
159 filsys.s_isize = n + 3;
160
161#endif
162f3:
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
197cfile(par)
198struct 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 = &in;
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
309gmode(c, s, m0, m1, m2, m3)
310char 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
322long
323getnum()
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
342getstr()
343{
344 int i, c;
345
346loop:
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
372rdfs(bno, bf)
373daddr_t bno;
374char *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
386wtfs(bno, bf)
387daddr_t bno;
388char *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
400daddr_t
401alloc()
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
421bfree(bno)
422daddr_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
437entry(inum, str, adbc, db, aibc, ib)
438ino_t inum;
439char *str;
440int *adbc, *aibc;
441char *db;
442daddr_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
460newblk(adbc, db, aibc, ib)
461int *adbc, *aibc;
462char *db;
463daddr_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
482getch()
483{
484
485#ifndef STANDALONE
486 if(charp)
487#endif
488 return(*charp++);
489#ifndef STANDALONE
490 return(getc(fin));
491#endif
492}
493
494bflist()
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
550iput(ip, aibc, ib)
551struct inode *ip;
552int *aibc;
553daddr_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
610badblk(bno)
611daddr_t bno;
612{
613
614 return(0);
615}