Annotation of coherent/d/bin/dump/dump.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Dump a filesystem onto a
                      3:  * tape. Dump only those files that
                      4:  * have checked since the last
                      5:  * dump.
                      6:  */
                      7: #include <stdio.h>
                      8: #include <sys/types.h>
                      9: #include <discbuf.h>
                     10: #include <dumptape.h>
                     11: #include <canon.h>
                     12: #include <sys/filsys.h>
                     13: 
                     14: char   *dtn    = DTAPE;                /* Tape name */
                     15: FILE   *dtp;                           /* Tape file pointer */
                     16: char   *fsn    = DFSYS;                /* File system name */
                     17: int    block   = 20;                   /* Blocking factor */
                     18: int    density = 1600;                 /* Tape density, bpi */
                     19: long   length  = 2300L*12L*100L;       /* Length of tape, inches/100 */
                     20: long   used;                           /* Tape used, inches/100 */
                     21: struct dumpheader dh;                  /* Dump header */
                     22: int    reel    = 1;                    /* Reel # */
                     23: int    uflag   = 1;                    /* Update dates file flag */
                     24: int    vflag;                          /* Verbose flag */
                     25: int    Sflag;                          /* Set when sizes are in blocks */
                     26: int    level   = 9;                    /* Dump level */
                     27: time_t bdate;                          /* Date at beginning of dump */
                     28: time_t ddate;                          /* Dump since date */
                     29: char   *map;                           /* Map pointer */
                     30: char   *ddbuf;                         /* Dump data buffer */
                     31: char   *ddend;                         /* Dump data buffer end pointer */
                     32: int    ddnbuf;                         /* Buffer size */
                     33: union  dumpdata *ddptr;                /* Pointer to current item */
                     34: ino_t  isize;                          /* # of inodes */
                     35: char   dev[DIRSIZ+1];                  /* Name of device, squashed */
                     36: char   fname[6];                       /* File system name */
                     37: char   fpack[6];                       /* File system pack name */
                     38: long   ninodes;                        /* # of inodes dumped */
                     39: long   nblocks;                        /* # of blocks of data */
                     40: long   nsparse;                        /* # of sparse blocks deleted */
                     41: char   helpmessage[]           = "\
                     42: Usage: dump [bdfsuvS0123456789 [args]] filesystem ...\n\
                     43: ";
                     44: 
                     45: /*
                     46:  * Tables used by imap.
                     47:  * This effectively implements
                     48:  * the access polynomial for the indirect
                     49:  * blocks.
                     50:  */
                     51: daddr_t        ranges[]        = {
                     52:        ND,
                     53:        ND+(daddr_t)1*NBN,
                     54:        ND+(daddr_t)1*NBN + (daddr_t)1*NBN*NBN,
                     55:        ND+(daddr_t)1*NBN + (daddr_t)1*NBN*NBN + (daddr_t)1*NBN*NBN*NBN
                     56: };
                     57: 
                     58: char   offsets[]       = {
                     59:        0,
                     60:        ND,
                     61:        ND+1,
                     62:        ND+1+1
                     63: };
                     64: 
                     65: daddr_t        coeff[]         = {
                     66:        1,
                     67:        (daddr_t) NBN,
                     68:        (daddr_t) NBN*NBN,
                     69:        (daddr_t) NBN*NBN*NBN
                     70: };
                     71: 
                     72: /*
                     73:  * One pass compilers are
                     74:  * such fun.
                     75:  */
                     76: long   time();
                     77: long   ddlen();
                     78: union  dumpdata *ddnextbuf();
                     79: long   getddate();
                     80: char   *ctime();
                     81: daddr_t        imap();
                     82: char   *calloc();
                     83: 
                     84: main(argc, argv)
                     85: char *argv[];
                     86: {
                     87:        register DISCBUF *dbp;
                     88:        register struct filsys *fsp;
                     89:        unsigned fi;
                     90: 
                     91:        init(argc, argv);
                     92:        if (*fsn == 0)
                     93:                fatal("no filesystem specified");
                     94:        if ((dbfp=fopen(fsn, "r")) == NULL)
                     95:                fatal("%s: cannot open filesystem", fsn);
                     96:        if ((dtp=fopen(dtn, "w")) == NULL)
                     97:                fatal("%s: cannot open dump file",  dtn);
                     98:        squash(dev, fsn);
                     99:        bdate = time((long *) 0);
                    100:        ddate = getddate();
                    101:        if (vflag) {
                    102:                if (ddate == 0)
                    103:                        fprintf(stderr, "dump: since epoch\n");
                    104:                else
                    105:                        fprintf(stderr, "dump: since %s", ctime(&ddate));
                    106:        }
                    107:        dbclaim(5);
                    108:        sync();
                    109:        dbp = dbread((long) SUPERI);
                    110:        fsp = (struct filsys *) (dbp->db_data);
                    111:        fi = fsp->s_isize;
                    112:        canshort(fi);
                    113:        isize = (fi-INODEI)*INOPB;
                    114:        strncpy(fname, fsp->s_fname, sizeof(fname));
                    115:        strncpy(fpack, fsp->s_fpack, sizeof(fpack));
                    116:        dbfree(dbp, 0);
                    117:        if ((map=calloc(isize, sizeof(char))) == NULL)
                    118:                fatal("out of memory (map)");
                    119:        walk((ino_t) ROOTIN);
                    120:        nextvol();
                    121:        dumpinomap();
                    122:        dump(DD_DIR);           /* Directories */
                    123:        dump(0);                /* Files */
                    124:        dumpfinish();
                    125:        if (uflag)
                    126:                putddate();
                    127:        if (vflag) {
                    128:                if (Sflag)
                    129:                        used /= 512; else
                    130:                        used /= 100*12;
                    131:                fprintf(stderr, "dump: length is %ld ", used);
                    132:                if (Sflag)
                    133:                        fprintf(stderr, "blocks\n");
                    134:                else if (used == 1)
                    135:                        fprintf(stderr, "foot\n");
                    136:                else
                    137:                        fprintf(stderr, "feet\n");
                    138:                fprintf(stderr, "dump: %ld inodes, ",  ninodes);
                    139:                fprintf(stderr, "%ld real blocks, ",   nblocks);
                    140:                fprintf(stderr, "%ld sparse blocks\n", nsparse);
                    141:        }
                    142:        exit(0);
                    143: }
                    144: 
                    145: /*
                    146:  * Scan the command line and
                    147:  * set options. Perhaps reset the name
                    148:  * of the filesystem, the dump tape
                    149:  * and the dump origin.
                    150:  */
                    151: init(argc, argv)
                    152: char *argv[];
                    153: {
                    154:        register char *p;
                    155:        register c, i;
                    156: 
                    157:        if (argc > 1) {
                    158:                uflag = 0;
                    159:                i = 1;
                    160:                p = argv[1];
                    161:                while ((c = *p++) != '\0') {
                    162:                        switch (c) {
                    163: 
                    164:                        case 'f':
                    165:                                if (++i >= argc)
                    166:                                        usage();
                    167:                                dtn = argv[i];
                    168:                                break;
                    169: 
                    170:                        case 'u':
                    171:                                uflag = 1;
                    172:                                break;
                    173: 
                    174:                        case 'v':
                    175:                                vflag = 1;
                    176:                                break;
                    177: 
                    178:                        case 's':
                    179:                                if (++i >= argc)
                    180:                                        usage();
                    181:                                length = (long)12*100*num(argv[i], "length",
                    182:                                        600, 4800);
                    183:                                break;
                    184: 
                    185:                        case 'S':
                    186:                                if (++i >= argc)
                    187:                                        usage();
                    188:                                Sflag++;
                    189:                                length = (long)512 * num(argv[i], "block size",
                    190:                                        0, (unsigned)65535L);
                    191:                                break;
                    192: 
                    193:                        case 'b':
                    194:                                if (++i >= argc)
                    195:                                        usage();
                    196:                                block = num(argv[i], "blocking", 1, 20);
                    197:                                break;
                    198: 
                    199:                        case 'd':
                    200:                                if (++i >= argc)
                    201:                                        usage();
                    202:                                density = num(argv[i], "density", 800, 6250);
                    203:                                break;
                    204: 
                    205:                        case '0':
                    206:                        case '1':
                    207:                        case '2':
                    208:                        case '3':
                    209:                        case '4':
                    210:                        case '5':
                    211:                        case '6':
                    212:                        case '7':
                    213:                        case '8':
                    214:                        case '9':
                    215:                                level = c-'0';
                    216:                                break;
                    217: 
                    218:                        default:
                    219:                                usage();
                    220:                        }
                    221:                }
                    222:                if (++i < argc)
                    223:                        fsn = argv[i];
                    224:        }
                    225: }
                    226: 
                    227: /*
                    228:  * Collect and range check
                    229:  * numeric arguments.
                    230:  */
                    231: num(s, msg, ll, hl)
                    232: register char *s;
                    233: char *msg;
                    234: unsigned ll, hl;
                    235: {
                    236:        register c, n;
                    237: 
                    238:        n = 0;
                    239:        while ((c=*s++)>='0' && c<='9')
                    240:                n = 10*n + c - '0';
                    241:        if (c!='\0' || n<ll || n>hl)
                    242:                fatal("bad %s specification", msg);
                    243:        return (n);
                    244: }
                    245: 
                    246: /*
                    247:  * Walk down the file system,
                    248:  * looking for files that should be
                    249:  * dumped. Mark them in the map.
                    250:  * All directories that lead to changed
                    251:  * inodes are forced to be dumped.
                    252:  */
                    253: walk(ino)
                    254: ino_t ino;
                    255: {
                    256:        register DISCBUF *dbp;
                    257:        register struct direct *dirp;
                    258:        int flag, nent, ndir;
                    259:        long pb, dirb;
                    260:        struct dinode dinode;
                    261:        ino_t ent[BUFSIZ/sizeof(struct direct)];
                    262: 
                    263:        if ((map[ino-1]&DD_DEJA) != 0)
                    264:                return (0);
                    265:        ireadin(&dinode, ino);
                    266:        canshort(dinode.di_mode);
                    267:        cantime(dinode.di_ctime);
                    268:        cantime(dinode.di_mtime);
                    269:        /*
                    270:         * Normally pipes stay in core,
                    271:         * and are not in directories. Just to be
                    272:         * safe we pretend any pipe is a clear
                    273:         * inode.
                    274:         */
                    275:        if ((dinode.di_mode&IFMT) == IFPIPE)
                    276:                return (0);
                    277:        map[ino-1] |= DD_BUSY;
                    278:        if ((dinode.di_mode&IFMT) != IFDIR) {
                    279:                if (level==0||dinode.di_mtime>ddate||dinode.di_ctime>ddate) {
                    280:                        map[ino-1] |= DD_DUMP;
                    281:                        return (1);
                    282:                }
                    283:                return (0);
                    284:        }
                    285:        map[ino-1] |= DD_DEJA|DD_DIR;
                    286:        flag = dirb = 0;
                    287:        cansize(dinode.di_size);
                    288:        while (dinode.di_size != 0) {
                    289:                if ((pb = imap(&dinode, dirb++)) == 0) {
                    290:                        dinode.di_size -= BUFSIZ;
                    291:                        continue;
                    292:                }
                    293:                /*
                    294:                 * Writing the code is this
                    295:                 * strange fashon makes it require 1 cache
                    296:                 * buffer, not 1 per level.
                    297:                 */
                    298:                dbp = dbread(pb);
                    299:                nent = 0;
                    300:                ndir = BUFSIZ / sizeof(struct direct);
                    301:                if (dinode.di_size < BUFSIZ)
                    302:                        ndir = dinode.di_size / sizeof(struct direct);
                    303:                dirp = (struct direct *) (dbp->db_data);
                    304:                while (ndir--) {
                    305:                        if (dirp->d_ino != 0) {
                    306:                                ent[nent] = dirp->d_ino;
                    307:                                canino(ent[nent]);
                    308:                                ++nent;
                    309:                        }
                    310:                        ++dirp;
                    311:                        dinode.di_size -= sizeof(struct direct);
                    312:                }
                    313:                dbfree(dbp, 0);
                    314:                while (nent--) {
                    315:                        if (walk(ent[nent]))
                    316:                                flag = 1;
                    317:                }
                    318:        }
                    319:        if (flag!=0 || level==0 || dinode.di_ctime>ddate)
                    320:                map[ino-1] |= DD_DUMP;
                    321:        map[ino-1] &= ~DD_DEJA;
                    322:        return (flag);
                    323: }
                    324: 
                    325: /*
                    326:  * Read in an inode.
                    327:  * Leave it in the buffer in disc
                    328:  * (that is, cannonical) format.
                    329:  */
                    330: ireadin(diop, ino)
                    331: register struct dinode *diop;
                    332: ino_t ino;
                    333: {
                    334:        register struct dinode *diip;
                    335:        DISCBUF *dbp;
                    336: 
                    337:        dbp = dbread((long)((ino-1)/INOPB + INODEI));
                    338:        diip = (struct dinode *)(dbp->db_data) + (ino-1)%INOPB;
                    339:        *diop = *diip;          /* Structure assignment */
                    340:        dbfree(dbp, 0);
                    341: }
                    342: 
                    343: /*
                    344:  * Map logical block `lb' in the
                    345:  * file whose in core inode is pointed to
                    346:  * by `ip' to the associated physical
                    347:  * block. Return 0 if the block will not
                    348:  * map.
                    349:  */
                    350: daddr_t
                    351: imap(ip, lb)
                    352: register struct dinode *ip;
                    353: daddr_t lb;
                    354: {
                    355:        register il;
                    356:        daddr_t bpos, pb;
                    357:        DISCBUF *dbp;
                    358:        register daddr_t *bp;
                    359:        register daddr_t addrs[NADDR];
                    360: 
                    361:        l3tol(addrs, ip->di_addr, NADDR);
                    362:        for (il=0; il<4; il++)
                    363:                if (lb < ranges[il]) {
                    364:                        if (il != 0)
                    365:                                lb -= ranges[il-1];
                    366:                        bpos = lb/coeff[il];
                    367:                        lb %= coeff[il];
                    368:                        bp = &addrs[(int)bpos + offsets[il]];
                    369:                        if ((pb = *bp) != 0) {
                    370:                                while (il-- > 0) {
                    371:                                        dbp = dbread((long) pb);
                    372:                                        bpos = lb/coeff[il];
                    373:                                        lb %= coeff[il];
                    374:                                        bp = (daddr_t *)(dbp->db_data) + bpos;
                    375:                                        dbfree(dbp, 0);
                    376:                                        if ((pb = *bp) == 0)
                    377:                                                break;
                    378:                                        candaddr(pb);
                    379:                                }
                    380:                        }
                    381:                        return (pb);
                    382:                }
                    383:        return (0);
                    384: }
                    385: 
                    386: 
                    387: /*
                    388:  * Dump out the map.
                    389:  * The map is packed into ordinary
                    390:  * tape blocks.
                    391:  */
                    392: dumpinomap()
                    393: {
                    394:        register ino_t ibase;
                    395:        register char *imapp;
                    396:        register nmap;
                    397:        union dumpdata *ddp;
                    398: 
                    399:        ibase = 0;
                    400:        while ((nmap = isize-ibase) > 0) {
                    401:                ddp = ddnextbuf();
                    402:                ddp->dd_type = DD_MAP;
                    403:                ddp->dd_ino = ibase+1;
                    404:                if (nmap > BUFSIZ)
                    405:                        nmap = BUFSIZ;
                    406:                ddp->dd_nmap = nmap;
                    407:                canint(ddp->dd_type);
                    408:                canino(ddp->dd_ino);
                    409:                canint(ddp->dd_nmap);
                    410:                imapp = &ddp->dd_map[0];
                    411:                do {
                    412:                        *imapp++ = map[ibase++];
                    413:                } while (--nmap);
                    414:        }
                    415: }
                    416: 
                    417: /*
                    418:  * Fabricate a dump header and
                    419:  * write it to the dump file. All the
                    420:  * stuff in the header is in the
                    421:  * usual canonical format. This makes it
                    422:  * a little easier to move tapes from
                    423:  * one machine to another.
                    424:  */
                    425: dumpheader()
                    426: {
                    427:        register char *p;
                    428:        register checksum;
                    429: 
                    430:        dh.dh_magic = DH_MAG;
                    431:        dh.dh_nino = isize;
                    432:        dh.dh_bdate = bdate;
                    433:        dh.dh_ddate = ddate;
                    434:        dh.dh_level = level;
                    435:        dh.dh_reel = reel++;
                    436:        dh.dh_blocking = block;
                    437:        dh.dh_nbyte = Sflag ? length : 0;
                    438:        strncpy(dh.dh_dev, dev, DIRSIZ);
                    439:        strncpy(dh.dh_fname, fname, 6);
                    440:        strncpy(dh.dh_fpack, fpack, 6);
                    441:        p = (char *) &dh;
                    442:        checksum = 0;
                    443:        while (p < (char *) &dh.dh_checksum)
                    444:                checksum += (*p++) & 0377;
                    445:        dh.dh_checksum = checksum;
                    446:        canint(dh.dh_magic);
                    447:        canino(dh.dh_nino);
                    448:        cantime(dh.dh_bdate);
                    449:        cantime(dh.dh_ddate);
                    450:        canint(dh.dh_level);
                    451:        canint(dh.dh_reel);
                    452:        canint(dh.dh_blocking);
                    453:        cansize(dh.dh_nbyte);
                    454:        canint(dh.dh_checksum);
                    455:        if (write(fileno(dtp), &dh, sizeof dh) != sizeof dh)
                    456:                fatal("header write error");
                    457: }
                    458: 
                    459: /*
                    460:  * Put out the end of tape item
                    461:  * and the very end of the very last
                    462:  * dump tape.
                    463:  */
                    464: dumpfinish()
                    465: {
                    466:        register union dumpdata *ddp;
                    467: 
                    468:        ddp = ddnextbuf();
                    469:        ddp->dd_type = DD_EOT;
                    470:        canint(ddp->dd_type);
                    471:        ddflush();
                    472: }
                    473: 
                    474: /*
                    475:  * Dump out all inodes with
                    476:  * the appropriate flags set in the
                    477:  * map.
                    478:  */
                    479: dump(flag)
                    480: register flag;
                    481: {
                    482:        register ino_t i;
                    483:        register mapentry;
                    484: 
                    485:        for (i=0; i<isize; ++i) {
                    486:                mapentry = map[i];
                    487:                if ((mapentry&DD_DUMP)!=0 && (mapentry&DD_DIR)==flag) {
                    488:                        dumpi(i+1);
                    489:                        map[i] = 0;
                    490:                }
                    491:        }
                    492: }
                    493: 
                    494: /*
                    495:  * Dump an inode.
                    496:  */
                    497: dumpi(ino)
                    498: ino_t ino;
                    499: {
                    500:        struct dinode dinode;
                    501:        register union dumpdata *ddp;
                    502:        register DISCBUF *dbp;
                    503:        daddr_t lb, pb;
                    504:        int size;
                    505: 
                    506:        ++ninodes;
                    507:        ireadin(&dinode, ino);
                    508:        ddp = ddnextbuf();
                    509:        ddp->dd_type = DD_INO;
                    510:        ddp->dd_ino  = ino;
                    511:        canint(ddp->dd_type);
                    512:        canino(ddp->dd_ino);
                    513:        copyb(&ddp->dd_dinode, &dinode, sizeof(struct dinode));
                    514:        lb = 0;
                    515:        cansize(dinode.di_size);
                    516:        while (dinode.di_size != 0) {
                    517:                pb = imap(&dinode, lb);
                    518:                size = dinode.di_size<BUFSIZ ? dinode.di_size : BUFSIZ;
                    519:                if (pb != 0) {
                    520:                        dbp = dbread(pb);
                    521:                        if (allzeros(dbp->db_data, size) == 0) {
                    522:                                ++nblocks;
                    523:                                ddp = ddnextbuf();
                    524:                                ddp->dd_type = DD_DATA;
                    525:                                ddp->dd_ino  = ino;
                    526:                                ddp->dd_block = lb;
                    527:                                ddp->dd_size = size;
                    528:                                canint(ddp->dd_type);
                    529:                                canino(ddp->dd_ino);
                    530:                                candaddr(ddp->dd_block);
                    531:                                canint(ddp->dd_size);
                    532:                                copyb(ddp->dd_data, dbp->db_data, size);
                    533:                        } else
                    534:                                ++nsparse;
                    535:                        dbfree(dbp, 0);
                    536:                }
                    537:                dinode.di_size -= size;
                    538:                ++lb;
                    539:        }
                    540: }
                    541: 
                    542: /*
                    543:  * Check if a disc block is all
                    544:  * zero bytes. True return if it is.
                    545:  */
                    546: allzeros(cp, nb)
                    547: register char  *cp;
                    548: register int   nb;
                    549: {
                    550:        do {
                    551:                if (*cp++ != 0)
                    552:                        return (0);
                    553:        } while (--nb);
                    554:        return (1);
                    555: }
                    556: 
                    557: /*
                    558:  * Copy a block of bytes.
                    559:  */
                    560: copyb(atp, afp, anb)
                    561: char *atp, *afp;
                    562: {
                    563:        register char *tp, *fp;
                    564:        register nb;
                    565: 
                    566:        if ((nb = anb) != 0) {
                    567:                tp = atp;
                    568:                fp = afp;
                    569:                do {
                    570:                        *tp++ = *fp++;
                    571:                } while (--nb);
                    572:        }
                    573: }
                    574: 
                    575: /*
                    576:  * Return a pointer to the
                    577:  * next data buffer.
                    578:  */
                    579: union  dumpdata *
                    580: ddnextbuf()
                    581: {
                    582:        register char *p;
                    583:        register n;
                    584: 
                    585:        if (ddbuf == NULL) {
                    586:                ddnbuf = block * sizeof(union dumpdata);
                    587:                if ((ddbuf = malloc(ddnbuf)) == NULL)
                    588:                        fatal("out of memory (buffer)");
                    589:                ddend = &ddbuf[ddnbuf];
                    590:                ddptr = (union dumpdata *) ddbuf;
                    591:        }
                    592:        if ((char *) ddptr == ddend) {
                    593:                ddflush();
                    594:                ddptr = (union dumpdata *) ddbuf;
                    595:        }
                    596:        if ((char *) ddptr == ddbuf) {
                    597:                p = ddbuf;
                    598:                n = ddnbuf;
                    599:                do {
                    600:                        *p++ = 0;
                    601:                } while (--n);
                    602:        }
                    603:        return (ddptr++);
                    604: }
                    605: 
                    606: /*
                    607:  * Write out the big data buffer.
                    608:  */
                    609: ddflush()
                    610: {
                    611:        used += ddlen(ddnbuf);
                    612:        if (used >= length) {
                    613:                nextvol();
                    614:                used += ddlen(ddnbuf);
                    615:        }
                    616:        if (write(fileno(dtp), ddbuf, ddnbuf) != ddnbuf)
                    617:                fatal("dump write error");
                    618: }
                    619: 
                    620: /*
                    621:  * Request next dump volume.
                    622:  */
                    623: nextvol()
                    624: {
                    625:        char buf[40];
                    626: 
                    627:        if (Sflag != 0 || reel != 1) {
                    628:                fclose(dtp);
                    629:                fprintf(stderr, "dump: mount %s %d, type return key ...",
                    630:                        Sflag ? "volume" : "reel", reel);
                    631:                if (gets(buf) == NULL)
                    632:                        exit(1);
                    633:                if ((dtp = fopen(dtn, "w")) == NULL)
                    634:                        fatal("%s: cannot open dump file", dtn);
                    635:        }
                    636:        dumpheader();
                    637:        used = ddlen(sizeof(dh));
                    638: }
                    639: 
                    640: /*
                    641:  * Given a record size in bytes,
                    642:  * return the number of inches/100 of tape
                    643:  * that will get used.
                    644:  * For blocked devices, the granularity is
                    645:  * actually in bytes.
                    646:  */
                    647: long
                    648: ddlen(nbytes)
                    649: {
                    650:        if (Sflag)
                    651:                return (nbytes);
                    652:        return (100L*((nbytes+density-1)/density) + 75);
                    653: }
                    654: 
                    655: /*
                    656:  * Update the dump date in the
                    657:  * dump date file. The date used is the
                    658:  * date at the beginning of the dump.
                    659:  */
                    660: putddate()
                    661: {
                    662:        register FILE *ddfp;
                    663:        struct idates id;
                    664: 
                    665:        if ((ddfp = fopen(DDATE, "r+w")) == NULL) {
                    666:                fprintf(stderr, "dump: cannot update dump date\n");
                    667:                return;
                    668:        }
                    669:        while (fread(&id, sizeof(id), 1, ddfp) == 1) {
                    670:                if (strncmp(id.id_name, dev, DIRSIZ) == 0
                    671:                && id.id_incno==level) {
                    672:                        fseek(ddfp, (long)-sizeof(id), 1);
                    673:                        break;
                    674:                }
                    675:        }
                    676:        strncpy(id.id_name, dev, DIRSIZ);
                    677:        id.id_incno = level;
                    678:        id.id_ddate = bdate;
                    679:        if (fwrite(&id, sizeof(id), 1, ddfp) != 1)
                    680:                fprintf(stderr, "dump: error updating date file\n");
                    681:        fclose(ddfp);
                    682: }
                    683: 
                    684: /*
                    685:  * Get dump date.
                    686:  */
                    687: long
                    688: getddate()
                    689: {
                    690:        register FILE *ddfp;
                    691:        register long ddate;
                    692:        struct idates id;
                    693: 
                    694:        ddate = 0;
                    695:        if ((ddfp = fopen(DDATE, "r")) != NULL) {
                    696:                while (fread(&id, sizeof(id), 1, ddfp) == 1) {
                    697:                        if (strncmp(id.id_name, dev, DIRSIZ)==0
                    698:                        && id.id_incno<level
                    699:                        && id.id_ddate>ddate)
                    700:                                ddate = id.id_ddate;
                    701:                }
                    702:                fclose(ddfp);
                    703:        }
                    704:        return (ddate);
                    705: }
                    706: 
                    707: /*
                    708:  * Print out a fatal diagnostic
                    709:  * and die.
                    710:  */
                    711: fatal(a)
                    712: {
                    713:        fprintf(stderr, "dump: %r", &a);
                    714:        fprintf(stderr, "\n");
                    715:        exit(1);
                    716: }
                    717: 
                    718: /*
                    719:  * Print out a usage message and
                    720:  * exit. If you can figure out how to use
                    721:  * dump from the usage message you are
                    722:  * a better man than I.
                    723:  */
                    724: usage()
                    725: {
                    726:        fprintf(stderr, helpmessage);
                    727:        exit(1);
                    728: }
                    729: 
                    730: /*
                    731:  * Squash off any structure
                    732:  * before the last part of a file
                    733:  * name and put it in the supplied
                    734:  * buffer.
                    735:  */
                    736: squash(tp, fp)
                    737: register char *tp, *fp;
                    738: {
                    739:        register char *np;
                    740: 
                    741:        np = fp;
                    742:        while (*fp != '\0') {
                    743:                if (*fp == '/')
                    744:                        np = fp+1;
                    745:                ++fp;
                    746:        }
                    747:        while (*tp++ = *np++)
                    748:                ;
                    749: }

unix.superglobalmegacorp.com

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