121171Sdist /* 221171Sdist * Copyright (c) 1983 Regents of the University of California. 321171Sdist * All rights reserved. The Berkeley software License Agreement 421171Sdist * specifies the terms and conditions for redistribution. 521171Sdist */ 621171Sdist 710315Smckusick #ifndef lint 8*34268Smckusick static char sccsid[] = "@(#)utilities.c 5.3 (Berkeley) 05/13/88"; 921171Sdist #endif not lint 1010315Smckusick 1110315Smckusick #include "restore.h" 1210315Smckusick 1310315Smckusick /* 1410315Smckusick * Insure that all the components of a pathname exist. 1510315Smckusick */ 1611645Smckusick pathcheck(name) 1710315Smckusick char *name; 1810315Smckusick { 1910315Smckusick register char *cp; 2010315Smckusick struct entry *ep; 2111312Smckusick char *start; 2210315Smckusick 2310315Smckusick start = index(name, '/'); 2411312Smckusick if (start == 0) 2511645Smckusick return; 2610315Smckusick for (cp = start; *cp != '\0'; cp++) { 2710315Smckusick if (*cp != '/') 2810315Smckusick continue; 2910315Smckusick *cp = '\0'; 3010315Smckusick ep = lookupname(name); 3110315Smckusick if (ep == NIL) { 3211995Smckusick ep = addentry(name, psearch(name), NODE); 3310315Smckusick newnode(ep); 3410315Smckusick } 3518009Smckusick ep->e_flags |= NEW|KEEP; 3610315Smckusick *cp = '/'; 3710315Smckusick } 3810315Smckusick } 3910315Smckusick 4010315Smckusick /* 4110315Smckusick * Change a name to a unique temporary name. 4210315Smckusick */ 4310315Smckusick mktempname(ep) 4410315Smckusick register struct entry *ep; 4510315Smckusick { 4611645Smckusick char oldname[MAXPATHLEN]; 4710315Smckusick 4810315Smckusick if (ep->e_flags & TMPNAME) 4910315Smckusick badentry(ep, "mktempname: called with TMPNAME"); 5010315Smckusick ep->e_flags |= TMPNAME; 5111995Smckusick (void) strcpy(oldname, myname(ep)); 5211645Smckusick freename(ep->e_name); 5311645Smckusick ep->e_name = savename(gentempname(ep)); 5411645Smckusick ep->e_namlen = strlen(ep->e_name); 5510315Smckusick renameit(oldname, myname(ep)); 5610315Smckusick } 5710315Smckusick 5810315Smckusick /* 5911645Smckusick * Generate a temporary name for an entry. 6011645Smckusick */ 6111645Smckusick char * 6211645Smckusick gentempname(ep) 6311645Smckusick struct entry *ep; 6411645Smckusick { 6511645Smckusick static char name[MAXPATHLEN]; 6611645Smckusick struct entry *np; 6711645Smckusick long i = 0; 6811645Smckusick 6911645Smckusick for (np = lookupino(ep->e_ino); np != NIL && np != ep; np = np->e_links) 7011645Smckusick i++; 7111645Smckusick if (np == NIL) 7211645Smckusick badentry(ep, "not on ino list"); 7311733Smckusick (void) sprintf(name, "%s%d%d", TMPHDR, i, ep->e_ino); 7411645Smckusick return (name); 7511645Smckusick } 7611645Smckusick 7711645Smckusick /* 7810315Smckusick * Rename a file or directory. 7910315Smckusick */ 8010315Smckusick renameit(from, to) 8110315Smckusick char *from, *to; 8210315Smckusick { 83*34268Smckusick if (!Nflag && rename(from, to) < 0) { 8412557Smckusick fprintf(stderr, "Warning: cannot rename %s to %s", from, to); 8512557Smckusick (void) fflush(stderr); 8612557Smckusick perror(""); 8711923Smckusick return; 8810315Smckusick } 8910315Smckusick vprintf(stdout, "rename %s to %s\n", from, to); 9010315Smckusick } 9110315Smckusick 9210315Smckusick /* 9310315Smckusick * Create a new node (directory). 9410315Smckusick */ 9510315Smckusick newnode(np) 9610315Smckusick struct entry *np; 9710315Smckusick { 9810315Smckusick char *cp; 9910315Smckusick 10010315Smckusick if (np->e_type != NODE) 10110315Smckusick badentry(np, "newnode: not a node"); 10210315Smckusick cp = myname(np); 103*34268Smckusick if (!Nflag && mkdir(cp, 0777) < 0) { 10418006Smckusick np->e_flags |= EXISTED; 10511740Smckusick fprintf(stderr, "Warning: "); 10611995Smckusick (void) fflush(stderr); 10711740Smckusick perror(cp); 10811740Smckusick return; 10910315Smckusick } 11010315Smckusick vprintf(stdout, "Make node %s\n", cp); 11110315Smckusick } 11210315Smckusick 11310315Smckusick /* 11410315Smckusick * Remove an old node (directory). 11510315Smckusick */ 11610315Smckusick removenode(ep) 11710315Smckusick register struct entry *ep; 11810315Smckusick { 11910315Smckusick char *cp; 12010315Smckusick 12110315Smckusick if (ep->e_type != NODE) 12210315Smckusick badentry(ep, "removenode: not a node"); 12310315Smckusick if (ep->e_entries != NIL) 12410315Smckusick badentry(ep, "removenode: non-empty directory"); 12511923Smckusick ep->e_flags |= REMOVED; 12611923Smckusick ep->e_flags &= ~TMPNAME; 12710315Smckusick cp = myname(ep); 128*34268Smckusick if (!Nflag && rmdir(cp) < 0) { 12911923Smckusick fprintf(stderr, "Warning: "); 13011995Smckusick (void) fflush(stderr); 13111923Smckusick perror(cp); 13211923Smckusick return; 13310315Smckusick } 13410315Smckusick vprintf(stdout, "Remove node %s\n", cp); 13510315Smckusick } 13610315Smckusick 13710315Smckusick /* 13810315Smckusick * Remove a leaf. 13910315Smckusick */ 14010315Smckusick removeleaf(ep) 14110315Smckusick register struct entry *ep; 14210315Smckusick { 14310315Smckusick char *cp; 14410315Smckusick 14510315Smckusick if (ep->e_type != LEAF) 14610315Smckusick badentry(ep, "removeleaf: not a leaf"); 14711923Smckusick ep->e_flags |= REMOVED; 14811923Smckusick ep->e_flags &= ~TMPNAME; 14910315Smckusick cp = myname(ep); 150*34268Smckusick if (!Nflag && unlink(cp) < 0) { 15111923Smckusick fprintf(stderr, "Warning: "); 15211995Smckusick (void) fflush(stderr); 15311923Smckusick perror(cp); 15411923Smckusick return; 15510315Smckusick } 15610315Smckusick vprintf(stdout, "Remove leaf %s\n", cp); 15710315Smckusick } 15810315Smckusick 15910315Smckusick /* 16010315Smckusick * Create a link. 16110315Smckusick */ 16210315Smckusick linkit(existing, new, type) 16310315Smckusick char *existing, *new; 16410315Smckusick int type; 16510315Smckusick { 16610315Smckusick 16710315Smckusick if (type == SYMLINK) { 168*34268Smckusick if (!Nflag && symlink(existing, new) < 0) { 16911923Smckusick fprintf(stderr, 17015782Smckusick "Warning: cannot create symbolic link %s->%s: ", 17110315Smckusick new, existing); 17212557Smckusick (void) fflush(stderr); 17312557Smckusick perror(""); 17415782Smckusick return (FAIL); 17510315Smckusick } 17610315Smckusick } else if (type == HARDLINK) { 177*34268Smckusick if (!Nflag && link(existing, new) < 0) { 17811923Smckusick fprintf(stderr, 17915782Smckusick "Warning: cannot create hard link %s->%s: ", 18010315Smckusick new, existing); 18112557Smckusick (void) fflush(stderr); 18212557Smckusick perror(""); 18315782Smckusick return (FAIL); 18410315Smckusick } 18510315Smckusick } else { 18610315Smckusick panic("linkit: unknown type %d\n", type); 18715782Smckusick return (FAIL); 18810315Smckusick } 18910315Smckusick vprintf(stdout, "Create %s link %s->%s\n", 19010315Smckusick type == SYMLINK ? "symbolic" : "hard", new, existing); 19115782Smckusick return (GOOD); 19210315Smckusick } 19310315Smckusick 19410315Smckusick /* 19510315Smckusick * find lowest number file (above "start") that needs to be extracted 19610315Smckusick */ 19710315Smckusick ino_t 19810315Smckusick lowerbnd(start) 19910315Smckusick ino_t start; 20010315Smckusick { 20110315Smckusick register struct entry *ep; 20210315Smckusick 20310315Smckusick for ( ; start < maxino; start++) { 20410315Smckusick ep = lookupino(start); 20511995Smckusick if (ep == NIL || ep->e_type == NODE) 20610315Smckusick continue; 20711645Smckusick if (ep->e_flags & (NEW|EXTRACT)) 20810315Smckusick return (start); 20910315Smckusick } 21010315Smckusick return (start); 21110315Smckusick } 21210315Smckusick 21310315Smckusick /* 21410315Smckusick * find highest number file (below "start") that needs to be extracted 21510315Smckusick */ 21610315Smckusick ino_t 21710315Smckusick upperbnd(start) 21810315Smckusick ino_t start; 21910315Smckusick { 22010315Smckusick register struct entry *ep; 22110315Smckusick 22210315Smckusick for ( ; start > ROOTINO; start--) { 22310315Smckusick ep = lookupino(start); 22411995Smckusick if (ep == NIL || ep->e_type == NODE) 22510315Smckusick continue; 22611645Smckusick if (ep->e_flags & (NEW|EXTRACT)) 22710315Smckusick return (start); 22810315Smckusick } 22910315Smckusick return (start); 23010315Smckusick } 23110315Smckusick 23210315Smckusick /* 23310315Smckusick * report on a badly formed entry 23410315Smckusick */ 23510315Smckusick badentry(ep, msg) 23610315Smckusick register struct entry *ep; 23710315Smckusick char *msg; 23810315Smckusick { 23910315Smckusick 24010315Smckusick fprintf(stderr, "bad entry: %s\n", msg); 24110315Smckusick fprintf(stderr, "name: %s\n", myname(ep)); 24210315Smckusick fprintf(stderr, "parent name %s\n", myname(ep->e_parent)); 24310315Smckusick if (ep->e_sibling != NIL) 24410315Smckusick fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling)); 24510315Smckusick if (ep->e_entries != NIL) 24610315Smckusick fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries)); 24710315Smckusick if (ep->e_links != NIL) 24810315Smckusick fprintf(stderr, "next link name: %s\n", myname(ep->e_links)); 24911645Smckusick if (ep->e_next != NIL) 25011645Smckusick fprintf(stderr, "next hashchain name: %s\n", myname(ep->e_next)); 25110315Smckusick fprintf(stderr, "entry type: %s\n", 25210315Smckusick ep->e_type == NODE ? "NODE" : "LEAF"); 25310315Smckusick fprintf(stderr, "inode number: %ld\n", ep->e_ino); 25411898Smckusick panic("flags: %s\n", flagvalues(ep)); 25511898Smckusick } 25611898Smckusick 25711898Smckusick /* 25811898Smckusick * Construct a string indicating the active flag bits of an entry. 25911898Smckusick */ 26011898Smckusick char * 26111898Smckusick flagvalues(ep) 26211898Smckusick register struct entry *ep; 26311898Smckusick { 26411898Smckusick static char flagbuf[BUFSIZ]; 26511898Smckusick 26611898Smckusick (void) strcpy(flagbuf, "|NIL"); 26710315Smckusick flagbuf[0] = '\0'; 26810315Smckusick if (ep->e_flags & REMOVED) 26911898Smckusick (void) strcat(flagbuf, "|REMOVED"); 27010315Smckusick if (ep->e_flags & TMPNAME) 27111898Smckusick (void) strcat(flagbuf, "|TMPNAME"); 27210315Smckusick if (ep->e_flags & EXTRACT) 27311898Smckusick (void) strcat(flagbuf, "|EXTRACT"); 27410315Smckusick if (ep->e_flags & NEW) 27511898Smckusick (void) strcat(flagbuf, "|NEW"); 27610315Smckusick if (ep->e_flags & KEEP) 27711898Smckusick (void) strcat(flagbuf, "|KEEP"); 27818006Smckusick if (ep->e_flags & EXISTED) 27918006Smckusick (void) strcat(flagbuf, "|EXISTED"); 28011898Smckusick return (&flagbuf[1]); 28110315Smckusick } 28210315Smckusick 28310315Smckusick /* 28411995Smckusick * Check to see if a name is on a dump tape. 28511321Smckusick */ 28611995Smckusick ino_t 28711995Smckusick dirlookup(name) 28811995Smckusick char *name; 28911995Smckusick { 29011995Smckusick ino_t ino; 29111995Smckusick 29211995Smckusick ino = psearch(name); 29311995Smckusick if (ino == 0 || BIT(ino, dumpmap) == 0) 29411995Smckusick fprintf(stderr, "%s is not on tape\n", name); 29511995Smckusick return (ino); 29611995Smckusick } 29711995Smckusick 29811995Smckusick /* 29911995Smckusick * Elicit a reply. 30010315Smckusick */ 30110315Smckusick reply(question) 30210315Smckusick char *question; 30310315Smckusick { 30410315Smckusick char c; 30510315Smckusick 30610315Smckusick do { 30724185Smckusick fprintf(stderr, "%s? [yn] ", question); 30812557Smckusick (void) fflush(stderr); 30911995Smckusick c = getc(terminal); 31011995Smckusick while (c != '\n' && getc(terminal) != '\n') 31117711Smckusick if (feof(terminal)) 31224185Smckusick return (FAIL); 31310315Smckusick } while (c != 'y' && c != 'n'); 31410315Smckusick if (c == 'y') 31510315Smckusick return (GOOD); 31610315Smckusick return (FAIL); 31710315Smckusick } 31811995Smckusick 31911995Smckusick /* 32011995Smckusick * handle unexpected inconsistencies 32111995Smckusick */ 32211995Smckusick /* VARARGS1 */ 32311995Smckusick panic(msg, d1, d2) 32411995Smckusick char *msg; 32511995Smckusick long d1, d2; 32611995Smckusick { 32711995Smckusick 32811995Smckusick fprintf(stderr, msg, d1, d2); 32911995Smckusick if (reply("abort") == GOOD) { 33011995Smckusick if (reply("dump core") == GOOD) 33111995Smckusick abort(); 33211995Smckusick done(1); 33311995Smckusick } 33411995Smckusick } 335