utilities.c revision 1558
11558Srgrimes/* 21558Srgrimes * Copyright (c) 1983, 1993 31558Srgrimes * The Regents of the University of California. All rights reserved. 41558Srgrimes * 51558Srgrimes * Redistribution and use in source and binary forms, with or without 61558Srgrimes * modification, are permitted provided that the following conditions 71558Srgrimes * are met: 81558Srgrimes * 1. Redistributions of source code must retain the above copyright 91558Srgrimes * notice, this list of conditions and the following disclaimer. 101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111558Srgrimes * notice, this list of conditions and the following disclaimer in the 121558Srgrimes * documentation and/or other materials provided with the distribution. 131558Srgrimes * 3. All advertising materials mentioning features or use of this software 141558Srgrimes * must display the following acknowledgement: 151558Srgrimes * This product includes software developed by the University of 161558Srgrimes * California, Berkeley and its contributors. 171558Srgrimes * 4. Neither the name of the University nor the names of its contributors 181558Srgrimes * may be used to endorse or promote products derived from this software 191558Srgrimes * without specific prior written permission. 201558Srgrimes * 211558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311558Srgrimes * SUCH DAMAGE. 321558Srgrimes */ 331558Srgrimes 341558Srgrimes#ifndef lint 351558Srgrimesstatic char sccsid[] = "@(#)utilities.c 8.2 (Berkeley) 3/25/94"; 361558Srgrimes#endif /* not lint */ 371558Srgrimes 381558Srgrimes#include <sys/param.h> 391558Srgrimes#include <sys/stat.h> 401558Srgrimes 411558Srgrimes#include <ufs/ufs/dinode.h> 421558Srgrimes#include <ufs/ufs/dir.h> 431558Srgrimes 441558Srgrimes#include <errno.h> 451558Srgrimes#include <stdio.h> 461558Srgrimes#include <stdlib.h> 471558Srgrimes#include <string.h> 481558Srgrimes#include <unistd.h> 491558Srgrimes 501558Srgrimes#include "restore.h" 511558Srgrimes#include "extern.h" 521558Srgrimes 531558Srgrimes/* 541558Srgrimes * Insure that all the components of a pathname exist. 551558Srgrimes */ 561558Srgrimesvoid 571558Srgrimespathcheck(name) 581558Srgrimes char *name; 591558Srgrimes{ 601558Srgrimes register char *cp; 611558Srgrimes struct entry *ep; 621558Srgrimes char *start; 631558Srgrimes 641558Srgrimes start = index(name, '/'); 651558Srgrimes if (start == 0) 661558Srgrimes return; 671558Srgrimes for (cp = start; *cp != '\0'; cp++) { 681558Srgrimes if (*cp != '/') 691558Srgrimes continue; 701558Srgrimes *cp = '\0'; 711558Srgrimes ep = lookupname(name); 721558Srgrimes if (ep == NULL) { 731558Srgrimes /* Safe; we know the pathname exists in the dump. */ 741558Srgrimes ep = addentry(name, pathsearch(name)->d_ino, NODE); 751558Srgrimes newnode(ep); 761558Srgrimes } 771558Srgrimes ep->e_flags |= NEW|KEEP; 781558Srgrimes *cp = '/'; 791558Srgrimes } 801558Srgrimes} 811558Srgrimes 821558Srgrimes/* 831558Srgrimes * Change a name to a unique temporary name. 841558Srgrimes */ 851558Srgrimesvoid 861558Srgrimesmktempname(ep) 871558Srgrimes register struct entry *ep; 881558Srgrimes{ 891558Srgrimes char oldname[MAXPATHLEN]; 901558Srgrimes 911558Srgrimes if (ep->e_flags & TMPNAME) 921558Srgrimes badentry(ep, "mktempname: called with TMPNAME"); 931558Srgrimes ep->e_flags |= TMPNAME; 941558Srgrimes (void) strcpy(oldname, myname(ep)); 951558Srgrimes freename(ep->e_name); 961558Srgrimes ep->e_name = savename(gentempname(ep)); 971558Srgrimes ep->e_namlen = strlen(ep->e_name); 981558Srgrimes renameit(oldname, myname(ep)); 991558Srgrimes} 1001558Srgrimes 1011558Srgrimes/* 1021558Srgrimes * Generate a temporary name for an entry. 1031558Srgrimes */ 1041558Srgrimeschar * 1051558Srgrimesgentempname(ep) 1061558Srgrimes struct entry *ep; 1071558Srgrimes{ 1081558Srgrimes static char name[MAXPATHLEN]; 1091558Srgrimes struct entry *np; 1101558Srgrimes long i = 0; 1111558Srgrimes 1121558Srgrimes for (np = lookupino(ep->e_ino); 1131558Srgrimes np != NULL && np != ep; np = np->e_links) 1141558Srgrimes i++; 1151558Srgrimes if (np == NULL) 1161558Srgrimes badentry(ep, "not on ino list"); 1171558Srgrimes (void) sprintf(name, "%s%d%d", TMPHDR, i, ep->e_ino); 1181558Srgrimes return (name); 1191558Srgrimes} 1201558Srgrimes 1211558Srgrimes/* 1221558Srgrimes * Rename a file or directory. 1231558Srgrimes */ 1241558Srgrimesvoid 1251558Srgrimesrenameit(from, to) 1261558Srgrimes char *from, *to; 1271558Srgrimes{ 1281558Srgrimes if (!Nflag && rename(from, to) < 0) { 1291558Srgrimes fprintf(stderr, "warning: cannot rename %s to %s: %s\n", 1301558Srgrimes from, to, strerror(errno)); 1311558Srgrimes return; 1321558Srgrimes } 1331558Srgrimes vprintf(stdout, "rename %s to %s\n", from, to); 1341558Srgrimes} 1351558Srgrimes 1361558Srgrimes/* 1371558Srgrimes * Create a new node (directory). 1381558Srgrimes */ 1391558Srgrimesvoid 1401558Srgrimesnewnode(np) 1411558Srgrimes struct entry *np; 1421558Srgrimes{ 1431558Srgrimes char *cp; 1441558Srgrimes 1451558Srgrimes if (np->e_type != NODE) 1461558Srgrimes badentry(np, "newnode: not a node"); 1471558Srgrimes cp = myname(np); 1481558Srgrimes if (!Nflag && mkdir(cp, 0777) < 0) { 1491558Srgrimes np->e_flags |= EXISTED; 1501558Srgrimes fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno)); 1511558Srgrimes return; 1521558Srgrimes } 1531558Srgrimes vprintf(stdout, "Make node %s\n", cp); 1541558Srgrimes} 1551558Srgrimes 1561558Srgrimes/* 1571558Srgrimes * Remove an old node (directory). 1581558Srgrimes */ 1591558Srgrimesvoid 1601558Srgrimesremovenode(ep) 1611558Srgrimes register struct entry *ep; 1621558Srgrimes{ 1631558Srgrimes char *cp; 1641558Srgrimes 1651558Srgrimes if (ep->e_type != NODE) 1661558Srgrimes badentry(ep, "removenode: not a node"); 1671558Srgrimes if (ep->e_entries != NULL) 1681558Srgrimes badentry(ep, "removenode: non-empty directory"); 1691558Srgrimes ep->e_flags |= REMOVED; 1701558Srgrimes ep->e_flags &= ~TMPNAME; 1711558Srgrimes cp = myname(ep); 1721558Srgrimes if (!Nflag && rmdir(cp) < 0) { 1731558Srgrimes fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno)); 1741558Srgrimes return; 1751558Srgrimes } 1761558Srgrimes vprintf(stdout, "Remove node %s\n", cp); 1771558Srgrimes} 1781558Srgrimes 1791558Srgrimes/* 1801558Srgrimes * Remove a leaf. 1811558Srgrimes */ 1821558Srgrimesvoid 1831558Srgrimesremoveleaf(ep) 1841558Srgrimes register struct entry *ep; 1851558Srgrimes{ 1861558Srgrimes char *cp; 1871558Srgrimes 1881558Srgrimes if (ep->e_type != LEAF) 1891558Srgrimes badentry(ep, "removeleaf: not a leaf"); 1901558Srgrimes ep->e_flags |= REMOVED; 1911558Srgrimes ep->e_flags &= ~TMPNAME; 1921558Srgrimes cp = myname(ep); 1931558Srgrimes if (!Nflag && unlink(cp) < 0) { 1941558Srgrimes fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno)); 1951558Srgrimes return; 1961558Srgrimes } 1971558Srgrimes vprintf(stdout, "Remove leaf %s\n", cp); 1981558Srgrimes} 1991558Srgrimes 2001558Srgrimes/* 2011558Srgrimes * Create a link. 2021558Srgrimes */ 2031558Srgrimesint 2041558Srgrimeslinkit(existing, new, type) 2051558Srgrimes char *existing, *new; 2061558Srgrimes int type; 2071558Srgrimes{ 2081558Srgrimes 2091558Srgrimes if (type == SYMLINK) { 2101558Srgrimes if (!Nflag && symlink(existing, new) < 0) { 2111558Srgrimes fprintf(stderr, 2121558Srgrimes "warning: cannot create symbolic link %s->%s: %s\n", 2131558Srgrimes new, existing, strerror(errno)); 2141558Srgrimes return (FAIL); 2151558Srgrimes } 2161558Srgrimes } else if (type == HARDLINK) { 2171558Srgrimes if (!Nflag && link(existing, new) < 0) { 2181558Srgrimes fprintf(stderr, 2191558Srgrimes "warning: cannot create hard link %s->%s: %s\n", 2201558Srgrimes new, existing, strerror(errno)); 2211558Srgrimes return (FAIL); 2221558Srgrimes } 2231558Srgrimes } else { 2241558Srgrimes panic("linkit: unknown type %d\n", type); 2251558Srgrimes return (FAIL); 2261558Srgrimes } 2271558Srgrimes vprintf(stdout, "Create %s link %s->%s\n", 2281558Srgrimes type == SYMLINK ? "symbolic" : "hard", new, existing); 2291558Srgrimes return (GOOD); 2301558Srgrimes} 2311558Srgrimes 2321558Srgrimes/* 2331558Srgrimes * find lowest number file (above "start") that needs to be extracted 2341558Srgrimes */ 2351558Srgrimesino_t 2361558Srgrimeslowerbnd(start) 2371558Srgrimes ino_t start; 2381558Srgrimes{ 2391558Srgrimes register struct entry *ep; 2401558Srgrimes 2411558Srgrimes for ( ; start < maxino; start++) { 2421558Srgrimes ep = lookupino(start); 2431558Srgrimes if (ep == NULL || ep->e_type == NODE) 2441558Srgrimes continue; 2451558Srgrimes if (ep->e_flags & (NEW|EXTRACT)) 2461558Srgrimes return (start); 2471558Srgrimes } 2481558Srgrimes return (start); 2491558Srgrimes} 2501558Srgrimes 2511558Srgrimes/* 2521558Srgrimes * find highest number file (below "start") that needs to be extracted 2531558Srgrimes */ 2541558Srgrimesino_t 2551558Srgrimesupperbnd(start) 2561558Srgrimes ino_t start; 2571558Srgrimes{ 2581558Srgrimes register struct entry *ep; 2591558Srgrimes 2601558Srgrimes for ( ; start > ROOTINO; start--) { 2611558Srgrimes ep = lookupino(start); 2621558Srgrimes if (ep == NULL || ep->e_type == NODE) 2631558Srgrimes continue; 2641558Srgrimes if (ep->e_flags & (NEW|EXTRACT)) 2651558Srgrimes return (start); 2661558Srgrimes } 2671558Srgrimes return (start); 2681558Srgrimes} 2691558Srgrimes 2701558Srgrimes/* 2711558Srgrimes * report on a badly formed entry 2721558Srgrimes */ 2731558Srgrimesvoid 2741558Srgrimesbadentry(ep, msg) 2751558Srgrimes register struct entry *ep; 2761558Srgrimes char *msg; 2771558Srgrimes{ 2781558Srgrimes 2791558Srgrimes fprintf(stderr, "bad entry: %s\n", msg); 2801558Srgrimes fprintf(stderr, "name: %s\n", myname(ep)); 2811558Srgrimes fprintf(stderr, "parent name %s\n", myname(ep->e_parent)); 2821558Srgrimes if (ep->e_sibling != NULL) 2831558Srgrimes fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling)); 2841558Srgrimes if (ep->e_entries != NULL) 2851558Srgrimes fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries)); 2861558Srgrimes if (ep->e_links != NULL) 2871558Srgrimes fprintf(stderr, "next link name: %s\n", myname(ep->e_links)); 2881558Srgrimes if (ep->e_next != NULL) 2891558Srgrimes fprintf(stderr, 2901558Srgrimes "next hashchain name: %s\n", myname(ep->e_next)); 2911558Srgrimes fprintf(stderr, "entry type: %s\n", 2921558Srgrimes ep->e_type == NODE ? "NODE" : "LEAF"); 2931558Srgrimes fprintf(stderr, "inode number: %ld\n", ep->e_ino); 2941558Srgrimes panic("flags: %s\n", flagvalues(ep)); 2951558Srgrimes} 2961558Srgrimes 2971558Srgrimes/* 2981558Srgrimes * Construct a string indicating the active flag bits of an entry. 2991558Srgrimes */ 3001558Srgrimeschar * 3011558Srgrimesflagvalues(ep) 3021558Srgrimes register struct entry *ep; 3031558Srgrimes{ 3041558Srgrimes static char flagbuf[BUFSIZ]; 3051558Srgrimes 3061558Srgrimes (void) strcpy(flagbuf, "|NIL"); 3071558Srgrimes flagbuf[0] = '\0'; 3081558Srgrimes if (ep->e_flags & REMOVED) 3091558Srgrimes (void) strcat(flagbuf, "|REMOVED"); 3101558Srgrimes if (ep->e_flags & TMPNAME) 3111558Srgrimes (void) strcat(flagbuf, "|TMPNAME"); 3121558Srgrimes if (ep->e_flags & EXTRACT) 3131558Srgrimes (void) strcat(flagbuf, "|EXTRACT"); 3141558Srgrimes if (ep->e_flags & NEW) 3151558Srgrimes (void) strcat(flagbuf, "|NEW"); 3161558Srgrimes if (ep->e_flags & KEEP) 3171558Srgrimes (void) strcat(flagbuf, "|KEEP"); 3181558Srgrimes if (ep->e_flags & EXISTED) 3191558Srgrimes (void) strcat(flagbuf, "|EXISTED"); 3201558Srgrimes return (&flagbuf[1]); 3211558Srgrimes} 3221558Srgrimes 3231558Srgrimes/* 3241558Srgrimes * Check to see if a name is on a dump tape. 3251558Srgrimes */ 3261558Srgrimesino_t 3271558Srgrimesdirlookup(name) 3281558Srgrimes const char *name; 3291558Srgrimes{ 3301558Srgrimes struct direct *dp; 3311558Srgrimes ino_t ino; 3321558Srgrimes 3331558Srgrimes ino = ((dp = pathsearch(name)) == NULL) ? 0 : dp->d_ino; 3341558Srgrimes 3351558Srgrimes if (ino == 0 || TSTINO(ino, dumpmap) == 0) 3361558Srgrimes fprintf(stderr, "%s is not on the tape\n", name); 3371558Srgrimes return (ino); 3381558Srgrimes} 3391558Srgrimes 3401558Srgrimes/* 3411558Srgrimes * Elicit a reply. 3421558Srgrimes */ 3431558Srgrimesint 3441558Srgrimesreply(question) 3451558Srgrimes char *question; 3461558Srgrimes{ 3471558Srgrimes char c; 3481558Srgrimes 3491558Srgrimes do { 3501558Srgrimes fprintf(stderr, "%s? [yn] ", question); 3511558Srgrimes (void) fflush(stderr); 3521558Srgrimes c = getc(terminal); 3531558Srgrimes while (c != '\n' && getc(terminal) != '\n') 3541558Srgrimes if (feof(terminal)) 3551558Srgrimes return (FAIL); 3561558Srgrimes } while (c != 'y' && c != 'n'); 3571558Srgrimes if (c == 'y') 3581558Srgrimes return (GOOD); 3591558Srgrimes return (FAIL); 3601558Srgrimes} 3611558Srgrimes 3621558Srgrimes/* 3631558Srgrimes * handle unexpected inconsistencies 3641558Srgrimes */ 3651558Srgrimes#if __STDC__ 3661558Srgrimes#include <stdarg.h> 3671558Srgrimes#else 3681558Srgrimes#include <varargs.h> 3691558Srgrimes#endif 3701558Srgrimes 3711558Srgrimesvoid 3721558Srgrimes#if __STDC__ 3731558Srgrimespanic(const char *fmt, ...) 3741558Srgrimes#else 3751558Srgrimespanic(fmt, va_alist) 3761558Srgrimes char *fmt; 3771558Srgrimes va_dcl 3781558Srgrimes#endif 3791558Srgrimes{ 3801558Srgrimes va_list ap; 3811558Srgrimes#if __STDC__ 3821558Srgrimes va_start(ap, fmt); 3831558Srgrimes#else 3841558Srgrimes va_start(ap); 3851558Srgrimes#endif 3861558Srgrimes 3871558Srgrimes vfprintf(stderr, fmt, ap); 3881558Srgrimes if (yflag) 3891558Srgrimes return; 3901558Srgrimes if (reply("abort") == GOOD) { 3911558Srgrimes if (reply("dump core") == GOOD) 3921558Srgrimes abort(); 3931558Srgrimes done(1); 3941558Srgrimes } 3951558Srgrimes} 396