121171Sdist /* 2*36105Sbostic * Copyright (c) 1983 The Regents of the University of California. 3*36105Sbostic * All rights reserved. 4*36105Sbostic * 5*36105Sbostic * Redistribution and use in source and binary forms are permitted 6*36105Sbostic * provided that the above copyright notice and this paragraph are 7*36105Sbostic * duplicated in all such forms and that any documentation, 8*36105Sbostic * advertising materials, and other materials related to such 9*36105Sbostic * distribution and use acknowledge that the software was developed 10*36105Sbostic * by the University of California, Berkeley. The name of the 11*36105Sbostic * University may not be used to endorse or promote products derived 12*36105Sbostic * from this software without specific prior written permission. 13*36105Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*36105Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*36105Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621171Sdist */ 1721171Sdist 1810315Smckusick #ifndef lint 19*36105Sbostic static char sccsid[] = "@(#)utilities.c 5.4 (Berkeley) 10/24/88"; 20*36105Sbostic #endif /* not lint */ 2110315Smckusick 2210315Smckusick #include "restore.h" 2310315Smckusick 2410315Smckusick /* 2510315Smckusick * Insure that all the components of a pathname exist. 2610315Smckusick */ 2711645Smckusick pathcheck(name) 2810315Smckusick char *name; 2910315Smckusick { 3010315Smckusick register char *cp; 3110315Smckusick struct entry *ep; 3211312Smckusick char *start; 3310315Smckusick 3410315Smckusick start = index(name, '/'); 3511312Smckusick if (start == 0) 3611645Smckusick return; 3710315Smckusick for (cp = start; *cp != '\0'; cp++) { 3810315Smckusick if (*cp != '/') 3910315Smckusick continue; 4010315Smckusick *cp = '\0'; 4110315Smckusick ep = lookupname(name); 4210315Smckusick if (ep == NIL) { 4311995Smckusick ep = addentry(name, psearch(name), NODE); 4410315Smckusick newnode(ep); 4510315Smckusick } 4618009Smckusick ep->e_flags |= NEW|KEEP; 4710315Smckusick *cp = '/'; 4810315Smckusick } 4910315Smckusick } 5010315Smckusick 5110315Smckusick /* 5210315Smckusick * Change a name to a unique temporary name. 5310315Smckusick */ 5410315Smckusick mktempname(ep) 5510315Smckusick register struct entry *ep; 5610315Smckusick { 5711645Smckusick char oldname[MAXPATHLEN]; 5810315Smckusick 5910315Smckusick if (ep->e_flags & TMPNAME) 6010315Smckusick badentry(ep, "mktempname: called with TMPNAME"); 6110315Smckusick ep->e_flags |= TMPNAME; 6211995Smckusick (void) strcpy(oldname, myname(ep)); 6311645Smckusick freename(ep->e_name); 6411645Smckusick ep->e_name = savename(gentempname(ep)); 6511645Smckusick ep->e_namlen = strlen(ep->e_name); 6610315Smckusick renameit(oldname, myname(ep)); 6710315Smckusick } 6810315Smckusick 6910315Smckusick /* 7011645Smckusick * Generate a temporary name for an entry. 7111645Smckusick */ 7211645Smckusick char * 7311645Smckusick gentempname(ep) 7411645Smckusick struct entry *ep; 7511645Smckusick { 7611645Smckusick static char name[MAXPATHLEN]; 7711645Smckusick struct entry *np; 7811645Smckusick long i = 0; 7911645Smckusick 8011645Smckusick for (np = lookupino(ep->e_ino); np != NIL && np != ep; np = np->e_links) 8111645Smckusick i++; 8211645Smckusick if (np == NIL) 8311645Smckusick badentry(ep, "not on ino list"); 8411733Smckusick (void) sprintf(name, "%s%d%d", TMPHDR, i, ep->e_ino); 8511645Smckusick return (name); 8611645Smckusick } 8711645Smckusick 8811645Smckusick /* 8910315Smckusick * Rename a file or directory. 9010315Smckusick */ 9110315Smckusick renameit(from, to) 9210315Smckusick char *from, *to; 9310315Smckusick { 9434268Smckusick if (!Nflag && rename(from, to) < 0) { 9512557Smckusick fprintf(stderr, "Warning: cannot rename %s to %s", from, to); 9612557Smckusick (void) fflush(stderr); 9712557Smckusick perror(""); 9811923Smckusick return; 9910315Smckusick } 10010315Smckusick vprintf(stdout, "rename %s to %s\n", from, to); 10110315Smckusick } 10210315Smckusick 10310315Smckusick /* 10410315Smckusick * Create a new node (directory). 10510315Smckusick */ 10610315Smckusick newnode(np) 10710315Smckusick struct entry *np; 10810315Smckusick { 10910315Smckusick char *cp; 11010315Smckusick 11110315Smckusick if (np->e_type != NODE) 11210315Smckusick badentry(np, "newnode: not a node"); 11310315Smckusick cp = myname(np); 11434268Smckusick if (!Nflag && mkdir(cp, 0777) < 0) { 11518006Smckusick np->e_flags |= EXISTED; 11611740Smckusick fprintf(stderr, "Warning: "); 11711995Smckusick (void) fflush(stderr); 11811740Smckusick perror(cp); 11911740Smckusick return; 12010315Smckusick } 12110315Smckusick vprintf(stdout, "Make node %s\n", cp); 12210315Smckusick } 12310315Smckusick 12410315Smckusick /* 12510315Smckusick * Remove an old node (directory). 12610315Smckusick */ 12710315Smckusick removenode(ep) 12810315Smckusick register struct entry *ep; 12910315Smckusick { 13010315Smckusick char *cp; 13110315Smckusick 13210315Smckusick if (ep->e_type != NODE) 13310315Smckusick badentry(ep, "removenode: not a node"); 13410315Smckusick if (ep->e_entries != NIL) 13510315Smckusick badentry(ep, "removenode: non-empty directory"); 13611923Smckusick ep->e_flags |= REMOVED; 13711923Smckusick ep->e_flags &= ~TMPNAME; 13810315Smckusick cp = myname(ep); 13934268Smckusick if (!Nflag && rmdir(cp) < 0) { 14011923Smckusick fprintf(stderr, "Warning: "); 14111995Smckusick (void) fflush(stderr); 14211923Smckusick perror(cp); 14311923Smckusick return; 14410315Smckusick } 14510315Smckusick vprintf(stdout, "Remove node %s\n", cp); 14610315Smckusick } 14710315Smckusick 14810315Smckusick /* 14910315Smckusick * Remove a leaf. 15010315Smckusick */ 15110315Smckusick removeleaf(ep) 15210315Smckusick register struct entry *ep; 15310315Smckusick { 15410315Smckusick char *cp; 15510315Smckusick 15610315Smckusick if (ep->e_type != LEAF) 15710315Smckusick badentry(ep, "removeleaf: not a leaf"); 15811923Smckusick ep->e_flags |= REMOVED; 15911923Smckusick ep->e_flags &= ~TMPNAME; 16010315Smckusick cp = myname(ep); 16134268Smckusick if (!Nflag && unlink(cp) < 0) { 16211923Smckusick fprintf(stderr, "Warning: "); 16311995Smckusick (void) fflush(stderr); 16411923Smckusick perror(cp); 16511923Smckusick return; 16610315Smckusick } 16710315Smckusick vprintf(stdout, "Remove leaf %s\n", cp); 16810315Smckusick } 16910315Smckusick 17010315Smckusick /* 17110315Smckusick * Create a link. 17210315Smckusick */ 17310315Smckusick linkit(existing, new, type) 17410315Smckusick char *existing, *new; 17510315Smckusick int type; 17610315Smckusick { 17710315Smckusick 17810315Smckusick if (type == SYMLINK) { 17934268Smckusick if (!Nflag && symlink(existing, new) < 0) { 18011923Smckusick fprintf(stderr, 18115782Smckusick "Warning: cannot create symbolic link %s->%s: ", 18210315Smckusick new, existing); 18312557Smckusick (void) fflush(stderr); 18412557Smckusick perror(""); 18515782Smckusick return (FAIL); 18610315Smckusick } 18710315Smckusick } else if (type == HARDLINK) { 18834268Smckusick if (!Nflag && link(existing, new) < 0) { 18911923Smckusick fprintf(stderr, 19015782Smckusick "Warning: cannot create hard link %s->%s: ", 19110315Smckusick new, existing); 19212557Smckusick (void) fflush(stderr); 19312557Smckusick perror(""); 19415782Smckusick return (FAIL); 19510315Smckusick } 19610315Smckusick } else { 19710315Smckusick panic("linkit: unknown type %d\n", type); 19815782Smckusick return (FAIL); 19910315Smckusick } 20010315Smckusick vprintf(stdout, "Create %s link %s->%s\n", 20110315Smckusick type == SYMLINK ? "symbolic" : "hard", new, existing); 20215782Smckusick return (GOOD); 20310315Smckusick } 20410315Smckusick 20510315Smckusick /* 20610315Smckusick * find lowest number file (above "start") that needs to be extracted 20710315Smckusick */ 20810315Smckusick ino_t 20910315Smckusick lowerbnd(start) 21010315Smckusick ino_t start; 21110315Smckusick { 21210315Smckusick register struct entry *ep; 21310315Smckusick 21410315Smckusick for ( ; start < maxino; start++) { 21510315Smckusick ep = lookupino(start); 21611995Smckusick if (ep == NIL || ep->e_type == NODE) 21710315Smckusick continue; 21811645Smckusick if (ep->e_flags & (NEW|EXTRACT)) 21910315Smckusick return (start); 22010315Smckusick } 22110315Smckusick return (start); 22210315Smckusick } 22310315Smckusick 22410315Smckusick /* 22510315Smckusick * find highest number file (below "start") that needs to be extracted 22610315Smckusick */ 22710315Smckusick ino_t 22810315Smckusick upperbnd(start) 22910315Smckusick ino_t start; 23010315Smckusick { 23110315Smckusick register struct entry *ep; 23210315Smckusick 23310315Smckusick for ( ; start > ROOTINO; start--) { 23410315Smckusick ep = lookupino(start); 23511995Smckusick if (ep == NIL || ep->e_type == NODE) 23610315Smckusick continue; 23711645Smckusick if (ep->e_flags & (NEW|EXTRACT)) 23810315Smckusick return (start); 23910315Smckusick } 24010315Smckusick return (start); 24110315Smckusick } 24210315Smckusick 24310315Smckusick /* 24410315Smckusick * report on a badly formed entry 24510315Smckusick */ 24610315Smckusick badentry(ep, msg) 24710315Smckusick register struct entry *ep; 24810315Smckusick char *msg; 24910315Smckusick { 25010315Smckusick 25110315Smckusick fprintf(stderr, "bad entry: %s\n", msg); 25210315Smckusick fprintf(stderr, "name: %s\n", myname(ep)); 25310315Smckusick fprintf(stderr, "parent name %s\n", myname(ep->e_parent)); 25410315Smckusick if (ep->e_sibling != NIL) 25510315Smckusick fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling)); 25610315Smckusick if (ep->e_entries != NIL) 25710315Smckusick fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries)); 25810315Smckusick if (ep->e_links != NIL) 25910315Smckusick fprintf(stderr, "next link name: %s\n", myname(ep->e_links)); 26011645Smckusick if (ep->e_next != NIL) 26111645Smckusick fprintf(stderr, "next hashchain name: %s\n", myname(ep->e_next)); 26210315Smckusick fprintf(stderr, "entry type: %s\n", 26310315Smckusick ep->e_type == NODE ? "NODE" : "LEAF"); 26410315Smckusick fprintf(stderr, "inode number: %ld\n", ep->e_ino); 26511898Smckusick panic("flags: %s\n", flagvalues(ep)); 26611898Smckusick } 26711898Smckusick 26811898Smckusick /* 26911898Smckusick * Construct a string indicating the active flag bits of an entry. 27011898Smckusick */ 27111898Smckusick char * 27211898Smckusick flagvalues(ep) 27311898Smckusick register struct entry *ep; 27411898Smckusick { 27511898Smckusick static char flagbuf[BUFSIZ]; 27611898Smckusick 27711898Smckusick (void) strcpy(flagbuf, "|NIL"); 27810315Smckusick flagbuf[0] = '\0'; 27910315Smckusick if (ep->e_flags & REMOVED) 28011898Smckusick (void) strcat(flagbuf, "|REMOVED"); 28110315Smckusick if (ep->e_flags & TMPNAME) 28211898Smckusick (void) strcat(flagbuf, "|TMPNAME"); 28310315Smckusick if (ep->e_flags & EXTRACT) 28411898Smckusick (void) strcat(flagbuf, "|EXTRACT"); 28510315Smckusick if (ep->e_flags & NEW) 28611898Smckusick (void) strcat(flagbuf, "|NEW"); 28710315Smckusick if (ep->e_flags & KEEP) 28811898Smckusick (void) strcat(flagbuf, "|KEEP"); 28918006Smckusick if (ep->e_flags & EXISTED) 29018006Smckusick (void) strcat(flagbuf, "|EXISTED"); 29111898Smckusick return (&flagbuf[1]); 29210315Smckusick } 29310315Smckusick 29410315Smckusick /* 29511995Smckusick * Check to see if a name is on a dump tape. 29611321Smckusick */ 29711995Smckusick ino_t 29811995Smckusick dirlookup(name) 29911995Smckusick char *name; 30011995Smckusick { 30111995Smckusick ino_t ino; 30211995Smckusick 30311995Smckusick ino = psearch(name); 30411995Smckusick if (ino == 0 || BIT(ino, dumpmap) == 0) 30511995Smckusick fprintf(stderr, "%s is not on tape\n", name); 30611995Smckusick return (ino); 30711995Smckusick } 30811995Smckusick 30911995Smckusick /* 31011995Smckusick * Elicit a reply. 31110315Smckusick */ 31210315Smckusick reply(question) 31310315Smckusick char *question; 31410315Smckusick { 31510315Smckusick char c; 31610315Smckusick 31710315Smckusick do { 31824185Smckusick fprintf(stderr, "%s? [yn] ", question); 31912557Smckusick (void) fflush(stderr); 32011995Smckusick c = getc(terminal); 32111995Smckusick while (c != '\n' && getc(terminal) != '\n') 32217711Smckusick if (feof(terminal)) 32324185Smckusick return (FAIL); 32410315Smckusick } while (c != 'y' && c != 'n'); 32510315Smckusick if (c == 'y') 32610315Smckusick return (GOOD); 32710315Smckusick return (FAIL); 32810315Smckusick } 32911995Smckusick 33011995Smckusick /* 33111995Smckusick * handle unexpected inconsistencies 33211995Smckusick */ 33311995Smckusick /* VARARGS1 */ 33411995Smckusick panic(msg, d1, d2) 33511995Smckusick char *msg; 33611995Smckusick long d1, d2; 33711995Smckusick { 33811995Smckusick 33911995Smckusick fprintf(stderr, msg, d1, d2); 34011995Smckusick if (reply("abort") == GOOD) { 34111995Smckusick if (reply("dump core") == GOOD) 34211995Smckusick abort(); 34311995Smckusick done(1); 34411995Smckusick } 34511995Smckusick } 346