|
|
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.