121171Sdist /* 261536Sbostic * Copyright (c) 1983, 1993 361536Sbostic * The Regents of the University of California. All rights reserved. 436105Sbostic * 542709Sbostic * %sccs.include.redist.c% 621171Sdist */ 721171Sdist 810315Smckusick #ifndef lint 9*66443Sbostic static char sccsid[] = "@(#)utilities.c 8.2 (Berkeley) 03/25/94"; 1036105Sbostic #endif /* not lint */ 1110315Smckusick 1256567Sbostic #include <sys/param.h> 1356567Sbostic #include <sys/stat.h> 1456567Sbostic 1556567Sbostic #include <ufs/ufs/dinode.h> 1656947Smckusick #include <ufs/ufs/dir.h> 1756567Sbostic 1856567Sbostic #include <errno.h> 1956567Sbostic #include <stdio.h> 2056567Sbostic #include <stdlib.h> 2156567Sbostic #include <string.h> 2256567Sbostic #include <unistd.h> 2356567Sbostic 2410315Smckusick #include "restore.h" 2556567Sbostic #include "extern.h" 2610315Smckusick 2710315Smckusick /* 2810315Smckusick * Insure that all the components of a pathname exist. 2910315Smckusick */ 3056567Sbostic void 3111645Smckusick pathcheck(name) 3210315Smckusick char *name; 3310315Smckusick { 3410315Smckusick register char *cp; 3510315Smckusick struct entry *ep; 3611312Smckusick char *start; 3710315Smckusick 3810315Smckusick start = index(name, '/'); 3911312Smckusick if (start == 0) 4011645Smckusick return; 4110315Smckusick for (cp = start; *cp != '\0'; cp++) { 4210315Smckusick if (*cp != '/') 4310315Smckusick continue; 4410315Smckusick *cp = '\0'; 4510315Smckusick ep = lookupname(name); 4656567Sbostic if (ep == NULL) { 47*66443Sbostic /* Safe; we know the pathname exists in the dump. */ 4856947Smckusick ep = addentry(name, pathsearch(name)->d_ino, NODE); 4910315Smckusick newnode(ep); 5010315Smckusick } 5118009Smckusick ep->e_flags |= NEW|KEEP; 5210315Smckusick *cp = '/'; 5310315Smckusick } 5410315Smckusick } 5510315Smckusick 5610315Smckusick /* 5710315Smckusick * Change a name to a unique temporary name. 5810315Smckusick */ 5956567Sbostic void 6010315Smckusick mktempname(ep) 6110315Smckusick register struct entry *ep; 6210315Smckusick { 6311645Smckusick char oldname[MAXPATHLEN]; 6410315Smckusick 6510315Smckusick if (ep->e_flags & TMPNAME) 6610315Smckusick badentry(ep, "mktempname: called with TMPNAME"); 6710315Smckusick ep->e_flags |= TMPNAME; 6811995Smckusick (void) strcpy(oldname, myname(ep)); 6911645Smckusick freename(ep->e_name); 7011645Smckusick ep->e_name = savename(gentempname(ep)); 7111645Smckusick ep->e_namlen = strlen(ep->e_name); 7210315Smckusick renameit(oldname, myname(ep)); 7310315Smckusick } 7410315Smckusick 7510315Smckusick /* 7611645Smckusick * Generate a temporary name for an entry. 7711645Smckusick */ 7811645Smckusick char * 7911645Smckusick gentempname(ep) 8011645Smckusick struct entry *ep; 8111645Smckusick { 8211645Smckusick static char name[MAXPATHLEN]; 8311645Smckusick struct entry *np; 8411645Smckusick long i = 0; 8511645Smckusick 8656567Sbostic for (np = lookupino(ep->e_ino); 8756567Sbostic np != NULL && np != ep; np = np->e_links) 8811645Smckusick i++; 8956567Sbostic if (np == NULL) 9011645Smckusick badentry(ep, "not on ino list"); 9111733Smckusick (void) sprintf(name, "%s%d%d", TMPHDR, i, ep->e_ino); 9211645Smckusick return (name); 9311645Smckusick } 9411645Smckusick 9511645Smckusick /* 9610315Smckusick * Rename a file or directory. 9710315Smckusick */ 9856567Sbostic void 9910315Smckusick renameit(from, to) 10010315Smckusick char *from, *to; 10110315Smckusick { 10234268Smckusick if (!Nflag && rename(from, to) < 0) { 10356567Sbostic fprintf(stderr, "warning: cannot rename %s to %s: %s\n", 10456567Sbostic from, to, strerror(errno)); 10511923Smckusick return; 10610315Smckusick } 10710315Smckusick vprintf(stdout, "rename %s to %s\n", from, to); 10810315Smckusick } 10910315Smckusick 11010315Smckusick /* 11110315Smckusick * Create a new node (directory). 11210315Smckusick */ 11356567Sbostic void 11410315Smckusick newnode(np) 11510315Smckusick struct entry *np; 11610315Smckusick { 11710315Smckusick char *cp; 11810315Smckusick 11910315Smckusick if (np->e_type != NODE) 12010315Smckusick badentry(np, "newnode: not a node"); 12110315Smckusick cp = myname(np); 12234268Smckusick if (!Nflag && mkdir(cp, 0777) < 0) { 12318006Smckusick np->e_flags |= EXISTED; 12456567Sbostic fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno)); 12511740Smckusick return; 12610315Smckusick } 12710315Smckusick vprintf(stdout, "Make node %s\n", cp); 12810315Smckusick } 12910315Smckusick 13010315Smckusick /* 13110315Smckusick * Remove an old node (directory). 13210315Smckusick */ 13356567Sbostic void 13410315Smckusick removenode(ep) 13510315Smckusick register struct entry *ep; 13610315Smckusick { 13710315Smckusick char *cp; 13810315Smckusick 13910315Smckusick if (ep->e_type != NODE) 14010315Smckusick badentry(ep, "removenode: not a node"); 14156567Sbostic if (ep->e_entries != NULL) 14210315Smckusick badentry(ep, "removenode: non-empty directory"); 14311923Smckusick ep->e_flags |= REMOVED; 14411923Smckusick ep->e_flags &= ~TMPNAME; 14510315Smckusick cp = myname(ep); 14634268Smckusick if (!Nflag && rmdir(cp) < 0) { 14756567Sbostic fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno)); 14811923Smckusick return; 14910315Smckusick } 15010315Smckusick vprintf(stdout, "Remove node %s\n", cp); 15110315Smckusick } 15210315Smckusick 15310315Smckusick /* 15410315Smckusick * Remove a leaf. 15510315Smckusick */ 15656567Sbostic void 15710315Smckusick removeleaf(ep) 15810315Smckusick register struct entry *ep; 15910315Smckusick { 16010315Smckusick char *cp; 16110315Smckusick 16210315Smckusick if (ep->e_type != LEAF) 16310315Smckusick badentry(ep, "removeleaf: not a leaf"); 16411923Smckusick ep->e_flags |= REMOVED; 16511923Smckusick ep->e_flags &= ~TMPNAME; 16610315Smckusick cp = myname(ep); 16734268Smckusick if (!Nflag && unlink(cp) < 0) { 16856567Sbostic fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno)); 16911923Smckusick return; 17010315Smckusick } 17110315Smckusick vprintf(stdout, "Remove leaf %s\n", cp); 17210315Smckusick } 17310315Smckusick 17410315Smckusick /* 17510315Smckusick * Create a link. 17610315Smckusick */ 17756567Sbostic int 17810315Smckusick linkit(existing, new, type) 17910315Smckusick char *existing, *new; 18010315Smckusick int type; 18110315Smckusick { 18210315Smckusick 18310315Smckusick if (type == SYMLINK) { 18434268Smckusick if (!Nflag && symlink(existing, new) < 0) { 18511923Smckusick fprintf(stderr, 18656567Sbostic "warning: cannot create symbolic link %s->%s: %s\n", 18756567Sbostic new, existing, strerror(errno)); 18815782Smckusick return (FAIL); 18910315Smckusick } 19010315Smckusick } else if (type == HARDLINK) { 19134268Smckusick if (!Nflag && link(existing, new) < 0) { 19211923Smckusick fprintf(stderr, 19356567Sbostic "warning: cannot create hard link %s->%s: %s\n", 19456567Sbostic new, existing, strerror(errno)); 19515782Smckusick return (FAIL); 19610315Smckusick } 19710315Smckusick } else { 19810315Smckusick panic("linkit: unknown type %d\n", type); 19915782Smckusick return (FAIL); 20010315Smckusick } 20110315Smckusick vprintf(stdout, "Create %s link %s->%s\n", 20210315Smckusick type == SYMLINK ? "symbolic" : "hard", new, existing); 20315782Smckusick return (GOOD); 20410315Smckusick } 20510315Smckusick 20610315Smckusick /* 20710315Smckusick * find lowest number file (above "start") that needs to be extracted 20810315Smckusick */ 20910315Smckusick ino_t 21010315Smckusick lowerbnd(start) 21110315Smckusick ino_t start; 21210315Smckusick { 21310315Smckusick register struct entry *ep; 21410315Smckusick 21510315Smckusick for ( ; start < maxino; start++) { 21610315Smckusick ep = lookupino(start); 21756567Sbostic if (ep == NULL || ep->e_type == NODE) 21810315Smckusick continue; 21911645Smckusick if (ep->e_flags & (NEW|EXTRACT)) 22010315Smckusick return (start); 22110315Smckusick } 22210315Smckusick return (start); 22310315Smckusick } 22410315Smckusick 22510315Smckusick /* 22610315Smckusick * find highest number file (below "start") that needs to be extracted 22710315Smckusick */ 22810315Smckusick ino_t 22910315Smckusick upperbnd(start) 23010315Smckusick ino_t start; 23110315Smckusick { 23210315Smckusick register struct entry *ep; 23310315Smckusick 23410315Smckusick for ( ; start > ROOTINO; start--) { 23510315Smckusick ep = lookupino(start); 23656567Sbostic if (ep == NULL || ep->e_type == NODE) 23710315Smckusick continue; 23811645Smckusick if (ep->e_flags & (NEW|EXTRACT)) 23910315Smckusick return (start); 24010315Smckusick } 24110315Smckusick return (start); 24210315Smckusick } 24310315Smckusick 24410315Smckusick /* 24510315Smckusick * report on a badly formed entry 24610315Smckusick */ 24756567Sbostic void 24810315Smckusick badentry(ep, msg) 24910315Smckusick register struct entry *ep; 25010315Smckusick char *msg; 25110315Smckusick { 25210315Smckusick 25310315Smckusick fprintf(stderr, "bad entry: %s\n", msg); 25410315Smckusick fprintf(stderr, "name: %s\n", myname(ep)); 25510315Smckusick fprintf(stderr, "parent name %s\n", myname(ep->e_parent)); 25656567Sbostic if (ep->e_sibling != NULL) 25710315Smckusick fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling)); 25856567Sbostic if (ep->e_entries != NULL) 25910315Smckusick fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries)); 26056567Sbostic if (ep->e_links != NULL) 26110315Smckusick fprintf(stderr, "next link name: %s\n", myname(ep->e_links)); 26256567Sbostic if (ep->e_next != NULL) 26356567Sbostic fprintf(stderr, 26456567Sbostic "next hashchain name: %s\n", myname(ep->e_next)); 26510315Smckusick fprintf(stderr, "entry type: %s\n", 26610315Smckusick ep->e_type == NODE ? "NODE" : "LEAF"); 26710315Smckusick fprintf(stderr, "inode number: %ld\n", ep->e_ino); 26811898Smckusick panic("flags: %s\n", flagvalues(ep)); 26911898Smckusick } 27011898Smckusick 27111898Smckusick /* 27211898Smckusick * Construct a string indicating the active flag bits of an entry. 27311898Smckusick */ 27411898Smckusick char * 27511898Smckusick flagvalues(ep) 27611898Smckusick register struct entry *ep; 27711898Smckusick { 27811898Smckusick static char flagbuf[BUFSIZ]; 27911898Smckusick 28011898Smckusick (void) strcpy(flagbuf, "|NIL"); 28110315Smckusick flagbuf[0] = '\0'; 28210315Smckusick if (ep->e_flags & REMOVED) 28311898Smckusick (void) strcat(flagbuf, "|REMOVED"); 28410315Smckusick if (ep->e_flags & TMPNAME) 28511898Smckusick (void) strcat(flagbuf, "|TMPNAME"); 28610315Smckusick if (ep->e_flags & EXTRACT) 28711898Smckusick (void) strcat(flagbuf, "|EXTRACT"); 28810315Smckusick if (ep->e_flags & NEW) 28911898Smckusick (void) strcat(flagbuf, "|NEW"); 29010315Smckusick if (ep->e_flags & KEEP) 29111898Smckusick (void) strcat(flagbuf, "|KEEP"); 29218006Smckusick if (ep->e_flags & EXISTED) 29318006Smckusick (void) strcat(flagbuf, "|EXISTED"); 29411898Smckusick return (&flagbuf[1]); 29510315Smckusick } 29610315Smckusick 29710315Smckusick /* 29811995Smckusick * Check to see if a name is on a dump tape. 29911321Smckusick */ 30011995Smckusick ino_t 30111995Smckusick dirlookup(name) 30257896Sbostic const char *name; 30311995Smckusick { 304*66443Sbostic struct direct *dp; 30511995Smckusick ino_t ino; 306*66443Sbostic 307*66443Sbostic ino = ((dp = pathsearch(name)) == NULL) ? 0 : dp->d_ino; 30811995Smckusick 30956427Smckusick if (ino == 0 || TSTINO(ino, dumpmap) == 0) 310*66443Sbostic fprintf(stderr, "%s is not on the tape\n", name); 31111995Smckusick return (ino); 31211995Smckusick } 31311995Smckusick 31411995Smckusick /* 31511995Smckusick * Elicit a reply. 31610315Smckusick */ 31756567Sbostic int 31810315Smckusick reply(question) 31910315Smckusick char *question; 32010315Smckusick { 32110315Smckusick char c; 32210315Smckusick 32310315Smckusick do { 32424185Smckusick fprintf(stderr, "%s? [yn] ", question); 32512557Smckusick (void) fflush(stderr); 32611995Smckusick c = getc(terminal); 32711995Smckusick while (c != '\n' && getc(terminal) != '\n') 32817711Smckusick if (feof(terminal)) 32924185Smckusick return (FAIL); 33010315Smckusick } while (c != 'y' && c != 'n'); 33110315Smckusick if (c == 'y') 33210315Smckusick return (GOOD); 33310315Smckusick return (FAIL); 33410315Smckusick } 33511995Smckusick 33611995Smckusick /* 33711995Smckusick * handle unexpected inconsistencies 33811995Smckusick */ 33956567Sbostic #if __STDC__ 34056567Sbostic #include <stdarg.h> 34156567Sbostic #else 34256567Sbostic #include <varargs.h> 34356567Sbostic #endif 34456567Sbostic 34556567Sbostic void 34656567Sbostic #if __STDC__ 34756567Sbostic panic(const char *fmt, ...) 34856567Sbostic #else 34956567Sbostic panic(fmt, va_alist) 35056567Sbostic char *fmt; 35156567Sbostic va_dcl 35256567Sbostic #endif 35311995Smckusick { 35456567Sbostic va_list ap; 35556567Sbostic #if __STDC__ 35656567Sbostic va_start(ap, fmt); 35756567Sbostic #else 35856567Sbostic va_start(ap); 35956567Sbostic #endif 36011995Smckusick 36156567Sbostic vfprintf(stderr, fmt, ap); 36242489Smckusick if (yflag) 36342489Smckusick return; 36411995Smckusick if (reply("abort") == GOOD) { 36511995Smckusick if (reply("dump core") == GOOD) 36611995Smckusick abort(); 36711995Smckusick done(1); 36811995Smckusick } 36911995Smckusick } 370