[BACK]Return to tape.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sbin / restore

Annotation of src/sbin/restore/tape.c, Revision 1.12

1.10      cgd         1: /*
1.11      mycroft     2:  * Copyright (c) 1983, 1993
                      3:  *     The Regents of the University of California.  All rights reserved.
1.10      cgd         4:  * (c) UNIX System Laboratories, Inc.
                      5:  * All or some portions of this file are derived from material licensed
                      6:  * to the University of California by American Telephone and Telegraph
                      7:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
                      8:  * the permission of UNIX System Laboratories, Inc.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
                     20:  *     This product includes software developed by the University of
                     21:  *     California, Berkeley and its contributors.
                     22:  * 4. Neither the name of the University nor the names of its contributors
                     23:  *    may be used to endorse or promote products derived from this software
                     24:  *    without specific prior written permission.
                     25:  *
                     26:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     27:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     28:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     29:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     30:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     31:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     32:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     33:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     34:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     35:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     36:  * SUCH DAMAGE.
                     37:  */
                     38:
                     39: #ifndef lint
1.11      mycroft    40: /*static char sccsid[] = "from: @(#)tape.c     8.3 (Berkeley) 4/1/94";*/
1.12    ! mycroft    41: static char *rcsid = "$Id: tape.c,v 1.11 1994/06/08 19:33:45 mycroft Exp $";
1.10      cgd        42: #endif /* not lint */
                     43:
                     44: #include <sys/param.h>
                     45: #include <sys/file.h>
                     46: #include <sys/ioctl.h>
                     47: #include <sys/mtio.h>
                     48: #include <sys/stat.h>
                     49:
1.11      mycroft    50: #include <ufs/ufs/dinode.h>
1.10      cgd        51: #include <protocols/dumprestore.h>
                     52:
                     53: #include <errno.h>
                     54: #include <setjmp.h>
                     55: #include <stdio.h>
                     56: #include <stdlib.h>
                     57: #include <string.h>
                     58: #include <unistd.h>
                     59:
                     60: #include "restore.h"
                     61: #include "extern.h"
                     62: #include "pathnames.h"
                     63:
                     64: static long    fssize = MAXBSIZE;
                     65: static int     mt = -1;
                     66: static int     pipein = 0;
                     67: static char    magtape[BUFSIZ];
                     68: static int     blkcnt;
                     69: static int     numtrec;
                     70: static char    *tapebuf;
                     71: static union   u_spcl endoftapemark;
                     72: static long    blksread;               /* blocks read since last header */
                     73: static long    tpblksread = 0;         /* TP_BSIZE blocks read */
                     74: static long    tapesread;
                     75: static jmp_buf restart;
                     76: static int     gettingfile = 0;        /* restart has a valid frame */
                     77: static char    *host = NULL;
                     78:
                     79: static int     ofile;
                     80: static char    *map;
                     81: static char    lnkbuf[MAXPATHLEN + 1];
                     82: static int     pathlen;
                     83:
                     84: int            oldinofmt;      /* old inode format conversion required */
                     85: int            Bcvt;           /* Swap Bytes (for CCI or sun) */
                     86: static int     Qcvt;           /* Swap quads (for sun) */
                     87:
                     88: #define        FLUSHTAPEBUF()  blkcnt = ntrec + 1
                     89:
                     90: static void     accthdr __P((struct s_spcl *));
                     91: static int      checksum __P((int *));
                     92: static void     findinode __P((struct s_spcl *));
                     93: static void     findtapeblksize __P((void));
                     94: static int      gethead __P((struct s_spcl *));
                     95: static void     readtape __P((char *));
                     96: static void     setdumpnum __P((void));
                     97: static u_long   swabl __P((u_long));
                     98: static u_char  *swablong __P((u_char *, int));
                     99: static u_char  *swabshort __P((u_char *, int));
                    100: static void     terminateinput __P((void));
                    101: static void     xtrfile __P((char *, long));
                    102: static void     xtrlnkfile __P((char *, long));
                    103: static void     xtrlnkskip __P((char *, long));
                    104: static void     xtrmap __P((char *, long));
                    105: static void     xtrmapskip __P((char *, long));
                    106: static void     xtrskip __P((char *, long));
                    107:
                    108: /*
                    109:  * Set up an input source
                    110:  */
                    111: void
                    112: setinput(source)
                    113:        char *source;
                    114: {
                    115:        FLUSHTAPEBUF();
                    116:        if (bflag)
                    117:                newtapebuf(ntrec);
                    118:        else
                    119:                newtapebuf(NTREC > HIGHDENSITYTREC ? NTREC : HIGHDENSITYTREC);
                    120:        terminal = stdin;
                    121:
                    122: #ifdef RRESTORE
                    123:        if (index(source, ':')) {
                    124:                host = source;
                    125:                source = index(host, ':');
                    126:                *source++ = '\0';
                    127:                if (rmthost(host) == 0)
                    128:                        done(1);
                    129:        } else
                    130: #endif
                    131:        if (strcmp(source, "-") == 0) {
                    132:                /*
                    133:                 * Since input is coming from a pipe we must establish
                    134:                 * our own connection to the terminal.
                    135:                 */
                    136:                terminal = fopen(_PATH_TTY, "r");
                    137:                if (terminal == NULL) {
                    138:                        (void)fprintf(stderr, "cannot open %s: %s\n",
                    139:                            _PATH_TTY, strerror(errno));
                    140:                        terminal = fopen(_PATH_DEVNULL, "r");
                    141:                        if (terminal == NULL) {
                    142:                                (void)fprintf(stderr, "cannot open %s: %s\n",
                    143:                                    _PATH_DEVNULL, strerror(errno));
                    144:                                done(1);
                    145:                        }
                    146:                }
                    147:                pipein++;
                    148:        }
                    149:        setuid(getuid());       /* no longer need or want root privileges */
                    150:        (void) strcpy(magtape, source);
                    151: }
                    152:
                    153: void
                    154: newtapebuf(size)
                    155:        long size;
                    156: {
                    157:        static tapebufsize = -1;
                    158:
                    159:        ntrec = size;
                    160:        if (size <= tapebufsize)
                    161:                return;
                    162:        if (tapebuf != NULL)
                    163:                free(tapebuf);
                    164:        tapebuf = malloc(size * TP_BSIZE);
                    165:        if (tapebuf == NULL) {
                    166:                fprintf(stderr, "Cannot allocate space for tape buffer\n");
                    167:                done(1);
                    168:        }
                    169:        tapebufsize = size;
                    170: }
                    171:
                    172: /*
                    173:  * Verify that the tape drive can be accessed and
                    174:  * that it actually is a dump tape.
                    175:  */
                    176: void
                    177: setup()
                    178: {
                    179:        int i, j, *ip;
                    180:        struct stat stbuf;
                    181:
                    182:        vprintf(stdout, "Verify tape and initialize maps\n");
                    183: #ifdef RRESTORE
                    184:        if (host)
1.11      mycroft   185:                mt = rmtopen(magtape, 0);
1.10      cgd       186:        else
                    187: #endif
                    188:        if (pipein)
                    189:                mt = 0;
                    190:        else
                    191:                mt = open(magtape, O_RDONLY, 0);
                    192:        if (mt < 0) {
                    193:                fprintf(stderr, "%s: %s\n", magtape, strerror(errno));
                    194:                done(1);
                    195:        }
                    196:        volno = 1;
                    197:        setdumpnum();
                    198:        FLUSHTAPEBUF();
                    199:        if (!pipein && !bflag)
                    200:                findtapeblksize();
                    201:        if (gethead(&spcl) == FAIL) {
                    202:                blkcnt--; /* push back this block */
                    203:                blksread--;
                    204:                tpblksread--;
                    205:                cvtflag++;
                    206:                if (gethead(&spcl) == FAIL) {
                    207:                        fprintf(stderr, "Tape is not a dump tape\n");
                    208:                        done(1);
                    209:                }
                    210:                fprintf(stderr, "Converting to new file system format.\n");
                    211:        }
                    212:        if (pipein) {
                    213:                endoftapemark.s_spcl.c_magic = cvtflag ? OFS_MAGIC : NFS_MAGIC;
                    214:                endoftapemark.s_spcl.c_type = TS_END;
                    215:                ip = (int *)&endoftapemark;
                    216:                j = sizeof(union u_spcl) / sizeof(int);
                    217:                i = 0;
                    218:                do
                    219:                        i += *ip++;
                    220:                while (--j);
                    221:                endoftapemark.s_spcl.c_checksum = CHECKSUM - i;
                    222:        }
                    223:        if (vflag || command == 't')
                    224:                printdumpinfo();
                    225:        dumptime = spcl.c_ddate;
                    226:        dumpdate = spcl.c_date;
                    227:        if (stat(".", &stbuf) < 0) {
                    228:                fprintf(stderr, "cannot stat .: %s\n", strerror(errno));
                    229:                done(1);
                    230:        }
                    231:        if (stbuf.st_blksize > 0 && stbuf.st_blksize <= MAXBSIZE)
                    232:                fssize = stbuf.st_blksize;
                    233:        if (((fssize - 1) & fssize) != 0) {
                    234:                fprintf(stderr, "bad block size %d\n", fssize);
                    235:                done(1);
                    236:        }
                    237:        if (spcl.c_volume != 1) {
                    238:                fprintf(stderr, "Tape is not volume 1 of the dump\n");
                    239:                done(1);
                    240:        }
                    241:        if (gethead(&spcl) == FAIL) {
                    242:                dprintf(stdout, "header read failed at %d blocks\n", blksread);
                    243:                panic("no header after volume mark!\n");
                    244:        }
                    245:        findinode(&spcl);
                    246:        if (spcl.c_type != TS_CLRI) {
                    247:                fprintf(stderr, "Cannot find file removal list\n");
                    248:                done(1);
                    249:        }
                    250:        maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1;
                    251:        dprintf(stdout, "maxino = %d\n", maxino);
                    252:        map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY));
                    253:        if (map == NULL)
                    254:                panic("no memory for file removal list\n");
                    255:        clrimap = map;
                    256:        curfile.action = USING;
                    257:        getfile(xtrmap, xtrmapskip);
                    258:        if (spcl.c_type != TS_BITS) {
                    259:                fprintf(stderr, "Cannot find file dump list\n");
                    260:                done(1);
                    261:        }
                    262:        map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY));
                    263:        if (map == (char *)NULL)
                    264:                panic("no memory for file dump list\n");
                    265:        dumpmap = map;
                    266:        curfile.action = USING;
                    267:        getfile(xtrmap, xtrmapskip);
                    268: }
                    269:
                    270: /*
                    271:  * Prompt user to load a new dump volume.
                    272:  * "Nextvol" is the next suggested volume to use.
                    273:  * This suggested volume is enforced when doing full
                    274:  * or incremental restores, but can be overrridden by
                    275:  * the user when only extracting a subset of the files.
                    276:  */
                    277: void
                    278: getvol(nextvol)
                    279:        long nextvol;
                    280: {
                    281:        long newvol, savecnt, wantnext, i;
                    282:        union u_spcl tmpspcl;
                    283: #      define tmpbuf tmpspcl.s_spcl
                    284:        char buf[TP_BSIZE];
                    285:
                    286:        if (nextvol == 1) {
                    287:                tapesread = 0;
                    288:                gettingfile = 0;
                    289:        }
                    290:        if (pipein) {
                    291:                if (nextvol != 1)
                    292:                        panic("Changing volumes on pipe input?\n");
                    293:                if (volno == 1)
                    294:                        return;
                    295:                goto gethdr;
                    296:        }
                    297:        savecnt = blksread;
                    298: again:
                    299:        if (pipein)
                    300:                done(1); /* pipes do not get a second chance */
                    301:        if (command == 'R' || command == 'r' || curfile.action != SKIP) {
                    302:                newvol = nextvol;
                    303:                wantnext = 1;
                    304:        } else {
                    305:                newvol = 0;
                    306:                wantnext = 0;
                    307:        }
                    308:        while (newvol <= 0) {
                    309:                if (tapesread == 0) {
                    310:                        fprintf(stderr, "%s%s%s%s%s",
                    311:                            "You have not read any tapes yet.\n",
                    312:                            "Unless you know which volume your",
                    313:                            " file(s) are on you should start\n",
                    314:                            "with the last volume and work",
                    315:                            " towards towards the first.\n");
                    316:                } else {
                    317:                        fprintf(stderr, "You have read volumes");
                    318:                        strcpy(buf, ": ");
                    319:                        for (i = 1; i < 32; i++)
                    320:                                if (tapesread & (1 << i)) {
                    321:                                        fprintf(stderr, "%s%d", buf, i);
                    322:                                        strcpy(buf, ", ");
                    323:                                }
                    324:                        fprintf(stderr, "\n");
                    325:                }
                    326:                do      {
                    327:                        fprintf(stderr, "Specify next volume #: ");
                    328:                        (void) fflush(stderr);
                    329:                        (void) fgets(buf, BUFSIZ, terminal);
                    330:                } while (!feof(terminal) && buf[0] == '\n');
                    331:                if (feof(terminal))
                    332:                        done(1);
                    333:                newvol = atoi(buf);
                    334:                if (newvol <= 0) {
                    335:                        fprintf(stderr,
                    336:                            "Volume numbers are positive numerics\n");
                    337:                }
                    338:        }
                    339:        if (newvol == volno) {
                    340:                tapesread |= 1 << volno;
                    341:                return;
                    342:        }
                    343:        closemt();
                    344:        fprintf(stderr, "Mount tape volume %d\n", newvol);
                    345:        fprintf(stderr, "Enter ``none'' if there are no more tapes\n");
                    346:        fprintf(stderr, "otherwise enter tape name (default: %s) ", magtape);
                    347:        (void) fflush(stderr);
                    348:        (void) fgets(buf, BUFSIZ, terminal);
                    349:        if (feof(terminal))
                    350:                done(1);
                    351:        if (!strcmp(buf, "none\n")) {
                    352:                terminateinput();
                    353:                return;
                    354:        }
                    355:        if (buf[0] != '\n') {
                    356:                (void) strcpy(magtape, buf);
                    357:                magtape[strlen(magtape) - 1] = '\0';
                    358:        }
                    359: #ifdef RRESTORE
                    360:        if (host)
                    361:                mt = rmtopen(magtape, 0);
                    362:        else
                    363: #endif
                    364:                mt = open(magtape, O_RDONLY, 0);
                    365:
                    366:        if (mt == -1) {
                    367:                fprintf(stderr, "Cannot open %s\n", magtape);
                    368:                volno = -1;
                    369:                goto again;
                    370:        }
                    371: gethdr:
                    372:        volno = newvol;
                    373:        setdumpnum();
                    374:        FLUSHTAPEBUF();
                    375:        if (gethead(&tmpbuf) == FAIL) {
                    376:                dprintf(stdout, "header read failed at %d blocks\n", blksread);
                    377:                fprintf(stderr, "tape is not dump tape\n");
                    378:                volno = 0;
                    379:                goto again;
                    380:        }
                    381:        if (tmpbuf.c_volume != volno) {
                    382:                fprintf(stderr, "Wrong volume (%d)\n", tmpbuf.c_volume);
                    383:                volno = 0;
                    384:                goto again;
                    385:        }
                    386:        if (tmpbuf.c_date != dumpdate || tmpbuf.c_ddate != dumptime) {
                    387:                fprintf(stderr, "Wrong dump date\n\tgot: %s",
                    388:                        ctime(&tmpbuf.c_date));
                    389:                fprintf(stderr, "\twanted: %s", ctime(&dumpdate));
                    390:                volno = 0;
                    391:                goto again;
                    392:        }
                    393:        tapesread |= 1 << volno;
                    394:        blksread = savecnt;
                    395:        /*
                    396:         * If continuing from the previous volume, skip over any
                    397:         * blocks read already at the end of the previous volume.
                    398:         *
                    399:         * If coming to this volume at random, skip to the beginning
                    400:         * of the next record.
                    401:         */
                    402:        dprintf(stdout, "read %ld recs, tape starts with %ld\n",
                    403:                tpblksread, tmpbuf.c_firstrec);
                    404:        if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER)) {
                    405:                if (!wantnext) {
                    406:                        tpblksread = tmpbuf.c_firstrec;
                    407:                        for (i = tmpbuf.c_count; i > 0; i--)
                    408:                                readtape(buf);
                    409:                } else if (tmpbuf.c_firstrec > 0 &&
                    410:                           tmpbuf.c_firstrec < tpblksread - 1) {
                    411:                        /*
                    412:                         * -1 since we've read the volume header
                    413:                         */
                    414:                        i = tpblksread - tmpbuf.c_firstrec - 1;
                    415:                        dprintf(stderr, "Skipping %d duplicate record%s.\n",
                    416:                                i, i > 1 ? "s" : "");
                    417:                        while (--i >= 0)
                    418:                                readtape(buf);
                    419:                }
                    420:        }
                    421:        if (curfile.action == USING) {
                    422:                if (volno == 1)
                    423:                        panic("active file into volume 1\n");
                    424:                return;
                    425:        }
                    426:        /*
                    427:         * Skip up to the beginning of the next record
                    428:         */
                    429:        if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER))
                    430:                for (i = tmpbuf.c_count; i > 0; i--)
                    431:                        readtape(buf);
                    432:        (void) gethead(&spcl);
                    433:        findinode(&spcl);
                    434:        if (gettingfile) {
                    435:                gettingfile = 0;
                    436:                longjmp(restart, 1);
                    437:        }
                    438: }
                    439:
                    440: /*
                    441:  * Handle unexpected EOF.
                    442:  */
                    443: static void
                    444: terminateinput()
                    445: {
                    446:
                    447:        if (gettingfile && curfile.action == USING) {
                    448:                printf("Warning: %s %s\n",
                    449:                    "End-of-input encountered while extracting", curfile.name);
                    450:        }
                    451:        curfile.name = "<name unknown>";
                    452:        curfile.action = UNKNOWN;
                    453:        curfile.dip = NULL;
                    454:        curfile.ino = maxino;
                    455:        if (gettingfile) {
                    456:                gettingfile = 0;
                    457:                longjmp(restart, 1);
                    458:        }
                    459: }
                    460:
                    461: /*
                    462:  * handle multiple dumps per tape by skipping forward to the
                    463:  * appropriate one.
                    464:  */
                    465: static void
                    466: setdumpnum()
                    467: {
                    468:        struct mtop tcom;
                    469:
                    470:        if (dumpnum == 1 || volno != 1)
                    471:                return;
                    472:        if (pipein) {
                    473:                fprintf(stderr, "Cannot have multiple dumps on pipe input\n");
                    474:                done(1);
                    475:        }
                    476:        tcom.mt_op = MTFSF;
                    477:        tcom.mt_count = dumpnum - 1;
                    478: #ifdef RRESTORE
                    479:        if (host)
                    480:                rmtioctl(MTFSF, dumpnum - 1);
                    481:        else
                    482: #endif
                    483:                if (ioctl(mt, (int)MTIOCTOP, (char *)&tcom) < 0)
                    484:                        fprintf(stderr, "ioctl MTFSF: %s\n", strerror(errno));
                    485: }
                    486:
                    487: void
                    488: printdumpinfo()
                    489: {
                    490:        fprintf(stdout, "Dump   date: %s", ctime(&spcl.c_date));
                    491:        fprintf(stdout, "Dumped from: %s",
                    492:            (spcl.c_ddate == 0) ? "the epoch\n" : ctime(&spcl.c_ddate));
                    493:        if (spcl.c_host[0] == '\0')
                    494:                return;
                    495:        fprintf(stderr, "Level %d dump of %s on %s:%s\n",
                    496:                spcl.c_level, spcl.c_filesys, spcl.c_host, spcl.c_dev);
                    497:        fprintf(stderr, "Label: %s\n", spcl.c_label);
                    498: }
                    499:
                    500: int
                    501: extractfile(name)
                    502:        char *name;
                    503: {
                    504:        int mode;
                    505:        struct timeval timep[2];
                    506:        struct entry *ep;
                    507:
                    508:        curfile.name = name;
                    509:        curfile.action = USING;
                    510:        timep[0].tv_sec = curfile.dip->di_atime.ts_sec;
                    511:        timep[0].tv_usec = curfile.dip->di_atime.ts_nsec / 1000;
                    512:        timep[1].tv_sec = curfile.dip->di_mtime.ts_sec;
                    513:        timep[1].tv_usec = curfile.dip->di_mtime.ts_nsec / 1000;
                    514:        mode = curfile.dip->di_mode;
                    515:        switch (mode & IFMT) {
                    516:
                    517:        default:
                    518:                fprintf(stderr, "%s: unknown file mode 0%o\n", name, mode);
                    519:                skipfile();
                    520:                return (FAIL);
                    521:
                    522:        case IFSOCK:
                    523:                vprintf(stdout, "skipped socket %s\n", name);
                    524:                skipfile();
                    525:                return (GOOD);
                    526:
                    527:        case IFDIR:
                    528:                if (mflag) {
                    529:                        ep = lookupname(name);
                    530:                        if (ep == NULL || ep->e_flags & EXTRACT)
                    531:                                panic("unextracted directory %s\n", name);
                    532:                        skipfile();
                    533:                        return (GOOD);
                    534:                }
                    535:                vprintf(stdout, "extract file %s\n", name);
                    536:                return (genliteraldir(name, curfile.ino));
                    537:
                    538:        case IFLNK:
                    539:                lnkbuf[0] = '\0';
                    540:                pathlen = 0;
                    541:                getfile(xtrlnkfile, xtrlnkskip);
                    542:                if (pathlen == 0) {
                    543:                        vprintf(stdout,
                    544:                            "%s: zero length symbolic link (ignored)\n", name);
                    545:                        return (GOOD);
                    546:                }
                    547:                return (linkit(lnkbuf, name, SYMLINK));
1.12    ! mycroft   548:
        !           549:        case IFIFO:
        !           550:                vprintf(stdout, "extract fifo %s\n", name);
        !           551:                if (Nflag) {
        !           552:                        skipfile();
        !           553:                        return (GOOD);
        !           554:                }
        !           555:                if (mkfifo(name, mode) < 0) {
        !           556:                        fprintf(stderr, "%s: cannot create fifo: %s\n",
        !           557:                            name, strerror(errno));
        !           558:                        skipfile();
        !           559:                        return (FAIL);
        !           560:                }
        !           561:                (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid);
        !           562:                (void) chmod(name, mode);
        !           563:                skipfile();
        !           564:                utimes(name, timep);
        !           565:                return (GOOD);
1.10      cgd       566:
                    567:        case IFCHR:
                    568:        case IFBLK:
                    569:                vprintf(stdout, "extract special file %s\n", name);
                    570:                if (Nflag) {
                    571:                        skipfile();
                    572:                        return (GOOD);
                    573:                }
                    574:                if (mknod(name, mode, (int)curfile.dip->di_rdev) < 0) {
                    575:                        fprintf(stderr, "%s: cannot create special file: %s\n",
                    576:                            name, strerror(errno));
                    577:                        skipfile();
                    578:                        return (FAIL);
                    579:                }
                    580:                (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid);
                    581:                (void) chmod(name, mode);
                    582:                skipfile();
                    583:                utimes(name, timep);
                    584:                return (GOOD);
                    585:
                    586:        case IFREG:
                    587:                vprintf(stdout, "extract file %s\n", name);
                    588:                if (Nflag) {
                    589:                        skipfile();
                    590:                        return (GOOD);
                    591:                }
                    592:                if ((ofile = creat(name, 0666)) < 0) {
                    593:                        fprintf(stderr, "%s: cannot create file: %s\n",
                    594:                            name, strerror(errno));
                    595:                        skipfile();
                    596:                        return (FAIL);
                    597:                }
                    598:                (void) fchown(ofile, curfile.dip->di_uid, curfile.dip->di_gid);
                    599:                (void) fchmod(ofile, mode);
                    600:                getfile(xtrfile, xtrskip);
                    601:                (void) close(ofile);
                    602:                utimes(name, timep);
                    603:                return (GOOD);
                    604:        }
                    605:        /* NOTREACHED */
                    606: }
                    607:
                    608: /*
                    609:  * skip over bit maps on the tape
                    610:  */
                    611: void
                    612: skipmaps()
                    613: {
                    614:
                    615:        while (spcl.c_type == TS_BITS || spcl.c_type == TS_CLRI)
                    616:                skipfile();
                    617: }
                    618:
                    619: /*
                    620:  * skip over a file on the tape
                    621:  */
                    622: void
                    623: skipfile()
                    624: {
                    625:
                    626:        curfile.action = SKIP;
                    627:        getfile(xtrnull, xtrnull);
                    628: }
                    629:
                    630: /*
                    631:  * Extract a file from the tape.
                    632:  * When an allocated block is found it is passed to the fill function;
                    633:  * when an unallocated block (hole) is found, a zeroed buffer is passed
                    634:  * to the skip function.
                    635:  */
                    636: void
                    637: getfile(fill, skip)
                    638:        void    (*fill) __P((char *, long));
                    639:        void    (*skip) __P((char *, long));
                    640: {
                    641:        register int i;
                    642:        int curblk = 0;
                    643:        long size = spcl.c_dinode.di_size;
                    644:        static char clearedbuf[MAXBSIZE];
                    645:        char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE];
                    646:        char junk[TP_BSIZE];
                    647:
                    648:        if (spcl.c_type == TS_END)
                    649:                panic("ran off end of tape\n");
                    650:        if (spcl.c_magic != NFS_MAGIC)
                    651:                panic("not at beginning of a file\n");
                    652:        if (!gettingfile && setjmp(restart) != 0)
                    653:                return;
                    654:        gettingfile++;
                    655: loop:
                    656:        for (i = 0; i < spcl.c_count; i++) {
                    657:                if (spcl.c_addr[i]) {
                    658:                        readtape(&buf[curblk++][0]);
                    659:                        if (curblk == fssize / TP_BSIZE) {
                    660:                                (*fill)((char *)buf, size > TP_BSIZE ?
                    661:                                     (long) (fssize) :
                    662:                                     (curblk - 1) * TP_BSIZE + size);
                    663:                                curblk = 0;
                    664:                        }
                    665:                } else {
                    666:                        if (curblk > 0) {
                    667:                                (*fill)((char *)buf, size > TP_BSIZE ?
                    668:                                     (long) (curblk * TP_BSIZE) :
                    669:                                     (curblk - 1) * TP_BSIZE + size);
                    670:                                curblk = 0;
                    671:                        }
                    672:                        (*skip)(clearedbuf, size > TP_BSIZE ?
                    673:                                (long) TP_BSIZE : size);
                    674:                }
                    675:                if ((size -= TP_BSIZE) <= 0) {
                    676:                        for (i++; i < spcl.c_count; i++)
                    677:                                if (spcl.c_addr[i])
                    678:                                        readtape(junk);
                    679:                        break;
                    680:                }
                    681:        }
                    682:        if (gethead(&spcl) == GOOD && size > 0) {
                    683:                if (spcl.c_type == TS_ADDR)
                    684:                        goto loop;
                    685:                dprintf(stdout,
                    686:                        "Missing address (header) block for %s at %d blocks\n",
                    687:                        curfile.name, blksread);
                    688:        }
                    689:        if (curblk > 0)
                    690:                (*fill)((char *)buf, (curblk * TP_BSIZE) + size);
                    691:        findinode(&spcl);
                    692:        gettingfile = 0;
                    693: }
                    694:
                    695: /*
                    696:  * Write out the next block of a file.
                    697:  */
                    698: static void
                    699: xtrfile(buf, size)
                    700:        char    *buf;
                    701:        long    size;
                    702: {
                    703:
                    704:        if (Nflag)
                    705:                return;
                    706:        if (write(ofile, buf, (int) size) == -1) {
                    707:                fprintf(stderr,
                    708:                    "write error extracting inode %d, name %s\nwrite: %s\n",
                    709:                        curfile.ino, curfile.name, strerror(errno));
                    710:                done(1);
                    711:        }
                    712: }
                    713:
                    714: /*
                    715:  * Skip over a hole in a file.
                    716:  */
                    717: /* ARGSUSED */
                    718: static void
                    719: xtrskip(buf, size)
                    720:        char *buf;
                    721:        long size;
                    722: {
                    723:
                    724:        if (lseek(ofile, size, SEEK_CUR) == -1) {
                    725:                fprintf(stderr,
                    726:                    "seek error extracting inode %d, name %s\nlseek: %s\n",
                    727:                        curfile.ino, curfile.name, strerror(errno));
                    728:                done(1);
                    729:        }
                    730: }
                    731:
                    732: /*
                    733:  * Collect the next block of a symbolic link.
                    734:  */
                    735: static void
                    736: xtrlnkfile(buf, size)
                    737:        char    *buf;
                    738:        long    size;
                    739: {
                    740:
                    741:        pathlen += size;
                    742:        if (pathlen > MAXPATHLEN) {
                    743:                fprintf(stderr, "symbolic link name: %s->%s%s; too long %d\n",
                    744:                    curfile.name, lnkbuf, buf, pathlen);
                    745:                done(1);
                    746:        }
                    747:        (void) strcat(lnkbuf, buf);
                    748: }
                    749:
                    750: /*
                    751:  * Skip over a hole in a symbolic link (should never happen).
                    752:  */
                    753: /* ARGSUSED */
                    754: static void
                    755: xtrlnkskip(buf, size)
                    756:        char *buf;
                    757:        long size;
                    758: {
                    759:
                    760:        fprintf(stderr, "unallocated block in symbolic link %s\n",
                    761:                curfile.name);
                    762:        done(1);
                    763: }
                    764:
                    765: /*
                    766:  * Collect the next block of a bit map.
                    767:  */
                    768: static void
                    769: xtrmap(buf, size)
                    770:        char    *buf;
                    771:        long    size;
                    772: {
                    773:
                    774:        bcopy(buf, map, size);
                    775:        map += size;
                    776: }
                    777:
                    778: /*
                    779:  * Skip over a hole in a bit map (should never happen).
                    780:  */
                    781: /* ARGSUSED */
                    782: static void
                    783: xtrmapskip(buf, size)
                    784:        char *buf;
                    785:        long size;
                    786: {
                    787:
                    788:        panic("hole in map\n");
                    789:        map += size;
                    790: }
                    791:
                    792: /*
                    793:  * Noop, when an extraction function is not needed.
                    794:  */
                    795: /* ARGSUSED */
                    796: void
                    797: xtrnull(buf, size)
                    798:        char *buf;
                    799:        long size;
                    800: {
                    801:
                    802:        return;
                    803: }
                    804:
                    805: /*
                    806:  * Read TP_BSIZE blocks from the input.
                    807:  * Handle read errors, and end of media.
                    808:  */
                    809: static void
                    810: readtape(buf)
                    811:        char *buf;
                    812: {
                    813:        long rd, newvol, i;
                    814:        int cnt, seek_failed;
                    815:
                    816:        if (blkcnt < numtrec) {
                    817:                bcopy(&tapebuf[(blkcnt++ * TP_BSIZE)], buf, (long)TP_BSIZE);
                    818:                blksread++;
                    819:                tpblksread++;
                    820:                return;
                    821:        }
                    822:        for (i = 0; i < ntrec; i++)
                    823:                ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0;
                    824:        if (numtrec == 0)
                    825:                numtrec = ntrec;
                    826:        cnt = ntrec * TP_BSIZE;
                    827:        rd = 0;
                    828: getmore:
                    829: #ifdef RRESTORE
                    830:        if (host)
                    831:                i = rmtread(&tapebuf[rd], cnt);
                    832:        else
                    833: #endif
                    834:                i = read(mt, &tapebuf[rd], cnt);
                    835:        /*
                    836:         * Check for mid-tape short read error.
                    837:         * If found, skip rest of buffer and start with the next.
                    838:         */
                    839:        if (!pipein && numtrec < ntrec && i > 0) {
                    840:                dprintf(stdout, "mid-media short read error.\n");
                    841:                numtrec = ntrec;
                    842:        }
                    843:        /*
                    844:         * Handle partial block read.
                    845:         */
                    846:        if (pipein && i == 0 && rd > 0)
                    847:                i = rd;
                    848:        else if (i > 0 && i != ntrec * TP_BSIZE) {
                    849:                if (pipein) {
                    850:                        rd += i;
                    851:                        cnt -= i;
                    852:                        if (cnt > 0)
                    853:                                goto getmore;
                    854:                        i = rd;
                    855:                } else {
                    856:                        /*
                    857:                         * Short read. Process the blocks read.
                    858:                         */
                    859:                        if (i % TP_BSIZE != 0)
                    860:                                vprintf(stdout,
                    861:                                    "partial block read: %d should be %d\n",
                    862:                                    i, ntrec * TP_BSIZE);
                    863:                        numtrec = i / TP_BSIZE;
                    864:                }
                    865:        }
                    866:        /*
                    867:         * Handle read error.
                    868:         */
                    869:        if (i < 0) {
                    870:                fprintf(stderr, "Tape read error while ");
                    871:                switch (curfile.action) {
                    872:                default:
                    873:                        fprintf(stderr, "trying to set up tape\n");
                    874:                        break;
                    875:                case UNKNOWN:
                    876:                        fprintf(stderr, "trying to resynchronize\n");
                    877:                        break;
                    878:                case USING:
                    879:                        fprintf(stderr, "restoring %s\n", curfile.name);
                    880:                        break;
                    881:                case SKIP:
                    882:                        fprintf(stderr, "skipping over inode %d\n",
                    883:                                curfile.ino);
                    884:                        break;
                    885:                }
                    886:                if (!yflag && !reply("continue"))
                    887:                        done(1);
                    888:                i = ntrec * TP_BSIZE;
                    889:                bzero(tapebuf, i);
                    890: #ifdef RRESTORE
                    891:                if (host)
                    892:                        seek_failed = (rmtseek(i, 1) < 0);
                    893:                else
                    894: #endif
                    895:                        seek_failed = (lseek(mt, i, SEEK_CUR) == (off_t)-1);
                    896:
                    897:                if (seek_failed) {
                    898:                        fprintf(stderr,
                    899:                            "continuation failed: %s\n", strerror(errno));
                    900:                        done(1);
                    901:                }
                    902:        }
                    903:        /*
                    904:         * Handle end of tape.
                    905:         */
                    906:        if (i == 0) {
                    907:                vprintf(stdout, "End-of-tape encountered\n");
                    908:                if (!pipein) {
                    909:                        newvol = volno + 1;
                    910:                        volno = 0;
                    911:                        numtrec = 0;
                    912:                        getvol(newvol);
                    913:                        readtape(buf);
                    914:                        return;
                    915:                }
                    916:                if (rd % TP_BSIZE != 0)
                    917:                        panic("partial block read: %d should be %d\n",
                    918:                                rd, ntrec * TP_BSIZE);
                    919:                terminateinput();
                    920:                bcopy((char *)&endoftapemark, &tapebuf[rd], (long)TP_BSIZE);
                    921:        }
                    922:        blkcnt = 0;
                    923:        bcopy(&tapebuf[(blkcnt++ * TP_BSIZE)], buf, (long)TP_BSIZE);
                    924:        blksread++;
                    925:        tpblksread++;
                    926: }
                    927:
                    928: static void
                    929: findtapeblksize()
                    930: {
                    931:        register long i;
                    932:
                    933:        for (i = 0; i < ntrec; i++)
                    934:                ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0;
                    935:        blkcnt = 0;
                    936: #ifdef RRESTORE
                    937:        if (host)
                    938:                i = rmtread(tapebuf, ntrec * TP_BSIZE);
                    939:        else
                    940: #endif
                    941:                i = read(mt, tapebuf, ntrec * TP_BSIZE);
                    942:
                    943:        if (i <= 0) {
                    944:                fprintf(stderr, "tape read error: %s\n", strerror(errno));
                    945:                done(1);
                    946:        }
                    947:        if (i % TP_BSIZE != 0) {
                    948:                fprintf(stderr, "Tape block size (%d) %s (%d)\n",
                    949:                        i, "is not a multiple of dump block size", TP_BSIZE);
                    950:                done(1);
                    951:        }
                    952:        ntrec = i / TP_BSIZE;
                    953:        numtrec = ntrec;
                    954:        vprintf(stdout, "Tape block size is %d\n", ntrec);
                    955: }
                    956:
                    957: void
                    958: closemt()
                    959: {
                    960:
                    961:        if (mt < 0)
                    962:                return;
                    963: #ifdef RRESTORE
                    964:        if (host)
                    965:                rmtclose();
                    966:        else
                    967: #endif
                    968:                (void) close(mt);
                    969: }
                    970:
                    971: /*
                    972:  * Read the next block from the tape.
                    973:  * Check to see if it is one of several vintage headers.
                    974:  * If it is an old style header, convert it to a new style header.
                    975:  * If it is not any valid header, return an error.
                    976:  */
                    977: static int
                    978: gethead(buf)
                    979:        struct s_spcl *buf;
                    980: {
                    981:        long i;
                    982:        union {
                    983:                quad_t  qval;
                    984:                long    val[2];
                    985:        } qcvt;
                    986:        union u_ospcl {
                    987:                char dummy[TP_BSIZE];
                    988:                struct  s_ospcl {
                    989:                        long    c_type;
                    990:                        long    c_date;
                    991:                        long    c_ddate;
                    992:                        long    c_volume;
                    993:                        long    c_tapea;
                    994:                        u_short c_inumber;
                    995:                        long    c_magic;
                    996:                        long    c_checksum;
                    997:                        struct odinode {
                    998:                                unsigned short odi_mode;
                    999:                                u_short odi_nlink;
                   1000:                                u_short odi_uid;
                   1001:                                u_short odi_gid;
                   1002:                                long    odi_size;
                   1003:                                long    odi_rdev;
                   1004:                                char    odi_addr[36];
                   1005:                                long    odi_atime;
                   1006:                                long    odi_mtime;
                   1007:                                long    odi_ctime;
                   1008:                        } c_dinode;
                   1009:                        long    c_count;
                   1010:                        char    c_addr[256];
                   1011:                } s_ospcl;
                   1012:        } u_ospcl;
                   1013:
                   1014:        if (!cvtflag) {
                   1015:                readtape((char *)buf);
                   1016:                if (buf->c_magic != NFS_MAGIC) {
                   1017:                        if (swabl(buf->c_magic) != NFS_MAGIC)
                   1018:                                return (FAIL);
                   1019:                        if (!Bcvt) {
                   1020:                                vprintf(stdout, "Note: Doing Byte swapping\n");
                   1021:                                Bcvt = 1;
                   1022:                        }
                   1023:                }
                   1024:                if (checksum((int *)buf) == FAIL)
                   1025:                        return (FAIL);
                   1026:                if (Bcvt)
                   1027:                        swabst((u_char *)"8l4s31l", (u_char *)buf);
                   1028:                goto good;
                   1029:        }
                   1030:        readtape((char *)(&u_ospcl.s_ospcl));
                   1031:        bzero((char *)buf, (long)TP_BSIZE);
                   1032:        buf->c_type = u_ospcl.s_ospcl.c_type;
                   1033:        buf->c_date = u_ospcl.s_ospcl.c_date;
                   1034:        buf->c_ddate = u_ospcl.s_ospcl.c_ddate;
                   1035:        buf->c_volume = u_ospcl.s_ospcl.c_volume;
                   1036:        buf->c_tapea = u_ospcl.s_ospcl.c_tapea;
                   1037:        buf->c_inumber = u_ospcl.s_ospcl.c_inumber;
                   1038:        buf->c_checksum = u_ospcl.s_ospcl.c_checksum;
                   1039:        buf->c_magic = u_ospcl.s_ospcl.c_magic;
                   1040:        buf->c_dinode.di_mode = u_ospcl.s_ospcl.c_dinode.odi_mode;
                   1041:        buf->c_dinode.di_nlink = u_ospcl.s_ospcl.c_dinode.odi_nlink;
                   1042:        buf->c_dinode.di_uid = u_ospcl.s_ospcl.c_dinode.odi_uid;
                   1043:        buf->c_dinode.di_gid = u_ospcl.s_ospcl.c_dinode.odi_gid;
                   1044:        buf->c_dinode.di_size = u_ospcl.s_ospcl.c_dinode.odi_size;
                   1045:        buf->c_dinode.di_rdev = u_ospcl.s_ospcl.c_dinode.odi_rdev;
                   1046:        buf->c_dinode.di_atime.ts_sec = u_ospcl.s_ospcl.c_dinode.odi_atime;
                   1047:        buf->c_dinode.di_mtime.ts_sec = u_ospcl.s_ospcl.c_dinode.odi_mtime;
                   1048:        buf->c_dinode.di_ctime.ts_sec = u_ospcl.s_ospcl.c_dinode.odi_ctime;
                   1049:        buf->c_count = u_ospcl.s_ospcl.c_count;
                   1050:        bcopy(u_ospcl.s_ospcl.c_addr, buf->c_addr, (long)256);
                   1051:        if (u_ospcl.s_ospcl.c_magic != OFS_MAGIC ||
                   1052:            checksum((int *)(&u_ospcl.s_ospcl)) == FAIL)
                   1053:                return(FAIL);
                   1054:        buf->c_magic = NFS_MAGIC;
                   1055:
                   1056: good:
                   1057:        if ((buf->c_dinode.di_size == 0 || buf->c_dinode.di_size > 0xfffffff) &&
                   1058:            (buf->c_dinode.di_mode & IFMT) == IFDIR && Qcvt == 0) {
                   1059:                qcvt.qval = buf->c_dinode.di_size;
                   1060:                if (qcvt.val[0] || qcvt.val[1]) {
                   1061:                        printf("Note: Doing Quad swapping\n");
                   1062:                        Qcvt = 1;
                   1063:                }
                   1064:        }
                   1065:        if (Qcvt) {
                   1066:                qcvt.qval = buf->c_dinode.di_size;
                   1067:                i = qcvt.val[1];
                   1068:                qcvt.val[1] = qcvt.val[0];
                   1069:                qcvt.val[0] = i;
                   1070:                buf->c_dinode.di_size = qcvt.qval;
                   1071:        }
                   1072:
                   1073:        switch (buf->c_type) {
                   1074:
                   1075:        case TS_CLRI:
                   1076:        case TS_BITS:
                   1077:                /*
                   1078:                 * Have to patch up missing information in bit map headers
                   1079:                 */
                   1080:                buf->c_inumber = 0;
                   1081:                buf->c_dinode.di_size = buf->c_count * TP_BSIZE;
                   1082:                for (i = 0; i < buf->c_count; i++)
                   1083:                        buf->c_addr[i]++;
                   1084:                break;
                   1085:
                   1086:        case TS_TAPE:
                   1087:                if ((buf->c_flags & DR_NEWINODEFMT) == 0)
                   1088:                        oldinofmt = 1;
                   1089:                /* fall through */
                   1090:        case TS_END:
                   1091:                buf->c_inumber = 0;
                   1092:                break;
                   1093:
                   1094:        case TS_INODE:
                   1095:        case TS_ADDR:
                   1096:                break;
                   1097:
                   1098:        default:
                   1099:                panic("gethead: unknown inode type %d\n", buf->c_type);
                   1100:                break;
                   1101:        }
                   1102:        /*
                   1103:         * If we are restoring a filesystem with old format inodes,
                   1104:         * copy the uid/gid to the new location.
                   1105:         */
                   1106:        if (oldinofmt) {
                   1107:                buf->c_dinode.di_uid = buf->c_dinode.di_ouid;
                   1108:                buf->c_dinode.di_gid = buf->c_dinode.di_ogid;
                   1109:        }
                   1110:        if (dflag)
                   1111:                accthdr(buf);
                   1112:        return(GOOD);
                   1113: }
                   1114:
                   1115: /*
                   1116:  * Check that a header is where it belongs and predict the next header
                   1117:  */
                   1118: static void
                   1119: accthdr(header)
                   1120:        struct s_spcl *header;
                   1121: {
                   1122:        static ino_t previno = 0x7fffffff;
                   1123:        static int prevtype;
                   1124:        static long predict;
                   1125:        long blks, i;
                   1126:
                   1127:        if (header->c_type == TS_TAPE) {
                   1128:                fprintf(stderr, "Volume header (%s inode format) ",
                   1129:                    oldinofmt ? "old" : "new");
                   1130:                if (header->c_firstrec)
                   1131:                        fprintf(stderr, "begins with record %d",
                   1132:                                header->c_firstrec);
                   1133:                fprintf(stderr, "\n");
                   1134:                previno = 0x7fffffff;
                   1135:                return;
                   1136:        }
                   1137:        if (previno == 0x7fffffff)
                   1138:                goto newcalc;
                   1139:        switch (prevtype) {
                   1140:        case TS_BITS:
                   1141:                fprintf(stderr, "Dump mask header");
                   1142:                break;
                   1143:        case TS_CLRI:
                   1144:                fprintf(stderr, "Remove mask header");
                   1145:                break;
                   1146:        case TS_INODE:
                   1147:                fprintf(stderr, "File header, ino %d", previno);
                   1148:                break;
                   1149:        case TS_ADDR:
                   1150:                fprintf(stderr, "File continuation header, ino %d", previno);
                   1151:                break;
                   1152:        case TS_END:
                   1153:                fprintf(stderr, "End of tape header");
                   1154:                break;
                   1155:        }
                   1156:        if (predict != blksread - 1)
                   1157:                fprintf(stderr, "; predicted %d blocks, got %d blocks",
                   1158:                        predict, blksread - 1);
                   1159:        fprintf(stderr, "\n");
                   1160: newcalc:
                   1161:        blks = 0;
                   1162:        if (header->c_type != TS_END)
                   1163:                for (i = 0; i < header->c_count; i++)
                   1164:                        if (header->c_addr[i] != 0)
                   1165:                                blks++;
                   1166:        predict = blks;
                   1167:        blksread = 0;
                   1168:        prevtype = header->c_type;
                   1169:        previno = header->c_inumber;
                   1170: }
                   1171:
                   1172: /*
                   1173:  * Find an inode header.
                   1174:  * Complain if had to skip, and complain is set.
                   1175:  */
                   1176: static void
                   1177: findinode(header)
                   1178:        struct s_spcl *header;
                   1179: {
                   1180:        static long skipcnt = 0;
                   1181:        long i;
                   1182:        char buf[TP_BSIZE];
                   1183:
                   1184:        curfile.name = "<name unknown>";
                   1185:        curfile.action = UNKNOWN;
                   1186:        curfile.dip = NULL;
                   1187:        curfile.ino = 0;
                   1188:        do {
                   1189:                if (header->c_magic != NFS_MAGIC) {
                   1190:                        skipcnt++;
                   1191:                        while (gethead(header) == FAIL ||
                   1192:                            header->c_date != dumpdate)
                   1193:                                skipcnt++;
                   1194:                }
                   1195:                switch (header->c_type) {
                   1196:
                   1197:                case TS_ADDR:
                   1198:                        /*
                   1199:                         * Skip up to the beginning of the next record
                   1200:                         */
                   1201:                        for (i = 0; i < header->c_count; i++)
                   1202:                                if (header->c_addr[i])
                   1203:                                        readtape(buf);
                   1204:                        while (gethead(header) == FAIL ||
                   1205:                            header->c_date != dumpdate)
                   1206:                                skipcnt++;
                   1207:                        break;
                   1208:
                   1209:                case TS_INODE:
                   1210:                        curfile.dip = &header->c_dinode;
                   1211:                        curfile.ino = header->c_inumber;
                   1212:                        break;
                   1213:
                   1214:                case TS_END:
                   1215:                        curfile.ino = maxino;
                   1216:                        break;
                   1217:
                   1218:                case TS_CLRI:
                   1219:                        curfile.name = "<file removal list>";
                   1220:                        break;
                   1221:
                   1222:                case TS_BITS:
                   1223:                        curfile.name = "<file dump list>";
                   1224:                        break;
                   1225:
                   1226:                case TS_TAPE:
                   1227:                        panic("unexpected tape header\n");
                   1228:                        /* NOTREACHED */
                   1229:
                   1230:                default:
                   1231:                        panic("unknown tape header type %d\n", spcl.c_type);
                   1232:                        /* NOTREACHED */
                   1233:
                   1234:                }
                   1235:        } while (header->c_type == TS_ADDR);
                   1236:        if (skipcnt > 0)
                   1237:                fprintf(stderr, "resync restore, skipped %d blocks\n", skipcnt);
                   1238:        skipcnt = 0;
                   1239: }
                   1240:
                   1241: static int
                   1242: checksum(buf)
                   1243:        register int *buf;
                   1244: {
                   1245:        register int i, j;
                   1246:
                   1247:        j = sizeof(union u_spcl) / sizeof(int);
                   1248:        i = 0;
                   1249:        if(!Bcvt) {
                   1250:                do
                   1251:                        i += *buf++;
                   1252:                while (--j);
                   1253:        } else {
                   1254:                /* What happens if we want to read restore tapes
                   1255:                        for a 16bit int machine??? */
                   1256:                do
                   1257:                        i += swabl(*buf++);
                   1258:                while (--j);
                   1259:        }
                   1260:
                   1261:        if (i != CHECKSUM) {
                   1262:                fprintf(stderr, "Checksum error %o, inode %d file %s\n", i,
                   1263:                        curfile.ino, curfile.name);
                   1264:                return(FAIL);
                   1265:        }
                   1266:        return(GOOD);
                   1267: }
                   1268:
                   1269: #ifdef RRESTORE
                   1270: #if __STDC__
                   1271: #include <stdarg.h>
                   1272: #else
                   1273: #include <varargs.h>
                   1274: #endif
                   1275:
                   1276: void
                   1277: #if __STDC__
                   1278: msg(const char *fmt, ...)
                   1279: #else
                   1280: msg(fmt, va_alist)
                   1281:        char *fmt;
                   1282:        va_dcl
                   1283: #endif
                   1284: {
                   1285:        va_list ap;
                   1286: #if __STDC__
                   1287:        va_start(ap, fmt);
                   1288: #else
                   1289:        va_start(ap);
                   1290: #endif
                   1291:        (void)vfprintf(stderr, fmt, ap);
                   1292:        va_end(ap);
                   1293: }
                   1294: #endif /* RRESTORE */
                   1295:
                   1296: static u_char *
                   1297: swabshort(sp, n)
                   1298:        register u_char *sp;
                   1299:        register int n;
                   1300: {
                   1301:        char c;
                   1302:
                   1303:        while (--n >= 0) {
                   1304:                c = sp[0]; sp[0] = sp[1]; sp[1] = c;
                   1305:                sp += 2;
                   1306:        }
                   1307:        return (sp);
                   1308: }
                   1309:
                   1310: static u_char *
                   1311: swablong(sp, n)
                   1312:        register u_char *sp;
                   1313:        register int n;
                   1314: {
                   1315:        char c;
                   1316:
                   1317:        while (--n >= 0) {
                   1318:                c = sp[0]; sp[0] = sp[3]; sp[3] = c;
                   1319:                c = sp[2]; sp[2] = sp[1]; sp[1] = c;
                   1320:                sp += 4;
                   1321:        }
                   1322:        return (sp);
                   1323: }
                   1324:
                   1325: void
                   1326: swabst(cp, sp)
                   1327:        register u_char *cp, *sp;
                   1328: {
                   1329:        int n = 0;
                   1330:
                   1331:        while (*cp) {
                   1332:                switch (*cp) {
                   1333:                case '0': case '1': case '2': case '3': case '4':
                   1334:                case '5': case '6': case '7': case '8': case '9':
                   1335:                        n = (n * 10) + (*cp++ - '0');
                   1336:                        continue;
                   1337:
                   1338:                case 's': case 'w': case 'h':
                   1339:                        if (n == 0)
                   1340:                                n = 1;
                   1341:                        sp = swabshort(sp, n);
                   1342:                        break;
                   1343:
                   1344:                case 'l':
                   1345:                        if (n == 0)
                   1346:                                n = 1;
                   1347:                        sp = swablong(sp, n);
                   1348:                        break;
                   1349:
                   1350:                default: /* Any other character, like 'b' counts as byte. */
                   1351:                        if (n == 0)
                   1352:                                n = 1;
                   1353:                        sp += n;
                   1354:                        break;
                   1355:                }
                   1356:                cp++;
                   1357:                n = 0;
                   1358:        }
                   1359: }
                   1360:
                   1361: static u_long
                   1362: swabl(x)
                   1363:        u_long x;
                   1364: {
                   1365:        swabst((u_char *)"l", (u_char *)&x);
                   1366:        return (x);
                   1367: }

CVSweb <webmaster@jp.NetBSD.org>