110315Smckusick /* Copyright (c) 1983 Regents of the University of California */ 210315Smckusick 310315Smckusick #ifndef lint 4*11645Smckusick static char sccsid[] = "@(#)utilities.c 3.6 (Berkeley) 83/03/23"; 510315Smckusick #endif 610315Smckusick 710315Smckusick #include "restore.h" 810315Smckusick 910315Smckusick /* 1010315Smckusick * Insure that all the components of a pathname exist. 1110315Smckusick */ 12*11645Smckusick pathcheck(name) 1310315Smckusick char *name; 1410315Smckusick { 1510315Smckusick register char *cp; 1610315Smckusick struct entry *ep; 1711312Smckusick char *start; 1810315Smckusick 1910315Smckusick start = index(name, '/'); 2011312Smckusick if (start == 0) 21*11645Smckusick return; 2210315Smckusick for (cp = start; *cp != '\0'; cp++) { 2310315Smckusick if (*cp != '/') 2410315Smckusick continue; 2510315Smckusick *cp = '\0'; 2610315Smckusick ep = lookupname(name); 2710315Smckusick if (ep == NIL) { 28*11645Smckusick ep = addentry(name, ep->e_ino, NODE); 29*11645Smckusick ep->e_flags |= KEEP; 3010315Smckusick newnode(ep); 3110315Smckusick } 3210315Smckusick *cp = '/'; 3310315Smckusick } 3410315Smckusick } 3510315Smckusick 3610315Smckusick /* 3710315Smckusick * Change a name to a unique temporary name. 3810315Smckusick */ 3910315Smckusick mktempname(ep) 4010315Smckusick register struct entry *ep; 4110315Smckusick { 42*11645Smckusick char oldname[MAXPATHLEN]; 4310315Smckusick 4410315Smckusick if (ep->e_flags & TMPNAME) 4510315Smckusick badentry(ep, "mktempname: called with TMPNAME"); 4610315Smckusick ep->e_flags |= TMPNAME; 4710315Smckusick strcpy(oldname, myname(ep)); 48*11645Smckusick freename(ep->e_name); 49*11645Smckusick ep->e_name = savename(gentempname(ep)); 50*11645Smckusick ep->e_namlen = strlen(ep->e_name); 5110315Smckusick renameit(oldname, myname(ep)); 5210315Smckusick } 5310315Smckusick 5410315Smckusick /* 55*11645Smckusick * Generate a temporary name for an entry. 56*11645Smckusick */ 57*11645Smckusick char * 58*11645Smckusick gentempname(ep) 59*11645Smckusick struct entry *ep; 60*11645Smckusick { 61*11645Smckusick static char name[MAXPATHLEN]; 62*11645Smckusick struct entry *np; 63*11645Smckusick long i = 0; 64*11645Smckusick 65*11645Smckusick for (np = lookupino(ep->e_ino); np != NIL && np != ep; np = np->e_links) 66*11645Smckusick i++; 67*11645Smckusick if (np == NIL) 68*11645Smckusick badentry(ep, "not on ino list"); 69*11645Smckusick sprintf(name, "%s%d%d", TMPHDR, i, ep->e_ino); 70*11645Smckusick return (name); 71*11645Smckusick } 72*11645Smckusick 73*11645Smckusick /* 7410315Smckusick * Rename a file or directory. 7510315Smckusick */ 7610315Smckusick renameit(from, to) 7710315Smckusick char *from, *to; 7810315Smckusick { 7910315Smckusick if (rename(from, to) < 0) { 8010315Smckusick perror("renameit"); 8110315Smckusick panic("Cannot rename %s to %s\n", from, to); 8210315Smckusick } 8310315Smckusick vprintf(stdout, "rename %s to %s\n", from, to); 8410315Smckusick } 8510315Smckusick 8610315Smckusick /* 8710315Smckusick * Create a new node (directory). 8810315Smckusick */ 8910315Smckusick newnode(np) 9010315Smckusick struct entry *np; 9110315Smckusick { 9210315Smckusick char *cp; 9310315Smckusick 9410315Smckusick if (np->e_type != NODE) 9510315Smckusick badentry(np, "newnode: not a node"); 9610315Smckusick cp = myname(np); 9711312Smckusick if (mkdir(cp, 0777) < 0) { 9811314Smckusick if (command == 'x') { 9911314Smckusick perror(cp); 10011314Smckusick return; 10111314Smckusick } 10210315Smckusick perror("newnode"); 10310315Smckusick panic("Cannot make node %s\n", cp); 10410315Smckusick } 10510315Smckusick vprintf(stdout, "Make node %s\n", cp); 10610315Smckusick } 10710315Smckusick 10810315Smckusick /* 10910315Smckusick * Remove an old node (directory). 11010315Smckusick */ 11110315Smckusick removenode(ep) 11210315Smckusick register struct entry *ep; 11310315Smckusick { 11410315Smckusick char *cp; 11510315Smckusick 11610315Smckusick if (ep->e_type != NODE) 11710315Smckusick badentry(ep, "removenode: not a node"); 11810315Smckusick if (ep->e_entries != NIL) 11910315Smckusick badentry(ep, "removenode: non-empty directory"); 12010315Smckusick cp = myname(ep); 12110315Smckusick if (rmdir(cp) < 0) { 12210315Smckusick perror("removenode"); 12310315Smckusick panic("Cannot remove node %s\n", cp); 12410315Smckusick } 12510315Smckusick ep->e_flags |= REMOVED; 126*11645Smckusick ep->e_flags &= ~TMPNAME; 12710315Smckusick vprintf(stdout, "Remove node %s\n", cp); 12810315Smckusick } 12910315Smckusick 13010315Smckusick /* 13110315Smckusick * Remove a leaf. 13210315Smckusick */ 13310315Smckusick removeleaf(ep) 13410315Smckusick register struct entry *ep; 13510315Smckusick { 13610315Smckusick char *cp; 13710315Smckusick 13810315Smckusick if (ep->e_type != LEAF) 13910315Smckusick badentry(ep, "removeleaf: not a leaf"); 14010315Smckusick cp = myname(ep); 14110315Smckusick if (unlink(cp) < 0) { 14210315Smckusick perror("removeleaf"); 14310315Smckusick panic("Cannot remove leaf %s\n", cp); 14410315Smckusick } 14510315Smckusick ep->e_flags |= REMOVED; 14610315Smckusick ep->e_flags &= ~TMPNAME; 14710315Smckusick vprintf(stdout, "Remove leaf %s\n", cp); 14810315Smckusick } 14910315Smckusick 15010315Smckusick /* 15110315Smckusick * Create a link. 15210315Smckusick */ 15310315Smckusick linkit(existing, new, type) 15410315Smckusick char *existing, *new; 15510315Smckusick int type; 15610315Smckusick { 15710315Smckusick 15810315Smckusick if (type == SYMLINK) { 15910315Smckusick if (symlink(existing, new) < 0) { 16010315Smckusick perror("linkit"); 16110315Smckusick panic("Cannot create symbolic link %s->%s\n", 16210315Smckusick new, existing); 16310315Smckusick } 16410315Smckusick } else if (type == HARDLINK) { 16510315Smckusick if (link(existing, new) < 0) { 16610315Smckusick perror("linkit"); 16710315Smckusick panic("Cannot create hard link %s->%s\n", 16810315Smckusick new, existing); 16910315Smckusick } 17010315Smckusick } else { 17110315Smckusick panic("linkit: unknown type %d\n", type); 17210315Smckusick } 17310315Smckusick vprintf(stdout, "Create %s link %s->%s\n", 17410315Smckusick type == SYMLINK ? "symbolic" : "hard", new, existing); 17510315Smckusick } 17610315Smckusick 17710315Smckusick /* 17810315Smckusick * find lowest number file (above "start") that needs to be extracted 17910315Smckusick */ 18010315Smckusick ino_t 18110315Smckusick lowerbnd(start) 18210315Smckusick ino_t start; 18310315Smckusick { 18410315Smckusick register struct entry *ep; 18510315Smckusick 18610315Smckusick for ( ; start < maxino; start++) { 18710315Smckusick ep = lookupino(start); 18810315Smckusick if (ep == NIL) 18910315Smckusick continue; 190*11645Smckusick if (ep->e_flags & (NEW|EXTRACT)) 19110315Smckusick return (start); 19210315Smckusick } 19310315Smckusick return (start); 19410315Smckusick } 19510315Smckusick 19610315Smckusick /* 19710315Smckusick * find highest number file (below "start") that needs to be extracted 19810315Smckusick */ 19910315Smckusick ino_t 20010315Smckusick upperbnd(start) 20110315Smckusick ino_t start; 20210315Smckusick { 20310315Smckusick register struct entry *ep; 20410315Smckusick 20510315Smckusick for ( ; start > ROOTINO; start--) { 20610315Smckusick ep = lookupino(start); 20710315Smckusick if (ep == NIL) 20810315Smckusick continue; 209*11645Smckusick if (ep->e_flags & (NEW|EXTRACT)) 21010315Smckusick return (start); 21110315Smckusick } 21210315Smckusick return (start); 21310315Smckusick } 21410315Smckusick 21510315Smckusick /* 21610315Smckusick * report on a badly formed entry 21710315Smckusick */ 21810315Smckusick badentry(ep, msg) 21910315Smckusick register struct entry *ep; 22010315Smckusick char *msg; 22110315Smckusick { 22210315Smckusick char flagbuf[BUFSIZ]; 22310315Smckusick 22410315Smckusick fprintf(stderr, "bad entry: %s\n", msg); 22510315Smckusick fprintf(stderr, "name: %s\n", myname(ep)); 22610315Smckusick fprintf(stderr, "parent name %s\n", myname(ep->e_parent)); 22710315Smckusick if (ep->e_sibling != NIL) 22810315Smckusick fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling)); 22910315Smckusick if (ep->e_entries != NIL) 23010315Smckusick fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries)); 23110315Smckusick if (ep->e_links != NIL) 23210315Smckusick fprintf(stderr, "next link name: %s\n", myname(ep->e_links)); 233*11645Smckusick if (ep->e_next != NIL) 234*11645Smckusick fprintf(stderr, "next hashchain name: %s\n", myname(ep->e_next)); 23510315Smckusick fprintf(stderr, "entry type: %s\n", 23610315Smckusick ep->e_type == NODE ? "NODE" : "LEAF"); 23710315Smckusick fprintf(stderr, "inode number: %ld\n", ep->e_ino); 23810315Smckusick strcpy(flagbuf, "|NIL"); 23910315Smckusick flagbuf[0] = '\0'; 24010315Smckusick if (ep->e_flags & REMOVED) 24110315Smckusick strcat(flagbuf, "|REMOVED"); 24210315Smckusick if (ep->e_flags & TMPNAME) 24310315Smckusick strcat(flagbuf, "|TMPNAME"); 24410315Smckusick if (ep->e_flags & EXTRACT) 24510315Smckusick strcat(flagbuf, "|EXTRACT"); 24610315Smckusick if (ep->e_flags & NEW) 24710315Smckusick strcat(flagbuf, "|NEW"); 24810315Smckusick if (ep->e_flags & KEEP) 24910315Smckusick strcat(flagbuf, "|KEEP"); 25010315Smckusick panic("flags: %s\n", &flagbuf[1]); 25110315Smckusick } 25210315Smckusick 25310315Smckusick /* 25411321Smckusick * canonicalize file names to always start with ``./'' 25511321Smckusick */ 25611321Smckusick canon(rawname, canonname) 25711321Smckusick char *rawname, *canonname; 25811321Smckusick { 25911321Smckusick int len; 26011321Smckusick 26111321Smckusick if (strcmp(rawname, ".") == 0 || strncmp(rawname, "./", 2) == 0) 262*11645Smckusick (void) strcpy(canonname, ""); 26311321Smckusick else if (rawname[0] == '/') 264*11645Smckusick (void) strcpy(canonname, "."); 26511321Smckusick else 266*11645Smckusick (void) strcpy(canonname, "./"); 267*11645Smckusick (void) strcat(canonname, rawname); 26811321Smckusick len = strlen(canonname) - 1; 26911321Smckusick if (canonname[len] == '/') 27011321Smckusick canonname[len] = '\0'; 27111321Smckusick } 27211321Smckusick 27311321Smckusick /* 27410315Smckusick * elicit a reply 27510315Smckusick */ 27610315Smckusick reply(question) 27710315Smckusick char *question; 27810315Smckusick { 27910315Smckusick char c; 28010315Smckusick 28110315Smckusick fprintf(stderr, "%s? ", question); 28210315Smckusick do { 28310315Smckusick fprintf(stderr, "[yn] "); 28410315Smckusick c = getchar(); 28510315Smckusick while (c != '\n' && getchar() != '\n') 28610315Smckusick /* void */; 28710315Smckusick } while (c != 'y' && c != 'n'); 28810315Smckusick if (c == 'y') 28910315Smckusick return (GOOD); 29010315Smckusick return (FAIL); 29110315Smckusick } 292