|
|
1.1 root 1: /*
2: * mkfs.c
3: * 7/14/92
4: * Make a filesystem.
5: * Efficiently, rec 84.08.31
6: */
7:
8: #define VERSION "1.2"
9: #define NDEBUG 1 /* No assertions turned on */
10: #define ES_SUCCESS 0 /* No problems at all */
11: #define ES_IGNORED 1 /* Some problems ignored */
12: #define ES_FORMAT 2 /* Proto file format error */
13: #define ES_FATAL 4 /* Process aborted */
14:
15: #include <stdio.h>
16: #include <ctype.h>
17: #include <errno.h>
18: #define syserror (sys_errlist[errno])
19: #include <sys/filsys.h>
20: #include <sys/ino.h>
21: #include <sys/fblk.h>
22: #include <sys/dir.h>
23: #include <l.out.h>
24: #include <sys/timeb.h>
25: #include <canon.h>
26: #include <sys/stat.h>
27: #include <access.h>
28: #include <assert.h>
29: #include <string.h>
30: #include <sys/mdata.h>
31:
32: #define inodeb(i) (INODEI + ((i)-1)/8)
33: #define inodei(i) (((i)-1)%8)
34: #define NDLEV 25 /* Maximum directory nesting */
35:
36: char s755[20];
37: char sB[20];
38:
39: struct protoargs { /* Parameter management */
40: char *p_bname, *p_fname, *p_fpack;
41: char *p_fsize, *p_nino, *p_intn, *p_intm;
42: };
43:
44: struct entre { /* Directory management */
45: ino_t e_ino;
46: char *e_name;
47: };
48:
49: struct xnode { /* Minimal inode management */
50: ino_t x_ino;
51: int x_mode;
52: int x_uid;
53: int x_gid;
54: dev_t x_dev;
55: char *x_name;
56: int x_nlink;
57: fsize_t x_size;
58: time_t x_atime;
59: time_t x_mtime;
60: time_t x_ctime;
61: daddr_t x_start;
62: struct ynode *x_y;
63: struct entre x_ents[];
64: };
65:
66: struct ynode { /* Medial inode management */
67: ino_t y_ino;
68: fsize_t y_seek;
69: daddr_t y_nb; /* Number of blocks total */
70: daddr_t y_ni; /* Number of indirect blocks total */
71: int y_niiib; /* Number of triple indirect blocks */
72: int y_niib; /* Number of double indirect blocks */
73: daddr_t y_nib; /* Number of single indirect blocks */
74: daddr_t y_ndb; /* Number of data blocks */
75: daddr_t *y_db; /* Data block base */
76: daddr_t *y_ib; /* Single indirect block base */
77: daddr_t *y_iib; /* Double indirect block base */
78: daddr_t *y_iiib; /* Triple indirect block base */
79: daddr_t y_b[]; /* Actual block addresses, indirect first */
80: };
81:
82: struct pfp { /* Input parsing */
83: char *p_fn; /* File name if any */
84: int p_ln; /* Line number if any */
85: int p_dln; /* Line number increment if any */
86: char *p_ip; /* Initial stream pointer */
87: char *p_cp; /* Current stream pointer */
88: struct pfp *p_fp; /* Previous stream record */
89: };
90:
91: extern char devnull[];
92: extern char ascii0[];
93: extern char ascii1[];
94: extern int nino;
95: extern char *special;
96: extern char *proto;
97: extern struct filsys S;
98: extern int FS;
99: extern struct protoargs P;
100: extern struct protoargs N;
101: extern ino_t E[NDLEV];
102: extern int Elevel;
103: extern struct xnode **X;
104: extern char pnil[];
105: extern struct pfp pfp;
106: extern char *argv0;
107: extern int estatus;
108: extern char miscbuf[BSIZE];
109:
110: extern struct entre *getentre();
111: extern ino_t getxnode();
112: extern ino_t getlink();
113: extern char *gettoken();
114: extern char *getline();
115: extern int getopen();
116: extern int getclose();
117: #define getch() ((*pfp.p_cp != 0) ? *pfp.p_cp++ : -1)
118: #define ungetch(c) ((c>=0 && pfp.p_cp>pfp.p_ip) ? (*--pfp.p_cp = c) : -1)
119: extern daddr_t balloc();
120: extern ino_t ialloc();
121: extern char *bcache();
122: extern char *realloc();
123:
124: time_t time();
125: char *xmalloc();
126: char *xrealloc();
127: char *strncpy();
128: char *strcat();
129: fsize_t ftell();
130: long atol();
131: int atoi();
132:
133: /* FILE data.c */
134: char devnull[] = "/dev/null";
135: char ascii0[] = "0";
136: char ascii1[] = "1";
137:
138: int nino; /* Number of inodes on new file system */
139: char *special; /* Special file specified */
140: char *proto; /* Proto file specified */
141: struct filsys S; /* Super block for new file system */
142: int FS; /* File descriptor of file system */
143: struct protoargs P; /* File system prototype parameters */
144: struct protoargs N = { /* Some names */
145: "bootstrap file", "file system name", "file pack name",
146: "file system size", "number of inodes", "interleave n", "interleave m"
147: };
148: ino_t E[NDLEV]; /* Current nesting of directory inodes */
149: int Elevel = -1; /* Current nesting level of directory inodes */
150: struct xnode **X; /* I-list pointers for new file system */
151: char pnil[] = "";
152: struct pfp pfp = { pnil, 0, 0, pnil, pnil, NULL }; /* Initial stream */
153: char *argv0 = "mkfs"; /* Command name */
154: int estatus = ES_SUCCESS; /* Exit status */
155: char miscbuf[BSIZE];
156:
157: int dflag = 0; /* Preserve dates if on; set w/ -d opt. */
158:
159: /* FILE main.c */
160: /*
161: * Magic number of i-nodes as a function of
162: * filesystem size in blocks.
163: */
164: magic()
165: {
166: register char *p;
167: daddr_t fsize;
168: unsigned long nino;
169: static char b[8];
170:
171: fsize = atol(P.p_fsize);
172: if (fsize > 1000)
173: nino = fsize / 7;
174: else
175: nino = fsize / 5;
176: if (nino > 65000U) /* must fit into a short! */
177: nino = 65000U;
178: p = b+8;
179: while (nino != 0) {
180: *--p = nino % 10 + '0';
181: nino /= 10;
182: }
183: P.p_nino = p;
184: }
185:
186: main(argc, argv)
187: char *argv[];
188: {
189: int anyopts = 0;
190: if (argc < 1)
191: return eusage();
192:
193: strcpy(s755, "\nd--755 0 0\n$\n");
194: strcpy(sB, "B----- 0 0\n");
195:
196: argv0 = argv[0];
197: /*
198: * Collect options.
199: */
200: while (argc > 1 && argv[1][0] == '-') {
201: switch (argv[1][1]) {
202: case 'b': P.p_bname = argv[2]; break;
203: case 'f': P.p_fname = argv[2]; break;
204: case 'i': P.p_nino = argv[2]; break;
205: case 'm': P.p_intm = argv[2]; break;
206: case 'n': P.p_intn = argv[2]; break;
207: case 'p': P.p_fpack = argv[2]; break;
208: case 'd': dflag = 1; --argc; ++argv; continue;
209: case 'V': fprintf(stderr, "%s: V%s\n", argv0, VERSION);
210: --argc; ++argv; continue;
211: default: return eusage();
212: }
213: anyopts += 1;
214: argc -= 2;
215: argv += 2;
216: }
217: /*
218: * Parse primary arguments and read or construct
219: * prototype description.
220: */
221: if (argc != 3)
222: return eusage();
223: special = argv[1];
224: if ( ! unnatural(argv[2])) {
225: P.p_fsize = argv[2];
226: if (mkproto() < 0)
227: return estatus;
228: } else {
229: proto = argv[2];
230: if (rdproto() < 0)
231: return estatus;
232: else if (anyopts)
233: eignore("superfluous command line options");
234: }
235: /*
236: * Scan real or imaginary proto file.
237: */
238: getboot();
239: if (getsuper() < 0
240: || getdir() < 0
241: || (estatus&ES_FORMAT))
242: return estatus;
243: /*
244: * Scan in core i list and allocate blocks.
245: */
246: scanilist();
247: if (estatus&ES_FATAL)
248: return (estatus);
249: /*
250: * Write the new file system.
251: */
252: if (putboot() < 0
253: || putsuper() < 0
254: || putilist() < 0
255: || putdata() < 0
256: || putfree() < 0)
257: return (estatus);
258: return (estatus);
259: }
260:
261: /*
262: * Prepare proto file for input.
263: * rdproto copies file into memory,
264: * mkproto constructs proto file in memory,
265: * each sets up gettoken() to read tokens.
266: */
267: rdproto()
268: {
269: register char *p;
270: register int n;
271: register int fd;
272: register int nb;
273:
274: if ((fd = open(proto, 0)) < 0)
275: return badopen("descriptor file", proto);
276: nb = 0;
277: n = BSIZE;
278: p = xmalloc(n);
279: while ((n = read(fd, p+nb, BSIZE)) == BSIZE) {
280: nb += BSIZE;
281: p = xrealloc(p, nb+BSIZE);
282: }
283: p[nb+n] = 0;
284: getopen(p, proto, 1);
285: return (0);
286: }
287:
288: mkproto()
289: {
290: register char *p, *p1, *p0;
291:
292: p0 = p = xmalloc(BSIZE);
293:
294: if ((p1 = P.p_bname) == NULL && (P.p_fname!=NULL || P.p_fpack != NULL))
295: P.p_bname = devnull;
296: if (P.p_fpack != NULL && P.p_fname == NULL)
297: P.p_fname = "noname";
298:
299: if ((p1 = P.p_bname) != NULL) {
300: while (*p = *p1++) ++p;
301: if ((p1 = P.p_fname) != NULL) {
302: *p++ = ' ';
303: while (*p = *p1++) ++p;
304: if ((p1 = P.p_fpack) != NULL) {
305: *p++ = ' ';
306: while (*p = *p1++) ++p;
307: }
308: }
309: }
310: *p++ = '\n';
311: if (unnatural((p1 = P.p_fsize)))
312: return badvalue(N.p_fsize, p1), -1;
313: while (*p = *p1++) ++p;
314: if (P.p_nino == NULL)
315: magic();
316: if (unnatural((p1 = P.p_nino)))
317: return badvalue(N.p_nino, p1), -1;
318: *p++ = ' ';
319: while (*p = *p1++) ++p;
320: if ((p1 = P.p_intn) != NULL) {
321: if (unnatural(p1))
322: return badvalue(N.p_intn, p1), -1;
323: *p++ = ' ';
324: while (*p = *p1++) ++p;
325: if ((p1 = P.p_intm) != NULL) {
326: if (unnatural(p1))
327: return badvalue(N.p_intm, p1), -1;
328: *p++ = ' ';
329: while (*p = *p1++) ++p;
330: }
331: }
332: p1 = s755;
333: while (*p = *p1++) ++p;
334: getopen(p0, NULL, 0);
335: return (0);
336: }
337:
338: /* FILE get.c */
339: /*
340: * First pass activity -- scan proto file
341: * getboot() reads the boot file name.
342: * getsuper() reads the super block parameters and initializes
343: * the in memory file system structure.
344: * getbad() reads and actuates the bad block specification.
345: * getdir() reads the remainder of the proto file and constructs
346: * a directory tree and xnode list for the file system.
347: */
348: getboot()
349: {
350: P.p_bname = gettoken();
351: if (P.p_bname == NULL)
352: P.p_bname = devnull;
353: }
354:
355: getsuper()
356: {
357: register char *ch;
358: register int i;
359:
360: if ((FS = open(special, 2)) < 0)
361: return badopen("special file", special);
362:
363: if ((P.p_fname = gettoken()) == NULL) {
364: P.p_fname = "noname";
365: strncpy(S.s_fname, P.p_fname, 6);
366: } else
367: for (ch = P.p_fname, i = 0; *ch != ' ' && *ch != '\t' &&
368: *ch != '\n' && *ch != '\r' && i < 6; i++, ch++)
369: S.s_fname[i] = *ch;
370:
371: if ((P.p_fpack = gettoken()) == NULL) {
372: P.p_fpack = "nopack";
373: strncpy(S.s_fpack, P.p_fpack, 6);
374: } else
375: for (ch = P.p_fpack, i = 0; *ch != ' ' && *ch != '\t' &&
376: *ch != '\n' && *ch != '\r' && i < 6; i++, ch++)
377: S.s_fpack[i] = *ch;
378:
379: if (getline() == NULL)
380: return earlyeof();
381: if ((P.p_fsize = gettoken()) == NULL)
382: return efatal("no value for %s", N.p_fsize);
383: else if (unnatural(P.p_fsize))
384: return badvalue(N.p_fsize, P.p_fsize), -1;
385: S.s_fsize = atol(P.p_fsize);
386: if ((P.p_nino = gettoken()) == NULL)
387: magic();
388: else if (unnatural(P.p_nino))
389: return badvalue(N.p_nino, P.p_nino), -1;
390: S.s_isize = (atoi(P.p_nino)+INOPB-1)/INOPB + INODEI;
391: if ((P.p_intn = gettoken()) == NULL)
392: P.p_intn = ascii1;
393: else if (unnatural(P.p_intn))
394: return badvalue(N.p_intn, P.p_intn), -1;
395: S.s_n = atoi(P.p_intn);
396: if ((P.p_intm = gettoken()) == NULL)
397: P.p_intm = ascii1;
398: else if (unnatural(P.p_intm))
399: return badvalue(N.p_intm, P.p_intm), -1;
400: S.s_m = atoi(P.p_intm);
401: if (getline() == NULL)
402: return earlyeof();
403:
404: /* Set the initial ifree list so that bad file can be initialized */
405: S.s_ninode = 0;
406: S.s_tinode = (S.s_isize - INODEI) * INOPB;
407: S.s_inode[S.s_ninode++] = BADFIN+1;
408: S.s_inode[S.s_ninode++] = BADFIN;
409: nino = S.s_tinode;
410: /* Allocate memory i list */
411: X = xmalloc(S.s_tinode * sizeof(*X));
412: clear(X, S.s_tinode * sizeof(*X));
413: /* Read the bad block list */
414: if (getbad() < 0)
415: return (-1);
416: /* Initialize the free block list */
417: bbegin();
418: /* Fixup the bad block file, ie allocate indirects */
419: xfixup(X[BADFIN-1]);
420: /* Set the time of construction */
421: time(&S.s_time);
422: return (0);
423: }
424:
425: getbad()
426: {
427: register int c;
428: register daddr_t b;
429: register char *tp;
430: static char mymsg1[] = "illegal bad block number '%s'";
431: static char mymsg2[] = "out of bounds bad block number '%s'";
432:
433: if (getxnode(sB) != BADFIN)
434: return efatal("bad block file != inode %d", BADFIN);
435: xexpand(X[BADFIN-1]);
436: for (;;) {
437: if ((c = getch()) != '%') {
438: ungetch(c);
439: break;
440: }
441: if ((c = getch()) != 'b') {
442: ungetch(c);
443: c = '%';
444: ungetch(c);
445: break;
446: }
447: while ((tp = gettoken()) != NULL) {
448: if (unnatural(tp)) {
449: eformat(mymsg1, tp);
450: continue;
451: }
452: b = atol(tp);
453: if (b >= S.s_fsize) {
454: eformat(mymsg2, tp);
455: continue;
456: }
457: xextend(X[BADFIN-1], b);
458: }
459: getline();
460: }
461: return (0);
462: }
463:
464: getdir()
465: {
466: char *cp1, *cp2;
467: struct entre *ep;
468: struct xnode *xp;
469: int inum;
470:
471: for (;;) {
472: if (Elevel < 0) {
473: cp1 = getline();
474: } else {
475: cp1 = gettoken();
476: cp2 = getline();
477: }
478: if (cp1 == NULL)
479: return earlyeof();
480: if (*cp1 == '$') {
481: if (Elevel-- < 0) {
482: assert(proto != NULL);
483: efatal("misplaced '$' in '%s'", proto);
484: }
485: if (Elevel < 0)
486: break;
487: continue;
488: }
489: if (Elevel >= 0) {
490: ep = getentre(cp1);
491: } else
492: cp2 = cp1;
493: inum = getxnode(cp2);
494: if (Elevel >= 0)
495: ep->e_ino = inum;
496: if (inum == 0)
497: continue;
498: assert(inum > BADFIN);
499: assert(inum <= nino);
500: xp = X[inum-1];
501: xp->x_nlink += 1;
502: assert(xp != NULL);
503: if ((xp->x_mode&IFMT) == IFDIR) {
504: if (++Elevel >= NDLEV)
505: return efatal("directories too deep");
506: E[Elevel] = inum;
507: ep = getentre(".");
508: ep->e_ino = inum;
509: xp = X[inum-1];
510: xp->x_nlink += 1;
511: ep = getentre("..");
512: if (Elevel != 0)
513: inum = E[Elevel-1];
514: ep->e_ino = inum;
515: xp = X[inum-1];
516: xp->x_nlink += 1;
517: }
518: }
519: return (0);
520: }
521:
522: struct entre *
523: getentre(cp)
524: char *cp;
525: {
526: register struct xnode *xp;
527: register struct entre *ep;
528: register int inum;
529: int nent;
530:
531: assert(Elevel >= 0);
532: inum = E[Elevel];
533: assert(inum > BADFIN);
534: assert(inum <= nino);
535: xp = X[inum-1];
536: assert(xp != NULL);
537: assert((xp->x_mode&IFMT) == IFDIR);
538: xp->x_size += sizeof(struct direct);
539: nent = xp->x_size / sizeof(struct direct);
540: xp = xrealloc(xp, sizeof(*xp) + nent*sizeof(*ep));
541: X[inum-1] = xp;
542: ep = &xp->x_ents[nent-1];
543: ep->e_ino = 0;
544: ep->e_name = cp;
545: return (ep);
546: }
547:
548: ino_t
549: getxnode(cp)
550: char *cp;
551: {
552: register struct xnode *xp;
553: register ino_t inum;
554: char *type, *uid, *gid, *name;
555: int mode;
556: dev_t dev;
557: struct stat sbuf;
558:
559: if (cp == NULL)
560: missing_spec:
561: return eformat("missing file specification");
562: getopen(cp, NULL, 0);
563: type = gettoken();
564: uid = gettoken();
565: gid = gettoken();
566: name = gettoken();
567: getclose();
568: if (type == NULL)
569: goto missing_spec;
570: inum = 0;
571: sbuf.st_size = 0;
572: sbuf.st_mtime = sbuf.st_atime = sbuf.st_ctime = S.s_time;
573: dev = 0;
574: if (*type == 'l') { /* Link to previously defined file */
575: if (name == NULL)
576: return eformat("missing link name '%s'", cp);
577: inum = getlink((*name=='/' ? E[0] : E[Elevel]), name);
578: if (inum == 0)
579: return eformat("unknown link name '%s'", name);
580: return (inum);
581: }
582: switch (type[0]) {
583: case 'b':
584: case 'c':
585: if (name == NULL)
586: return eformat("missing device specification");
587: else
588: dev = getdev(name);
589: goto common;
590: case 'd':
591: case 'p':
592: goto common;
593: case 'B':
594: goto common;
595: case '-':
596: if (name == NULL)
597: return eformat("missing source for regular file");
598: else if (access(name, AREAD) < 0)
599: return eignore("access to '%s' failed: %s", name, syserror);
600: else if (stat(name, &sbuf) < 0)
601: return eignore("stat of '%s' failed: %s", name, syserror);
602: else if ((sbuf.st_mode&IFMT) != IFREG)
603: return eformat("'%s' is not a regular file", name);
604: common:
605: if ((mode = getmode(type)) == 0)
606: return (0);
607: if (uid == NULL || unnatural(uid))
608: return eformat("bad user id '%s'", uid);
609: if (gid == NULL || unnatural(gid))
610: return eformat("bad or missing group id '%s'", gid);
611: break;
612: default:
613: return eformat("bad file specification '%s'", cp);
614: }
615: xp = xmalloc(sizeof(*xp));
616: xp->x_size = sbuf.st_size;
617: xp->x_atime = sbuf.st_atime;
618: xp->x_mtime = sbuf.st_mtime;
619: xp->x_ctime = sbuf.st_ctime;
620: xp->x_nlink = 0;
621: xp->x_y = NULL;
622: xp->x_start = 0;
623: xp->x_ino = inum = ialloc();
624: xp->x_mode = mode;
625: xp->x_dev = dev;
626: xp->x_uid = atoi(uid);
627: xp->x_gid = atoi(gid);
628: xp->x_name = name;
629: X[inum-1] = xp;
630: return (inum);
631: }
632:
633: /* Translate proto mode specification into mode word */
634: getmode(cp)
635: char *cp;
636: {
637: register char *p;
638: register int mode;
639: register int i;
640: static char mymessage[] = "mode format: %s char should be one of %s";
641:
642: p = cp;
643: assert(p != NULL);
644: mode = 0;
645: switch (*p++) {
646: case 'b': mode |= IFBLK; break;
647: case 'c': mode |= IFCHR; break;
648: case 'd': mode |= IFDIR; break;
649: case 'p': mode |= IFPIPE; break;
650: case '-': mode |= IFREG; break;
651: case 'B': mode |= IFREG; return (mode);
652: case 'l': assert(p[-1] != 'l'); break;
653: default: return eformat(mymessage, "1st", "[bcdlp-]");
654: }
655: switch (*p++) {
656: case 'u': mode |= ISUID; break;
657: case '-': break;
658: default: return eformat(mymessage, "2nd", "[u-]");
659: }
660: switch (*p++) {
661: case 'g': mode |= ISGID; break;
662: case '-': break;
663: default: return eformat(mymessage, "3rd", "[g-]");
664: }
665: for (i = 1<<6; i > 0; i >>= 3) switch (*p++) {
666: case '7': mode += i;
667: case '6': mode += i;
668: case '5': mode += i;
669: case '4': mode += i;
670: case '3': mode += i;
671: case '2': mode += i;
672: case '1': mode += i;
673: case '0':
674: case '-': break;
675: default: return eformat(mymessage, "4th, 5th, or 6th", "[01234567-]");
676: }
677: return (mode);
678: }
679:
680: getdev(cp)
681: char *cp;
682: {
683: char *majp, *minp;
684:
685: getopen(cp, NULL, 0);
686: majp = gettoken();
687: minp = gettoken();
688: getclose();
689: if (majp == NULL || unnatural(majp))
690: return badvalue("major number", cp);
691: if (minp == NULL || unnatural(minp))
692: return badvalue("minor number", cp);
693: return makedev(atoi(majp), atoi(minp));
694: }
695:
696: /*
697: * Lookup a name in our directory tree.
698: */
699: ino_t
700: getlink(inum, name)
701: ino_t inum;
702: char *name;
703: {
704: int i, nent;
705: struct entre *ep;
706: struct xnode *xp;
707:
708: assert(inum > BADFIN);
709: assert(inum <= nino);
710: xp = X[inum-1];
711: nextname:
712: assert(xp != NULL);
713: ep = xp->x_ents;
714: nent = xp->x_size / sizeof(struct direct);
715: while (*name == '/')
716: name += 1;
717: if (*name == 0)
718: return (inum);
719: while (--nent >= 0) {
720: if (ep->e_ino == 0) {
721: ep += 1;
722: continue;
723: }
724: for (i = 0; ; i += 1) {
725: if (name[i] != '\0' && name[i] != '/'
726: && name[i] != ep->e_name[i])
727: break;
728: if (i == DIRSIZ
729: || ep->e_name[i] == 0) {
730: inum = ep->e_ino;
731: assert(inum > BADFIN);
732: assert(inum <= nino);
733: if (name[i] == 0)
734: return (inum);
735: if (name[i] == '/') {
736: name += i;
737: xp = X[inum-1];
738: assert(xp != NULL);
739: if ((xp->x_mode&IFMT) != IFDIR)
740: return (0);
741: goto nextname;
742: }
743: return (0);
744: }
745: }
746: ep += 1;
747: }
748: return (0);
749: }
750:
751: /*
752: * Intermediate pass, prepare for writing.
753: * scanilist() scans the xnode list and allocates data blocks
754: * and indirect mapping blocks.
755: */
756: scanilist()
757: {
758: register int i;
759: register struct xnode *xp;
760:
761: for (i = BADFIN+1; i <= nino; i += 1) {
762: if ((xp = X[i-1]) == NULL)
763: continue;
764: xexpand(xp);
765: xcontract(xp);
766: }
767: }
768:
769: /* FILE put.c */
770: /*
771: * Second pass --
772: * we write everything in the order it appears
773: * without intervening reads.
774: * putboot() writes the boot block.
775: * putsuper() writes the super block.
776: * putilist() writes the ilist.
777: * putdata() writes the files.
778: * putfree() fills in the free block list.
779: */
780: putboot()
781: {
782: register int fd;
783: register struct ldheader *ldp;
784: char *bp;
785: fsize_t fsize;
786:
787: if ((fd = open(P.p_bname, 0)) < 0) {
788: eignore("open %s '%s': %s\n", N.p_bname, P.p_bname, syserror);
789: return (0);
790: }
791: bp = bcache((daddr_t)BOOTBI);
792: if (read(fd, bp, BSIZE) == BSIZE) {
793: ldp = (struct ldheader *)bp;
794: canint(ldp->l_magic);
795: if (ldp->l_magic == L_MAGIC) {
796: cansize(ldp->l_ssize[L_PRVD]);
797: cansize(ldp->l_ssize[L_SHRD]);
798: cansize(ldp->l_ssize[L_PRVI]);
799: cansize(ldp->l_ssize[L_SHRI]);
800: fsize = ldp->l_ssize[L_PRVD] + ldp->l_ssize[L_SHRD]
801: + ldp->l_ssize[L_PRVI] + ldp->l_ssize[L_SHRI];
802: if (fsize > BSIZE)
803: eignore("%s '%s' truncated to %d",
804: N.p_bname, P.p_bname, BSIZE);
805: lseek(fd, 44L, 0);
806: read(fd, bp, BSIZE);
807: } else
808: canint(ldp->l_magic);
809: }
810: close(fd);
811: return (0);
812: }
813:
814: putsuper()
815: {
816: register char *bp;
817:
818: bp = bcache((daddr_t)SUPERI);
819: copy(bp, &S, BSIZE);
820: cansuper(bp);
821: return (0);
822: }
823:
824: /*
825: * Canonicalize the super block.
826: */
827: cansuper(sbp)
828: register struct filsys *sbp;
829: {
830: canshort(sbp->s_isize);
831: candaddr(sbp->s_fsize);
832: canshort(sbp->s_nfree);
833: {
834: register daddr_t *dp;
835: register int i;
836:
837: i = NICFREE;
838: dp = &sbp->s_free[NICFREE];
839: while (--i >= 0) {
840: dp -= 1; /* Watch for side effects */
841: candaddr(*dp);
842: }
843: }
844: canshort(sbp->s_ninode);
845: {
846: register ino_t *ip;
847: register int i;
848:
849: i = NICINOD;
850: ip = &sbp->s_inode[NICINOD];
851: while (--i >= 0) {
852: ip -= 1;
853: canino(*ip);
854: }
855: }
856: cantime(sbp->s_time);
857: candaddr(sbp->s_tfree);
858: canino(sbp->s_tinode);
859: canshort(sbp->s_m);
860: canshort(sbp->s_n);
861: canlong(sbp->s_unique);
862: }
863:
864: putilist()
865: {
866: register struct xnode *xp;
867: struct dinode din;
868: ino_t inum;
869:
870: clear(&din, sizeof(din));
871: for (inum = BADFIN; inum <= nino; inum += 1) {
872: if (bad((daddr_t)inodeb(inum))) {
873: inum += INOPB;
874: continue;
875: }
876: xp = X[inum-1];
877: if (xp == NULL) {
878: iput(inum, &din);
879: continue;
880: }
881: din.di_mode = xp->x_mode;
882: if (dflag) {
883: din.di_mtime = xp->x_mtime;
884: din.di_atime = xp->x_atime;
885: din.di_ctime = xp->x_ctime;
886: } else {
887: din.di_mtime = S.s_time;
888: din.di_ctime = S.s_time;
889: din.di_atime = S.s_time;
890: }
891: din.di_size = xp->x_size;
892: din.di_nlink = xp->x_nlink;
893: din.di_uid = xp->x_uid;
894: din.di_gid = xp->x_gid;
895: switch (xp->x_mode&IFMT) {
896: case IFBLK:
897: case IFCHR:
898: din.di_a.di_rdev = xp->x_dev;
899: break;
900: case IFDIR:
901: case IFREG:
902: if (inum != BADFIN)
903: xexpand(xp);
904: xymerge(xp, &din);
905: if (inum != BADFIN)
906: xcontract(xp);
907: break;
908: }
909: iput(inum, &din);
910: clear(&din, sizeof(din));
911: }
912: return (0);
913: }
914:
915: putdata()
916: {
917: register int i;
918: register struct xnode *xp;
919:
920: putbad();
921: for (i = BADFIN+1; i <= nino; i += 1) {
922: if ((xp = X[i-1]) == NULL)
923: continue;
924: if ((xp->x_mode&IFMT) == IFDIR)
925: putdir(xp);
926: else if ((xp->x_mode&IFMT) == IFREG)
927: putreg(xp);
928: }
929: return (0);
930: }
931:
932: putbad()
933: {
934: register struct ynode *yp;
935:
936: assert(X[BADFIN-1] != NULL);
937: yp = X[BADFIN-1]->x_y;
938: assert(yp != NULL);
939: if (yp->y_ni)
940: xindir(yp);
941: }
942:
943: putdir(xp)
944: struct xnode *xp;
945: {
946: struct direct dir;
947: register struct entre *ep;
948: int i, nent;
949:
950: xexpand(xp);
951: nent = xp->x_size / sizeof(struct direct);
952: for (i = 0; i < nent; i += 1) {
953: ep = xp->x_ents + i;
954: dir.d_ino = ep->e_ino;
955: strncpy(dir.d_name, ep->e_name, DIRSIZ);
956: if (strlen(ep->e_name) > DIRSIZ)
957: eignore("directory name '%s' truncated to %d chars",
958: ep->e_name, DIRSIZ);
959: canino(dir.d_ino);
960: xwrite(xp, &dir, sizeof(struct direct));
961: }
962: xcontract(xp);
963: }
964:
965: putreg(xp)
966: struct xnode *xp;
967: {
968: int fd, nb;
969: fsize_t size;
970: struct stat sbuf;
971:
972: if (stat(xp->x_name, &sbuf) < 0)
973: return eignore("stat of %s failed: %s", xp->x_name, syserror);
974: if (sbuf.st_size != xp->x_size)
975: return eignore("size of %s has changed", xp->x_name);
976: if ((fd = open(xp->x_name, 0)) < 0)
977: return eignore("open %s failed: %s", xp->x_name, syserror);
978: xexpand(xp);
979: size = xp->x_size;
980: while (size > 0) {
981: nb = read(fd, miscbuf, BSIZE);
982: if (nb < 0) {
983: eignore("read %s failed: %s", xp->x_name, syserror);
984: break;
985: }
986: xwrite(xp, miscbuf, BSIZE);
987: size -= nb;
988: }
989: xcontract(xp);
990: close(fd);
991: }
992:
993: putfree()
994: {
995: daddr_t b;
996: register daddr_t *dp;
997: register int n;
998:
999: while (S.s_nfree > 0) {
1000: while (S.s_nfree > 1)
1001: b = balloc();
1002: b = balloc(); /* Forces load of next free block */
1003: dp = bcache(b);
1004: ((struct fblk *)dp)->df_nfree = n = S.s_nfree;
1005: canint(((struct flbk *)dp)->df_nfree);
1006: dp = &((struct fblk *)dp)->df_free[0];
1007: copy(dp, S.s_free, n * sizeof(daddr_t));
1008: while (--n >= 0) {
1009: candaddr(*dp);
1010: dp += 1;
1011: }
1012: }
1013: bcache((daddr_t)-1); /* Flush */
1014: return (0);
1015: }
1016:
1017: /* FILE misc.c */
1018: /*
1019: * Allocation with fatal errors.
1020: */
1021: char *
1022: xmalloc(nb)
1023: {
1024: char *p;
1025:
1026: p = malloc(nb);
1027: if (p != NULL)
1028: return (p);
1029: efatal("memory allocation failed");
1030: }
1031:
1032: char *
1033: xrealloc(p, nb)
1034: char *p;
1035: {
1036: p = realloc(p, nb);
1037: if (p != NULL)
1038: return (p);
1039: efatal("memory reallocation failed");
1040: }
1041:
1042: /*
1043: * Errors.
1044: */
1045: char usage[] = "Usage: %s [ option ... ] special proto\n"
1046: "Options:\n"
1047: "\t-b boot\n"
1048: "\t-d\n"
1049: "\t-f name\n"
1050: "\t-i inodes\n"
1051: "\t-m arg\n"
1052: "\t-n arg\n"
1053: "\t-p pack\n";
1054:
1055: eusage()
1056: {
1057: fprintf(stderr, usage, argv0, argv0);
1058: estatus |= ES_FATAL;
1059: exit(estatus);
1060: }
1061:
1062: eerror(es, fs, ap)
1063: int es;
1064: char *fs;
1065: char **ap;
1066: {
1067: fprintf(stderr, "%s: ", argv0);
1068: if (pfp.p_fn) fprintf(stderr, "in %s: ", pfp.p_fn);
1069: if (pfp.p_ln) fprintf(stderr, "at %d: ", pfp.p_ln);
1070: fprintf(stderr, fs, ap);
1071: estatus |= es;
1072: if (estatus & ES_FATAL)
1073: exit(estatus);
1074: return (0);
1075: }
1076:
1077: efatal(a1)
1078: char *a1;
1079: {
1080: return eerror(ES_FATAL, "%r\n", &a1);
1081: }
1082:
1083: eignore(a1)
1084: char *a1;
1085: {
1086: return eerror(ES_IGNORED, "%r (ignored)\n", &a1);
1087: }
1088:
1089: eformat(a1)
1090: char *a1;
1091: {
1092: return eerror(ES_FORMAT, "%r\n", &a1);
1093: }
1094:
1095: badvalue(np, vp)
1096: char *np, *vp;
1097: {
1098: return eformat("bad value for %s: %s", np, vp);
1099: }
1100:
1101: badopen(np, cp)
1102: char *cp, *np;
1103: {
1104: return efatal("open '%s' as %s failed: %s", cp, np, syserror);
1105: }
1106:
1107: earlyeof()
1108: {
1109: assert(proto != NULL);
1110: return efatal("unexpected end of descriptor file: %s", proto);
1111: }
1112:
1113: /*
1114: * Token and line input.
1115: * getopen() pushes the current input string,
1116: * getclose() pops the previous input string,
1117: * gettoken() returns a pointer to the beginning of the next token,
1118: * getline() returns pointer to the same and advances to next line.
1119: * both return NULL on unexpected end of file.
1120: */
1121: getopen(cp, fn, dln)
1122: char *cp;
1123: char *fn;
1124: int dln;
1125: {
1126: struct pfp *tp;
1127:
1128: tp = xmalloc(sizeof(*tp));
1129: *tp = pfp;
1130: pfp.p_fn = fn;
1131: pfp.p_ln = 0;
1132: pfp.p_dln = dln;
1133: pfp.p_ip = pfp.p_cp = cp;
1134: pfp.p_fp = tp;
1135: }
1136:
1137: getclose()
1138: {
1139: struct pfp *tp;
1140:
1141: assert(pfp.p_fp != NULL);
1142: tp = pfp.p_fp;
1143: pfp = *tp;
1144: free(tp);
1145: }
1146:
1147: char *
1148: gettoken()
1149: {
1150: register int c;
1151: register char *p, *tp;
1152:
1153: pfp.p_ln += pfp.p_dln;
1154: pfp.p_dln = 0;
1155: p = pfp.p_cp;
1156:
1157: /* DEBUG - this code is writing into string literals! */
1158: #if _I386 && !NDEBUG
1159: if ((int)pfp.p_cp < 0x400000) {
1160: fprintf(stderr, "pfp.p_cp=%x:%s\n",
1161: pfp.p_cp, pfp.p_cp);
1162: fflush(stderr);
1163: exit(1);
1164: }
1165: #endif
1166:
1167: while ((c = *p) == ' ' || c == '\t')
1168: *p++ = 0;
1169: pfp.p_cp = tp = p;
1170: if (c == 0 || c == '\n')
1171: return (NULL);
1172: do
1173: c = *p++;
1174: while (c != 0 && c != ' ' && c != '\t' && c != '\n');
1175: pfp.p_cp = p - 1;
1176: return (tp);
1177: }
1178:
1179: char *
1180: getline()
1181: {
1182: register int c;
1183: register char *p, *tp;
1184:
1185: pfp.p_ln += pfp.p_dln;
1186: pfp.p_dln = 0;
1187: p = pfp.p_cp;
1188: while ((c = *p) == ' ' || c == '\t')
1189: *p++ = 0;
1190: pfp.p_cp = tp = p;
1191: if (c == 0)
1192: return earlyeof();
1193: if (c == '\n') {
1194: *p++ = 0;
1195: pfp.p_cp += 1;
1196: if (pfp.p_ln) pfp.p_dln = 1;
1197: return (tp);
1198: }
1199: do
1200: c = *p++;
1201: while (c != 0 && c != '\n');
1202: if (c == 0)
1203: return earlyeof();
1204: pfp.p_cp = p;
1205: p[-1] = 0;
1206: return (tp);
1207: }
1208:
1209: /*
1210: * Miscellaneous.
1211: */
1212: unnatural(cp)
1213: char *cp;
1214: {
1215: register char *p;
1216:
1217: p = cp;
1218: while (isdigit(*p)) p += 1;
1219: switch (*p) {
1220: case 0:
1221: case ' ':
1222: case '\t':
1223: case '\n':
1224: return (0);
1225: default:
1226: return (-1);
1227: }
1228: }
1229:
1230: clear(bp, n)
1231: register char *bp;
1232: register unsigned n;
1233: {
1234: if (n) do {
1235: *bp++ = 0;
1236: } while (--n);
1237: }
1238:
1239: copy(bp1, bp2, n)
1240: register char *bp1;
1241: register char *bp2;
1242: register unsigned n;
1243: {
1244: if (n) do {
1245: *bp1++ = *bp2++;
1246: } while (--n);
1247: }
1248:
1249: iszero(bp, n)
1250: register char *bp;
1251: register unsigned n;
1252: {
1253: if (n) do
1254: if (*bp++ != 0) return (0);
1255: while (--n);
1256: return (1);
1257: }
1258:
1259: /* FILE xmisc.c */
1260: /*
1261: * xexpand() - creates a block map for the inode.
1262: * indirect blocks are allocated sequentially, followed by data blocks
1263: * also sequentially.
1264: * xcontract() - discards the block map.
1265: * xextend() - appends a specified data block to the bad inode.
1266: * xymerge() - merges block addresses into disk inode structure.
1267: * xwrite() - writes data and necessary indirect blocks into filesystem.
1268: */
1269: int xwatch = 0;
1270:
1271: xexpand(xp)
1272: struct xnode *xp;
1273: {
1274: register struct ynode *yp;
1275: register daddr_t *dp;
1276: register daddr_t nb;
1277: daddr_t b;
1278:
1279: assert(xp != NULL);
1280: assert(xp->x_ino >= BADFIN);
1281: assert(xp->x_ino <= nino);
1282: yp = xp->x_y;
1283: assert(yp == NULL);
1284: xp->x_y = yp = xmalloc(sizeof(*yp) + NADDR * sizeof(daddr_t));
1285: clear(yp, sizeof(*yp) + NADDR * sizeof(daddr_t));
1286: yp->y_ino = xp->x_ino;
1287: yp->y_seek = 0;
1288: xblkuse(xp);
1289: nb = yp->y_nb;
1290: if (nb > NADDR) {
1291: xp->x_y = yp = xrealloc(yp, sizeof(*yp)
1292: + ((unsigned)nb) * sizeof(daddr_t));
1293: clear(yp->y_b, ((unsigned)nb) * sizeof(daddr_t));
1294: }
1295: /* Set up pointers */
1296: yp->y_iiib = yp->y_b;
1297: yp->y_iib = yp->y_iiib + yp->y_niiib;
1298: yp->y_ib = yp->y_iib + yp->y_niib;
1299: yp->y_db = yp->y_ib + yp->y_nib;
1300: /* Resynchronize the allocator */
1301: if (b = xp->x_start)
1302: bstart(xp->x_start);
1303: /* Allocate blocks */
1304: dp = yp->y_b;
1305: nb = yp->y_nb;
1306: while (--nb >= 0)
1307: *dp++ = balloc();
1308: if (xp->x_start == 0)
1309: xp->x_start = yp->y_b[0];
1310: }
1311:
1312: xblkuse(xp)
1313: struct xnode *xp;
1314: {
1315: register struct ynode *yp;
1316: register daddr_t nb;
1317:
1318: yp = xp->x_y;
1319: nb = xp->x_size + BSIZE - 1;
1320: nb /= BSIZE;
1321: yp->y_niiib = 0;
1322: yp->y_niib = 0;
1323: yp->y_nib = 0;
1324: yp->y_ndb = 0;
1325: yp->y_ni = 0;
1326: if (nb > ND) {
1327: if (nb > ND+NBN) {
1328: if (nb > ND+NBN+NBN*NBN) {
1329: nb -= ND+NBN+NBN*NBN;
1330: assert(nb > 0 && nb < NBN*NBN*(long)NBN);
1331: yp->y_ndb += nb;
1332: nb += NBN-1;
1333: nb /= NBN;
1334: yp->y_nib += nb;
1335: nb += NBN-1;
1336: nb /= NBN;
1337: yp->y_niib += nb;
1338: assert(((nb+NBN-1)/NBN) == 1);
1339: yp->y_niiib += 1;
1340: nb = ND+NBN+NBN*NBN;
1341: }
1342: nb -= ND+NBN;
1343: assert(nb > 0 && nb < NBN*NBN);
1344: yp->y_ndb += nb;
1345: nb += NBN-1;
1346: nb /= NBN;
1347: yp->y_nib += nb;
1348: assert(((nb+NBN-1)/NBN) == 1);
1349: yp->y_niib += 1;
1350: nb = ND+NBN;
1351: }
1352: nb -= ND;
1353: assert(nb > 0 && nb < NBN);
1354: yp->y_ndb += nb;
1355: assert(((nb+NBN-1)/NBN) == 1);
1356: yp->y_nib += 1;
1357: nb = ND;
1358: }
1359: assert(nb >= 0 && nb <= ND);
1360: yp->y_ndb += nb;
1361: yp->y_ni = yp->y_nib + yp->y_niib + yp->y_niiib;
1362: yp->y_nb = yp->y_ndb + yp->y_ni;
1363: }
1364:
1365: xcontract(xp)
1366: register struct xnode *xp;
1367: {
1368: register struct ynode *yp;
1369:
1370: assert(xp != NULL);
1371: assert(xp->x_ino >= BADFIN);
1372: assert(xp->x_ino <= nino);
1373: yp = xp->x_y;
1374: assert(yp != NULL);
1375: assert(yp->y_ino == xp->x_ino);
1376: xp->x_y = NULL;
1377: free(yp);
1378: }
1379:
1380: xymerge(xp, dip)
1381: struct xnode *xp;
1382: struct dinode *dip;
1383: {
1384: register struct ynode *yp;
1385: char *l3p;
1386:
1387: assert(xp != NULL);
1388: assert(xp->x_ino >= BADFIN);
1389: assert(xp->x_ino <= nino);
1390: yp = xp->x_y;
1391: assert(yp != NULL);
1392: assert(yp->y_ino == xp->x_ino);
1393: l3p = dip->di_addr;
1394: ltol3(l3p, yp->y_db, ND);
1395: l3p += 3*ND;
1396: if (yp->y_nib)
1397: ltol3(l3p, yp->y_ib, 1);
1398: l3p += 3;
1399: if (yp->y_niib)
1400: ltol3(l3p, yp->y_iib, 1);
1401: l3p += 3;
1402: if (yp->y_niiib)
1403: ltol3(l3p, yp->y_iiib, 1);
1404: }
1405:
1406: xwrite(xp, cp, nb)
1407: struct xnode *xp;
1408: char *cp;
1409: int nb;
1410: {
1411: register struct ynode *yp;
1412: daddr_t bn;
1413: int bo;
1414: char *bp;
1415:
1416: assert(xp != NULL);
1417: assert(xp->x_ino > BADFIN);
1418: assert(xp->x_ino <= nino);
1419: yp = xp->x_y;
1420: assert(yp != NULL);
1421: assert(yp->y_ino == xp->x_ino);
1422: if (yp->y_seek == 0 && yp->y_ni != 0)
1423: xindir(yp); /* Write indirect blocks */
1424: bn = yp->y_seek / BSIZE;
1425: assert(bn < yp->y_ndb);
1426: bo = yp->y_seek % BSIZE;
1427: assert(bo+nb <= BSIZE);
1428: bp = bcache(yp->y_db[(int)bn]);
1429: copy(bp+bo, cp, nb);
1430: yp->y_seek += nb;
1431: }
1432:
1433: xindir(yp)
1434: register struct ynode *yp;
1435: {
1436: /* Triple indirect block */
1437: if (yp->y_niiib)
1438: xindblks(yp->y_iiib, yp->y_iib+1, (daddr_t)yp->y_niib-1);
1439: /* Double indirect blocks */
1440: if (yp->y_niib)
1441: xindblks(yp->y_iib, yp->y_ib+1, (daddr_t)yp->y_nib-1);
1442: /* Single indirect blocks */
1443: if (yp->y_nib)
1444: xindblks(yp->y_ib, yp->y_db+ND, (daddr_t)yp->y_ndb-ND);
1445: }
1446:
1447: xindblks(dp, sp, nb)
1448: register daddr_t *dp, *sp, nb;
1449: {
1450: register int n;
1451:
1452: while (nb > 0) {
1453: if (nb >= NBN)
1454: n = NBN;
1455: else
1456: n = nb;
1457: xindblk(*dp, sp, n);
1458: dp += 1;
1459: sp += n;
1460: nb -= n;
1461: }
1462: }
1463:
1464:
1465: xindblk(b, bp, nd)
1466: daddr_t b, *bp;
1467: register int nd;
1468: {
1469: register daddr_t *dp;
1470: dp = bcache(b);
1471: copy(dp, bp, nd * sizeof(daddr_t));
1472: while (--nd >= 0) {
1473: candaddr(*dp);
1474: dp += 1;
1475: }
1476: }
1477:
1478: /*
1479: * Extend the bad block file.
1480: */
1481: xextend(xp, b)
1482: struct xnode *xp;
1483: daddr_t b;
1484: {
1485: register struct ynode *yp;
1486: int nd;
1487:
1488: assert(xp != NULL);
1489: assert(xp->x_ino == BADFIN);
1490: yp = xp->x_y;
1491: assert(yp != NULL);
1492: assert(yp->y_ino == BADFIN);
1493: assert(b < S.s_fsize);
1494: if (bad(b))
1495: return eignore("duplicated bad block %ld", b);
1496: else if (b == BOOTBI)
1497: return eignore("boot block (%ld) is bad", b);
1498: else if (b == SUPERI)
1499: return efatal("super block (%ld) is bad", b);
1500: else if (b == inodeb(BADFIN))
1501: return efatal("first inode block (%ld) is bad", b);
1502: else if (b < S.s_isize)
1503: S.s_tinode -= INOPB;
1504: else
1505: S.s_tfree -= 1;
1506: xp->x_size += BSIZE;
1507: nd = yp->y_ndb += 1;
1508: if (nd > NADDR)
1509: xp->x_y = yp = xrealloc(yp, sizeof(*yp) + nd * sizeof(daddr_t));
1510: yp->y_b[nd-1] = b;
1511: }
1512:
1513: bad(b)
1514: daddr_t b;
1515: {
1516: struct ynode *yp;
1517: register daddr_t *dp;
1518: register int i;
1519:
1520: assert(X[BADFIN-1] != NULL);
1521: yp = X[BADFIN-1]->x_y;
1522: assert(yp != NULL);
1523: assert(yp->y_ino == BADFIN);
1524: i = yp->y_ndb;
1525: dp = yp->y_db;
1526: while (--i >= 0)
1527: if (b == *dp)
1528: return (1);
1529: else
1530: dp += 1;
1531: return (0);
1532: }
1533:
1534: xfixup(xp)
1535: struct xnode *xp;
1536: {
1537: struct ynode *yp;
1538: register daddr_t *dp1, *dp2;
1539: register int i;
1540:
1541:
1542: assert(xp != NULL);
1543: assert(xp->x_ino == BADFIN);
1544: yp = xp->x_y;
1545: assert(yp != NULL);
1546: xblkuse(xp);
1547: if (yp->y_ni) {
1548: yp = xrealloc(yp, sizeof(*yp) + yp->y_nb * sizeof(daddr_t));
1549: xp->x_y = yp;
1550: yp->y_iiib = yp->y_b;
1551: yp->y_iib = yp->y_iiib + yp->y_niiib;
1552: yp->y_ib = yp->y_iib + yp->y_niib;
1553: yp->y_db = yp->y_ib + yp->y_nib;
1554: dp1 = yp->y_db + yp->y_ndb;
1555: dp2 = yp->y_b + yp->y_ndb;
1556: i = yp->y_ndb;
1557: while (--i >= 0)
1558: *--dp1 = *--dp2;
1559: dp1 = yp->y_b;
1560: i = yp->y_ni;
1561: while (--i >= 0)
1562: *dp1++ = balloc();
1563: }
1564: }
1565:
1566: xdump(xp)
1567: register struct xnode *xp;
1568: {
1569: register struct ynode *yp;
1570:
1571: yp = xp->x_y;
1572: fprintf(stderr, "%d %x %ld\n", xp->x_ino, xp->x_mode, xp->x_size);
1573: if (yp->y_niiib)
1574: xlist("indir^3", yp->y_iiib, (daddr_t)yp->y_niiib);
1575: if (yp->y_niib)
1576: xlist("indir^2", yp->y_iib, (daddr_t)yp->y_niib);
1577: if (yp->y_nib)
1578: xlist("indir^1", yp->y_ib, (daddr_t)yp->y_nib);
1579: if (yp->y_ndb)
1580: xlist("data", yp->y_db, (daddr_t)yp->y_ndb);
1581: }
1582: xlist(cp, dp, n)
1583: char *cp;
1584: daddr_t *dp;
1585: daddr_t n;
1586: {
1587: fprintf(stderr, " %d %s: ", n, cp);
1588: for (;;) {
1589: fprintf(stderr, "%ld", dp[0]);
1590: dp += 1;
1591: n -= 1;
1592: if (n == 0)
1593: break;
1594: if (dp[0] == dp[-1]+1) {
1595: fprintf(stderr, "..");
1596: while (dp[0] == dp[-1]+1) {
1597: dp += 1;
1598: n -= 1;
1599: if (n == 0)
1600: break;
1601: }
1602: fprintf(stderr, "%ld", dp[-1]);
1603: if (n == 0)
1604: break;
1605: }
1606: fprintf(stderr, ", ");
1607: }
1608: fprintf(stderr, "\n");
1609: }
1610:
1611: /* FILE imisc.c */
1612: /*
1613: * Inode cache management.
1614: * iput() - writes an inode to disk.
1615: */
1616: /*
1617: * Write the inode `ip' containing the inode `i' onto the
1618: * filesystem in canonical form.
1619: */
1620: iput(i, dip1)
1621: ino_t i;
1622: register struct dinode *dip1;
1623: {
1624: register struct dinode *dip2;
1625:
1626: dip2 = bcache((daddr_t)inodeb(i));
1627: dip2 += inodei(i);
1628: *dip2 = *dip1;
1629: canshort(dip2->di_mode);
1630: canshort(dip2->di_nlink);
1631: canshort(dip2->di_uid);
1632: canshort(dip2->di_gid);
1633: cansize(dip2->di_size);
1634: cantime(dip2->di_atime);
1635: cantime(dip2->di_mtime);
1636: cantime(dip2->di_ctime);
1637: switch (dip1->di_mode&IFMT) {
1638: case IFCHR:
1639: case IFBLK:
1640: candev(dip2->di_a.di_rdev);
1641: break;
1642: }
1643: }
1644:
1645: /*
1646: * Return a free inode number.
1647: */
1648: ino_t
1649: ialloc()
1650: {
1651: ino_t inum;
1652: ino_t in;
1653: ino_t *ip;
1654: daddr_t b;
1655:
1656: if (S.s_ninode == 0)
1657: return efatal("out of inodes");
1658: inum = S.s_inode[--S.s_ninode];
1659: if (S.s_ninode == 0) {
1660: ip = &S.s_inode[NICINOD];
1661: in = inum + 1;
1662: while ((b = inodeb(in)) < S.s_isize && ip >S.s_inode) {
1663: if (bad(b)) {
1664: in += INOPB;
1665: continue;
1666: }
1667: *--ip = in++;
1668: }
1669: S.s_ninode = NICINOD;
1670: if (ip != S.s_inode) {
1671: S.s_ninode -= ip - S.s_inode;
1672: copy(S.s_inode, ip, S.s_ninode * sizeof(ino_t));
1673: }
1674: }
1675: --S.s_tinode;
1676: return (inum);
1677: }
1678:
1679: /* FILE bmisc.c */
1680: /*
1681: * Block management.
1682: * bbegin() - set the seed of the block allocator.
1683: * balloc() - allocate a block.
1684: * bstart() - resynchronize the allocation.
1685: * bmap() - implement interleave mapping.
1686: * bcache() - single block buffer cache.
1687: */
1688: int bwatch = 0;
1689:
1690: static daddr_t bseed;
1691: static daddr_t bmap();
1692:
1693: bbegin()
1694: {
1695: /* Must be called after the bad block list is initialized */
1696: assert(X != NULL);
1697: assert(X[BADFIN-1] != NULL);
1698: assert(X[BADFIN-1]->x_y != NULL);
1699: bseed = S.s_isize;
1700: S.s_tfree += S.s_fsize - S.s_isize;
1701: clear(S.s_free, NICFREE*sizeof(daddr_t));
1702: S.s_nfree = 1;
1703: while (bad(S.s_free[0] = bmap(bseed)))
1704: ++bseed;
1705: }
1706:
1707: daddr_t
1708: balloc()
1709: {
1710: register daddr_t *dp;
1711: register daddr_t b, b1;
1712:
1713: if (S.s_nfree == 0)
1714: return 0;
1715: b = S.s_free[--S.s_nfree];
1716: if (S.s_nfree == 0) {
1717: clear(S.s_free, sizeof S.s_free);
1718: dp = &S.s_free[NICFREE];
1719: while (dp > S.s_free && ++bseed < S.s_fsize) {
1720: b1 = bmap(bseed);
1721: if (bad(b1))
1722: continue;
1723: *--dp = b1;
1724: }
1725: S.s_nfree = NICFREE - (dp - S.s_free);
1726: if (dp != S.s_free)
1727: copy(S.s_free, dp, S.s_nfree * sizeof(daddr_t));
1728: }
1729: --S.s_tfree;
1730: return (b);
1731: }
1732:
1733: bstart(b)
1734: daddr_t b;
1735: {
1736: if (S.s_nfree && S.s_free[S.s_nfree-1] == b)
1737: return;
1738: bbegin();
1739: while (S.s_nfree && S.s_free[S.s_nfree-1] != b)
1740: balloc();
1741: assert(S.s_nfree != 0);
1742: }
1743:
1744: #define MAXINTN 255 /* maptab must be int * if > 255 */
1745: static unsigned char *maptab; /* Interleave table */
1746: static daddr_t mapbot;
1747: static daddr_t maptop;
1748: /*
1749: * Return a mapped block number with interleaving.
1750: */
1751: static daddr_t
1752: bmap(b)
1753: daddr_t b;
1754: {
1755: register short i;
1756: register int ints;
1757:
1758: if (maptab == NULL) {
1759: if (S.s_n > MAXINTN
1760: || S.s_m > S.s_n
1761: || S.s_n%S.s_m != 0)
1762: efatal("%d/%d: bad interleave factor", S.s_m, S.s_n);
1763: maptab = xmalloc(S.s_n);
1764: mapbot = ((S.s_isize + S.s_n - 1) / S.s_n) * S.s_n;
1765: maptop = (S.s_fsize / S.s_n) * S.s_n;
1766: ints = S.s_n / S.s_m;
1767: for (i=0; i < S.s_n; i++)
1768: maptab[i] = (i / ints) + (i % ints) * S.s_m;
1769: }
1770: if (b >= mapbot && b < maptop) {
1771: i = b % S.s_n;
1772: b -= i;
1773: b += maptab[i];
1774: }
1775: return (b);
1776: }
1777:
1778: char *
1779: bcache(b)
1780: daddr_t b;
1781: {
1782: static daddr_t bcacheb = -1;
1783: static char buffer[BSIZE];
1784: if (bcacheb != b) {
1785: if (bcacheb >= 0) {
1786: lseek(FS, (long)bcacheb*BSIZE, 0);
1787: if (bwatch) bdump(b, bcacheb, buffer);
1788: if (write(FS, buffer, BSIZE) != BSIZE)
1789: eignore("filesystem write error at block %ld", b);
1790: }
1791: clear(buffer, BSIZE);
1792: }
1793: bcacheb = b;
1794: return (buffer);
1795: }
1796:
1797: bdump(b1, b2, bp)
1798: daddr_t b1, b2;
1799: char *bp;
1800: {
1801: int i, j;
1802: fprintf(stderr, "bcache(%ld) writes(%ld) = {", b1, b2);
1803: if (iszero(bp, BSIZE))
1804: fprintf(stderr, " 0 ");
1805: else {
1806: fprintf(stderr, "\n");
1807: for (i = 0; i < 32; i += 1) {
1808: for (j = 0; j < 16; j += 1)
1809: fprintf(stderr, " %02x", *bp++ & 0377);
1810: fprintf(stderr, "\n");
1811: }
1812: }
1813: fprintf(stderr, "}\n");
1814: }
1815:
1816: /* end of mkfs.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.