|
|
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); /* "." or ".." */ ! 185: if (dp != NULL && ! 186: (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)) { ! 187: dp = rst_readdir(dirp); /* "." or ".." */ ! 188: } else { ! 189: np = lookupino(ino); ! 190: if (np == NULL) ! 191: panic("corrupted symbol table\n"); ! 192: fprintf(stderr, ". and .. are not the first two entries in directory %s\n", myname(np)); ! 193: dp = (struct direct *)NULL; ! 194: } ! 195: if (dp != NULL && ! 196: (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)) { ! 197: dp = rst_readdir(dirp); /* first real entry */ ! 198: } else { ! 199: np = lookupino(ino); ! 200: if (np == NULL) ! 201: panic("corrupted symbol table\n"); ! 202: fprintf(stderr, ". and .. are not the first two entries in directory %s\n", myname(np)); ! 203: dp = (struct direct *)NULL; ! 204: } ! 205: bpt = telldir(dirp); ! 206: /* ! 207: * a zero inode signals end of directory ! 208: */ ! 209: while (dp != NULL && dp->d_ino != 0) { ! 210: locname[namelen] = '\0'; ! 211: if (namelen + dp->d_namlen >= MAXPATHLEN) { ! 212: fprintf(stderr, "%s%s: name exceeds %d char\n", ! 213: locname, dp->d_name, MAXPATHLEN); ! 214: } else { ! 215: (void) strncat(locname, dp->d_name, (int)dp->d_namlen); ! 216: treescan(locname, dp->d_ino, todo); ! 217: rst_seekdir(dirp, bpt, itp->t_seekpt); ! 218: } ! 219: dp = rst_readdir(dirp); ! 220: bpt = telldir(dirp); ! 221: } ! 222: if (dp == NULL) ! 223: fprintf(stderr, "corrupted directory: %s.\n", locname); ! 224: } ! 225: ! 226: /* ! 227: * Search the directory tree rooted at inode ROOTINO ! 228: * for the path pointed at by n ! 229: */ ! 230: ino_t ! 231: psearch(n) ! 232: char *n; ! 233: { ! 234: register char *cp, *cp1; ! 235: ino_t ino; ! 236: char c; ! 237: ! 238: ino = ROOTINO; ! 239: if (*(cp = n) == '/') ! 240: cp++; ! 241: next: ! 242: cp1 = cp + 1; ! 243: while (*cp1 != '/' && *cp1) ! 244: cp1++; ! 245: c = *cp1; ! 246: *cp1 = 0; ! 247: ino = search(ino, cp); ! 248: if (ino == 0) { ! 249: *cp1 = c; ! 250: return(0); ! 251: } ! 252: *cp1 = c; ! 253: if (c == '/') { ! 254: cp = cp1+1; ! 255: goto next; ! 256: } ! 257: return(ino); ! 258: } ! 259: ! 260: /* ! 261: * search the directory inode ino ! 262: * looking for entry cp ! 263: */ ! 264: ino_t ! 265: search(inum, cp) ! 266: ino_t inum; ! 267: char *cp; ! 268: { ! 269: register struct direct *dp; ! 270: register struct inotab *itp; ! 271: int len; ! 272: ! 273: itp = inotablookup(inum); ! 274: if (itp == NULL) ! 275: return(0); ! 276: rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); ! 277: len = strlen(cp); ! 278: do { ! 279: dp = rst_readdir(dirp); ! 280: if (dp == NULL || dp->d_ino == 0) ! 281: return (0); ! 282: } while (dp->d_namlen != len || strncmp(dp->d_name, cp, len) != 0); ! 283: return(dp->d_ino); ! 284: } ! 285: ! 286: /* ! 287: * Put the directory entries in the directory file ! 288: */ ! 289: putdir(buf, size) ! 290: char *buf; ! 291: int size; ! 292: { ! 293: struct direct cvtbuf; ! 294: register struct odirect *odp; ! 295: struct odirect *eodp; ! 296: register struct direct *dp; ! 297: long loc, i; ! 298: ! 299: if (cvtflag) { ! 300: eodp = (struct odirect *)&buf[size]; ! 301: for (odp = (struct odirect *)buf; odp < eodp; odp++) ! 302: if (odp->d_ino != 0) { ! 303: dcvt(odp, &cvtbuf); ! 304: putent(&cvtbuf); ! 305: } ! 306: } else { ! 307: for (loc = 0; loc < size; ) { ! 308: dp = (struct direct *)(buf + loc); ! 309: i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1)); ! 310: if (dp->d_reclen == 0 || dp->d_reclen > i) { ! 311: loc += i; ! 312: continue; ! 313: } ! 314: loc += dp->d_reclen; ! 315: if (dp->d_ino != 0) { ! 316: putent(dp); ! 317: } ! 318: } ! 319: } ! 320: } ! 321: ! 322: /* ! 323: * These variables are "local" to the following two functions. ! 324: */ ! 325: char dirbuf[DIRBLKSIZ]; ! 326: long dirloc = 0; ! 327: long prev = 0; ! 328: ! 329: /* ! 330: * add a new directory entry to a file. ! 331: */ ! 332: putent(dp) ! 333: struct direct *dp; ! 334: { ! 335: dp->d_reclen = DIRSIZ(dp); ! 336: if (dirloc + dp->d_reclen > DIRBLKSIZ) { ! 337: ((struct direct *)(dirbuf + prev))->d_reclen = ! 338: DIRBLKSIZ - prev; ! 339: (void) fwrite(dirbuf, 1, DIRBLKSIZ, df); ! 340: dirloc = 0; ! 341: } ! 342: bcopy((char *)dp, dirbuf + dirloc, (long)dp->d_reclen); ! 343: prev = dirloc; ! 344: dirloc += dp->d_reclen; ! 345: } ! 346: ! 347: /* ! 348: * flush out a directory that is finished. ! 349: */ ! 350: flushent() ! 351: { ! 352: ! 353: ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev; ! 354: (void) fwrite(dirbuf, (int)dirloc, 1, df); ! 355: seekpt = ftell(df); ! 356: dirloc = 0; ! 357: } ! 358: ! 359: dcvt(odp, ndp) ! 360: register struct odirect *odp; ! 361: register struct direct *ndp; ! 362: { ! 363: ! 364: bzero((char *)ndp, (long)(sizeof *ndp)); ! 365: ndp->d_ino = odp->d_ino; ! 366: (void) strncpy(ndp->d_name, odp->d_name, ODIRSIZ); ! 367: ndp->d_namlen = strlen(ndp->d_name); ! 368: ndp->d_reclen = DIRSIZ(ndp); ! 369: } ! 370: ! 371: /* ! 372: * Seek to an entry in a directory. ! 373: * Only values returned by ``telldir'' should be passed to rst_seekdir. ! 374: * This routine handles many directories in a single file. ! 375: * It takes the base of the directory in the file, plus ! 376: * the desired seek offset into it. ! 377: */ ! 378: void ! 379: rst_seekdir(dirp, loc, base) ! 380: register DIR *dirp; ! 381: daddr_t loc, base; ! 382: { ! 383: ! 384: if (loc == telldir(dirp)) ! 385: return; ! 386: loc -= base; ! 387: if (loc < 0) ! 388: fprintf(stderr, "bad seek pointer to rst_seekdir %d\n", loc); ! 389: (void) lseek(dirp->dd_fd, base + (loc & ~(DIRBLKSIZ - 1)), 0); ! 390: dirp->dd_loc = loc & (DIRBLKSIZ - 1); ! 391: if (dirp->dd_loc != 0) ! 392: dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ); ! 393: } ! 394: ! 395: /* ! 396: * get next entry in a directory. ! 397: */ ! 398: struct direct * ! 399: rst_readdir(dirp) ! 400: register DIR *dirp; ! 401: { ! 402: register struct direct *dp; ! 403: ! 404: for (;;) { ! 405: if (dirp->dd_loc == 0) { ! 406: dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, ! 407: DIRBLKSIZ); ! 408: if (dirp->dd_size <= 0) { ! 409: dprintf(stderr, "error reading directory\n"); ! 410: return NULL; ! 411: } ! 412: } ! 413: if (dirp->dd_loc >= dirp->dd_size) { ! 414: dirp->dd_loc = 0; ! 415: continue; ! 416: } ! 417: dp = (struct direct *)(dirp->dd_buf + dirp->dd_loc); ! 418: if (dp->d_reclen == 0 || ! 419: dp->d_reclen > DIRBLKSIZ + 1 - dirp->dd_loc) { ! 420: dprintf(stderr, "corrupted directory: bad reclen %d\n", ! 421: dp->d_reclen); ! 422: return NULL; ! 423: } ! 424: dirp->dd_loc += dp->d_reclen; ! 425: if (dp->d_ino == 0 && strcmp(dp->d_name, "/") != 0) ! 426: continue; ! 427: if (dp->d_ino >= maxino) { ! 428: dprintf(stderr, "corrupted directory: bad inum %d\n", ! 429: dp->d_ino); ! 430: continue; ! 431: } ! 432: return (dp); ! 433: } ! 434: } ! 435: ! 436: /* ! 437: * Set the mode, owner, and times for all new or changed directories ! 438: */ ! 439: setdirmodes() ! 440: { ! 441: FILE *mf; ! 442: struct modeinfo node; ! 443: struct entry *ep; ! 444: char *cp; ! 445: ! 446: vprintf(stdout, "Set directory mode, owner, and times.\n"); ! 447: mf = fopen(modefile, "r"); ! 448: if (mf == NULL) { ! 449: perror("fopen"); ! 450: panic("cannot open mode file %s\n", modefile); ! 451: } ! 452: clearerr(mf); ! 453: for (;;) { ! 454: (void) fread((char *)&node, 1, sizeof(struct modeinfo), mf); ! 455: if (feof(mf)) ! 456: break; ! 457: ep = lookupino(node.ino); ! 458: if (command == 'i' || command == 'x' || command == 'X') { ! 459: if (ep == NIL) ! 460: continue; ! 461: if (node.ino == ROOTINO && ! 462: reply("set owner/mode for '.'") == FAIL) ! 463: continue; ! 464: } ! 465: if (ep == NIL) ! 466: panic("cannot find directory inode %d\n", node.ino); ! 467: cp = myname(ep); ! 468: (void) chown(cp, node.uid, node.gid); ! 469: (void) chmod(cp, node.mode); ! 470: utime(cp, node.timep); ! 471: ep->e_flags &= ~NEW; ! 472: } ! 473: if (ferror(mf)) ! 474: panic("error setting directory modes\n"); ! 475: (void) fclose(mf); ! 476: } ! 477: ! 478: /* ! 479: * Generate a literal copy of a directory. ! 480: */ ! 481: genliteraldir(name, ino) ! 482: char *name; ! 483: ino_t ino; ! 484: { ! 485: register struct inotab *itp; ! 486: int ofile, dp, i, size; ! 487: char buf[BUFSIZ]; ! 488: ! 489: itp = inotablookup(ino); ! 490: if (itp == NULL) ! 491: panic("Cannot find directory inode %d named %s\n", ino, name); ! 492: if ((ofile = creat(name, 0666)) < 0) { ! 493: fprintf(stderr, "%s: ", name); ! 494: (void) fflush(stderr); ! 495: perror("cannot create file"); ! 496: return (FAIL); ! 497: } ! 498: rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); ! 499: dp = dup(dirp->dd_fd); ! 500: for (i = itp->t_size; i > 0; i -= BUFSIZ) { ! 501: size = i < BUFSIZ ? i : BUFSIZ; ! 502: if (read(dp, buf, (int) size) == -1) { ! 503: fprintf(stderr, ! 504: "write error extracting inode %d, name %s\n", ! 505: curfile.ino, curfile.name); ! 506: perror("read"); ! 507: done(1); ! 508: } ! 509: if (write(ofile, buf, (int) size) == -1) { ! 510: fprintf(stderr, ! 511: "write error extracting inode %d, name %s\n", ! 512: curfile.ino, curfile.name); ! 513: perror("write"); ! 514: done(1); ! 515: } ! 516: } ! 517: (void) close(dp); ! 518: (void) close(ofile); ! 519: return (GOOD); ! 520: } ! 521: ! 522: /* ! 523: * Do an "ls" style listing of a directory ! 524: */ ! 525: printlist(name, ino) ! 526: char *name; ! 527: ino_t ino; ! 528: { ! 529: register struct afile *fp; ! 530: register struct inotab *itp; ! 531: struct afile *dfp0, *dfplast; ! 532: struct afile single; ! 533: ! 534: itp = inotablookup(ino); ! 535: if (itp == NULL) { ! 536: single.fnum = ino; ! 537: single.fname = savename(rindex(name, '/') + 1); ! 538: dfp0 = &single; ! 539: dfplast = dfp0 + 1; ! 540: } else { ! 541: rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); ! 542: if (getdir(dirp, &dfp0, &dfplast) == FAIL) ! 543: return; ! 544: } ! 545: qsort((char *)dfp0, dfplast - dfp0, sizeof (struct afile), fcmp); ! 546: formatf(dfp0, dfplast); ! 547: for (fp = dfp0; fp < dfplast; fp++) ! 548: freename(fp->fname); ! 549: } ! 550: ! 551: /* ! 552: * Read the contents of a directory. ! 553: */ ! 554: getdir(dirp, pfp0, pfplast) ! 555: DIR *dirp; ! 556: struct afile **pfp0, **pfplast; ! 557: { ! 558: register struct afile *fp; ! 559: register struct direct *dp; ! 560: static struct afile *basefp = NULL; ! 561: static long nent = 20; ! 562: ! 563: if (basefp == NULL) { ! 564: basefp = (struct afile *)calloc((unsigned)nent, ! 565: sizeof (struct afile)); ! 566: if (basefp == NULL) { ! 567: fprintf(stderr, "ls: out of memory\n"); ! 568: return (FAIL); ! 569: } ! 570: } ! 571: fp = *pfp0 = basefp; ! 572: *pfplast = *pfp0 + nent; ! 573: while (dp = rst_readdir(dirp)) { ! 574: if (dp == NULL || dp->d_ino == 0) ! 575: break; ! 576: if (!dflag && BIT(dp->d_ino, dumpmap) == 0) ! 577: continue; ! 578: if (vflag == 0 && ! 579: (strcmp(dp->d_name, ".") == 0 || ! 580: strcmp(dp->d_name, "..") == 0)) ! 581: continue; ! 582: fp->fnum = dp->d_ino; ! 583: fp->fname = savename(dp->d_name); ! 584: fp++; ! 585: if (fp == *pfplast) { ! 586: basefp = (struct afile *)realloc((char *)basefp, ! 587: (unsigned)(2 * nent * sizeof (struct afile))); ! 588: if (basefp == 0) { ! 589: fprintf(stderr, "ls: out of memory\n"); ! 590: return (FAIL); ! 591: } ! 592: *pfp0 = basefp; ! 593: fp = *pfp0 + nent; ! 594: *pfplast = fp + nent; ! 595: nent *= 2; ! 596: } ! 597: } ! 598: *pfplast = fp; ! 599: return (GOOD); ! 600: } ! 601: ! 602: /* ! 603: * Print out a pretty listing of a directory ! 604: */ ! 605: formatf(fp0, fplast) ! 606: struct afile *fp0, *fplast; ! 607: { ! 608: register struct afile *fp; ! 609: struct entry *np; ! 610: int width = 0, w, nentry = fplast - fp0; ! 611: int i, j, len, columns, lines; ! 612: char *cp; ! 613: ! 614: if (fp0 == fplast) ! 615: return; ! 616: for (fp = fp0; fp < fplast; fp++) { ! 617: fp->ftype = inodetype(fp->fnum); ! 618: np = lookupino(fp->fnum); ! 619: if (np != NIL) ! 620: fp->fflags = np->e_flags; ! 621: else ! 622: fp->fflags = 0; ! 623: len = strlen(fmtentry(fp)); ! 624: if (len > width) ! 625: width = len; ! 626: } ! 627: width += 2; ! 628: columns = 80 / width; ! 629: if (columns == 0) ! 630: columns = 1; ! 631: lines = (nentry + columns - 1) / columns; ! 632: for (i = 0; i < lines; i++) { ! 633: for (j = 0; j < columns; j++) { ! 634: fp = fp0 + j * lines + i; ! 635: cp = fmtentry(fp); ! 636: fprintf(stderr, "%s", cp); ! 637: if (fp + lines >= fplast) { ! 638: fprintf(stderr, "\n"); ! 639: break; ! 640: } ! 641: w = strlen(cp); ! 642: while (w < width) { ! 643: w++; ! 644: fprintf(stderr, " "); ! 645: } ! 646: } ! 647: } ! 648: } ! 649: ! 650: /* ! 651: * Comparison routine for qsort. ! 652: */ ! 653: fcmp(f1, f2) ! 654: register struct afile *f1, *f2; ! 655: { ! 656: ! 657: return (strcmp(f1->fname, f2->fname)); ! 658: } ! 659: ! 660: /* ! 661: * Format a directory entry. ! 662: */ ! 663: char * ! 664: fmtentry(fp) ! 665: register struct afile *fp; ! 666: { ! 667: static char fmtres[BUFSIZ]; ! 668: register char *cp, *dp; ! 669: ! 670: if (vflag) ! 671: (void) sprintf(fmtres, "%5d ", fp->fnum); ! 672: else ! 673: fmtres[0] = '\0'; ! 674: dp = &fmtres[strlen(fmtres)]; ! 675: if (dflag && BIT(fp->fnum, dumpmap) == 0) ! 676: *dp++ = '^'; ! 677: else if ((fp->fflags & NEW) != 0) ! 678: *dp++ = '*'; ! 679: else ! 680: *dp++ = ' '; ! 681: for (cp = fp->fname; *cp; cp++) ! 682: if (!vflag && (*cp < ' ' || *cp >= 0177)) ! 683: *dp++ = '?'; ! 684: else ! 685: *dp++ = *cp; ! 686: if (fp->ftype == NODE) ! 687: *dp++ = '/'; ! 688: *dp++ = 0; ! 689: return (fmtres); ! 690: } ! 691: ! 692: /* ! 693: * Determine the type of an inode ! 694: */ ! 695: inodetype(ino) ! 696: ino_t ino; ! 697: { ! 698: struct inotab *itp; ! 699: ! 700: itp = inotablookup(ino); ! 701: if (itp == NULL) ! 702: return (LEAF); ! 703: return (NODE); ! 704: } ! 705: ! 706: /* ! 707: * Allocate and initialize a directory inode entry. ! 708: * If requested, save its pertinent mode, owner, and time info. ! 709: */ ! 710: struct inotab * ! 711: allocinotab(ino, dip, seekpt) ! 712: ino_t ino; ! 713: struct dinode *dip; ! 714: daddr_t seekpt; ! 715: { ! 716: register struct inotab *itp; ! 717: struct modeinfo node; ! 718: ! 719: itp = (struct inotab *)calloc(1, sizeof(struct inotab)); ! 720: if (itp == 0) ! 721: panic("no memory directory table\n"); ! 722: itp->t_next = inotab[INOHASH(ino)]; ! 723: inotab[INOHASH(ino)] = itp; ! 724: itp->t_ino = ino; ! 725: itp->t_seekpt = seekpt; ! 726: if (mf == NULL) ! 727: return(itp); ! 728: node.ino = ino; ! 729: node.timep[0] = dip->di_atime; ! 730: node.timep[1] = dip->di_mtime; ! 731: node.mode = dip->di_mode; ! 732: node.uid = dip->di_uid; ! 733: node.gid = dip->di_gid; ! 734: (void) fwrite((char *)&node, 1, sizeof(struct modeinfo), mf); ! 735: return(itp); ! 736: } ! 737: ! 738: /* ! 739: * Look up an inode in the table of directories ! 740: */ ! 741: struct inotab * ! 742: inotablookup(ino) ! 743: ino_t ino; ! 744: { ! 745: register struct inotab *itp; ! 746: ! 747: for (itp = inotab[INOHASH(ino)]; itp != NULL; itp = itp->t_next) ! 748: if (itp->t_ino == ino) ! 749: return(itp); ! 750: return ((struct inotab *)0); ! 751: } ! 752: ! 753: /* ! 754: * Clean up and exit ! 755: */ ! 756: done(exitcode) ! 757: int exitcode; ! 758: { ! 759: ! 760: closemt(); ! 761: if (modefile[0] != '#') ! 762: (void) unlink(modefile); ! 763: if (dirfile[0] != '#') ! 764: (void) unlink(dirfile); ! 765: exit(exitcode); ! 766: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.