Annotation of cci/usr/src/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); /* "." 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: }

unix.superglobalmegacorp.com

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