110315Smckusick /* Copyright (c) 1983 Regents of the University of California */ 210315Smckusick 310315Smckusick #ifndef lint 4*11321Smckusick static char sccsid[] = "@(#)utilities.c 3.4 (Berkeley) 83/02/28"; 510315Smckusick #endif 610315Smckusick 710315Smckusick #include "restore.h" 810315Smckusick 910315Smckusick /* 1011131Smckusick * Move the contents of a directory to a new directory. 1111131Smckusick */ 1211131Smckusick movecontents(from, to) 1311131Smckusick struct entry *from, *to; 1411131Smckusick { 1511131Smckusick register struct entry *ep; 1611131Smckusick struct entry *np; 1711131Smckusick register char *targetp; 1811131Smckusick char target[BUFSIZ]; 1911131Smckusick 2011131Smckusick strcpy(target, myname(to)); 2111131Smckusick targetp = &target[strlen(target)]; 2211131Smckusick *targetp++ = '/'; 2311131Smckusick for (ep = from->e_entries; ep != NIL; ) { 2411131Smckusick strcpy(targetp, ep->e_name); 2511131Smckusick if (ep->e_flags & TMPNAME) 2611131Smckusick badentry(ep, "movecontents: found TMPNAME"); 2711131Smckusick np = lookupname(target); 2811131Smckusick if (np != NIL) 2911131Smckusick mktempname(np); 3011131Smckusick renameit(myname(ep), target); 3111131Smckusick np = ep->e_sibling; 3211131Smckusick moveentry(ep, target); 3311131Smckusick ep = np; 3411131Smckusick } 3511131Smckusick } 3611131Smckusick 3711131Smckusick /* 3810315Smckusick * Insure that all the components of a pathname exist. 3910315Smckusick */ 4011131Smckusick struct entry * 4111131Smckusick pathcheck(name, type) 4210315Smckusick char *name; 4311131Smckusick char type; 4410315Smckusick { 4510315Smckusick register char *cp; 4610315Smckusick struct entry *ep; 4711312Smckusick char *start; 4810315Smckusick 4910315Smckusick start = index(name, '/'); 5011312Smckusick if (start == 0) 5111131Smckusick return (lookupino(ROOTINO)); 5210315Smckusick for (cp = start; *cp != '\0'; cp++) { 5310315Smckusick if (*cp != '/') 5410315Smckusick continue; 5510315Smckusick *cp = '\0'; 5610315Smckusick ep = lookupname(name); 5710315Smckusick if (ep == NIL) { 5811131Smckusick ep = addentry(name, (ino_t)0, NODE); 5911131Smckusick ep->e_flags |= type; 6010315Smckusick newnode(ep); 6110315Smckusick } 6210315Smckusick *cp = '/'; 6310315Smckusick } 6411131Smckusick return (ep); 6510315Smckusick } 6610315Smckusick 6710315Smckusick /* 6810315Smckusick * Change a name to a unique temporary name. 6910315Smckusick */ 7010315Smckusick mktempname(ep) 7110315Smckusick register struct entry *ep; 7210315Smckusick { 7310315Smckusick char oldname[BUFSIZ]; 7410315Smckusick 7510315Smckusick if (ep->e_flags & TMPNAME) 7610315Smckusick badentry(ep, "mktempname: called with TMPNAME"); 7710315Smckusick ep->e_flags |= TMPNAME; 7810315Smckusick strcpy(oldname, myname(ep)); 7910315Smckusick ep->e_name[ep->e_namlen++] = TMPCHAR; 8010315Smckusick ep->e_name[ep->e_namlen] = '\0'; 8110315Smckusick renameit(oldname, myname(ep)); 8210315Smckusick } 8310315Smckusick 8410315Smckusick /* 8510315Smckusick * Rename a file or directory. 8610315Smckusick */ 8710315Smckusick renameit(from, to) 8810315Smckusick char *from, *to; 8910315Smckusick { 9010315Smckusick if (rename(from, to) < 0) { 9110315Smckusick perror("renameit"); 9210315Smckusick panic("Cannot rename %s to %s\n", from, to); 9310315Smckusick } 9410315Smckusick vprintf(stdout, "rename %s to %s\n", from, to); 9510315Smckusick } 9610315Smckusick 9710315Smckusick /* 9810315Smckusick * Create a new node (directory). 9910315Smckusick */ 10010315Smckusick newnode(np) 10110315Smckusick struct entry *np; 10210315Smckusick { 10310315Smckusick char *cp; 10410315Smckusick 10510315Smckusick if (np->e_type != NODE) 10610315Smckusick badentry(np, "newnode: not a node"); 10710315Smckusick cp = myname(np); 10811312Smckusick if (mkdir(cp, 0777) < 0) { 10911314Smckusick if (command == 'x') { 11011314Smckusick perror(cp); 11111314Smckusick return; 11211314Smckusick } 11310315Smckusick perror("newnode"); 11410315Smckusick panic("Cannot make node %s\n", cp); 11510315Smckusick } 11610315Smckusick vprintf(stdout, "Make node %s\n", cp); 11710315Smckusick } 11810315Smckusick 11910315Smckusick /* 12010315Smckusick * Remove an old node (directory). 12110315Smckusick */ 12210315Smckusick removenode(ep) 12310315Smckusick register struct entry *ep; 12410315Smckusick { 12510315Smckusick char *cp; 12610315Smckusick 12710315Smckusick if (ep->e_type != NODE) 12810315Smckusick badentry(ep, "removenode: not a node"); 12910315Smckusick if (ep->e_entries != NIL) 13010315Smckusick badentry(ep, "removenode: non-empty directory"); 13110315Smckusick cp = myname(ep); 13210315Smckusick if (rmdir(cp) < 0) { 13310315Smckusick perror("removenode"); 13410315Smckusick panic("Cannot remove node %s\n", cp); 13510315Smckusick } 13610315Smckusick ep->e_flags |= REMOVED; 13711131Smckusick ep->e_flags &= ~(TMPNAME|TMPNODE); 13810315Smckusick vprintf(stdout, "Remove node %s\n", cp); 13910315Smckusick } 14010315Smckusick 14110315Smckusick /* 14210315Smckusick * Remove a leaf. 14310315Smckusick */ 14410315Smckusick removeleaf(ep) 14510315Smckusick register struct entry *ep; 14610315Smckusick { 14710315Smckusick char *cp; 14810315Smckusick 14910315Smckusick if (ep->e_type != LEAF) 15010315Smckusick badentry(ep, "removeleaf: not a leaf"); 15110315Smckusick cp = myname(ep); 15210315Smckusick if (unlink(cp) < 0) { 15310315Smckusick perror("removeleaf"); 15410315Smckusick panic("Cannot remove leaf %s\n", cp); 15510315Smckusick } 15610315Smckusick ep->e_flags |= REMOVED; 15710315Smckusick ep->e_flags &= ~TMPNAME; 15810315Smckusick vprintf(stdout, "Remove leaf %s\n", cp); 15910315Smckusick } 16010315Smckusick 16110315Smckusick /* 16210315Smckusick * Create a link. 16310315Smckusick */ 16410315Smckusick linkit(existing, new, type) 16510315Smckusick char *existing, *new; 16610315Smckusick int type; 16710315Smckusick { 16810315Smckusick 16910315Smckusick if (type == SYMLINK) { 17010315Smckusick if (symlink(existing, new) < 0) { 17110315Smckusick perror("linkit"); 17210315Smckusick panic("Cannot create symbolic link %s->%s\n", 17310315Smckusick new, existing); 17410315Smckusick } 17510315Smckusick } else if (type == HARDLINK) { 17610315Smckusick if (link(existing, new) < 0) { 17710315Smckusick perror("linkit"); 17810315Smckusick panic("Cannot create hard link %s->%s\n", 17910315Smckusick new, existing); 18010315Smckusick } 18110315Smckusick } else { 18210315Smckusick panic("linkit: unknown type %d\n", type); 18310315Smckusick } 18410315Smckusick vprintf(stdout, "Create %s link %s->%s\n", 18510315Smckusick type == SYMLINK ? "symbolic" : "hard", new, existing); 18610315Smckusick } 18710315Smckusick 18810315Smckusick /* 18910315Smckusick * find lowest number file (above "start") that needs to be extracted 19010315Smckusick */ 19110315Smckusick ino_t 19210315Smckusick lowerbnd(start) 19310315Smckusick ino_t start; 19410315Smckusick { 19510315Smckusick register struct entry *ep; 19610315Smckusick 19710315Smckusick for ( ; start < maxino; start++) { 19810315Smckusick ep = lookupino(start); 19910315Smckusick if (ep == NIL) 20010315Smckusick continue; 20111131Smckusick if (ep->e_flags & (NEW|EXTRACT|CHANGE)) 20210315Smckusick return (start); 20310315Smckusick } 20410315Smckusick return (start); 20510315Smckusick } 20610315Smckusick 20710315Smckusick /* 20810315Smckusick * find highest number file (below "start") that needs to be extracted 20910315Smckusick */ 21010315Smckusick ino_t 21110315Smckusick upperbnd(start) 21210315Smckusick ino_t start; 21310315Smckusick { 21410315Smckusick register struct entry *ep; 21510315Smckusick 21610315Smckusick for ( ; start > ROOTINO; start--) { 21710315Smckusick ep = lookupino(start); 21810315Smckusick if (ep == NIL) 21910315Smckusick continue; 22011131Smckusick if (ep->e_flags & (NEW|EXTRACT|CHANGE)) 22110315Smckusick return (start); 22210315Smckusick } 22310315Smckusick return (start); 22410315Smckusick } 22510315Smckusick 22610315Smckusick /* 22710315Smckusick * report on a badly formed entry 22810315Smckusick */ 22910315Smckusick badentry(ep, msg) 23010315Smckusick register struct entry *ep; 23110315Smckusick char *msg; 23210315Smckusick { 23310315Smckusick char flagbuf[BUFSIZ]; 23410315Smckusick 23510315Smckusick fprintf(stderr, "bad entry: %s\n", msg); 23610315Smckusick fprintf(stderr, "name: %s\n", myname(ep)); 23711131Smckusick if (ep->e_newname != NULL) 23811131Smckusick fprintf(stderr, "new name: %s\n", ep->e_newname); 23910315Smckusick fprintf(stderr, "parent name %s\n", myname(ep->e_parent)); 24010315Smckusick if (ep->e_sibling != NIL) 24110315Smckusick fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling)); 24210315Smckusick if (ep->e_entries != NIL) 24310315Smckusick fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries)); 24410315Smckusick if (ep->e_links != NIL) 24510315Smckusick fprintf(stderr, "next link name: %s\n", myname(ep->e_links)); 24610315Smckusick fprintf(stderr, "entry type: %s\n", 24710315Smckusick ep->e_type == NODE ? "NODE" : "LEAF"); 24810315Smckusick fprintf(stderr, "inode number: %ld\n", ep->e_ino); 24910315Smckusick strcpy(flagbuf, "|NIL"); 25010315Smckusick flagbuf[0] = '\0'; 25111131Smckusick if (ep->e_flags & REMOVE) 25211131Smckusick strcat(flagbuf, "|REMOVE"); 25310315Smckusick if (ep->e_flags & REMOVED) 25410315Smckusick strcat(flagbuf, "|REMOVED"); 25511131Smckusick if (ep->e_flags & RENAME) 25611131Smckusick strcat(flagbuf, "|RENAME"); 25710315Smckusick if (ep->e_flags & TMPNAME) 25810315Smckusick strcat(flagbuf, "|TMPNAME"); 25911131Smckusick if (ep->e_flags & TMPNODE) 26011131Smckusick strcat(flagbuf, "|TMPNODE"); 26110315Smckusick if (ep->e_flags & EXTRACT) 26210315Smckusick strcat(flagbuf, "|EXTRACT"); 26311131Smckusick if (ep->e_flags & RENUMBER) 26411131Smckusick strcat(flagbuf, "|RENUMBER"); 26511131Smckusick if (ep->e_flags & CHANGE) 26611131Smckusick strcat(flagbuf, "|CHANGE"); 26710315Smckusick if (ep->e_flags & NEW) 26810315Smckusick strcat(flagbuf, "|NEW"); 26910315Smckusick if (ep->e_flags & KEEP) 27010315Smckusick strcat(flagbuf, "|KEEP"); 27110315Smckusick panic("flags: %s\n", &flagbuf[1]); 27210315Smckusick } 27310315Smckusick 27410315Smckusick /* 275*11321Smckusick * canonicalize file names to always start with ``./'' 276*11321Smckusick */ 277*11321Smckusick canon(rawname, canonname) 278*11321Smckusick char *rawname, *canonname; 279*11321Smckusick { 280*11321Smckusick int len; 281*11321Smckusick 282*11321Smckusick if (strcmp(rawname, ".") == 0 || strncmp(rawname, "./", 2) == 0) 283*11321Smckusick strcpy(canonname, ""); 284*11321Smckusick else if (rawname[0] == '/') 285*11321Smckusick strcpy(canonname, "."); 286*11321Smckusick else 287*11321Smckusick strcpy(canonname, "./"); 288*11321Smckusick strcat(canonname, rawname); 289*11321Smckusick len = strlen(canonname) - 1; 290*11321Smckusick if (canonname[len] == '/') 291*11321Smckusick canonname[len] = '\0'; 292*11321Smckusick } 293*11321Smckusick 294*11321Smckusick /* 29510315Smckusick * elicit a reply 29610315Smckusick */ 29710315Smckusick reply(question) 29810315Smckusick char *question; 29910315Smckusick { 30010315Smckusick char c; 30110315Smckusick 30210315Smckusick fprintf(stderr, "%s? ", question); 30310315Smckusick do { 30410315Smckusick fprintf(stderr, "[yn] "); 30510315Smckusick c = getchar(); 30610315Smckusick while (c != '\n' && getchar() != '\n') 30710315Smckusick /* void */; 30810315Smckusick } while (c != 'y' && c != 'n'); 30910315Smckusick if (c == 'y') 31010315Smckusick return (GOOD); 31110315Smckusick return (FAIL); 31210315Smckusick } 313