Annotation of 43BSDReno/sbin/restore/restore.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1983 The Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms are permitted
                      6:  * provided that: (1) source distributions retain this entire copyright
                      7:  * notice and comment, and (2) distributions including binaries display
                      8:  * the following acknowledgement:  ``This product includes software
                      9:  * developed by the University of California, Berkeley and its contributors''
                     10:  * in the documentation or other materials provided with the distribution
                     11:  * and in all advertising materials mentioning features or use of this
                     12:  * software. Neither the name of the University nor the names of its
                     13:  * contributors may be used to endorse or promote products derived
                     14:  * from this software without specific prior written permission.
                     15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     16:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     18:  */
                     19: 
                     20: #ifndef lint
                     21: static char sccsid[] = "@(#)restore.c  5.7 (Berkeley) 6/1/90";
                     22: #endif /* not lint */
                     23: 
                     24: #include "restore.h"
                     25: 
                     26: /*
                     27:  * This implements the 't' option.
                     28:  * List entries on the tape.
                     29:  */
                     30: long
                     31: listfile(name, ino, type)
                     32:        char *name;
                     33:        ino_t ino;
                     34:        int type;
                     35: {
                     36:        long descend = hflag ? GOOD : FAIL;
                     37: 
                     38:        if (BIT(ino, dumpmap) == 0) {
                     39:                return (descend);
                     40:        }
                     41:        vprintf(stdout, "%s", type == LEAF ? "leaf" : "dir ");
                     42:        fprintf(stdout, "%10d\t%s\n", ino, name);
                     43:        return (descend);
                     44: }
                     45: 
                     46: /*
                     47:  * This implements the 'x' option.
                     48:  * Request that new entries be extracted.
                     49:  */
                     50: long
                     51: addfile(name, ino, type)
                     52:        char *name;
                     53:        ino_t ino;
                     54:        int type;
                     55: {
                     56:        register struct entry *ep;
                     57:        long descend = hflag ? GOOD : FAIL;
                     58:        char buf[100];
                     59: 
                     60:        if (BIT(ino, dumpmap) == 0) {
                     61:                dprintf(stdout, "%s: not on the tape\n", name);
                     62:                return (descend);
                     63:        }
                     64:        if (!mflag) {
                     65:                (void) sprintf(buf, "./%u", ino);
                     66:                name = buf;
                     67:                if (type == NODE) {
                     68:                        (void) genliteraldir(name, ino);
                     69:                        return (descend);
                     70:                }
                     71:        }
                     72:        ep = lookupino(ino);
                     73:        if (ep != NIL) {
                     74:                if (strcmp(name, myname(ep)) == 0) {
                     75:                        ep->e_flags |= NEW;
                     76:                        return (descend);
                     77:                }
                     78:                type |= LINK;
                     79:        }
                     80:        ep = addentry(name, ino, type);
                     81:        if (type == NODE)
                     82:                newnode(ep);
                     83:        ep->e_flags |= NEW;
                     84:        return (descend);
                     85: }
                     86: 
                     87: /*
                     88:  * This is used by the 'i' option to undo previous requests made by addfile.
                     89:  * Delete entries from the request queue.
                     90:  */
                     91: /* ARGSUSED */
                     92: long
                     93: deletefile(name, ino, type)
                     94:        char *name;
                     95:        ino_t ino;
                     96:        int type;
                     97: {
                     98:        long descend = hflag ? GOOD : FAIL;
                     99:        struct entry *ep;
                    100: 
                    101:        if (BIT(ino, dumpmap) == 0) {
                    102:                return (descend);
                    103:        }
                    104:        ep = lookupino(ino);
                    105:        if (ep != NIL)
                    106:                ep->e_flags &= ~NEW;
                    107:        return (descend);
                    108: }
                    109: 
                    110: /* 
                    111:  * The following four routines implement the incremental
                    112:  * restore algorithm. The first removes old entries, the second
                    113:  * does renames and calculates the extraction list, the third
                    114:  * cleans up link names missed by the first two, and the final
                    115:  * one deletes old directories.
                    116:  *
                    117:  * Directories cannot be immediately deleted, as they may have
                    118:  * other files in them which need to be moved out first. As
                    119:  * directories to be deleted are found, they are put on the 
                    120:  * following deletion list. After all deletions and renames
                    121:  * are done, this list is actually deleted.
                    122:  */
                    123: static struct entry *removelist;
                    124: 
                    125: /*
                    126:  *     Remove unneeded leaves from the old tree.
                    127:  *     Remove directories from the lookup chains.
                    128:  */
                    129: removeoldleaves()
                    130: {
                    131:        register struct entry *ep;
                    132:        register ino_t i;
                    133: 
                    134:        vprintf(stdout, "Mark entries to be removed.\n");
                    135:        for (i = ROOTINO + 1; i < maxino; i++) {
                    136:                ep = lookupino(i);
                    137:                if (ep == NIL)
                    138:                        continue;
                    139:                if (BIT(i, clrimap))
                    140:                        continue;
                    141:                for ( ; ep != NIL; ep = ep->e_links) {
                    142:                        dprintf(stdout, "%s: REMOVE\n", myname(ep));
                    143:                        if (ep->e_type == LEAF) {
                    144:                                removeleaf(ep);
                    145:                                freeentry(ep);
                    146:                        } else {
                    147:                                mktempname(ep);
                    148:                                deleteino(ep->e_ino);
                    149:                                ep->e_next = removelist;
                    150:                                removelist = ep;
                    151:                        }
                    152:                }
                    153:        }
                    154: }
                    155: 
                    156: /*
                    157:  *     For each directory entry on the incremental tape, determine which
                    158:  *     category it falls into as follows:
                    159:  *     KEEP - entries that are to be left alone.
                    160:  *     NEW - new entries to be added.
                    161:  *     EXTRACT - files that must be updated with new contents.
                    162:  *     LINK - new links to be added.
                    163:  *     Renames are done at the same time.
                    164:  */
                    165: long
                    166: nodeupdates(name, ino, type)
                    167:        char *name;
                    168:        ino_t ino;
                    169:        int type;
                    170: {
                    171:        register struct entry *ep, *np, *ip;
                    172:        long descend = GOOD;
                    173:        int lookuptype = 0;
                    174:        int key = 0;
                    175:                /* key values */
                    176: #              define ONTAPE   0x1     /* inode is on the tape */
                    177: #              define INOFND   0x2     /* inode already exists */
                    178: #              define NAMEFND  0x4     /* name already exists */
                    179: #              define MODECHG  0x8     /* mode of inode changed */
                    180:        extern char *keyval();
                    181: 
                    182:        /*
                    183:         * This routine is called once for each element in the 
                    184:         * directory hierarchy, with a full path name.
                    185:         * The "type" value is incorrectly specified as LEAF for
                    186:         * directories that are not on the dump tape.
                    187:         *
                    188:         * Check to see if the file is on the tape.
                    189:         */
                    190:        if (BIT(ino, dumpmap))
                    191:                key |= ONTAPE;
                    192:        /*
                    193:         * Check to see if the name exists, and if the name is a link.
                    194:         */
                    195:        np = lookupname(name);
                    196:        if (np != NIL) {
                    197:                key |= NAMEFND;
                    198:                ip = lookupino(np->e_ino);
                    199:                if (ip == NULL)
                    200:                        panic("corrupted symbol table\n");
                    201:                if (ip != np)
                    202:                        lookuptype = LINK;
                    203:        }
                    204:        /*
                    205:         * Check to see if the inode exists, and if one of its links
                    206:         * corresponds to the name (if one was found).
                    207:         */
                    208:        ip = lookupino(ino);
                    209:        if (ip != NIL) {
                    210:                key |= INOFND;
                    211:                for (ep = ip->e_links; ep != NIL; ep = ep->e_links) {
                    212:                        if (ep == np) {
                    213:                                ip = ep;
                    214:                                break;
                    215:                        }
                    216:                }
                    217:        }
                    218:        /*
                    219:         * If both a name and an inode are found, but they do not
                    220:         * correspond to the same file, then both the inode that has
                    221:         * been found and the inode corresponding to the name that
                    222:         * has been found need to be renamed. The current pathname
                    223:         * is the new name for the inode that has been found. Since
                    224:         * all files to be deleted have already been removed, the
                    225:         * named file is either a now unneeded link, or it must live
                    226:         * under a new name in this dump level. If it is a link, it
                    227:         * can be removed. If it is not a link, it is given a
                    228:         * temporary name in anticipation that it will be renamed
                    229:         * when it is later found by inode number.
                    230:         */
                    231:        if (((key & (INOFND|NAMEFND)) == (INOFND|NAMEFND)) && ip != np) {
                    232:                if (lookuptype == LINK) {
                    233:                        removeleaf(np);
                    234:                        freeentry(np);
                    235:                } else {
                    236:                        dprintf(stdout, "name/inode conflict, mktempname %s\n",
                    237:                                myname(np));
                    238:                        mktempname(np);
                    239:                }
                    240:                np = NIL;
                    241:                key &= ~NAMEFND;
                    242:        }
                    243:        if ((key & ONTAPE) &&
                    244:          (((key & INOFND) && ip->e_type != type) ||
                    245:           ((key & NAMEFND) && np->e_type != type)))
                    246:                key |= MODECHG;
                    247: 
                    248:        /*
                    249:         * Decide on the disposition of the file based on its flags.
                    250:         * Note that we have already handled the case in which
                    251:         * a name and inode are found that correspond to different files.
                    252:         * Thus if both NAMEFND and INOFND are set then ip == np.
                    253:         */
                    254:        switch (key) {
                    255: 
                    256:        /*
                    257:         * A previously existing file has been found.
                    258:         * Mark it as KEEP so that other links to the inode can be
                    259:         * detected, and so that it will not be reclaimed by the search
                    260:         * for unreferenced names.
                    261:         */
                    262:        case INOFND|NAMEFND:
                    263:                ip->e_flags |= KEEP;
                    264:                dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
                    265:                        flagvalues(ip));
                    266:                break;
                    267: 
                    268:        /*
                    269:         * A file on the tape has a name which is the same as a name
                    270:         * corresponding to a different file in the previous dump.
                    271:         * Since all files to be deleted have already been removed,
                    272:         * this file is either a now unneeded link, or it must live
                    273:         * under a new name in this dump level. If it is a link, it
                    274:         * can simply be removed. If it is not a link, it is given a
                    275:         * temporary name in anticipation that it will be renamed
                    276:         * when it is later found by inode number (see INOFND case
                    277:         * below). The entry is then treated as a new file.
                    278:         */
                    279:        case ONTAPE|NAMEFND:
                    280:        case ONTAPE|NAMEFND|MODECHG:
                    281:                if (lookuptype == LINK) {
                    282:                        removeleaf(np);
                    283:                        freeentry(np);
                    284:                } else {
                    285:                        mktempname(np);
                    286:                }
                    287:                /* fall through */
                    288: 
                    289:        /*
                    290:         * A previously non-existent file.
                    291:         * Add it to the file system, and request its extraction.
                    292:         * If it is a directory, create it immediately.
                    293:         * (Since the name is unused there can be no conflict)
                    294:         */
                    295:        case ONTAPE:
                    296:                ep = addentry(name, ino, type);
                    297:                if (type == NODE)
                    298:                        newnode(ep);
                    299:                ep->e_flags |= NEW|KEEP;
                    300:                dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
                    301:                        flagvalues(ep));
                    302:                break;
                    303: 
                    304:        /*
                    305:         * A file with the same inode number, but a different
                    306:         * name has been found. If the other name has not already
                    307:         * been found (indicated by the KEEP flag, see above) then
                    308:         * this must be a new name for the file, and it is renamed.
                    309:         * If the other name has been found then this must be a
                    310:         * link to the file. Hard links to directories are not
                    311:         * permitted, and are either deleted or converted to
                    312:         * symbolic links. Finally, if the file is on the tape,
                    313:         * a request is made to extract it.
                    314:         */
                    315:        case ONTAPE|INOFND:
                    316:                if (type == LEAF && (ip->e_flags & KEEP) == 0)
                    317:                        ip->e_flags |= EXTRACT;
                    318:                /* fall through */
                    319:        case INOFND:
                    320:                if ((ip->e_flags & KEEP) == 0) {
                    321:                        renameit(myname(ip), name);
                    322:                        moveentry(ip, name);
                    323:                        ip->e_flags |= KEEP;
                    324:                        dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
                    325:                                flagvalues(ip));
                    326:                        break;
                    327:                }
                    328:                if (ip->e_type == NODE) {
                    329:                        descend = FAIL;
                    330:                        fprintf(stderr,
                    331:                                "deleted hard link %s to directory %s\n",
                    332:                                name, myname(ip));
                    333:                        break;
                    334:                }
                    335:                ep = addentry(name, ino, type|LINK);
                    336:                ep->e_flags |= NEW;
                    337:                dprintf(stdout, "[%s] %s: %s|LINK\n", keyval(key), name,
                    338:                        flagvalues(ep));
                    339:                break;
                    340: 
                    341:        /*
                    342:         * A previously known file which is to be updated.
                    343:         */
                    344:        case ONTAPE|INOFND|NAMEFND:
                    345:                if (type == LEAF && lookuptype != LINK)
                    346:                        np->e_flags |= EXTRACT;
                    347:                np->e_flags |= KEEP;
                    348:                dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
                    349:                        flagvalues(np));
                    350:                break;
                    351: 
                    352:        /*
                    353:         * An inode is being reused in a completely different way.
                    354:         * Normally an extract can simply do an "unlink" followed
                    355:         * by a "creat". Here we must do effectively the same
                    356:         * thing. The complications arise because we cannot really
                    357:         * delete a directory since it may still contain files
                    358:         * that we need to rename, so we delete it from the symbol
                    359:         * table, and put it on the list to be deleted eventually.
                    360:         * Conversely if a directory is to be created, it must be
                    361:         * done immediately, rather than waiting until the 
                    362:         * extraction phase.
                    363:         */
                    364:        case ONTAPE|INOFND|MODECHG:
                    365:        case ONTAPE|INOFND|NAMEFND|MODECHG:
                    366:                if (ip->e_flags & KEEP) {
                    367:                        badentry(ip, "cannot KEEP and change modes");
                    368:                        break;
                    369:                }
                    370:                if (ip->e_type == LEAF) {
                    371:                        /* changing from leaf to node */
                    372:                        removeleaf(ip);
                    373:                        freeentry(ip);
                    374:                        ip = addentry(name, ino, type);
                    375:                        newnode(ip);
                    376:                } else {
                    377:                        /* changing from node to leaf */
                    378:                        if ((ip->e_flags & TMPNAME) == 0)
                    379:                                mktempname(ip);
                    380:                        deleteino(ip->e_ino);
                    381:                        ip->e_next = removelist;
                    382:                        removelist = ip;
                    383:                        ip = addentry(name, ino, type);
                    384:                }
                    385:                ip->e_flags |= NEW|KEEP;
                    386:                dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
                    387:                        flagvalues(ip));
                    388:                break;
                    389: 
                    390:        /*
                    391:         * A hard link to a diirectory that has been removed.
                    392:         * Ignore it.
                    393:         */
                    394:        case NAMEFND:
                    395:                dprintf(stdout, "[%s] %s: Extraneous name\n", keyval(key),
                    396:                        name);
                    397:                descend = FAIL;
                    398:                break;
                    399: 
                    400:        /*
                    401:         * If we find a directory entry for a file that is not on
                    402:         * the tape, then we must have found a file that was created
                    403:         * while the dump was in progress. Since we have no contents
                    404:         * for it, we discard the name knowing that it will be on the
                    405:         * next incremental tape.
                    406:         */
                    407:        case NIL:
                    408:                fprintf(stderr, "%s: (inode %d) not found on tape\n",
                    409:                        name, ino);
                    410:                break;
                    411: 
                    412:        /*
                    413:         * If any of these arise, something is grievously wrong with
                    414:         * the current state of the symbol table.
                    415:         */
                    416:        case INOFND|NAMEFND|MODECHG:
                    417:        case NAMEFND|MODECHG:
                    418:        case INOFND|MODECHG:
                    419:                fprintf(stderr, "[%s] %s: inconsistent state\n", keyval(key),
                    420:                        name);
                    421:                break;
                    422: 
                    423:        /*
                    424:         * These states "cannot" arise for any state of the symbol table.
                    425:         */
                    426:        case ONTAPE|MODECHG:
                    427:        case MODECHG:
                    428:        default:
                    429:                panic("[%s] %s: impossible state\n", keyval(key), name);
                    430:                break;
                    431:        }       
                    432:        return (descend);
                    433: }
                    434: 
                    435: /*
                    436:  * Calculate the active flags in a key.
                    437:  */
                    438: char *
                    439: keyval(key)
                    440:        int key;
                    441: {
                    442:        static char keybuf[32];
                    443: 
                    444:        (void) strcpy(keybuf, "|NIL");
                    445:        keybuf[0] = '\0';
                    446:        if (key & ONTAPE)
                    447:                (void) strcat(keybuf, "|ONTAPE");
                    448:        if (key & INOFND)
                    449:                (void) strcat(keybuf, "|INOFND");
                    450:        if (key & NAMEFND)
                    451:                (void) strcat(keybuf, "|NAMEFND");
                    452:        if (key & MODECHG)
                    453:                (void) strcat(keybuf, "|MODECHG");
                    454:        return (&keybuf[1]);
                    455: }
                    456: 
                    457: /*
                    458:  * Find unreferenced link names.
                    459:  */
                    460: findunreflinks()
                    461: {
                    462:        register struct entry *ep, *np;
                    463:        register ino_t i;
                    464: 
                    465:        vprintf(stdout, "Find unreferenced names.\n");
                    466:        for (i = ROOTINO; i < maxino; i++) {
                    467:                ep = lookupino(i);
                    468:                if (ep == NIL || ep->e_type == LEAF || BIT(i, dumpmap) == 0)
                    469:                        continue;
                    470:                for (np = ep->e_entries; np != NIL; np = np->e_sibling) {
                    471:                        if (np->e_flags == 0) {
                    472:                                dprintf(stdout,
                    473:                                    "%s: remove unreferenced name\n",
                    474:                                    myname(np));
                    475:                                removeleaf(np);
                    476:                                freeentry(np);
                    477:                        }
                    478:                }
                    479:        }
                    480:        /*
                    481:         * Any leaves remaining in removed directories is unreferenced.
                    482:         */
                    483:        for (ep = removelist; ep != NIL; ep = ep->e_next) {
                    484:                for (np = ep->e_entries; np != NIL; np = np->e_sibling) {
                    485:                        if (np->e_type == LEAF) {
                    486:                                if (np->e_flags != 0)
                    487:                                        badentry(np, "unreferenced with flags");
                    488:                                dprintf(stdout,
                    489:                                    "%s: remove unreferenced name\n",
                    490:                                    myname(np));
                    491:                                removeleaf(np);
                    492:                                freeentry(np);
                    493:                        }
                    494:                }
                    495:        }
                    496: }
                    497: 
                    498: /*
                    499:  * Remove old nodes (directories).
                    500:  * Note that this routine runs in O(N*D) where:
                    501:  *     N is the number of directory entries to be removed.
                    502:  *     D is the maximum depth of the tree.
                    503:  * If N == D this can be quite slow. If the list were
                    504:  * topologically sorted, the deletion could be done in
                    505:  * time O(N).
                    506:  */
                    507: removeoldnodes()
                    508: {
                    509:        register struct entry *ep, **prev;
                    510:        long change;
                    511: 
                    512:        vprintf(stdout, "Remove old nodes (directories).\n");
                    513:        do      {
                    514:                change = 0;
                    515:                prev = &removelist;
                    516:                for (ep = removelist; ep != NIL; ep = *prev) {
                    517:                        if (ep->e_entries != NIL) {
                    518:                                prev = &ep->e_next;
                    519:                                continue;
                    520:                        }
                    521:                        *prev = ep->e_next;
                    522:                        removenode(ep);
                    523:                        freeentry(ep);
                    524:                        change++;
                    525:                }
                    526:        } while (change);
                    527:        for (ep = removelist; ep != NIL; ep = ep->e_next)
                    528:                badentry(ep, "cannot remove, non-empty");
                    529: }
                    530: 
                    531: /*
                    532:  * This is the routine used to extract files for the 'r' command.
                    533:  * Extract new leaves.
                    534:  */
                    535: createleaves(symtabfile)
                    536:        char *symtabfile;
                    537: {
                    538:        register struct entry *ep;
                    539:        ino_t first;
                    540:        long curvol;
                    541: 
                    542:        if (command == 'R') {
                    543:                vprintf(stdout, "Continue extraction of new leaves\n");
                    544:        } else {
                    545:                vprintf(stdout, "Extract new leaves.\n");
                    546:                dumpsymtable(symtabfile, volno);
                    547:        }
                    548:        first = lowerbnd(ROOTINO);
                    549:        curvol = volno;
                    550:        while (curfile.ino < maxino) {
                    551:                first = lowerbnd(first);
                    552:                /*
                    553:                 * If the next available file is not the one which we
                    554:                 * expect then we have missed one or more files. Since
                    555:                 * we do not request files that were not on the tape,
                    556:                 * the lost files must have been due to a tape read error,
                    557:                 * or a file that was removed while the dump was in progress.
                    558:                 */
                    559:                while (first < curfile.ino) {
                    560:                        ep = lookupino(first);
                    561:                        if (ep == NIL)
                    562:                                panic("%d: bad first\n", first);
                    563:                        fprintf(stderr, "%s: not found on tape\n", myname(ep));
                    564:                        ep->e_flags &= ~(NEW|EXTRACT);
                    565:                        first = lowerbnd(first);
                    566:                }
                    567:                /*
                    568:                 * If we find files on the tape that have no corresponding
                    569:                 * directory entries, then we must have found a file that
                    570:                 * was created while the dump was in progress. Since we have 
                    571:                 * no name for it, we discard it knowing that it will be
                    572:                 * on the next incremental tape.
                    573:                 */
                    574:                if (first != curfile.ino) {
                    575:                        fprintf(stderr, "expected next file %d, got %d\n",
                    576:                                first, curfile.ino);
                    577:                        skipfile();
                    578:                        goto next;
                    579:                }
                    580:                ep = lookupino(curfile.ino);
                    581:                if (ep == NIL)
                    582:                        panic("unknown file on tape\n");
                    583:                if ((ep->e_flags & (NEW|EXTRACT)) == 0)
                    584:                        badentry(ep, "unexpected file on tape");
                    585:                /*
                    586:                 * If the file is to be extracted, then the old file must
                    587:                 * be removed since its type may change from one leaf type
                    588:                 * to another (eg "file" to "character special").
                    589:                 */
                    590:                if ((ep->e_flags & EXTRACT) != 0) {
                    591:                        removeleaf(ep);
                    592:                        ep->e_flags &= ~REMOVED;
                    593:                }
                    594:                (void) extractfile(myname(ep));
                    595:                ep->e_flags &= ~(NEW|EXTRACT);
                    596:                /*
                    597:                 * We checkpoint the restore after every tape reel, so
                    598:                 * as to simplify the amount of work re quired by the
                    599:                 * 'R' command.
                    600:                 */
                    601:        next:
                    602:                if (curvol != volno) {
                    603:                        dumpsymtable(symtabfile, volno);
                    604:                        skipmaps();
                    605:                        curvol = volno;
                    606:                }
                    607:        }
                    608: }
                    609: 
                    610: /*
                    611:  * This is the routine used to extract files for the 'x' and 'i' commands.
                    612:  * Efficiently extract a subset of the files on a tape.
                    613:  */
                    614: createfiles()
                    615: {
                    616:        register ino_t first, next, last;
                    617:        register struct entry *ep;
                    618:        long curvol;
                    619: 
                    620:        vprintf(stdout, "Extract requested files\n");
                    621:        curfile.action = SKIP;
                    622:        getvol((long)1);
                    623:        skipmaps();
                    624:        skipdirs();
                    625:        first = lowerbnd(ROOTINO);
                    626:        last = upperbnd(maxino - 1);
                    627:        for (;;) {
                    628:                first = lowerbnd(first);
                    629:                last = upperbnd(last);
                    630:                /*
                    631:                 * Check to see if any files remain to be extracted
                    632:                 */
                    633:                if (first > last)
                    634:                        return;
                    635:                /*
                    636:                 * Reject any volumes with inodes greater
                    637:                 * than the last one needed
                    638:                 */
                    639:                while (curfile.ino > last) {
                    640:                        curfile.action = SKIP;
                    641:                        getvol((long)0);
                    642:                        skipmaps();
                    643:                        skipdirs();
                    644:                }
                    645:                /*
                    646:                 * Decide on the next inode needed.
                    647:                 * Skip across the inodes until it is found
                    648:                 * or an out of order volume change is encountered
                    649:                 */
                    650:                next = lowerbnd(curfile.ino);
                    651:                do      {
                    652:                        curvol = volno;
                    653:                        while (next > curfile.ino && volno == curvol)
                    654:                                skipfile();
                    655:                        skipmaps();
                    656:                        skipdirs();
                    657:                } while (volno == curvol + 1);
                    658:                /*
                    659:                 * If volume change out of order occurred the
                    660:                 * current state must be recalculated
                    661:                 */
                    662:                if (volno != curvol)
                    663:                        continue;
                    664:                /*
                    665:                 * If the current inode is greater than the one we were
                    666:                 * looking for then we missed the one we were looking for.
                    667:                 * Since we only attempt to extract files listed in the
                    668:                 * dump map, the lost files must have been due to a tape
                    669:                 * read error, or a file that was removed while the dump
                    670:                 * was in progress. Thus we report all requested files
                    671:                 * between the one we were looking for, and the one we
                    672:                 * found as missing, and delete their request flags.
                    673:                 */
                    674:                while (next < curfile.ino) {
                    675:                        ep = lookupino(next);
                    676:                        if (ep == NIL)
                    677:                                panic("corrupted symbol table\n");
                    678:                        fprintf(stderr, "%s: not found on tape\n", myname(ep));
                    679:                        ep->e_flags &= ~NEW;
                    680:                        next = lowerbnd(next);
                    681:                }
                    682:                /*
                    683:                 * The current inode is the one that we are looking for,
                    684:                 * so extract it per its requested name.
                    685:                 */
                    686:                if (next == curfile.ino && next <= last) {
                    687:                        ep = lookupino(next);
                    688:                        if (ep == NIL)
                    689:                                panic("corrupted symbol table\n");
                    690:                        (void) extractfile(myname(ep));
                    691:                        ep->e_flags &= ~NEW;
                    692:                        if (volno != curvol)
                    693:                                skipmaps();
                    694:                }
                    695:        }
                    696: }
                    697: 
                    698: /*
                    699:  * Add links.
                    700:  */
                    701: createlinks()
                    702: {
                    703:        register struct entry *np, *ep;
                    704:        register ino_t i;
                    705:        char name[BUFSIZ];
                    706: 
                    707:        vprintf(stdout, "Add links\n");
                    708:        for (i = ROOTINO; i < maxino; i++) {
                    709:                ep = lookupino(i);
                    710:                if (ep == NIL)
                    711:                        continue;
                    712:                for (np = ep->e_links; np != NIL; np = np->e_links) {
                    713:                        if ((np->e_flags & NEW) == 0)
                    714:                                continue;
                    715:                        (void) strcpy(name, myname(ep));
                    716:                        if (ep->e_type == NODE) {
                    717:                                (void) linkit(name, myname(np), SYMLINK);
                    718:                        } else {
                    719:                                (void) linkit(name, myname(np), HARDLINK);
                    720:                        }
                    721:                        np->e_flags &= ~NEW;
                    722:                }
                    723:        }
                    724: }
                    725: 
                    726: /*
                    727:  * Check the symbol table.
                    728:  * We do this to insure that all the requested work was done, and
                    729:  * that no temporary names remain.
                    730:  */
                    731: checkrestore()
                    732: {
                    733:        register struct entry *ep;
                    734:        register ino_t i;
                    735: 
                    736:        vprintf(stdout, "Check the symbol table.\n");
                    737:        for (i = ROOTINO; i < maxino; i++) {
                    738:                for (ep = lookupino(i); ep != NIL; ep = ep->e_links) {
                    739:                        ep->e_flags &= ~KEEP;
                    740:                        if (ep->e_type == NODE)
                    741:                                ep->e_flags &= ~(NEW|EXISTED);
                    742:                        if (ep->e_flags != NULL)
                    743:                                badentry(ep, "incomplete operations");
                    744:                }
                    745:        }
                    746: }
                    747: 
                    748: /*
                    749:  * Compare with the directory structure on the tape
                    750:  * A paranoid check that things are as they should be.
                    751:  */
                    752: long
                    753: verifyfile(name, ino, type)
                    754:        char *name;
                    755:        ino_t ino;
                    756:        int type;
                    757: {
                    758:        struct entry *np, *ep;
                    759:        long descend = GOOD;
                    760: 
                    761:        ep = lookupname(name);
                    762:        if (ep == NIL) {
                    763:                fprintf(stderr, "Warning: missing name %s\n", name);
                    764:                return (FAIL);
                    765:        }
                    766:        np = lookupino(ino);
                    767:        if (np != ep)
                    768:                descend = FAIL;
                    769:        for ( ; np != NIL; np = np->e_links)
                    770:                if (np == ep)
                    771:                        break;
                    772:        if (np == NIL)
                    773:                panic("missing inumber %d\n", ino);
                    774:        if (ep->e_type == LEAF && type != LEAF)
                    775:                badentry(ep, "type should be LEAF");
                    776:        return (descend);
                    777: }

unix.superglobalmegacorp.com

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