121171Sdist /* 236105Sbostic * Copyright (c) 1983 The Regents of the University of California. 336105Sbostic * All rights reserved. 436105Sbostic * 542709Sbostic * %sccs.include.redist.c% 621171Sdist */ 721171Sdist 810315Smckusick #ifndef lint 9*56427Smckusick static char sccsid[] = "@(#)utilities.c 5.7 (Berkeley) 10/05/92"; 1036105Sbostic #endif /* not lint */ 1110315Smckusick 1210315Smckusick #include "restore.h" 1310315Smckusick 1410315Smckusick /* 1510315Smckusick * Insure that all the components of a pathname exist. 1610315Smckusick */ 1711645Smckusick pathcheck(name) 1810315Smckusick char *name; 1910315Smckusick { 2010315Smckusick register char *cp; 2110315Smckusick struct entry *ep; 2211312Smckusick char *start; 2310315Smckusick 2410315Smckusick start = index(name, '/'); 2511312Smckusick if (start == 0) 2611645Smckusick return; 2710315Smckusick for (cp = start; *cp != '\0'; cp++) { 2810315Smckusick if (*cp != '/') 2910315Smckusick continue; 3010315Smckusick *cp = '\0'; 3110315Smckusick ep = lookupname(name); 3210315Smckusick if (ep == NIL) { 3311995Smckusick ep = addentry(name, psearch(name), NODE); 3410315Smckusick newnode(ep); 3510315Smckusick } 3618009Smckusick ep->e_flags |= NEW|KEEP; 3710315Smckusick *cp = '/'; 3810315Smckusick } 3910315Smckusick } 4010315Smckusick 4110315Smckusick /* 4210315Smckusick * Change a name to a unique temporary name. 4310315Smckusick */ 4410315Smckusick mktempname(ep) 4510315Smckusick register struct entry *ep; 4610315Smckusick { 4711645Smckusick char oldname[MAXPATHLEN]; 4810315Smckusick 4910315Smckusick if (ep->e_flags & TMPNAME) 5010315Smckusick badentry(ep, "mktempname: called with TMPNAME"); 5110315Smckusick ep->e_flags |= TMPNAME; 5211995Smckusick (void) strcpy(oldname, myname(ep)); 5311645Smckusick freename(ep->e_name); 5411645Smckusick ep->e_name = savename(gentempname(ep)); 5511645Smckusick ep->e_namlen = strlen(ep->e_name); 5610315Smckusick renameit(oldname, myname(ep)); 5710315Smckusick } 5810315Smckusick 5910315Smckusick /* 6011645Smckusick * Generate a temporary name for an entry. 6111645Smckusick */ 6211645Smckusick char * 6311645Smckusick gentempname(ep) 6411645Smckusick struct entry *ep; 6511645Smckusick { 6611645Smckusick static char name[MAXPATHLEN]; 6711645Smckusick struct entry *np; 6811645Smckusick long i = 0; 6911645Smckusick 7011645Smckusick for (np = lookupino(ep->e_ino); np != NIL && np != ep; np = np->e_links) 7111645Smckusick i++; 7211645Smckusick if (np == NIL) 7311645Smckusick badentry(ep, "not on ino list"); 7411733Smckusick (void) sprintf(name, "%s%d%d", TMPHDR, i, ep->e_ino); 7511645Smckusick return (name); 7611645Smckusick } 7711645Smckusick 7811645Smckusick /* 7910315Smckusick * Rename a file or directory. 8010315Smckusick */ 8110315Smckusick renameit(from, to) 8210315Smckusick char *from, *to; 8310315Smckusick { 8434268Smckusick if (!Nflag && rename(from, to) < 0) { 8512557Smckusick fprintf(stderr, "Warning: cannot rename %s to %s", from, to); 8612557Smckusick (void) fflush(stderr); 8712557Smckusick perror(""); 8811923Smckusick return; 8910315Smckusick } 9010315Smckusick vprintf(stdout, "rename %s to %s\n", from, to); 9110315Smckusick } 9210315Smckusick 9310315Smckusick /* 9410315Smckusick * Create a new node (directory). 9510315Smckusick */ 9610315Smckusick newnode(np) 9710315Smckusick struct entry *np; 9810315Smckusick { 9910315Smckusick char *cp; 10010315Smckusick 10110315Smckusick if (np->e_type != NODE) 10210315Smckusick badentry(np, "newnode: not a node"); 10310315Smckusick cp = myname(np); 10434268Smckusick if (!Nflag && mkdir(cp, 0777) < 0) { 10518006Smckusick np->e_flags |= EXISTED; 10611740Smckusick fprintf(stderr, "Warning: "); 10711995Smckusick (void) fflush(stderr); 10811740Smckusick perror(cp); 10911740Smckusick return; 11010315Smckusick } 11110315Smckusick vprintf(stdout, "Make node %s\n", cp); 11210315Smckusick } 11310315Smckusick 11410315Smckusick /* 11510315Smckusick * Remove an old node (directory). 11610315Smckusick */ 11710315Smckusick removenode(ep) 11810315Smckusick register struct entry *ep; 11910315Smckusick { 12010315Smckusick char *cp; 12110315Smckusick 12210315Smckusick if (ep->e_type != NODE) 12310315Smckusick badentry(ep, "removenode: not a node"); 12410315Smckusick if (ep->e_entries != NIL) 12510315Smckusick badentry(ep, "removenode: non-empty directory"); 12611923Smckusick ep->e_flags |= REMOVED; 12711923Smckusick ep->e_flags &= ~TMPNAME; 12810315Smckusick cp = myname(ep); 12934268Smckusick if (!Nflag && rmdir(cp) < 0) { 13011923Smckusick fprintf(stderr, "Warning: "); 13111995Smckusick (void) fflush(stderr); 13211923Smckusick perror(cp); 13311923Smckusick return; 13410315Smckusick } 13510315Smckusick vprintf(stdout, "Remove node %s\n", cp); 13610315Smckusick } 13710315Smckusick 13810315Smckusick /* 13910315Smckusick * Remove a leaf. 14010315Smckusick */ 14110315Smckusick removeleaf(ep) 14210315Smckusick register struct entry *ep; 14310315Smckusick { 14410315Smckusick char *cp; 14510315Smckusick 14610315Smckusick if (ep->e_type != LEAF) 14710315Smckusick badentry(ep, "removeleaf: not a leaf"); 14811923Smckusick ep->e_flags |= REMOVED; 14911923Smckusick ep->e_flags &= ~TMPNAME; 15010315Smckusick cp = myname(ep); 15134268Smckusick if (!Nflag && unlink(cp) < 0) { 15211923Smckusick fprintf(stderr, "Warning: "); 15311995Smckusick (void) fflush(stderr); 15411923Smckusick perror(cp); 15511923Smckusick return; 15610315Smckusick } 15710315Smckusick vprintf(stdout, "Remove leaf %s\n", cp); 15810315Smckusick } 15910315Smckusick 16010315Smckusick /* 16110315Smckusick * Create a link. 16210315Smckusick */ 16310315Smckusick linkit(existing, new, type) 16410315Smckusick char *existing, *new; 16510315Smckusick int type; 16610315Smckusick { 16710315Smckusick 16810315Smckusick if (type == SYMLINK) { 16934268Smckusick if (!Nflag && symlink(existing, new) < 0) { 17011923Smckusick fprintf(stderr, 17115782Smckusick "Warning: cannot create symbolic link %s->%s: ", 17210315Smckusick new, existing); 17312557Smckusick (void) fflush(stderr); 17412557Smckusick perror(""); 17515782Smckusick return (FAIL); 17610315Smckusick } 17710315Smckusick } else if (type == HARDLINK) { 17834268Smckusick if (!Nflag && link(existing, new) < 0) { 17911923Smckusick fprintf(stderr, 18015782Smckusick "Warning: cannot create hard link %s->%s: ", 18110315Smckusick new, existing); 18212557Smckusick (void) fflush(stderr); 18312557Smckusick perror(""); 18415782Smckusick return (FAIL); 18510315Smckusick } 18610315Smckusick } else { 18710315Smckusick panic("linkit: unknown type %d\n", type); 18815782Smckusick return (FAIL); 18910315Smckusick } 19010315Smckusick vprintf(stdout, "Create %s link %s->%s\n", 19110315Smckusick type == SYMLINK ? "symbolic" : "hard", new, existing); 19215782Smckusick return (GOOD); 19310315Smckusick } 19410315Smckusick 19510315Smckusick /* 19610315Smckusick * find lowest number file (above "start") that needs to be extracted 19710315Smckusick */ 19810315Smckusick ino_t 19910315Smckusick lowerbnd(start) 20010315Smckusick ino_t start; 20110315Smckusick { 20210315Smckusick register struct entry *ep; 20310315Smckusick 20410315Smckusick for ( ; start < maxino; start++) { 20510315Smckusick ep = lookupino(start); 20611995Smckusick if (ep == NIL || ep->e_type == NODE) 20710315Smckusick continue; 20811645Smckusick if (ep->e_flags & (NEW|EXTRACT)) 20910315Smckusick return (start); 21010315Smckusick } 21110315Smckusick return (start); 21210315Smckusick } 21310315Smckusick 21410315Smckusick /* 21510315Smckusick * find highest number file (below "start") that needs to be extracted 21610315Smckusick */ 21710315Smckusick ino_t 21810315Smckusick upperbnd(start) 21910315Smckusick ino_t start; 22010315Smckusick { 22110315Smckusick register struct entry *ep; 22210315Smckusick 22310315Smckusick for ( ; start > ROOTINO; start--) { 22410315Smckusick ep = lookupino(start); 22511995Smckusick if (ep == NIL || ep->e_type == NODE) 22610315Smckusick continue; 22711645Smckusick if (ep->e_flags & (NEW|EXTRACT)) 22810315Smckusick return (start); 22910315Smckusick } 23010315Smckusick return (start); 23110315Smckusick } 23210315Smckusick 23310315Smckusick /* 23410315Smckusick * report on a badly formed entry 23510315Smckusick */ 23610315Smckusick badentry(ep, msg) 23710315Smckusick register struct entry *ep; 23810315Smckusick char *msg; 23910315Smckusick { 24010315Smckusick 24110315Smckusick fprintf(stderr, "bad entry: %s\n", msg); 24210315Smckusick fprintf(stderr, "name: %s\n", myname(ep)); 24310315Smckusick fprintf(stderr, "parent name %s\n", myname(ep->e_parent)); 24410315Smckusick if (ep->e_sibling != NIL) 24510315Smckusick fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling)); 24610315Smckusick if (ep->e_entries != NIL) 24710315Smckusick fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries)); 24810315Smckusick if (ep->e_links != NIL) 24910315Smckusick fprintf(stderr, "next link name: %s\n", myname(ep->e_links)); 25011645Smckusick if (ep->e_next != NIL) 25111645Smckusick fprintf(stderr, "next hashchain name: %s\n", myname(ep->e_next)); 25210315Smckusick fprintf(stderr, "entry type: %s\n", 25310315Smckusick ep->e_type == NODE ? "NODE" : "LEAF"); 25410315Smckusick fprintf(stderr, "inode number: %ld\n", ep->e_ino); 25511898Smckusick panic("flags: %s\n", flagvalues(ep)); 25611898Smckusick } 25711898Smckusick 25811898Smckusick /* 25911898Smckusick * Construct a string indicating the active flag bits of an entry. 26011898Smckusick */ 26111898Smckusick char * 26211898Smckusick flagvalues(ep) 26311898Smckusick register struct entry *ep; 26411898Smckusick { 26511898Smckusick static char flagbuf[BUFSIZ]; 26611898Smckusick 26711898Smckusick (void) strcpy(flagbuf, "|NIL"); 26810315Smckusick flagbuf[0] = '\0'; 26910315Smckusick if (ep->e_flags & REMOVED) 27011898Smckusick (void) strcat(flagbuf, "|REMOVED"); 27110315Smckusick if (ep->e_flags & TMPNAME) 27211898Smckusick (void) strcat(flagbuf, "|TMPNAME"); 27310315Smckusick if (ep->e_flags & EXTRACT) 27411898Smckusick (void) strcat(flagbuf, "|EXTRACT"); 27510315Smckusick if (ep->e_flags & NEW) 27611898Smckusick (void) strcat(flagbuf, "|NEW"); 27710315Smckusick if (ep->e_flags & KEEP) 27811898Smckusick (void) strcat(flagbuf, "|KEEP"); 27918006Smckusick if (ep->e_flags & EXISTED) 28018006Smckusick (void) strcat(flagbuf, "|EXISTED"); 28111898Smckusick return (&flagbuf[1]); 28210315Smckusick } 28310315Smckusick 28410315Smckusick /* 28511995Smckusick * Check to see if a name is on a dump tape. 28611321Smckusick */ 28711995Smckusick ino_t 28811995Smckusick dirlookup(name) 28911995Smckusick char *name; 29011995Smckusick { 29111995Smckusick ino_t ino; 29211995Smckusick 29311995Smckusick ino = psearch(name); 294*56427Smckusick if (ino == 0 || TSTINO(ino, dumpmap) == 0) 29511995Smckusick fprintf(stderr, "%s is not on tape\n", name); 29611995Smckusick return (ino); 29711995Smckusick } 29811995Smckusick 29911995Smckusick /* 30011995Smckusick * Elicit a reply. 30110315Smckusick */ 30210315Smckusick reply(question) 30310315Smckusick char *question; 30410315Smckusick { 30510315Smckusick char c; 30610315Smckusick 30710315Smckusick do { 30824185Smckusick fprintf(stderr, "%s? [yn] ", question); 30912557Smckusick (void) fflush(stderr); 31011995Smckusick c = getc(terminal); 31111995Smckusick while (c != '\n' && getc(terminal) != '\n') 31217711Smckusick if (feof(terminal)) 31324185Smckusick return (FAIL); 31410315Smckusick } while (c != 'y' && c != 'n'); 31510315Smckusick if (c == 'y') 31610315Smckusick return (GOOD); 31710315Smckusick return (FAIL); 31810315Smckusick } 31911995Smckusick 32011995Smckusick /* 32111995Smckusick * handle unexpected inconsistencies 32211995Smckusick */ 32311995Smckusick /* VARARGS1 */ 32411995Smckusick panic(msg, d1, d2) 32511995Smckusick char *msg; 32611995Smckusick long d1, d2; 32711995Smckusick { 32811995Smckusick 32911995Smckusick fprintf(stderr, msg, d1, d2); 33042489Smckusick if (yflag) 33142489Smckusick return; 33211995Smckusick if (reply("abort") == GOOD) { 33311995Smckusick if (reply("dump core") == GOOD) 33411995Smckusick abort(); 33511995Smckusick done(1); 33611995Smckusick } 33711995Smckusick } 338