Annotation of 42BSD/etc/restore/utilities.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char sccsid[] = "@(#)utilities.c        3.15    (Berkeley)      83/08/11";
                      3: #endif
                      4: 
                      5: /* Copyright (c) 1983 Regents of the University of California */
                      6: 
                      7: #include "restore.h"
                      8: 
                      9: char *copynext();
                     10: 
                     11: /*
                     12:  * Insure that all the components of a pathname exist.
                     13:  */
                     14: pathcheck(name)
                     15:        char *name;
                     16: {
                     17:        register char *cp;
                     18:        struct entry *ep;
                     19:        char *start;
                     20: 
                     21:        start = index(name, '/');
                     22:        if (start == 0)
                     23:                return;
                     24:        for (cp = start; *cp != '\0'; cp++) {
                     25:                if (*cp != '/')
                     26:                        continue;
                     27:                *cp = '\0';
                     28:                ep = lookupname(name);
                     29:                if (ep == NIL) {
                     30:                        ep = addentry(name, psearch(name), NODE);
                     31:                        newnode(ep);
                     32:                        ep->e_flags |= NEW|KEEP;
                     33:                }
                     34:                *cp = '/';
                     35:        }
                     36: }
                     37: 
                     38: /*
                     39:  * Change a name to a unique temporary name.
                     40:  */
                     41: mktempname(ep)
                     42:        register struct entry *ep;
                     43: {
                     44:        char oldname[MAXPATHLEN];
                     45: 
                     46:        if (ep->e_flags & TMPNAME)
                     47:                badentry(ep, "mktempname: called with TMPNAME");
                     48:        ep->e_flags |= TMPNAME;
                     49:        (void) strcpy(oldname, myname(ep));
                     50:        freename(ep->e_name);
                     51:        ep->e_name = savename(gentempname(ep));
                     52:        ep->e_namlen = strlen(ep->e_name);
                     53:        renameit(oldname, myname(ep));
                     54: }
                     55: 
                     56: /*
                     57:  * Generate a temporary name for an entry.
                     58:  */
                     59: char *
                     60: gentempname(ep)
                     61:        struct entry *ep;
                     62: {
                     63:        static char name[MAXPATHLEN];
                     64:        struct entry *np;
                     65:        long i = 0;
                     66: 
                     67:        for (np = lookupino(ep->e_ino); np != NIL && np != ep; np = np->e_links)
                     68:                i++;
                     69:        if (np == NIL)
                     70:                badentry(ep, "not on ino list");
                     71:        (void) sprintf(name, "%s%d%d", TMPHDR, i, ep->e_ino);
                     72:        return (name);
                     73: }
                     74: 
                     75: /*
                     76:  * Rename a file or directory.
                     77:  */
                     78: renameit(from, to)
                     79:        char *from, *to;
                     80: {
                     81:        if (rename(from, to) < 0) {
                     82:                fprintf(stderr, "Warning: cannot rename %s to %s", from, to);
                     83:                (void) fflush(stderr);
                     84:                perror("");
                     85:                return;
                     86:        }
                     87:        vprintf(stdout, "rename %s to %s\n", from, to);
                     88: }
                     89: 
                     90: /*
                     91:  * Create a new node (directory).
                     92:  */
                     93: newnode(np)
                     94:        struct entry *np;
                     95: {
                     96:        char *cp;
                     97: 
                     98:        if (np->e_type != NODE)
                     99:                badentry(np, "newnode: not a node");
                    100:        cp = myname(np);
                    101:        if (mkdir(cp, 0777) < 0) {
                    102:                fprintf(stderr, "Warning: ");
                    103:                (void) fflush(stderr);
                    104:                perror(cp);
                    105:                return;
                    106:        }
                    107:        vprintf(stdout, "Make node %s\n", cp);
                    108: }
                    109: 
                    110: /*
                    111:  * Remove an old node (directory).
                    112:  */
                    113: removenode(ep)
                    114:        register struct entry *ep;
                    115: {
                    116:        char *cp;
                    117: 
                    118:        if (ep->e_type != NODE)
                    119:                badentry(ep, "removenode: not a node");
                    120:        if (ep->e_entries != NIL)
                    121:                badentry(ep, "removenode: non-empty directory");
                    122:        ep->e_flags |= REMOVED;
                    123:        ep->e_flags &= ~TMPNAME;
                    124:        cp = myname(ep);
                    125:        if (rmdir(cp) < 0) {
                    126:                fprintf(stderr, "Warning: ");
                    127:                (void) fflush(stderr);
                    128:                perror(cp);
                    129:                return;
                    130:        }
                    131:        vprintf(stdout, "Remove node %s\n", cp);
                    132: }
                    133: 
                    134: /*
                    135:  * Remove a leaf.
                    136:  */
                    137: removeleaf(ep)
                    138:        register struct entry *ep;
                    139: {
                    140:        char *cp;
                    141: 
                    142:        if (ep->e_type != LEAF)
                    143:                badentry(ep, "removeleaf: not a leaf");
                    144:        ep->e_flags |= REMOVED;
                    145:        ep->e_flags &= ~TMPNAME;
                    146:        cp = myname(ep);
                    147:        if (unlink(cp) < 0) {
                    148:                fprintf(stderr, "Warning: ");
                    149:                (void) fflush(stderr);
                    150:                perror(cp);
                    151:                return;
                    152:        }
                    153:        vprintf(stdout, "Remove leaf %s\n", cp);
                    154: }
                    155: 
                    156: /*
                    157:  * Create a link.
                    158:  */
                    159: linkit(existing, new, type)
                    160:        char *existing, *new;
                    161:        int type;
                    162: {
                    163: 
                    164:        if (type == SYMLINK) {
                    165:                if (symlink(existing, new) < 0) {
                    166:                        fprintf(stderr,
                    167:                                "Warning: cannot create symbolic link %s->%s",
                    168:                                new, existing);
                    169:                        (void) fflush(stderr);
                    170:                        perror("");
                    171:                        return;
                    172:                }
                    173:        } else if (type == HARDLINK) {
                    174:                if (link(existing, new) < 0) {
                    175:                        fprintf(stderr,
                    176:                                "Warning: cannot create hard link %s->%s",
                    177:                                new, existing);
                    178:                        (void) fflush(stderr);
                    179:                        perror("");
                    180:                        return;
                    181:                }
                    182:        } else {
                    183:                panic("linkit: unknown type %d\n", type);
                    184:        }
                    185:        vprintf(stdout, "Create %s link %s->%s\n",
                    186:                type == SYMLINK ? "symbolic" : "hard", new, existing);
                    187: }
                    188: 
                    189: /*
                    190:  * find lowest number file (above "start") that needs to be extracted
                    191:  */
                    192: ino_t
                    193: lowerbnd(start)
                    194:        ino_t start;
                    195: {
                    196:        register struct entry *ep;
                    197: 
                    198:        for ( ; start < maxino; start++) {
                    199:                ep = lookupino(start);
                    200:                if (ep == NIL || ep->e_type == NODE)
                    201:                        continue;
                    202:                if (ep->e_flags & (NEW|EXTRACT))
                    203:                        return (start);
                    204:        }
                    205:        return (start);
                    206: }
                    207: 
                    208: /*
                    209:  * find highest number file (below "start") that needs to be extracted
                    210:  */
                    211: ino_t
                    212: upperbnd(start)
                    213:        ino_t start;
                    214: {
                    215:        register struct entry *ep;
                    216: 
                    217:        for ( ; start > ROOTINO; start--) {
                    218:                ep = lookupino(start);
                    219:                if (ep == NIL || ep->e_type == NODE)
                    220:                        continue;
                    221:                if (ep->e_flags & (NEW|EXTRACT))
                    222:                        return (start);
                    223:        }
                    224:        return (start);
                    225: }
                    226: 
                    227: /*
                    228:  * report on a badly formed entry
                    229:  */
                    230: badentry(ep, msg)
                    231:        register struct entry *ep;
                    232:        char *msg;
                    233: {
                    234: 
                    235:        fprintf(stderr, "bad entry: %s\n", msg);
                    236:        fprintf(stderr, "name: %s\n", myname(ep));
                    237:        fprintf(stderr, "parent name %s\n", myname(ep->e_parent));
                    238:        if (ep->e_sibling != NIL)
                    239:                fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling));
                    240:        if (ep->e_entries != NIL)
                    241:                fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries));
                    242:        if (ep->e_links != NIL)
                    243:                fprintf(stderr, "next link name: %s\n", myname(ep->e_links));
                    244:        if (ep->e_next != NIL)
                    245:                fprintf(stderr, "next hashchain name: %s\n", myname(ep->e_next));
                    246:        fprintf(stderr, "entry type: %s\n",
                    247:                ep->e_type == NODE ? "NODE" : "LEAF");
                    248:        fprintf(stderr, "inode number: %ld\n", ep->e_ino);
                    249:        panic("flags: %s\n", flagvalues(ep));
                    250: }
                    251: 
                    252: /*
                    253:  * Construct a string indicating the active flag bits of an entry.
                    254:  */
                    255: char *
                    256: flagvalues(ep)
                    257:        register struct entry *ep;
                    258: {
                    259:        static char flagbuf[BUFSIZ];
                    260: 
                    261:        (void) strcpy(flagbuf, "|NIL");
                    262:        flagbuf[0] = '\0';
                    263:        if (ep->e_flags & REMOVED)
                    264:                (void) strcat(flagbuf, "|REMOVED");
                    265:        if (ep->e_flags & TMPNAME)
                    266:                (void) strcat(flagbuf, "|TMPNAME");
                    267:        if (ep->e_flags & EXTRACT)
                    268:                (void) strcat(flagbuf, "|EXTRACT");
                    269:        if (ep->e_flags & NEW)
                    270:                (void) strcat(flagbuf, "|NEW");
                    271:        if (ep->e_flags & KEEP)
                    272:                (void) strcat(flagbuf, "|KEEP");
                    273:        return (&flagbuf[1]);
                    274: }
                    275: 
                    276: /*
                    277:  * Check to see if a name is on a dump tape.
                    278:  */
                    279: ino_t
                    280: dirlookup(name)
                    281:        char *name;
                    282: {
                    283:        ino_t ino;
                    284: 
                    285:        ino = psearch(name);
                    286:        if (ino == 0 || BIT(ino, dumpmap) == 0)
                    287:                fprintf(stderr, "%s is not on tape\n", name);
                    288:        return (ino);
                    289: }
                    290: 
                    291: /*
                    292:  * Canonicalize file names to always start with ``./'' and
                    293:  * remove any imbedded ".." components.
                    294:  */
                    295: canon(rawname, canonname)
                    296:        char *rawname, *canonname;
                    297: {
                    298:        register char *cp, *np;
                    299:        int len;
                    300: 
                    301:        if (strcmp(rawname, ".") == 0 || strncmp(rawname, "./", 2) == 0)
                    302:                (void) strcpy(canonname, "");
                    303:        else if (rawname[0] == '/')
                    304:                (void) strcpy(canonname, ".");
                    305:        else
                    306:                (void) strcpy(canonname, "./");
                    307:        (void) strcat(canonname, rawname);
                    308:        len = strlen(canonname) - 1;
                    309:        if (canonname[len] == '/')
                    310:                canonname[len] = '\0';
                    311:        /*
                    312:         * Eliminate extraneous ".." from pathnames.
                    313:         */
                    314:        for (np = canonname; *np != '\0'; ) {
                    315:                np++;
                    316:                cp = np;
                    317:                while (*np != '/' && *np != '\0')
                    318:                        np++;
                    319:                if (np - cp == 2 && strncmp(cp, "..", 2) == 0) {
                    320:                        cp--;
                    321:                        while (cp > &canonname[1] && *--cp != '/')
                    322:                                /* find beginning of name */;
                    323:                        (void) strcpy(cp, np);
                    324:                        np = cp;
                    325:                }
                    326:        }
                    327: }
                    328: 
                    329: /*
                    330:  * Elicit a reply.
                    331:  */
                    332: reply(question)
                    333:        char *question;
                    334: {
                    335:        char c;
                    336: 
                    337:        fprintf(stderr, "%s? ", question);
                    338:        do      {
                    339:                fprintf(stderr, "[yn] ");
                    340:                (void) fflush(stderr);
                    341:                c = getc(terminal);
                    342:                while (c != '\n' && getc(terminal) != '\n')
                    343:                        /* void */;
                    344:        } while (c != 'y' && c != 'n');
                    345:        if (c == 'y')
                    346:                return (GOOD);
                    347:        return (FAIL);
                    348: }
                    349: 
                    350: /*
                    351:  * Read and parse an interactive command.
                    352:  * The first word on the line is assigned to "cmd". If
                    353:  * there are no arguments on the command line, then "curdir"
                    354:  * is returned as the argument. If there are arguments
                    355:  * on the line they are returned one at a time on each
                    356:  * successive call to getcmd. Each argument is first assigned
                    357:  * to "name". If it does not start with "/" the pathname in
                    358:  * "curdir" is prepended to it. Finally "canon" is called to
                    359:  * eliminate any embedded ".." components.
                    360:  */
                    361: getcmd(curdir, cmd, name)
                    362:        char *curdir, *cmd, *name;
                    363: {
                    364:        register char *cp;
                    365:        static char *nextarg = NULL;
                    366:        static char input[BUFSIZ];
                    367:        char output[BUFSIZ];
                    368: #      define rawname input    /* save space by reusing input buffer */
                    369: 
                    370:        /*
                    371:         * Check to see if still processing arguments.
                    372:         */
                    373:        if (nextarg != NULL)
                    374:                goto getnext;
                    375:        /*
                    376:         * Read a command line and trim off trailing white space.
                    377:         */
                    378:        do      {
                    379:                fprintf(stderr, "restore > ");
                    380:                (void) fflush(stderr);
                    381:                (void) fgets(input, BUFSIZ, terminal);
                    382:        } while (!feof(terminal) && input[0] == '\n');
                    383:        if (feof(terminal)) {
                    384:                (void) strcpy(cmd, "quit");
                    385:                return;
                    386:        }
                    387:        for (cp = &input[strlen(input) - 2]; *cp == ' ' || *cp == '\t'; cp--)
                    388:                /* trim off trailing white space and newline */;
                    389:        *++cp = '\0';
                    390:        /*
                    391:         * Copy the command into "cmd".
                    392:         */
                    393:        cp = copynext(input, cmd);
                    394:        /*
                    395:         * If no argument, use curdir as the default.
                    396:         */
                    397:        if (*cp == '\0') {
                    398:                (void) strcpy(name, curdir);
                    399:                return;
                    400:        }
                    401:        nextarg = cp;
                    402:        /*
                    403:         * Find the next argument.
                    404:         */
                    405: getnext:
                    406:        cp = copynext(nextarg, rawname);
                    407:        if (*cp == '\0')
                    408:                nextarg = NULL;
                    409:        else
                    410:                nextarg = cp;
                    411:        /*
                    412:         * If it an absolute pathname, canonicalize it and return it.
                    413:         */
                    414:        if (rawname[0] == '/') {
                    415:                canon(rawname, name);
                    416:                return;
                    417:        }
                    418:        /*
                    419:         * For relative pathnames, prepend the current directory to
                    420:         * it then canonicalize and return it.
                    421:         */
                    422:        (void) strcpy(output, curdir);
                    423:        (void) strcat(output, "/");
                    424:        (void) strcat(output, rawname);
                    425:        canon(output, name);
                    426: #      undef rawname
                    427: }
                    428: 
                    429: /*
                    430:  * Strip off the next token of the input.
                    431:  */
                    432: char *
                    433: copynext(input, output)
                    434:        char *input, *output;
                    435: {
                    436:        register char *cp, *bp;
                    437:        char quote;
                    438: 
                    439:        for (cp = input; *cp == ' ' || *cp == '\t'; cp++)
                    440:                /* skip to argument */;
                    441:        bp = output;
                    442:        while (*cp != ' ' && *cp != '\t' && *cp != '\0') {
                    443:                /*
                    444:                 * Handle back slashes.
                    445:                 */
                    446:                if (*cp == '\\') {
                    447:                        if (*++cp == '\0') {
                    448:                                fprintf(stderr,
                    449:                                        "command lines cannot be continued\n");
                    450:                                continue;
                    451:                        }
                    452:                        *bp++ = *cp++;
                    453:                        continue;
                    454:                }
                    455:                /*
                    456:                 * The usual unquoted case.
                    457:                 */
                    458:                if (*cp != '\'' && *cp != '"') {
                    459:                        *bp++ = *cp++;
                    460:                        continue;
                    461:                }
                    462:                /*
                    463:                 * Handle single and double quotes.
                    464:                 */
                    465:                quote = *cp++;
                    466:                while (*cp != quote && *cp != '\0')
                    467:                        *bp++ = *cp++;
                    468:                if (*cp++ == '\0') {
                    469:                        fprintf(stderr, "missing %c\n", quote);
                    470:                        cp--;
                    471:                        continue;
                    472:                }
                    473:        }
                    474:        *bp = '\0';
                    475:        return (cp);
                    476: }
                    477: 
                    478: /*
                    479:  * respond to interrupts
                    480:  */
                    481: onintr()
                    482: {
                    483:        if (reply("restore interrupted, continue") == FAIL)
                    484:                done(1);
                    485:        if (signal(SIGINT, onintr) == SIG_IGN)
                    486:                (void) signal(SIGINT, SIG_IGN);
                    487:        if (signal(SIGTERM, onintr) == SIG_IGN)
                    488:                (void) signal(SIGTERM, SIG_IGN);
                    489: }
                    490: 
                    491: /*
                    492:  * handle unexpected inconsistencies
                    493:  */
                    494: /* VARARGS1 */
                    495: panic(msg, d1, d2)
                    496:        char *msg;
                    497:        long d1, d2;
                    498: {
                    499: 
                    500:        fprintf(stderr, msg, d1, d2);
                    501:        if (reply("abort") == GOOD) {
                    502:                if (reply("dump core") == GOOD)
                    503:                        abort();
                    504:                done(1);
                    505:        }
                    506: }

unix.superglobalmegacorp.com

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