|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)dirs.c 3.16 (Berkeley) 83/08/11"; ! 3: #endif ! 4: ! 5: /* Copyright (c) 1983 Regents of the University of California */ ! 6: ! 7: #include "restore.h" ! 8: #include <dumprestor.h> ! 9: #include <sys/file.h> ! 10: #include <sys/dir.h> ! 11: ! 12: /* ! 13: * Symbol table of directories read from tape. ! 14: */ ! 15: #define HASHSIZE 1000 ! 16: #define INOHASH(val) (val % HASHSIZE) ! 17: struct inotab { ! 18: struct inotab *t_next; ! 19: ino_t t_ino; ! 20: daddr_t t_seekpt; ! 21: long t_size; ! 22: }; ! 23: static struct inotab *inotab[HASHSIZE]; ! 24: extern struct inotab *inotablookup(); ! 25: extern struct inotab *allocinotab(); ! 26: ! 27: /* ! 28: * Information retained about directories. ! 29: */ ! 30: struct modeinfo { ! 31: ino_t ino; ! 32: time_t timep[2]; ! 33: short mode; ! 34: short uid; ! 35: short gid; ! 36: }; ! 37: ! 38: /* ! 39: * Global variables for this file. ! 40: */ ! 41: static daddr_t seekpt; ! 42: static FILE *df, *mf; ! 43: static DIR *dirp; ! 44: static char dirfile[32] = "#"; /* No file */ ! 45: static char modefile[32] = "#"; /* No file */ ! 46: extern ino_t search(); ! 47: struct direct *rst_readdir(); ! 48: extern void rst_seekdir(); ! 49: ! 50: /* ! 51: * Format of old style directories. ! 52: */ ! 53: #define ODIRSIZ 14 ! 54: struct odirect { ! 55: u_short d_ino; ! 56: char d_name[ODIRSIZ]; ! 57: }; ! 58: ! 59: /* ! 60: * Structure and routines associated with listing directories. ! 61: */ ! 62: struct afile { ! 63: ino_t fnum; /* inode number of file */ ! 64: char *fname; /* file name */ ! 65: short fflags; /* extraction flags, if any */ ! 66: char ftype; /* file type, e.g. LEAF or NODE */ ! 67: }; ! 68: extern int fcmp(); ! 69: extern char *fmtentry(); ! 70: ! 71: /* ! 72: * Extract directory contents, building up a directory structure ! 73: * on disk for extraction by name. ! 74: * If genmode is requested, save mode, owner, and times for all ! 75: * directories on the tape. ! 76: */ ! 77: extractdirs(genmode) ! 78: int genmode; ! 79: { ! 80: register int i; ! 81: register struct dinode *ip; ! 82: struct inotab *itp; ! 83: struct direct nulldir; ! 84: int putdir(), null(); ! 85: ! 86: vprintf(stdout, "Extract directories from tape\n"); ! 87: (void) sprintf(dirfile, "/tmp/rstdir%d", dumpdate); ! 88: df = fopen(dirfile, "w"); ! 89: if (df == 0) { ! 90: fprintf(stderr, ! 91: "restor: %s - cannot create directory temporary\n", ! 92: dirfile); ! 93: perror("fopen"); ! 94: done(1); ! 95: } ! 96: if (genmode != 0) { ! 97: (void) sprintf(modefile, "/tmp/rstmode%d", dumpdate); ! 98: mf = fopen(modefile, "w"); ! 99: if (mf == 0) { ! 100: fprintf(stderr, ! 101: "restor: %s - cannot create modefile \n", ! 102: modefile); ! 103: perror("fopen"); ! 104: done(1); ! 105: } ! 106: } ! 107: nulldir.d_ino = 0; ! 108: nulldir.d_namlen = 1; ! 109: (void) strcpy(nulldir.d_name, "/"); ! 110: nulldir.d_reclen = DIRSIZ(&nulldir); ! 111: for (;;) { ! 112: curfile.name = "<directory file - name unknown>"; ! 113: curfile.action = USING; ! 114: ip = curfile.dip; ! 115: i = ip->di_mode & IFMT; ! 116: if (i != IFDIR) { ! 117: (void) fclose(df); ! 118: dirp = opendir(dirfile); ! 119: if (dirp == NULL) ! 120: perror("opendir"); ! 121: if (mf != NULL) ! 122: (void) fclose(mf); ! 123: i = dirlookup("."); ! 124: if (i == 0) ! 125: panic("Root directory is not on tape\n"); ! 126: return; ! 127: } ! 128: itp = allocinotab(curfile.ino, ip, seekpt); ! 129: getfile(putdir, null); ! 130: putent(&nulldir); ! 131: flushent(); ! 132: itp->t_size = seekpt - itp->t_seekpt; ! 133: } ! 134: } ! 135: ! 136: /* ! 137: * skip over all the directories on the tape ! 138: */ ! 139: skipdirs() ! 140: { ! 141: ! 142: while ((curfile.dip->di_mode & IFMT) == IFDIR) { ! 143: skipfile(); ! 144: } ! 145: } ! 146: ! 147: /* ! 148: * Recursively find names and inumbers of all files in subtree ! 149: * pname and pass them off to be processed. ! 150: */ ! 151: treescan(pname, ino, todo) ! 152: char *pname; ! 153: ino_t ino; ! 154: long (*todo)(); ! 155: { ! 156: register struct inotab *itp; ! 157: register struct direct *dp; ! 158: register struct entry *np; ! 159: int namelen; ! 160: daddr_t bpt; ! 161: char locname[MAXPATHLEN + 1]; ! 162: ! 163: itp = inotablookup(ino); ! 164: if (itp == NULL) { ! 165: /* ! 166: * Pname is name of a simple file or an unchanged directory. ! 167: */ ! 168: (void) (*todo)(pname, ino, LEAF); ! 169: return; ! 170: } ! 171: /* ! 172: * Pname is a dumped directory name. ! 173: */ ! 174: if ((*todo)(pname, ino, NODE) == FAIL) ! 175: return; ! 176: /* ! 177: * begin search through the directory ! 178: * skipping over "." and ".." ! 179: */ ! 180: (void) strncpy(locname, pname, MAXPATHLEN); ! 181: (void) strncat(locname, "/", MAXPATHLEN); ! 182: namelen = strlen(locname); ! 183: rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); ! 184: dp = rst_readdir(dirp); /* "." */ ! 185: if (dp != NULL && strcmp(dp->d_name, ".") == 0) { ! 186: dp = rst_readdir(dirp); /* ".." */ ! 187: } else { ! 188: np = lookupino(ino); ! 189: if (np == NULL) ! 190: panic("corrupted symbol table\n"); ! 191: fprintf(stderr, ". missing from directory %s\n", myname(np)); ! 192: } ! 193: if (dp != NULL && strcmp(dp->d_name, "..") == 0) { ! 194: dp = rst_readdir(dirp); /* first real entry */ ! 195: } else { ! 196: np = lookupino(ino); ! 197: if (np == NULL) ! 198: panic("corrupted symbol table\n"); ! 199: fprintf(stderr, ".. missing from directory %s\n", myname(np)); ! 200: } ! 201: bpt = telldir(dirp); ! 202: /* ! 203: * a zero inode signals end of directory ! 204: */ ! 205: while (dp != NULL && dp->d_ino != 0) { ! 206: locname[namelen] = '\0'; ! 207: if (namelen + dp->d_namlen >= MAXPATHLEN) { ! 208: fprintf(stderr, "%s%s: name exceeds %d char\n", ! 209: locname, dp->d_name, MAXPATHLEN); ! 210: } else { ! 211: (void) strncat(locname, dp->d_name, (int)dp->d_namlen); ! 212: treescan(locname, dp->d_ino, todo); ! 213: rst_seekdir(dirp, bpt, itp->t_seekpt); ! 214: } ! 215: dp = rst_readdir(dirp); ! 216: bpt = telldir(dirp); ! 217: } ! 218: if (dp == NULL) ! 219: fprintf(stderr, "corrupted directory: %s.\n", locname); ! 220: } ! 221: ! 222: /* ! 223: * Search the directory tree rooted at inode ROOTINO ! 224: * for the path pointed at by n ! 225: */ ! 226: ino_t ! 227: psearch(n) ! 228: char *n; ! 229: { ! 230: register char *cp, *cp1; ! 231: ino_t ino; ! 232: char c; ! 233: ! 234: ino = ROOTINO; ! 235: if (*(cp = n) == '/') ! 236: cp++; ! 237: next: ! 238: cp1 = cp + 1; ! 239: while (*cp1 != '/' && *cp1) ! 240: cp1++; ! 241: c = *cp1; ! 242: *cp1 = 0; ! 243: ino = search(ino, cp); ! 244: if (ino == 0) { ! 245: *cp1 = c; ! 246: return(0); ! 247: } ! 248: *cp1 = c; ! 249: if (c == '/') { ! 250: cp = cp1+1; ! 251: goto next; ! 252: } ! 253: return(ino); ! 254: } ! 255: ! 256: /* ! 257: * search the directory inode ino ! 258: * looking for entry cp ! 259: */ ! 260: ino_t ! 261: search(inum, cp) ! 262: ino_t inum; ! 263: char *cp; ! 264: { ! 265: register struct direct *dp; ! 266: register struct inotab *itp; ! 267: int len; ! 268: ! 269: itp = inotablookup(inum); ! 270: if (itp == NULL) ! 271: return(0); ! 272: rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); ! 273: len = strlen(cp); ! 274: do { ! 275: dp = rst_readdir(dirp); ! 276: if (dp == NULL || dp->d_ino == 0) ! 277: return (0); ! 278: } while (dp->d_namlen != len || strncmp(dp->d_name, cp, len) != 0); ! 279: return(dp->d_ino); ! 280: } ! 281: ! 282: /* ! 283: * Put the directory entries in the directory file ! 284: */ ! 285: putdir(buf, size) ! 286: char *buf; ! 287: int size; ! 288: { ! 289: struct direct cvtbuf; ! 290: register struct odirect *odp; ! 291: struct odirect *eodp; ! 292: register struct direct *dp; ! 293: long loc, i; ! 294: ! 295: if (cvtflag) { ! 296: eodp = (struct odirect *)&buf[size]; ! 297: for (odp = (struct odirect *)buf; odp < eodp; odp++) ! 298: if (odp->d_ino != 0) { ! 299: dcvt(odp, &cvtbuf); ! 300: putent(&cvtbuf); ! 301: } ! 302: } else { ! 303: for (loc = 0; loc < size; ) { ! 304: dp = (struct direct *)(buf + loc); ! 305: i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1)); ! 306: if (dp->d_reclen == 0 || dp->d_reclen > i) { ! 307: loc += i; ! 308: continue; ! 309: } ! 310: loc += dp->d_reclen; ! 311: if (dp->d_ino != 0) { ! 312: putent(dp); ! 313: } ! 314: } ! 315: } ! 316: } ! 317: ! 318: /* ! 319: * These variables are "local" to the following two functions. ! 320: */ ! 321: char dirbuf[DIRBLKSIZ]; ! 322: long dirloc = 0; ! 323: long prev = 0; ! 324: ! 325: /* ! 326: * add a new directory entry to a file. ! 327: */ ! 328: putent(dp) ! 329: struct direct *dp; ! 330: { ! 331: dp->d_reclen = DIRSIZ(dp); ! 332: if (dirloc + dp->d_reclen > DIRBLKSIZ) { ! 333: ((struct direct *)(dirbuf + prev))->d_reclen = ! 334: DIRBLKSIZ - prev; ! 335: (void) fwrite(dirbuf, 1, DIRBLKSIZ, df); ! 336: dirloc = 0; ! 337: } ! 338: bcopy((char *)dp, dirbuf + dirloc, (long)dp->d_reclen); ! 339: prev = dirloc; ! 340: dirloc += dp->d_reclen; ! 341: } ! 342: ! 343: /* ! 344: * flush out a directory that is finished. ! 345: */ ! 346: flushent() ! 347: { ! 348: ! 349: ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev; ! 350: (void) fwrite(dirbuf, (int)dirloc, 1, df); ! 351: seekpt = ftell(df); ! 352: dirloc = 0; ! 353: } ! 354: ! 355: dcvt(odp, ndp) ! 356: register struct odirect *odp; ! 357: register struct direct *ndp; ! 358: { ! 359: ! 360: bzero((char *)ndp, (long)(sizeof *ndp)); ! 361: ndp->d_ino = odp->d_ino; ! 362: (void) strncpy(ndp->d_name, odp->d_name, ODIRSIZ); ! 363: ndp->d_namlen = strlen(ndp->d_name); ! 364: ndp->d_reclen = DIRSIZ(ndp); ! 365: } ! 366: ! 367: /* ! 368: * Seek to an entry in a directory. ! 369: * Only values returned by ``telldir'' should be passed to rst_seekdir. ! 370: * This routine handles many directories in a single file. ! 371: * It takes the base of the directory in the file, plus ! 372: * the desired seek offset into it. ! 373: */ ! 374: void ! 375: rst_seekdir(dirp, loc, base) ! 376: register DIR *dirp; ! 377: daddr_t loc, base; ! 378: { ! 379: ! 380: if (loc == telldir(dirp)) ! 381: return; ! 382: loc -= base; ! 383: if (loc < 0) ! 384: fprintf(stderr, "bad seek pointer to rst_seekdir %d\n", loc); ! 385: (void) lseek(dirp->dd_fd, base + (loc & ~(DIRBLKSIZ - 1)), 0); ! 386: dirp->dd_loc = loc & (DIRBLKSIZ - 1); ! 387: if (dirp->dd_loc != 0) ! 388: dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ); ! 389: } ! 390: ! 391: /* ! 392: * get next entry in a directory. ! 393: */ ! 394: struct direct * ! 395: rst_readdir(dirp) ! 396: register DIR *dirp; ! 397: { ! 398: register struct direct *dp; ! 399: ! 400: for (;;) { ! 401: if (dirp->dd_loc == 0) { ! 402: dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, ! 403: DIRBLKSIZ); ! 404: if (dirp->dd_size <= 0) { ! 405: dprintf(stderr, "error reading directory\n"); ! 406: return NULL; ! 407: } ! 408: } ! 409: if (dirp->dd_loc >= dirp->dd_size) { ! 410: dirp->dd_loc = 0; ! 411: continue; ! 412: } ! 413: dp = (struct direct *)(dirp->dd_buf + dirp->dd_loc); ! 414: if (dp->d_reclen == 0 || ! 415: dp->d_reclen > DIRBLKSIZ + 1 - dirp->dd_loc) { ! 416: dprintf(stderr, "corrupted directory: bad reclen %d\n", ! 417: dp->d_reclen); ! 418: return NULL; ! 419: } ! 420: dirp->dd_loc += dp->d_reclen; ! 421: if (dp->d_ino == 0 && strcmp(dp->d_name, "/") != 0) ! 422: continue; ! 423: if (dp->d_ino >= maxino) { ! 424: dprintf(stderr, "corrupted directory: bad inum %d\n", ! 425: dp->d_ino); ! 426: continue; ! 427: } ! 428: return (dp); ! 429: } ! 430: } ! 431: ! 432: /* ! 433: * Set the mode, owner, and times for all new or changed directories ! 434: */ ! 435: setdirmodes() ! 436: { ! 437: FILE *mf; ! 438: struct modeinfo node; ! 439: struct entry *ep; ! 440: char *cp; ! 441: ! 442: vprintf(stdout, "Set directory mode, owner, and times.\n"); ! 443: mf = fopen(modefile, "r"); ! 444: if (mf == NULL) { ! 445: perror("fopen"); ! 446: panic("cannot open mode file %s\n", modefile); ! 447: } ! 448: clearerr(mf); ! 449: for (;;) { ! 450: (void) fread((char *)&node, 1, sizeof(struct modeinfo), mf); ! 451: if (feof(mf)) ! 452: break; ! 453: ep = lookupino(node.ino); ! 454: if (command == 'i' || command == 'x') { ! 455: if (ep == NIL) ! 456: continue; ! 457: if (node.ino == ROOTINO && ! 458: reply("set owner/mode for '.'") == FAIL) ! 459: continue; ! 460: } ! 461: if (ep == NIL) ! 462: panic("cannot find directory inode %d\n", node.ino); ! 463: cp = myname(ep); ! 464: (void) chown(cp, node.uid, node.gid); ! 465: (void) chmod(cp, node.mode); ! 466: utime(cp, node.timep); ! 467: ep->e_flags &= ~NEW; ! 468: } ! 469: if (ferror(mf)) ! 470: panic("error setting directory modes\n"); ! 471: (void) fclose(mf); ! 472: } ! 473: ! 474: /* ! 475: * Generate a literal copy of a directory. ! 476: */ ! 477: genliteraldir(name, ino) ! 478: char *name; ! 479: ino_t ino; ! 480: { ! 481: register struct inotab *itp; ! 482: int ofile, dp, i, size; ! 483: char buf[BUFSIZ]; ! 484: ! 485: itp = inotablookup(ino); ! 486: if (itp == NULL) ! 487: panic("Cannot find directory inode %d named %s\n", ino, name); ! 488: if ((ofile = creat(name, 0666)) < 0) { ! 489: fprintf(stderr, "%s: ", name); ! 490: (void) fflush(stderr); ! 491: perror("cannot create file"); ! 492: return (FAIL); ! 493: } ! 494: rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); ! 495: dp = dup(dirp->dd_fd); ! 496: for (i = itp->t_size; i > 0; i -= BUFSIZ) { ! 497: size = i < BUFSIZ ? i : BUFSIZ; ! 498: if (read(dp, buf, (int) size) == -1) { ! 499: fprintf(stderr, ! 500: "write error extracting inode %d, name %s\n", ! 501: curfile.ino, curfile.name); ! 502: perror("read"); ! 503: done(1); ! 504: } ! 505: if (write(ofile, buf, (int) size) == -1) { ! 506: fprintf(stderr, ! 507: "write error extracting inode %d, name %s\n", ! 508: curfile.ino, curfile.name); ! 509: perror("write"); ! 510: done(1); ! 511: } ! 512: } ! 513: (void) close(dp); ! 514: (void) close(ofile); ! 515: return (GOOD); ! 516: } ! 517: ! 518: /* ! 519: * Do an "ls" style listing of a directory ! 520: */ ! 521: printlist(name, ino) ! 522: char *name; ! 523: ino_t ino; ! 524: { ! 525: register struct afile *fp; ! 526: register struct inotab *itp; ! 527: struct afile *dfp0, *dfplast; ! 528: struct afile single; ! 529: ! 530: itp = inotablookup(ino); ! 531: if (itp == NULL) { ! 532: single.fnum = ino; ! 533: single.fname = savename(rindex(name, '/') + 1); ! 534: dfp0 = &single; ! 535: dfplast = dfp0 + 1; ! 536: } else { ! 537: rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); ! 538: if (getdir(dirp, &dfp0, &dfplast) == FAIL) ! 539: return; ! 540: } ! 541: qsort((char *)dfp0, dfplast - dfp0, sizeof (struct afile), fcmp); ! 542: formatf(dfp0, dfplast); ! 543: for (fp = dfp0; fp < dfplast; fp++) ! 544: freename(fp->fname); ! 545: } ! 546: ! 547: /* ! 548: * Read the contents of a directory. ! 549: */ ! 550: getdir(dirp, pfp0, pfplast) ! 551: DIR *dirp; ! 552: struct afile **pfp0, **pfplast; ! 553: { ! 554: register struct afile *fp; ! 555: register struct direct *dp; ! 556: static struct afile *basefp = NULL; ! 557: static long nent = 20; ! 558: ! 559: if (basefp == NULL) { ! 560: basefp = (struct afile *)calloc((unsigned)nent, ! 561: sizeof (struct afile)); ! 562: if (basefp == NULL) { ! 563: fprintf(stderr, "ls: out of memory\n"); ! 564: return (FAIL); ! 565: } ! 566: } ! 567: fp = *pfp0 = basefp; ! 568: *pfplast = *pfp0 + nent; ! 569: while (dp = rst_readdir(dirp)) { ! 570: if (dp == NULL || dp->d_ino == 0) ! 571: break; ! 572: if (!dflag && BIT(dp->d_ino, dumpmap) == 0) ! 573: continue; ! 574: if (vflag == 0 && ! 575: (strcmp(dp->d_name, ".") == 0 || ! 576: strcmp(dp->d_name, "..") == 0)) ! 577: continue; ! 578: fp->fnum = dp->d_ino; ! 579: fp->fname = savename(dp->d_name); ! 580: fp++; ! 581: if (fp == *pfplast) { ! 582: basefp = (struct afile *)realloc((char *)basefp, ! 583: (unsigned)(2 * nent * sizeof (struct afile))); ! 584: if (basefp == 0) { ! 585: fprintf(stderr, "ls: out of memory\n"); ! 586: return (FAIL); ! 587: } ! 588: *pfp0 = basefp; ! 589: fp = *pfp0 + nent; ! 590: *pfplast = fp + nent; ! 591: nent *= 2; ! 592: } ! 593: } ! 594: *pfplast = fp; ! 595: return (GOOD); ! 596: } ! 597: ! 598: /* ! 599: * Print out a pretty listing of a directory ! 600: */ ! 601: formatf(fp0, fplast) ! 602: struct afile *fp0, *fplast; ! 603: { ! 604: register struct afile *fp; ! 605: struct entry *np; ! 606: int width = 0, w, nentry = fplast - fp0; ! 607: int i, j, len, columns, lines; ! 608: char *cp; ! 609: ! 610: if (fp0 == fplast) ! 611: return; ! 612: for (fp = fp0; fp < fplast; fp++) { ! 613: fp->ftype = inodetype(fp->fnum); ! 614: np = lookupino(fp->fnum); ! 615: if (np != NIL) ! 616: fp->fflags = np->e_flags; ! 617: else ! 618: fp->fflags = 0; ! 619: len = strlen(fmtentry(fp)); ! 620: if (len > width) ! 621: width = len; ! 622: } ! 623: width += 2; ! 624: columns = 80 / width; ! 625: if (columns == 0) ! 626: columns = 1; ! 627: lines = (nentry + columns - 1) / columns; ! 628: for (i = 0; i < lines; i++) { ! 629: for (j = 0; j < columns; j++) { ! 630: fp = fp0 + j * lines + i; ! 631: cp = fmtentry(fp); ! 632: fprintf(stderr, "%s", cp); ! 633: if (fp + lines >= fplast) { ! 634: fprintf(stderr, "\n"); ! 635: break; ! 636: } ! 637: w = strlen(cp); ! 638: while (w < width) { ! 639: w++; ! 640: fprintf(stderr, " "); ! 641: } ! 642: } ! 643: } ! 644: } ! 645: ! 646: /* ! 647: * Comparison routine for qsort. ! 648: */ ! 649: fcmp(f1, f2) ! 650: register struct afile *f1, *f2; ! 651: { ! 652: ! 653: return (strcmp(f1->fname, f2->fname)); ! 654: } ! 655: ! 656: /* ! 657: * Format a directory entry. ! 658: */ ! 659: char * ! 660: fmtentry(fp) ! 661: register struct afile *fp; ! 662: { ! 663: static char fmtres[BUFSIZ]; ! 664: register char *cp, *dp; ! 665: ! 666: if (vflag) ! 667: (void) sprintf(fmtres, "%5d ", fp->fnum); ! 668: else ! 669: fmtres[0] = '\0'; ! 670: dp = &fmtres[strlen(fmtres)]; ! 671: if (dflag && BIT(fp->fnum, dumpmap) == 0) ! 672: *dp++ = '^'; ! 673: else if ((fp->fflags & NEW) != 0) ! 674: *dp++ = '*'; ! 675: else ! 676: *dp++ = ' '; ! 677: for (cp = fp->fname; *cp; cp++) ! 678: if (!vflag && (*cp < ' ' || *cp >= 0177)) ! 679: *dp++ = '?'; ! 680: else ! 681: *dp++ = *cp; ! 682: if (fp->ftype == NODE) ! 683: *dp++ = '/'; ! 684: *dp++ = 0; ! 685: return (fmtres); ! 686: } ! 687: ! 688: /* ! 689: * Determine the type of an inode ! 690: */ ! 691: inodetype(ino) ! 692: ino_t ino; ! 693: { ! 694: struct inotab *itp; ! 695: ! 696: itp = inotablookup(ino); ! 697: if (itp == NULL) ! 698: return (LEAF); ! 699: return (NODE); ! 700: } ! 701: ! 702: /* ! 703: * Allocate and initialize a directory inode entry. ! 704: * If requested, save its pertinent mode, owner, and time info. ! 705: */ ! 706: struct inotab * ! 707: allocinotab(ino, dip, seekpt) ! 708: ino_t ino; ! 709: struct dinode *dip; ! 710: daddr_t seekpt; ! 711: { ! 712: register struct inotab *itp; ! 713: struct modeinfo node; ! 714: ! 715: itp = (struct inotab *)calloc(1, sizeof(struct inotab)); ! 716: if (itp == 0) ! 717: panic("no memory directory table\n"); ! 718: itp->t_next = inotab[INOHASH(ino)]; ! 719: inotab[INOHASH(ino)] = itp; ! 720: itp->t_ino = ino; ! 721: itp->t_seekpt = seekpt; ! 722: if (mf == NULL) ! 723: return(itp); ! 724: node.ino = ino; ! 725: node.timep[0] = dip->di_atime; ! 726: node.timep[1] = dip->di_mtime; ! 727: node.mode = dip->di_mode; ! 728: node.uid = dip->di_uid; ! 729: node.gid = dip->di_gid; ! 730: (void) fwrite((char *)&node, 1, sizeof(struct modeinfo), mf); ! 731: return(itp); ! 732: } ! 733: ! 734: /* ! 735: * Look up an inode in the table of directories ! 736: */ ! 737: struct inotab * ! 738: inotablookup(ino) ! 739: ino_t ino; ! 740: { ! 741: register struct inotab *itp; ! 742: ! 743: for (itp = inotab[INOHASH(ino)]; itp != NULL; itp = itp->t_next) ! 744: if (itp->t_ino == ino) ! 745: return(itp); ! 746: return ((struct inotab *)0); ! 747: } ! 748: ! 749: /* ! 750: * Clean up and exit ! 751: */ ! 752: done(exitcode) ! 753: int exitcode; ! 754: { ! 755: ! 756: closemt(); ! 757: if (modefile[0] != '#') ! 758: (void) unlink(modefile); ! 759: if (dirfile[0] != '#') ! 760: (void) unlink(dirfile); ! 761: exit(exitcode); ! 762: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.