1*10315Smckusick /* Copyright (c) 1983 Regents of the University of California */ 2*10315Smckusick 3*10315Smckusick #ifndef lint 4*10315Smckusick static char sccsid[] = "@(#)utilities.c 3.5 (Berkeley) 83/01/16"; 5*10315Smckusick #endif 6*10315Smckusick 7*10315Smckusick #include "restore.h" 8*10315Smckusick 9*10315Smckusick /* 10*10315Smckusick * Insure that all the components of a pathname exist. 11*10315Smckusick */ 12*10315Smckusick pathcheck(name) 13*10315Smckusick char *name; 14*10315Smckusick { 15*10315Smckusick register char *cp; 16*10315Smckusick struct entry *ep; 17*10315Smckusick char *start; 18*10315Smckusick 19*10315Smckusick start = index(name, '/'); 20*10315Smckusick if (start == 0) 21*10315Smckusick return; 22*10315Smckusick for (cp = start; *cp != '\0'; cp++) { 23*10315Smckusick if (*cp != '/') 24*10315Smckusick continue; 25*10315Smckusick *cp = '\0'; 26*10315Smckusick ep = lookupname(name); 27*10315Smckusick if (ep == NIL) { 28*10315Smckusick ep = addentry(name, ep->e_ino, NODE); 29*10315Smckusick ep->e_flags |= KEEP; 30*10315Smckusick newnode(ep); 31*10315Smckusick } 32*10315Smckusick *cp = '/'; 33*10315Smckusick } 34*10315Smckusick } 35*10315Smckusick 36*10315Smckusick /* 37*10315Smckusick * Change a name to a unique temporary name. 38*10315Smckusick */ 39*10315Smckusick mktempname(ep) 40*10315Smckusick register struct entry *ep; 41*10315Smckusick { 42*10315Smckusick char oldname[BUFSIZ]; 43*10315Smckusick 44*10315Smckusick if (ep->e_flags & TMPNAME) 45*10315Smckusick badentry(ep, "mktempname: called with TMPNAME"); 46*10315Smckusick ep->e_flags |= TMPNAME; 47*10315Smckusick strcpy(oldname, myname(ep)); 48*10315Smckusick ep->e_name[ep->e_namlen++] = TMPCHAR; 49*10315Smckusick ep->e_name[ep->e_namlen] = '\0'; 50*10315Smckusick renameit(oldname, myname(ep)); 51*10315Smckusick } 52*10315Smckusick 53*10315Smckusick /* 54*10315Smckusick * Rename a file or directory. 55*10315Smckusick */ 56*10315Smckusick renameit(from, to) 57*10315Smckusick char *from, *to; 58*10315Smckusick { 59*10315Smckusick if (rename(from, to) < 0) { 60*10315Smckusick perror("renameit"); 61*10315Smckusick panic("Cannot rename %s to %s\n", from, to); 62*10315Smckusick } 63*10315Smckusick vprintf(stdout, "rename %s to %s\n", from, to); 64*10315Smckusick } 65*10315Smckusick 66*10315Smckusick /* 67*10315Smckusick * Create a new node (directory). 68*10315Smckusick */ 69*10315Smckusick newnode(np) 70*10315Smckusick struct entry *np; 71*10315Smckusick { 72*10315Smckusick char *cp; 73*10315Smckusick 74*10315Smckusick if (np->e_type != NODE) 75*10315Smckusick badentry(np, "newnode: not a node"); 76*10315Smckusick cp = myname(np); 77*10315Smckusick if (mkdir(cp, 0777) < 0) { 78*10315Smckusick if (command == 'x') { 79*10315Smckusick perror(cp); 80*10315Smckusick return; 81*10315Smckusick } 82*10315Smckusick perror("newnode"); 83*10315Smckusick panic("Cannot make node %s\n", cp); 84*10315Smckusick } 85*10315Smckusick vprintf(stdout, "Make node %s\n", cp); 86*10315Smckusick } 87*10315Smckusick 88*10315Smckusick /* 89*10315Smckusick * Remove an old node (directory). 90*10315Smckusick */ 91*10315Smckusick removenode(ep) 92*10315Smckusick register struct entry *ep; 93*10315Smckusick { 94*10315Smckusick char *cp; 95*10315Smckusick 96*10315Smckusick if (ep->e_type != NODE) 97*10315Smckusick badentry(ep, "removenode: not a node"); 98*10315Smckusick if (ep->e_entries != NIL) 99*10315Smckusick badentry(ep, "removenode: non-empty directory"); 100*10315Smckusick cp = myname(ep); 101*10315Smckusick if (rmdir(cp) < 0) { 102*10315Smckusick perror("removenode"); 103*10315Smckusick panic("Cannot remove node %s\n", cp); 104*10315Smckusick } 105*10315Smckusick ep->e_flags |= REMOVED; 106*10315Smckusick ep->e_flags &= ~TMPNAME; 107*10315Smckusick vprintf(stdout, "Remove node %s\n", cp); 108*10315Smckusick } 109*10315Smckusick 110*10315Smckusick /* 111*10315Smckusick * Remove a leaf. 112*10315Smckusick */ 113*10315Smckusick removeleaf(ep) 114*10315Smckusick register struct entry *ep; 115*10315Smckusick { 116*10315Smckusick char *cp; 117*10315Smckusick 118*10315Smckusick if (ep->e_type != LEAF) 119*10315Smckusick badentry(ep, "removeleaf: not a leaf"); 120*10315Smckusick cp = myname(ep); 121*10315Smckusick if (unlink(cp) < 0) { 122*10315Smckusick perror("removeleaf"); 123*10315Smckusick panic("Cannot remove leaf %s\n", cp); 124*10315Smckusick } 125*10315Smckusick ep->e_flags |= REMOVED; 126*10315Smckusick ep->e_flags &= ~TMPNAME; 127*10315Smckusick vprintf(stdout, "Remove leaf %s\n", cp); 128*10315Smckusick } 129*10315Smckusick 130*10315Smckusick /* 131*10315Smckusick * Create a link. 132*10315Smckusick */ 133*10315Smckusick linkit(existing, new, type) 134*10315Smckusick char *existing, *new; 135*10315Smckusick int type; 136*10315Smckusick { 137*10315Smckusick 138*10315Smckusick if (type == SYMLINK) { 139*10315Smckusick if (symlink(existing, new) < 0) { 140*10315Smckusick perror("linkit"); 141*10315Smckusick panic("Cannot create symbolic link %s->%s\n", 142*10315Smckusick new, existing); 143*10315Smckusick } 144*10315Smckusick } else if (type == HARDLINK) { 145*10315Smckusick if (link(existing, new) < 0) { 146*10315Smckusick perror("linkit"); 147*10315Smckusick panic("Cannot create hard link %s->%s\n", 148*10315Smckusick new, existing); 149*10315Smckusick } 150*10315Smckusick } else { 151*10315Smckusick panic("linkit: unknown type %d\n", type); 152*10315Smckusick } 153*10315Smckusick vprintf(stdout, "Create %s link %s->%s\n", 154*10315Smckusick type == SYMLINK ? "symbolic" : "hard", new, existing); 155*10315Smckusick } 156*10315Smckusick 157*10315Smckusick /* 158*10315Smckusick * find lowest number file (above "start") that needs to be extracted 159*10315Smckusick */ 160*10315Smckusick ino_t 161*10315Smckusick lowerbnd(start) 162*10315Smckusick ino_t start; 163*10315Smckusick { 164*10315Smckusick register struct entry *ep; 165*10315Smckusick 166*10315Smckusick for ( ; start < maxino; start++) { 167*10315Smckusick ep = lookupino(start); 168*10315Smckusick if (ep == NIL) 169*10315Smckusick continue; 170*10315Smckusick if (ep->e_flags & (NEW|EXTRACT)) 171*10315Smckusick return (start); 172*10315Smckusick } 173*10315Smckusick return (start); 174*10315Smckusick } 175*10315Smckusick 176*10315Smckusick /* 177*10315Smckusick * find highest number file (below "start") that needs to be extracted 178*10315Smckusick */ 179*10315Smckusick ino_t 180*10315Smckusick upperbnd(start) 181*10315Smckusick ino_t start; 182*10315Smckusick { 183*10315Smckusick register struct entry *ep; 184*10315Smckusick 185*10315Smckusick for ( ; start > ROOTINO; start--) { 186*10315Smckusick ep = lookupino(start); 187*10315Smckusick if (ep == NIL) 188*10315Smckusick continue; 189*10315Smckusick if (ep->e_flags & (NEW|EXTRACT)) 190*10315Smckusick return (start); 191*10315Smckusick } 192*10315Smckusick return (start); 193*10315Smckusick } 194*10315Smckusick 195*10315Smckusick /* 196*10315Smckusick * report on a badly formed entry 197*10315Smckusick */ 198*10315Smckusick badentry(ep, msg) 199*10315Smckusick register struct entry *ep; 200*10315Smckusick char *msg; 201*10315Smckusick { 202*10315Smckusick char flagbuf[BUFSIZ]; 203*10315Smckusick 204*10315Smckusick fprintf(stderr, "bad entry: %s\n", msg); 205*10315Smckusick fprintf(stderr, "name: %s\n", myname(ep)); 206*10315Smckusick fprintf(stderr, "parent name %s\n", myname(ep->e_parent)); 207*10315Smckusick if (ep->e_sibling != NIL) 208*10315Smckusick fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling)); 209*10315Smckusick if (ep->e_entries != NIL) 210*10315Smckusick fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries)); 211*10315Smckusick if (ep->e_links != NIL) 212*10315Smckusick fprintf(stderr, "next link name: %s\n", myname(ep->e_links)); 213*10315Smckusick if (ep->e_next != NIL) 214*10315Smckusick fprintf(stderr, "next hashchain name: %s\n", myname(ep->e_next)); 215*10315Smckusick fprintf(stderr, "entry type: %s\n", 216*10315Smckusick ep->e_type == NODE ? "NODE" : "LEAF"); 217*10315Smckusick fprintf(stderr, "inode number: %ld\n", ep->e_ino); 218*10315Smckusick strcpy(flagbuf, "|NIL"); 219*10315Smckusick flagbuf[0] = '\0'; 220*10315Smckusick if (ep->e_flags & REMOVED) 221*10315Smckusick strcat(flagbuf, "|REMOVED"); 222*10315Smckusick if (ep->e_flags & TMPNAME) 223*10315Smckusick strcat(flagbuf, "|TMPNAME"); 224*10315Smckusick if (ep->e_flags & EXTRACT) 225*10315Smckusick strcat(flagbuf, "|EXTRACT"); 226*10315Smckusick if (ep->e_flags & NEW) 227*10315Smckusick strcat(flagbuf, "|NEW"); 228*10315Smckusick if (ep->e_flags & KEEP) 229*10315Smckusick strcat(flagbuf, "|KEEP"); 230*10315Smckusick panic("flags: %s\n", &flagbuf[1]); 231*10315Smckusick } 232*10315Smckusick 233*10315Smckusick /* 234*10315Smckusick * canonicalize file names to always start with ``./'' 235*10315Smckusick */ 236*10315Smckusick canon(rawname, canonname) 237*10315Smckusick char *rawname, *canonname; 238*10315Smckusick { 239*10315Smckusick int len; 240*10315Smckusick 241*10315Smckusick if (strcmp(rawname, ".") == 0 || strncmp(rawname, "./", 2) == 0) 242*10315Smckusick (void) strcpy(canonname, ""); 243*10315Smckusick else if (rawname[0] == '/') 244*10315Smckusick (void) strcpy(canonname, "."); 245*10315Smckusick else 246*10315Smckusick (void) strcpy(canonname, "./"); 247*10315Smckusick (void) strcat(canonname, rawname); 248*10315Smckusick len = strlen(canonname) - 1; 249*10315Smckusick if (canonname[len] == '/') 250*10315Smckusick canonname[len] = '\0'; 251*10315Smckusick } 252*10315Smckusick 253*10315Smckusick /* 254*10315Smckusick * elicit a reply 255*10315Smckusick */ 256*10315Smckusick reply(question) 257*10315Smckusick char *question; 258*10315Smckusick { 259*10315Smckusick char c; 260*10315Smckusick 261*10315Smckusick fprintf(stderr, "%s? ", question); 262*10315Smckusick do { 263*10315Smckusick fprintf(stderr, "[yn] "); 264*10315Smckusick c = getchar(); 265*10315Smckusick while (c != '\n' && getchar() != '\n') 266*10315Smckusick /* void */; 267*10315Smckusick } while (c != 'y' && c != 'n'); 268*10315Smckusick if (c == 'y') 269*10315Smckusick return (GOOD); 270*10315Smckusick return (FAIL); 271*10315Smckusick } 272