121171Sdist /* 236105Sbostic * Copyright (c) 1983 The Regents of the University of California. 336105Sbostic * All rights reserved. 436105Sbostic * 542709Sbostic * %sccs.include.redist.c% 621171Sdist */ 721171Sdist 810315Smckusick #ifndef lint 9*57896Sbostic static char sccsid[] = "@(#)utilities.c 5.11 (Berkeley) 02/10/93"; 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) { 4756947Smckusick ep = addentry(name, pathsearch(name)->d_ino, NODE); 4810315Smckusick newnode(ep); 4910315Smckusick } 5018009Smckusick ep->e_flags |= NEW|KEEP; 5110315Smckusick *cp = '/'; 5210315Smckusick } 5310315Smckusick } 5410315Smckusick 5510315Smckusick /* 5610315Smckusick * Change a name to a unique temporary name. 5710315Smckusick */ 5856567Sbostic void 5910315Smckusick mktempname(ep) 6010315Smckusick register struct entry *ep; 6110315Smckusick { 6211645Smckusick char oldname[MAXPATHLEN]; 6310315Smckusick 6410315Smckusick if (ep->e_flags & TMPNAME) 6510315Smckusick badentry(ep, "mktempname: called with TMPNAME"); 6610315Smckusick ep->e_flags |= TMPNAME; 6711995Smckusick (void) strcpy(oldname, myname(ep)); 6811645Smckusick freename(ep->e_name); 6911645Smckusick ep->e_name = savename(gentempname(ep)); 7011645Smckusick ep->e_namlen = strlen(ep->e_name); 7110315Smckusick renameit(oldname, myname(ep)); 7210315Smckusick } 7310315Smckusick 7410315Smckusick /* 7511645Smckusick * Generate a temporary name for an entry. 7611645Smckusick */ 7711645Smckusick char * 7811645Smckusick gentempname(ep) 7911645Smckusick struct entry *ep; 8011645Smckusick { 8111645Smckusick static char name[MAXPATHLEN]; 8211645Smckusick struct entry *np; 8311645Smckusick long i = 0; 8411645Smckusick 8556567Sbostic for (np = lookupino(ep->e_ino); 8656567Sbostic np != NULL && np != ep; np = np->e_links) 8711645Smckusick i++; 8856567Sbostic if (np == NULL) 8911645Smckusick badentry(ep, "not on ino list"); 9011733Smckusick (void) sprintf(name, "%s%d%d", TMPHDR, i, ep->e_ino); 9111645Smckusick return (name); 9211645Smckusick } 9311645Smckusick 9411645Smckusick /* 9510315Smckusick * Rename a file or directory. 9610315Smckusick */ 9756567Sbostic void 9810315Smckusick renameit(from, to) 9910315Smckusick char *from, *to; 10010315Smckusick { 10134268Smckusick if (!Nflag && rename(from, to) < 0) { 10256567Sbostic fprintf(stderr, "warning: cannot rename %s to %s: %s\n", 10356567Sbostic from, to, strerror(errno)); 10411923Smckusick return; 10510315Smckusick } 10610315Smckusick vprintf(stdout, "rename %s to %s\n", from, to); 10710315Smckusick } 10810315Smckusick 10910315Smckusick /* 11010315Smckusick * Create a new node (directory). 11110315Smckusick */ 11256567Sbostic void 11310315Smckusick newnode(np) 11410315Smckusick struct entry *np; 11510315Smckusick { 11610315Smckusick char *cp; 11710315Smckusick 11810315Smckusick if (np->e_type != NODE) 11910315Smckusick badentry(np, "newnode: not a node"); 12010315Smckusick cp = myname(np); 12134268Smckusick if (!Nflag && mkdir(cp, 0777) < 0) { 12218006Smckusick np->e_flags |= EXISTED; 12356567Sbostic fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno)); 12411740Smckusick return; 12510315Smckusick } 12610315Smckusick vprintf(stdout, "Make node %s\n", cp); 12710315Smckusick } 12810315Smckusick 12910315Smckusick /* 13010315Smckusick * Remove an old node (directory). 13110315Smckusick */ 13256567Sbostic void 13310315Smckusick removenode(ep) 13410315Smckusick register struct entry *ep; 13510315Smckusick { 13610315Smckusick char *cp; 13710315Smckusick 13810315Smckusick if (ep->e_type != NODE) 13910315Smckusick badentry(ep, "removenode: not a node"); 14056567Sbostic if (ep->e_entries != NULL) 14110315Smckusick badentry(ep, "removenode: non-empty directory"); 14211923Smckusick ep->e_flags |= REMOVED; 14311923Smckusick ep->e_flags &= ~TMPNAME; 14410315Smckusick cp = myname(ep); 14534268Smckusick if (!Nflag && rmdir(cp) < 0) { 14656567Sbostic fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno)); 14711923Smckusick return; 14810315Smckusick } 14910315Smckusick vprintf(stdout, "Remove node %s\n", cp); 15010315Smckusick } 15110315Smckusick 15210315Smckusick /* 15310315Smckusick * Remove a leaf. 15410315Smckusick */ 15556567Sbostic void 15610315Smckusick removeleaf(ep) 15710315Smckusick register struct entry *ep; 15810315Smckusick { 15910315Smckusick char *cp; 16010315Smckusick 16110315Smckusick if (ep->e_type != LEAF) 16210315Smckusick badentry(ep, "removeleaf: not a leaf"); 16311923Smckusick ep->e_flags |= REMOVED; 16411923Smckusick ep->e_flags &= ~TMPNAME; 16510315Smckusick cp = myname(ep); 16634268Smckusick if (!Nflag && unlink(cp) < 0) { 16756567Sbostic fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno)); 16811923Smckusick return; 16910315Smckusick } 17010315Smckusick vprintf(stdout, "Remove leaf %s\n", cp); 17110315Smckusick } 17210315Smckusick 17310315Smckusick /* 17410315Smckusick * Create a link. 17510315Smckusick */ 17656567Sbostic int 17710315Smckusick linkit(existing, new, type) 17810315Smckusick char *existing, *new; 17910315Smckusick int type; 18010315Smckusick { 18110315Smckusick 18210315Smckusick if (type == SYMLINK) { 18334268Smckusick if (!Nflag && symlink(existing, new) < 0) { 18411923Smckusick fprintf(stderr, 18556567Sbostic "warning: cannot create symbolic link %s->%s: %s\n", 18656567Sbostic new, existing, strerror(errno)); 18715782Smckusick return (FAIL); 18810315Smckusick } 18910315Smckusick } else if (type == HARDLINK) { 19034268Smckusick if (!Nflag && link(existing, new) < 0) { 19111923Smckusick fprintf(stderr, 19256567Sbostic "warning: cannot create hard link %s->%s: %s\n", 19356567Sbostic new, existing, strerror(errno)); 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); 21656567Sbostic if (ep == NULL || 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); 23556567Sbostic if (ep == NULL || 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 */ 24656567Sbostic void 24710315Smckusick badentry(ep, msg) 24810315Smckusick register struct entry *ep; 24910315Smckusick char *msg; 25010315Smckusick { 25110315Smckusick 25210315Smckusick fprintf(stderr, "bad entry: %s\n", msg); 25310315Smckusick fprintf(stderr, "name: %s\n", myname(ep)); 25410315Smckusick fprintf(stderr, "parent name %s\n", myname(ep->e_parent)); 25556567Sbostic if (ep->e_sibling != NULL) 25610315Smckusick fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling)); 25756567Sbostic if (ep->e_entries != NULL) 25810315Smckusick fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries)); 25956567Sbostic if (ep->e_links != NULL) 26010315Smckusick fprintf(stderr, "next link name: %s\n", myname(ep->e_links)); 26156567Sbostic if (ep->e_next != NULL) 26256567Sbostic fprintf(stderr, 26356567Sbostic "next hashchain name: %s\n", myname(ep->e_next)); 26410315Smckusick fprintf(stderr, "entry type: %s\n", 26510315Smckusick ep->e_type == NODE ? "NODE" : "LEAF"); 26610315Smckusick fprintf(stderr, "inode number: %ld\n", ep->e_ino); 26711898Smckusick panic("flags: %s\n", flagvalues(ep)); 26811898Smckusick } 26911898Smckusick 27011898Smckusick /* 27111898Smckusick * Construct a string indicating the active flag bits of an entry. 27211898Smckusick */ 27311898Smckusick char * 27411898Smckusick flagvalues(ep) 27511898Smckusick register struct entry *ep; 27611898Smckusick { 27711898Smckusick static char flagbuf[BUFSIZ]; 27811898Smckusick 27911898Smckusick (void) strcpy(flagbuf, "|NIL"); 28010315Smckusick flagbuf[0] = '\0'; 28110315Smckusick if (ep->e_flags & REMOVED) 28211898Smckusick (void) strcat(flagbuf, "|REMOVED"); 28310315Smckusick if (ep->e_flags & TMPNAME) 28411898Smckusick (void) strcat(flagbuf, "|TMPNAME"); 28510315Smckusick if (ep->e_flags & EXTRACT) 28611898Smckusick (void) strcat(flagbuf, "|EXTRACT"); 28710315Smckusick if (ep->e_flags & NEW) 28811898Smckusick (void) strcat(flagbuf, "|NEW"); 28910315Smckusick if (ep->e_flags & KEEP) 29011898Smckusick (void) strcat(flagbuf, "|KEEP"); 29118006Smckusick if (ep->e_flags & EXISTED) 29218006Smckusick (void) strcat(flagbuf, "|EXISTED"); 29311898Smckusick return (&flagbuf[1]); 29410315Smckusick } 29510315Smckusick 29610315Smckusick /* 29711995Smckusick * Check to see if a name is on a dump tape. 29811321Smckusick */ 29911995Smckusick ino_t 30011995Smckusick dirlookup(name) 301*57896Sbostic const char *name; 30211995Smckusick { 30311995Smckusick ino_t ino; 30411995Smckusick 30556947Smckusick ino = pathsearch(name)->d_ino; 30656427Smckusick if (ino == 0 || TSTINO(ino, dumpmap) == 0) 30711995Smckusick fprintf(stderr, "%s is not on tape\n", name); 30811995Smckusick return (ino); 30911995Smckusick } 31011995Smckusick 31111995Smckusick /* 31211995Smckusick * Elicit a reply. 31310315Smckusick */ 31456567Sbostic int 31510315Smckusick reply(question) 31610315Smckusick char *question; 31710315Smckusick { 31810315Smckusick char c; 31910315Smckusick 32010315Smckusick do { 32124185Smckusick fprintf(stderr, "%s? [yn] ", question); 32212557Smckusick (void) fflush(stderr); 32311995Smckusick c = getc(terminal); 32411995Smckusick while (c != '\n' && getc(terminal) != '\n') 32517711Smckusick if (feof(terminal)) 32624185Smckusick return (FAIL); 32710315Smckusick } while (c != 'y' && c != 'n'); 32810315Smckusick if (c == 'y') 32910315Smckusick return (GOOD); 33010315Smckusick return (FAIL); 33110315Smckusick } 33211995Smckusick 33311995Smckusick /* 33411995Smckusick * handle unexpected inconsistencies 33511995Smckusick */ 33656567Sbostic #if __STDC__ 33756567Sbostic #include <stdarg.h> 33856567Sbostic #else 33956567Sbostic #include <varargs.h> 34056567Sbostic #endif 34156567Sbostic 34256567Sbostic void 34356567Sbostic #if __STDC__ 34456567Sbostic panic(const char *fmt, ...) 34556567Sbostic #else 34656567Sbostic panic(fmt, va_alist) 34756567Sbostic char *fmt; 34856567Sbostic va_dcl 34956567Sbostic #endif 35011995Smckusick { 35156567Sbostic va_list ap; 35256567Sbostic #if __STDC__ 35356567Sbostic va_start(ap, fmt); 35456567Sbostic #else 35556567Sbostic va_start(ap); 35656567Sbostic #endif 35711995Smckusick 35856567Sbostic vfprintf(stderr, fmt, ap); 35942489Smckusick if (yflag) 36042489Smckusick return; 36111995Smckusick if (reply("abort") == GOOD) { 36211995Smckusick if (reply("dump core") == GOOD) 36311995Smckusick abort(); 36411995Smckusick done(1); 36511995Smckusick } 36611995Smckusick } 367