xref: /csrg-svn/sbin/restore/utilities.c (revision 56567)
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*56567Sbostic static char sccsid[] = "@(#)utilities.c	5.9 (Berkeley) 10/16/92";
1036105Sbostic #endif /* not lint */
1110315Smckusick 
12*56567Sbostic #include <sys/param.h>
13*56567Sbostic #include <sys/stat.h>
14*56567Sbostic 
15*56567Sbostic #include <ufs/ufs/dinode.h>
16*56567Sbostic 
17*56567Sbostic #include <errno.h>
18*56567Sbostic #include <stdio.h>
19*56567Sbostic #include <stdlib.h>
20*56567Sbostic #include <string.h>
21*56567Sbostic #include <unistd.h>
22*56567Sbostic 
2310315Smckusick #include "restore.h"
24*56567Sbostic #include "extern.h"
2510315Smckusick 
2610315Smckusick /*
2710315Smckusick  * Insure that all the components of a pathname exist.
2810315Smckusick  */
29*56567Sbostic void
3011645Smckusick pathcheck(name)
3110315Smckusick 	char *name;
3210315Smckusick {
3310315Smckusick 	register char *cp;
3410315Smckusick 	struct entry *ep;
3511312Smckusick 	char *start;
3610315Smckusick 
3710315Smckusick 	start = index(name, '/');
3811312Smckusick 	if (start == 0)
3911645Smckusick 		return;
4010315Smckusick 	for (cp = start; *cp != '\0'; cp++) {
4110315Smckusick 		if (*cp != '/')
4210315Smckusick 			continue;
4310315Smckusick 		*cp = '\0';
4410315Smckusick 		ep = lookupname(name);
45*56567Sbostic 		if (ep == NULL) {
4656432Smckusick 			ep = addentry(name, pathsearch(name), NODE);
4710315Smckusick 			newnode(ep);
4810315Smckusick 		}
4918009Smckusick 		ep->e_flags |= NEW|KEEP;
5010315Smckusick 		*cp = '/';
5110315Smckusick 	}
5210315Smckusick }
5310315Smckusick 
5410315Smckusick /*
5510315Smckusick  * Change a name to a unique temporary name.
5610315Smckusick  */
57*56567Sbostic void
5810315Smckusick mktempname(ep)
5910315Smckusick 	register struct entry *ep;
6010315Smckusick {
6111645Smckusick 	char oldname[MAXPATHLEN];
6210315Smckusick 
6310315Smckusick 	if (ep->e_flags & TMPNAME)
6410315Smckusick 		badentry(ep, "mktempname: called with TMPNAME");
6510315Smckusick 	ep->e_flags |= TMPNAME;
6611995Smckusick 	(void) strcpy(oldname, myname(ep));
6711645Smckusick 	freename(ep->e_name);
6811645Smckusick 	ep->e_name = savename(gentempname(ep));
6911645Smckusick 	ep->e_namlen = strlen(ep->e_name);
7010315Smckusick 	renameit(oldname, myname(ep));
7110315Smckusick }
7210315Smckusick 
7310315Smckusick /*
7411645Smckusick  * Generate a temporary name for an entry.
7511645Smckusick  */
7611645Smckusick char *
7711645Smckusick gentempname(ep)
7811645Smckusick 	struct entry *ep;
7911645Smckusick {
8011645Smckusick 	static char name[MAXPATHLEN];
8111645Smckusick 	struct entry *np;
8211645Smckusick 	long i = 0;
8311645Smckusick 
84*56567Sbostic 	for (np = lookupino(ep->e_ino);
85*56567Sbostic 	    np != NULL && np != ep; np = np->e_links)
8611645Smckusick 		i++;
87*56567Sbostic 	if (np == NULL)
8811645Smckusick 		badentry(ep, "not on ino list");
8911733Smckusick 	(void) sprintf(name, "%s%d%d", TMPHDR, i, ep->e_ino);
9011645Smckusick 	return (name);
9111645Smckusick }
9211645Smckusick 
9311645Smckusick /*
9410315Smckusick  * Rename a file or directory.
9510315Smckusick  */
96*56567Sbostic void
9710315Smckusick renameit(from, to)
9810315Smckusick 	char *from, *to;
9910315Smckusick {
10034268Smckusick 	if (!Nflag && rename(from, to) < 0) {
101*56567Sbostic 		fprintf(stderr, "warning: cannot rename %s to %s: %s\n",
102*56567Sbostic 		    from, to, strerror(errno));
10311923Smckusick 		return;
10410315Smckusick 	}
10510315Smckusick 	vprintf(stdout, "rename %s to %s\n", from, to);
10610315Smckusick }
10710315Smckusick 
10810315Smckusick /*
10910315Smckusick  * Create a new node (directory).
11010315Smckusick  */
111*56567Sbostic void
11210315Smckusick newnode(np)
11310315Smckusick 	struct entry *np;
11410315Smckusick {
11510315Smckusick 	char *cp;
11610315Smckusick 
11710315Smckusick 	if (np->e_type != NODE)
11810315Smckusick 		badentry(np, "newnode: not a node");
11910315Smckusick 	cp = myname(np);
12034268Smckusick 	if (!Nflag && mkdir(cp, 0777) < 0) {
12118006Smckusick 		np->e_flags |= EXISTED;
122*56567Sbostic 		fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno));
12311740Smckusick 		return;
12410315Smckusick 	}
12510315Smckusick 	vprintf(stdout, "Make node %s\n", cp);
12610315Smckusick }
12710315Smckusick 
12810315Smckusick /*
12910315Smckusick  * Remove an old node (directory).
13010315Smckusick  */
131*56567Sbostic void
13210315Smckusick removenode(ep)
13310315Smckusick 	register struct entry *ep;
13410315Smckusick {
13510315Smckusick 	char *cp;
13610315Smckusick 
13710315Smckusick 	if (ep->e_type != NODE)
13810315Smckusick 		badentry(ep, "removenode: not a node");
139*56567Sbostic 	if (ep->e_entries != NULL)
14010315Smckusick 		badentry(ep, "removenode: non-empty directory");
14111923Smckusick 	ep->e_flags |= REMOVED;
14211923Smckusick 	ep->e_flags &= ~TMPNAME;
14310315Smckusick 	cp = myname(ep);
14434268Smckusick 	if (!Nflag && rmdir(cp) < 0) {
145*56567Sbostic 		fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno));
14611923Smckusick 		return;
14710315Smckusick 	}
14810315Smckusick 	vprintf(stdout, "Remove node %s\n", cp);
14910315Smckusick }
15010315Smckusick 
15110315Smckusick /*
15210315Smckusick  * Remove a leaf.
15310315Smckusick  */
154*56567Sbostic void
15510315Smckusick removeleaf(ep)
15610315Smckusick 	register struct entry *ep;
15710315Smckusick {
15810315Smckusick 	char *cp;
15910315Smckusick 
16010315Smckusick 	if (ep->e_type != LEAF)
16110315Smckusick 		badentry(ep, "removeleaf: not a leaf");
16211923Smckusick 	ep->e_flags |= REMOVED;
16311923Smckusick 	ep->e_flags &= ~TMPNAME;
16410315Smckusick 	cp = myname(ep);
16534268Smckusick 	if (!Nflag && unlink(cp) < 0) {
166*56567Sbostic 		fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno));
16711923Smckusick 		return;
16810315Smckusick 	}
16910315Smckusick 	vprintf(stdout, "Remove leaf %s\n", cp);
17010315Smckusick }
17110315Smckusick 
17210315Smckusick /*
17310315Smckusick  * Create a link.
17410315Smckusick  */
175*56567Sbostic int
17610315Smckusick linkit(existing, new, type)
17710315Smckusick 	char *existing, *new;
17810315Smckusick 	int type;
17910315Smckusick {
18010315Smckusick 
18110315Smckusick 	if (type == SYMLINK) {
18234268Smckusick 		if (!Nflag && symlink(existing, new) < 0) {
18311923Smckusick 			fprintf(stderr,
184*56567Sbostic 			    "warning: cannot create symbolic link %s->%s: %s\n",
185*56567Sbostic 			    new, existing, strerror(errno));
18615782Smckusick 			return (FAIL);
18710315Smckusick 		}
18810315Smckusick 	} else if (type == HARDLINK) {
18934268Smckusick 		if (!Nflag && link(existing, new) < 0) {
19011923Smckusick 			fprintf(stderr,
191*56567Sbostic 			    "warning: cannot create hard link %s->%s: %s\n",
192*56567Sbostic 			    new, existing, strerror(errno));
19315782Smckusick 			return (FAIL);
19410315Smckusick 		}
19510315Smckusick 	} else {
19610315Smckusick 		panic("linkit: unknown type %d\n", type);
19715782Smckusick 		return (FAIL);
19810315Smckusick 	}
19910315Smckusick 	vprintf(stdout, "Create %s link %s->%s\n",
20010315Smckusick 		type == SYMLINK ? "symbolic" : "hard", new, existing);
20115782Smckusick 	return (GOOD);
20210315Smckusick }
20310315Smckusick 
20410315Smckusick /*
20510315Smckusick  * find lowest number file (above "start") that needs to be extracted
20610315Smckusick  */
20710315Smckusick ino_t
20810315Smckusick lowerbnd(start)
20910315Smckusick 	ino_t start;
21010315Smckusick {
21110315Smckusick 	register struct entry *ep;
21210315Smckusick 
21310315Smckusick 	for ( ; start < maxino; start++) {
21410315Smckusick 		ep = lookupino(start);
215*56567Sbostic 		if (ep == NULL || ep->e_type == NODE)
21610315Smckusick 			continue;
21711645Smckusick 		if (ep->e_flags & (NEW|EXTRACT))
21810315Smckusick 			return (start);
21910315Smckusick 	}
22010315Smckusick 	return (start);
22110315Smckusick }
22210315Smckusick 
22310315Smckusick /*
22410315Smckusick  * find highest number file (below "start") that needs to be extracted
22510315Smckusick  */
22610315Smckusick ino_t
22710315Smckusick upperbnd(start)
22810315Smckusick 	ino_t start;
22910315Smckusick {
23010315Smckusick 	register struct entry *ep;
23110315Smckusick 
23210315Smckusick 	for ( ; start > ROOTINO; start--) {
23310315Smckusick 		ep = lookupino(start);
234*56567Sbostic 		if (ep == NULL || ep->e_type == NODE)
23510315Smckusick 			continue;
23611645Smckusick 		if (ep->e_flags & (NEW|EXTRACT))
23710315Smckusick 			return (start);
23810315Smckusick 	}
23910315Smckusick 	return (start);
24010315Smckusick }
24110315Smckusick 
24210315Smckusick /*
24310315Smckusick  * report on a badly formed entry
24410315Smckusick  */
245*56567Sbostic void
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));
254*56567Sbostic 	if (ep->e_sibling != NULL)
25510315Smckusick 		fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling));
256*56567Sbostic 	if (ep->e_entries != NULL)
25710315Smckusick 		fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries));
258*56567Sbostic 	if (ep->e_links != NULL)
25910315Smckusick 		fprintf(stderr, "next link name: %s\n", myname(ep->e_links));
260*56567Sbostic 	if (ep->e_next != NULL)
261*56567Sbostic 		fprintf(stderr,
262*56567Sbostic 		    "next hashchain name: %s\n", myname(ep->e_next));
26310315Smckusick 	fprintf(stderr, "entry type: %s\n",
26410315Smckusick 		ep->e_type == NODE ? "NODE" : "LEAF");
26510315Smckusick 	fprintf(stderr, "inode number: %ld\n", ep->e_ino);
26611898Smckusick 	panic("flags: %s\n", flagvalues(ep));
26711898Smckusick }
26811898Smckusick 
26911898Smckusick /*
27011898Smckusick  * Construct a string indicating the active flag bits of an entry.
27111898Smckusick  */
27211898Smckusick char *
27311898Smckusick flagvalues(ep)
27411898Smckusick 	register struct entry *ep;
27511898Smckusick {
27611898Smckusick 	static char flagbuf[BUFSIZ];
27711898Smckusick 
27811898Smckusick 	(void) strcpy(flagbuf, "|NIL");
27910315Smckusick 	flagbuf[0] = '\0';
28010315Smckusick 	if (ep->e_flags & REMOVED)
28111898Smckusick 		(void) strcat(flagbuf, "|REMOVED");
28210315Smckusick 	if (ep->e_flags & TMPNAME)
28311898Smckusick 		(void) strcat(flagbuf, "|TMPNAME");
28410315Smckusick 	if (ep->e_flags & EXTRACT)
28511898Smckusick 		(void) strcat(flagbuf, "|EXTRACT");
28610315Smckusick 	if (ep->e_flags & NEW)
28711898Smckusick 		(void) strcat(flagbuf, "|NEW");
28810315Smckusick 	if (ep->e_flags & KEEP)
28911898Smckusick 		(void) strcat(flagbuf, "|KEEP");
29018006Smckusick 	if (ep->e_flags & EXISTED)
29118006Smckusick 		(void) strcat(flagbuf, "|EXISTED");
29211898Smckusick 	return (&flagbuf[1]);
29310315Smckusick }
29410315Smckusick 
29510315Smckusick /*
29611995Smckusick  * Check to see if a name is on a dump tape.
29711321Smckusick  */
29811995Smckusick ino_t
29911995Smckusick dirlookup(name)
30011995Smckusick 	char *name;
30111995Smckusick {
30211995Smckusick 	ino_t ino;
30311995Smckusick 
30456432Smckusick 	ino = pathsearch(name);
30556427Smckusick 	if (ino == 0 || TSTINO(ino, dumpmap) == 0)
30611995Smckusick 		fprintf(stderr, "%s is not on tape\n", name);
30711995Smckusick 	return (ino);
30811995Smckusick }
30911995Smckusick 
31011995Smckusick /*
31111995Smckusick  * Elicit a reply.
31210315Smckusick  */
313*56567Sbostic int
31410315Smckusick reply(question)
31510315Smckusick 	char *question;
31610315Smckusick {
31710315Smckusick 	char c;
31810315Smckusick 
31910315Smckusick 	do	{
32024185Smckusick 		fprintf(stderr, "%s? [yn] ", question);
32112557Smckusick 		(void) fflush(stderr);
32211995Smckusick 		c = getc(terminal);
32311995Smckusick 		while (c != '\n' && getc(terminal) != '\n')
32417711Smckusick 			if (feof(terminal))
32524185Smckusick 				return (FAIL);
32610315Smckusick 	} while (c != 'y' && c != 'n');
32710315Smckusick 	if (c == 'y')
32810315Smckusick 		return (GOOD);
32910315Smckusick 	return (FAIL);
33010315Smckusick }
33111995Smckusick 
33211995Smckusick /*
33311995Smckusick  * handle unexpected inconsistencies
33411995Smckusick  */
335*56567Sbostic #if __STDC__
336*56567Sbostic #include <stdarg.h>
337*56567Sbostic #else
338*56567Sbostic #include <varargs.h>
339*56567Sbostic #endif
340*56567Sbostic 
341*56567Sbostic void
342*56567Sbostic #if __STDC__
343*56567Sbostic panic(const char *fmt, ...)
344*56567Sbostic #else
345*56567Sbostic panic(fmt, va_alist)
346*56567Sbostic 	char *fmt;
347*56567Sbostic 	va_dcl
348*56567Sbostic #endif
34911995Smckusick {
350*56567Sbostic 	va_list ap;
351*56567Sbostic #if __STDC__
352*56567Sbostic 	va_start(ap, fmt);
353*56567Sbostic #else
354*56567Sbostic 	va_start(ap);
355*56567Sbostic #endif
35611995Smckusick 
357*56567Sbostic 	vfprintf(stderr, fmt, ap);
35842489Smckusick 	if (yflag)
35942489Smckusick 		return;
36011995Smckusick 	if (reply("abort") == GOOD) {
36111995Smckusick 		if (reply("dump core") == GOOD)
36211995Smckusick 			abort();
36311995Smckusick 		done(1);
36411995Smckusick 	}
36511995Smckusick }
366