Annotation of coherent/d/bin/dump/old/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 <types.h>
                      9: #include <discbuf.h>
                     10: #include <dumptape.h>
                     11: #include <canon.h>
                     12: #include <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 %D ", 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: %D inodes, ",  ninodes);
                    139:                fprintf(stderr, "%D real blocks, ",   nblocks);
                    140:                fprintf(stderr, "%D 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:        /*
                    269:         * Normally pipes stay in core,
                    270:         * and are not in directories. Just to be
                    271:         * safe we pretend any pipe is a clear
                    272:         * inode.
                    273:         */
                    274:        if ((dinode.di_mode&IFMT) == IFPIPE)
                    275:                return (0);
                    276:        map[ino-1] |= DD_BUSY;
                    277:        if ((dinode.di_mode&IFMT) != IFDIR) {
                    278:                if (level==0 || dinode.di_ctime>ddate) {
                    279:                        map[ino-1] |= DD_DUMP;
                    280:                        return (1);
                    281:                }
                    282:                return (0);
                    283:        }
                    284:        map[ino-1] |= DD_DEJA|DD_DIR;
                    285:        flag = dirb = 0;
                    286:        cansize(dinode.di_size);
                    287:        while (dinode.di_size != 0) {
                    288:                if ((pb = imap(&dinode, dirb++)) == 0) {
                    289:                        dinode.di_size -= BUFSIZ;
                    290:                        continue;
                    291:                }
                    292:                /*
                    293:                 * Writing the code is this
                    294:                 * strange fashon makes it require 1 cache
                    295:                 * buffer, not 1 per level.
                    296:                 */
                    297:                dbp = dbread(pb);
                    298:                nent = 0;
                    299:                ndir = BUFSIZ / sizeof(struct direct);
                    300:                if (dinode.di_size < BUFSIZ)
                    301:                        ndir = dinode.di_size / sizeof(struct direct);
                    302:                dirp = (struct direct *) (dbp->db_data);
                    303:                while (ndir--) {
                    304:                        if (dirp->d_ino != 0) {
                    305:                                ent[nent] = dirp->d_ino;
                    306:                                canino(ent[nent]);
                    307:                                ++nent;
                    308:                        }
                    309:                        ++dirp;
                    310:                        dinode.di_size -= sizeof(struct direct);
                    311:                }
                    312:                dbfree(dbp, 0);
                    313:                while (nent--) {
                    314:                        if (walk(ent[nent]))
                    315:                                flag = 1;
                    316:                }
                    317:        }
                    318:        if (flag!=0 || level==0 || dinode.di_ctime>ddate)
                    319:                map[ino-1] |= DD_DUMP;
                    320:        map[ino-1] &= ~DD_DEJA;
                    321:        return (flag);
                    322: }
                    323: 
                    324: /*
                    325:  * Read in an inode.
                    326:  * Leave it in the buffer in disc
                    327:  * (that is, cannonical) format.
                    328:  */
                    329: ireadin(diop, ino)
                    330: register struct dinode *diop;
                    331: ino_t ino;
                    332: {
                    333:        register struct dinode *diip;
                    334:        DISCBUF *dbp;
                    335: 
                    336:        dbp = dbread((long)((ino-1)/INOPB + INODEI));
                    337:        diip = (struct dinode *)(dbp->db_data) + (ino-1)%INOPB;
                    338:        *diop = *diip;          /* Structure assignment */
                    339:        dbfree(dbp, 0);
                    340: }
                    341: 
                    342: /*
                    343:  * Map logical block `lb' in the
                    344:  * file whose in core inode is pointed to
                    345:  * by `ip' to the associated physical
                    346:  * block. Return 0 if the block will not
                    347:  * map.
                    348:  */
                    349: daddr_t
                    350: imap(ip, lb)
                    351: register struct dinode *ip;
                    352: daddr_t lb;
                    353: {
                    354:        register il;
                    355:        daddr_t bpos, pb;
                    356:        DISCBUF *dbp;
                    357:        register daddr_t *bp;
                    358:        register daddr_t addrs[NADDR];
                    359: 
                    360:        l3tol(addrs, ip->di_addr, NADDR);
                    361:        for (il=0; il<4; il++)
                    362:                if (lb < ranges[il]) {
                    363:                        if (il != 0)
                    364:                                lb -= ranges[il-1];
                    365:                        bpos = lb/coeff[il];
                    366:                        lb %= coeff[il];
                    367:                        bp = &addrs[(int)bpos + offsets[il]];
                    368:                        if ((pb = *bp) != 0) {
                    369:                                while (il-- > 0) {
                    370:                                        dbp = dbread((long) pb);
                    371:                                        bpos = lb/coeff[il];
                    372:                                        lb %= coeff[il];
                    373:                                        bp = (daddr_t *)(dbp->db_data) + bpos;
                    374:                                        dbfree(dbp, 0);
                    375:                                        if ((pb = *bp) == 0)
                    376:                                                break;
                    377:                                        candaddr(pb);
                    378:                                }
                    379:                        }
                    380:                        return (pb);
                    381:                }
                    382:        return (0);
                    383: }
                    384: 
                    385: 
                    386: /*
                    387:  * Dump out the map.
                    388:  * The map is packed into ordinary
                    389:  * tape blocks.
                    390:  */
                    391: dumpinomap()
                    392: {
                    393:        register ino_t ibase;
                    394:        register char *imapp;
                    395:        register nmap;
                    396:        union dumpdata *ddp;
                    397: 
                    398:        ibase = 0;
                    399:        while ((nmap = isize-ibase) > 0) {
                    400:                ddp = ddnextbuf();
                    401:                ddp->dd_type = DD_MAP;
                    402:                ddp->dd_ino = ibase+1;
                    403:                if (nmap > BUFSIZ)
                    404:                        nmap = BUFSIZ;
                    405:                ddp->dd_nmap = nmap;
                    406:                canint(ddp->dd_type);
                    407:                canino(ddp->dd_ino);
                    408:                canint(ddp->dd_nmap);
                    409:                imapp = &ddp->dd_map[0];
                    410:                do {
                    411:                        *imapp++ = map[ibase++];
                    412:                } while (--nmap);
                    413:        }
                    414: }
                    415: 
                    416: /*
                    417:  * Fabricate a dump header and
                    418:  * write it to the dump file. All the
                    419:  * stuff in the header is in the
                    420:  * usual canonical format. This makes it
                    421:  * a little easier to move tapes from
                    422:  * one machine to another.
                    423:  */
                    424: dumpheader()
                    425: {
                    426:        register char *p;
                    427:        register checksum;
                    428: 
                    429:        dh.dh_magic = DH_MAG;
                    430:        dh.dh_nino = isize;
                    431:        dh.dh_bdate = bdate;
                    432:        dh.dh_ddate = ddate;
                    433:        dh.dh_level = level;
                    434:        dh.dh_reel = reel++;
                    435:        dh.dh_blocking = block;
                    436:        dh.dh_nbyte = Sflag ? length : 0;
                    437:        strncpy(dh.dh_dev, dev, DIRSIZ);
                    438:        strncpy(dh.dh_fname, fname, 6);
                    439:        strncpy(dh.dh_fpack, fpack, 6);
                    440:        p = (char *) &dh;
                    441:        checksum = 0;
                    442:        while (p < (char *) &dh.dh_checksum)
                    443:                checksum += (*p++) & 0377;
                    444:        dh.dh_checksum = checksum;
                    445:        canint(dh.dh_magic);
                    446:        canino(dh.dh_nino);
                    447:        cantime(dh.dh_bdate);
                    448:        cantime(dh.dh_ddate);
                    449:        canint(dh.dh_level);
                    450:        canint(dh.dh_reel);
                    451:        canint(dh.dh_blocking);
                    452:        cansize(dh.dh_nbyte);
                    453:        canint(dh.dh_checksum);
                    454:        if (write(fileno(dtp), &dh, sizeof dh) != sizeof dh)
                    455:                fatal("header write error");
                    456: }
                    457: 
                    458: /*
                    459:  * Put out the end of tape item
                    460:  * and the very end of the very last
                    461:  * dump tape.
                    462:  */
                    463: dumpfinish()
                    464: {
                    465:        register union dumpdata *ddp;
                    466: 
                    467:        ddp = ddnextbuf();
                    468:        ddp->dd_type = DD_EOT;
                    469:        canint(ddp->dd_type);
                    470:        ddflush();
                    471: }
                    472: 
                    473: /*
                    474:  * Dump out all inodes with
                    475:  * the appropriate flags set in the
                    476:  * map.
                    477:  */
                    478: dump(flag)
                    479: register flag;
                    480: {
                    481:        register ino_t i;
                    482:        register mapentry;
                    483: 
                    484:        for (i=0; i<isize; ++i) {
                    485:                mapentry = map[i];
                    486:                if ((mapentry&DD_DUMP)!=0 && (mapentry&DD_DIR)==flag) {
                    487:                        dumpi(i+1);
                    488:                        map[i] = 0;
                    489:                }
                    490:        }
                    491: }
                    492: 
                    493: /*
                    494:  * Dump an inode.
                    495:  */
                    496: dumpi(ino)
                    497: ino_t ino;
                    498: {
                    499:        struct dinode dinode;
                    500:        register union dumpdata *ddp;
                    501:        register DISCBUF *dbp;
                    502:        daddr_t lb, pb;
                    503:        int size;
                    504: 
                    505:        ++ninodes;
                    506:        ireadin(&dinode, ino);
                    507:        ddp = ddnextbuf();
                    508:        ddp->dd_type = DD_INO;
                    509:        ddp->dd_ino  = ino;
                    510:        canint(ddp->dd_type);
                    511:        canino(ddp->dd_ino);
                    512:        copyb(&ddp->dd_dinode, &dinode, sizeof(struct dinode));
                    513:        lb = 0;
                    514:        cansize(dinode.di_size);
                    515:        while (dinode.di_size != 0) {
                    516:                pb = imap(&dinode, lb);
                    517:                size = dinode.di_size<BUFSIZ ? dinode.di_size : BUFSIZ;
                    518:                if (pb != 0) {
                    519:                        dbp = dbread(pb);
                    520:                        if (allzeros(dbp->db_data, size) == 0) {
                    521:                                ++nblocks;
                    522:                                ddp = ddnextbuf();
                    523:                                ddp->dd_type = DD_DATA;
                    524:                                ddp->dd_ino  = ino;
                    525:                                ddp->dd_block = lb;
                    526:                                ddp->dd_size = size;
                    527:                                canint(ddp->dd_type);
                    528:                                canino(ddp->dd_ino);
                    529:                                candaddr(ddp->dd_block);
                    530:                                canint(ddp->dd_size);
                    531:                                copyb(ddp->dd_data, dbp->db_data, size);
                    532:                        } else
                    533:                                ++nsparse;
                    534:                        dbfree(dbp, 0);
                    535:                }
                    536:                dinode.di_size -= size;
                    537:                ++lb;
                    538:        }
                    539: }
                    540: 
                    541: /*
                    542:  * Check if a disc block is all
                    543:  * zero bytes. True return if it is.
                    544:  */
                    545: allzeros(cp, nb)
                    546: register char  *cp;
                    547: register int   nb;
                    548: {
                    549:        do {
                    550:                if (*cp++ != 0)
                    551:                        return (0);
                    552:        } while (--nb);
                    553:        return (1);
                    554: }
                    555: 
                    556: /*
                    557:  * Copy a block of bytes.
                    558:  */
                    559: copyb(atp, afp, anb)
                    560: char *atp, *afp;
                    561: {
                    562:        register char *tp, *fp;
                    563:        register nb;
                    564: 
                    565:        if ((nb = anb) != 0) {
                    566:                tp = atp;
                    567:                fp = afp;
                    568:                do {
                    569:                        *tp++ = *fp++;
                    570:                } while (--nb);
                    571:        }
                    572: }
                    573: 
                    574: /*
                    575:  * Return a pointer to the
                    576:  * next data buffer.
                    577:  */
                    578: union  dumpdata *
                    579: ddnextbuf()
                    580: {
                    581:        register char *p;
                    582:        register n;
                    583: 
                    584:        if (ddbuf == NULL) {
                    585:                ddnbuf = block * sizeof(union dumpdata);
                    586:                if ((ddbuf = malloc(ddnbuf)) == NULL)
                    587:                        fatal("out of memory (buffer)");
                    588:                ddend = &ddbuf[ddnbuf];
                    589:                ddptr = (union dumpdata *) ddbuf;
                    590:        }
                    591:        if ((char *) ddptr == ddend) {
                    592:                ddflush();
                    593:                ddptr = (union dumpdata *) ddbuf;
                    594:        }
                    595:        if ((char *) ddptr == ddbuf) {
                    596:                p = ddbuf;
                    597:                n = ddnbuf;
                    598:                do {
                    599:                        *p++ = 0;
                    600:                } while (--n);
                    601:        }
                    602:        return (ddptr++);
                    603: }
                    604: 
                    605: /*
                    606:  * Write out the big data buffer.
                    607:  */
                    608: ddflush()
                    609: {
                    610:        used += ddlen(ddnbuf);
                    611:        if (used >= length) {
                    612:                nextvol();
                    613:                used += ddlen(ddnbuf);
                    614:        }
                    615:        if (write(fileno(dtp), ddbuf, ddnbuf) != ddnbuf)
                    616:                fatal("dump write error");
                    617: }
                    618: 
                    619: /*
                    620:  * Request next dump volume.
                    621:  */
                    622: nextvol()
                    623: {
                    624:        char buf[40];
                    625: 
                    626:        if (Sflag != 0 || reel != 1) {
                    627:                fclose(dtp);
                    628:                fprintf(stderr, "dump: mount %s %d, type return key ...",
                    629:                        Sflag ? "volume" : "reel", reel);
                    630:                if (gets(buf) == NULL)
                    631:                        exit(1);
                    632:                if ((dtp = fopen(dtn, "w")) == NULL)
                    633:                        fatal("%s: cannot open dump file", dtn);
                    634:        }
                    635:        dumpheader();
                    636:        used = ddlen(sizeof(dh));
                    637: }
                    638: 
                    639: /*
                    640:  * Given a record size in bytes,
                    641:  * return the number of inches/100 of tape
                    642:  * that will get used.
                    643:  * For blocked devices, the granularity is
                    644:  * actually in bytes.
                    645:  */
                    646: long
                    647: ddlen(nbytes)
                    648: {
                    649:        if (Sflag)
                    650:                return (nbytes);
                    651:        return (100L*((nbytes+density-1)/density) + 75);
                    652: }
                    653: 
                    654: /*
                    655:  * Update the dump date in the
                    656:  * dump date file. The date used is the
                    657:  * date at the beginning of the dump.
                    658:  */
                    659: putddate()
                    660: {
                    661:        register FILE *ddfp;
                    662:        struct idates id;
                    663: 
                    664:        if ((ddfp = fopen(DDATE, "r+w")) == NULL) {
                    665:                fprintf(stderr, "dump: cannot update dump date\n");
                    666:                return;
                    667:        }
                    668:        while (fread(&id, sizeof(id), 1, ddfp) == 1) {
                    669:                if (strncmp(id.id_name, dev, DIRSIZ) == 0
                    670:                && id.id_incno==level) {
                    671:                        fseek(ddfp, (long)-sizeof(id), 1);
                    672:                        break;
                    673:                }
                    674:        }
                    675:        strncpy(id.id_name, dev, DIRSIZ);
                    676:        id.id_incno = level;
                    677:        id.id_ddate = bdate;
                    678:        if (fwrite(&id, sizeof(id), 1, ddfp) != 1)
                    679:                fprintf(stderr, "dump: error updating date file\n");
                    680:        fclose(ddfp);
                    681: }
                    682: 
                    683: /*
                    684:  * Get dump date.
                    685:  */
                    686: long
                    687: getddate()
                    688: {
                    689:        register FILE *ddfp;
                    690:        register long ddate;
                    691:        struct idates id;
                    692: 
                    693:        ddate = 0;
                    694:        if ((ddfp = fopen(DDATE, "r")) != NULL) {
                    695:                while (fread(&id, sizeof(id), 1, ddfp) == 1) {
                    696:                        if (strncmp(id.id_name, dev, DIRSIZ)==0
                    697:                        && id.id_incno<level
                    698:                        && id.id_ddate>ddate)
                    699:                                ddate = id.id_ddate;
                    700:                }
                    701:                fclose(ddfp);
                    702:        }
                    703:        return (ddate);
                    704: }
                    705: 
                    706: /*
                    707:  * Print out a fatal diagnostic
                    708:  * and die.
                    709:  */
                    710: fatal(a)
                    711: {
                    712:        fprintf(stderr, "dump: %r", &a);
                    713:        fprintf(stderr, "\n");
                    714:        exit(1);
                    715: }
                    716: 
                    717: /*
                    718:  * Print out a usage message and
                    719:  * exit. If you can figure out how to use
                    720:  * dump from the usage message you are
                    721:  * a better man than I.
                    722:  */
                    723: usage()
                    724: {
                    725:        fprintf(stderr, helpmessage);
                    726:        exit(1);
                    727: }
                    728: 
                    729: /*
                    730:  * Squash off any structure
                    731:  * before the last part of a file
                    732:  * name and put it in the supplied
                    733:  * buffer.
                    734:  */
                    735: squash(tp, fp)
                    736: register char *tp, *fp;
                    737: {
                    738:        register char *np;
                    739: 
                    740:        np = fp;
                    741:        while (*fp != '\0') {
                    742:                if (*fp == '/')
                    743:                        np = fp+1;
                    744:                ++fp;
                    745:        }
                    746:        while (*tp++ = *np++)
                    747:                ;
                    748: }

unix.superglobalmegacorp.com

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