Annotation of 42BSD/etc/restore/dirs.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.