xref: /csrg-svn/sbin/restore/utilities.c (revision 18006)
110315Smckusick #ifndef lint
2*18006Smckusick static char sccsid[] = "@(#)utilities.c	3.19	(Berkeley)	85/02/18";
310315Smckusick #endif
410315Smckusick 
514568Ssam /* Copyright (c) 1983 Regents of the University of California */
614568Ssam 
710315Smckusick #include "restore.h"
810315Smckusick 
910315Smckusick /*
1010315Smckusick  * Insure that all the components of a pathname exist.
1110315Smckusick  */
1211645Smckusick pathcheck(name)
1310315Smckusick 	char *name;
1410315Smckusick {
1510315Smckusick 	register char *cp;
1610315Smckusick 	struct entry *ep;
1711312Smckusick 	char *start;
1810315Smckusick 
1910315Smckusick 	start = index(name, '/');
2011312Smckusick 	if (start == 0)
2111645Smckusick 		return;
2210315Smckusick 	for (cp = start; *cp != '\0'; cp++) {
2310315Smckusick 		if (*cp != '/')
2410315Smckusick 			continue;
2510315Smckusick 		*cp = '\0';
2610315Smckusick 		ep = lookupname(name);
2710315Smckusick 		if (ep == NIL) {
2811995Smckusick 			ep = addentry(name, psearch(name), NODE);
2910315Smckusick 			newnode(ep);
3011995Smckusick 			ep->e_flags |= NEW|KEEP;
3110315Smckusick 		}
3210315Smckusick 		*cp = '/';
3310315Smckusick 	}
3410315Smckusick }
3510315Smckusick 
3610315Smckusick /*
3710315Smckusick  * Change a name to a unique temporary name.
3810315Smckusick  */
3910315Smckusick mktempname(ep)
4010315Smckusick 	register struct entry *ep;
4110315Smckusick {
4211645Smckusick 	char oldname[MAXPATHLEN];
4310315Smckusick 
4410315Smckusick 	if (ep->e_flags & TMPNAME)
4510315Smckusick 		badentry(ep, "mktempname: called with TMPNAME");
4610315Smckusick 	ep->e_flags |= TMPNAME;
4711995Smckusick 	(void) strcpy(oldname, myname(ep));
4811645Smckusick 	freename(ep->e_name);
4911645Smckusick 	ep->e_name = savename(gentempname(ep));
5011645Smckusick 	ep->e_namlen = strlen(ep->e_name);
5110315Smckusick 	renameit(oldname, myname(ep));
5210315Smckusick }
5310315Smckusick 
5410315Smckusick /*
5511645Smckusick  * Generate a temporary name for an entry.
5611645Smckusick  */
5711645Smckusick char *
5811645Smckusick gentempname(ep)
5911645Smckusick 	struct entry *ep;
6011645Smckusick {
6111645Smckusick 	static char name[MAXPATHLEN];
6211645Smckusick 	struct entry *np;
6311645Smckusick 	long i = 0;
6411645Smckusick 
6511645Smckusick 	for (np = lookupino(ep->e_ino); np != NIL && np != ep; np = np->e_links)
6611645Smckusick 		i++;
6711645Smckusick 	if (np == NIL)
6811645Smckusick 		badentry(ep, "not on ino list");
6911733Smckusick 	(void) sprintf(name, "%s%d%d", TMPHDR, i, ep->e_ino);
7011645Smckusick 	return (name);
7111645Smckusick }
7211645Smckusick 
7311645Smckusick /*
7410315Smckusick  * Rename a file or directory.
7510315Smckusick  */
7610315Smckusick renameit(from, to)
7710315Smckusick 	char *from, *to;
7810315Smckusick {
7910315Smckusick 	if (rename(from, to) < 0) {
8012557Smckusick 		fprintf(stderr, "Warning: cannot rename %s to %s", from, to);
8112557Smckusick 		(void) fflush(stderr);
8212557Smckusick 		perror("");
8311923Smckusick 		return;
8410315Smckusick 	}
8510315Smckusick 	vprintf(stdout, "rename %s to %s\n", from, to);
8610315Smckusick }
8710315Smckusick 
8810315Smckusick /*
8910315Smckusick  * Create a new node (directory).
9010315Smckusick  */
9110315Smckusick newnode(np)
9210315Smckusick 	struct entry *np;
9310315Smckusick {
9410315Smckusick 	char *cp;
9510315Smckusick 
9610315Smckusick 	if (np->e_type != NODE)
9710315Smckusick 		badentry(np, "newnode: not a node");
9810315Smckusick 	cp = myname(np);
9911312Smckusick 	if (mkdir(cp, 0777) < 0) {
100*18006Smckusick 		np->e_flags |= EXISTED;
10111740Smckusick 		fprintf(stderr, "Warning: ");
10211995Smckusick 		(void) fflush(stderr);
10311740Smckusick 		perror(cp);
10411740Smckusick 		return;
10510315Smckusick 	}
10610315Smckusick 	vprintf(stdout, "Make node %s\n", cp);
10710315Smckusick }
10810315Smckusick 
10910315Smckusick /*
11010315Smckusick  * Remove an old node (directory).
11110315Smckusick  */
11210315Smckusick removenode(ep)
11310315Smckusick 	register struct entry *ep;
11410315Smckusick {
11510315Smckusick 	char *cp;
11610315Smckusick 
11710315Smckusick 	if (ep->e_type != NODE)
11810315Smckusick 		badentry(ep, "removenode: not a node");
11910315Smckusick 	if (ep->e_entries != NIL)
12010315Smckusick 		badentry(ep, "removenode: non-empty directory");
12111923Smckusick 	ep->e_flags |= REMOVED;
12211923Smckusick 	ep->e_flags &= ~TMPNAME;
12310315Smckusick 	cp = myname(ep);
12410315Smckusick 	if (rmdir(cp) < 0) {
12511923Smckusick 		fprintf(stderr, "Warning: ");
12611995Smckusick 		(void) fflush(stderr);
12711923Smckusick 		perror(cp);
12811923Smckusick 		return;
12910315Smckusick 	}
13010315Smckusick 	vprintf(stdout, "Remove node %s\n", cp);
13110315Smckusick }
13210315Smckusick 
13310315Smckusick /*
13410315Smckusick  * Remove a leaf.
13510315Smckusick  */
13610315Smckusick removeleaf(ep)
13710315Smckusick 	register struct entry *ep;
13810315Smckusick {
13910315Smckusick 	char *cp;
14010315Smckusick 
14110315Smckusick 	if (ep->e_type != LEAF)
14210315Smckusick 		badentry(ep, "removeleaf: not a leaf");
14311923Smckusick 	ep->e_flags |= REMOVED;
14411923Smckusick 	ep->e_flags &= ~TMPNAME;
14510315Smckusick 	cp = myname(ep);
14610315Smckusick 	if (unlink(cp) < 0) {
14711923Smckusick 		fprintf(stderr, "Warning: ");
14811995Smckusick 		(void) fflush(stderr);
14911923Smckusick 		perror(cp);
15011923Smckusick 		return;
15110315Smckusick 	}
15210315Smckusick 	vprintf(stdout, "Remove leaf %s\n", cp);
15310315Smckusick }
15410315Smckusick 
15510315Smckusick /*
15610315Smckusick  * Create a link.
15710315Smckusick  */
15810315Smckusick linkit(existing, new, type)
15910315Smckusick 	char *existing, *new;
16010315Smckusick 	int type;
16110315Smckusick {
16210315Smckusick 
16310315Smckusick 	if (type == SYMLINK) {
16410315Smckusick 		if (symlink(existing, new) < 0) {
16511923Smckusick 			fprintf(stderr,
16615782Smckusick 				"Warning: cannot create symbolic link %s->%s: ",
16710315Smckusick 				new, existing);
16812557Smckusick 			(void) fflush(stderr);
16912557Smckusick 			perror("");
17015782Smckusick 			return (FAIL);
17110315Smckusick 		}
17210315Smckusick 	} else if (type == HARDLINK) {
17310315Smckusick 		if (link(existing, new) < 0) {
17411923Smckusick 			fprintf(stderr,
17515782Smckusick 				"Warning: cannot create hard link %s->%s: ",
17610315Smckusick 				new, existing);
17712557Smckusick 			(void) fflush(stderr);
17812557Smckusick 			perror("");
17915782Smckusick 			return (FAIL);
18010315Smckusick 		}
18110315Smckusick 	} else {
18210315Smckusick 		panic("linkit: unknown type %d\n", type);
18315782Smckusick 		return (FAIL);
18410315Smckusick 	}
18510315Smckusick 	vprintf(stdout, "Create %s link %s->%s\n",
18610315Smckusick 		type == SYMLINK ? "symbolic" : "hard", new, existing);
18715782Smckusick 	return (GOOD);
18810315Smckusick }
18910315Smckusick 
19010315Smckusick /*
19110315Smckusick  * find lowest number file (above "start") that needs to be extracted
19210315Smckusick  */
19310315Smckusick ino_t
19410315Smckusick lowerbnd(start)
19510315Smckusick 	ino_t start;
19610315Smckusick {
19710315Smckusick 	register struct entry *ep;
19810315Smckusick 
19910315Smckusick 	for ( ; start < maxino; start++) {
20010315Smckusick 		ep = lookupino(start);
20111995Smckusick 		if (ep == NIL || ep->e_type == NODE)
20210315Smckusick 			continue;
20311645Smckusick 		if (ep->e_flags & (NEW|EXTRACT))
20410315Smckusick 			return (start);
20510315Smckusick 	}
20610315Smckusick 	return (start);
20710315Smckusick }
20810315Smckusick 
20910315Smckusick /*
21010315Smckusick  * find highest number file (below "start") that needs to be extracted
21110315Smckusick  */
21210315Smckusick ino_t
21310315Smckusick upperbnd(start)
21410315Smckusick 	ino_t start;
21510315Smckusick {
21610315Smckusick 	register struct entry *ep;
21710315Smckusick 
21810315Smckusick 	for ( ; start > ROOTINO; start--) {
21910315Smckusick 		ep = lookupino(start);
22011995Smckusick 		if (ep == NIL || ep->e_type == NODE)
22110315Smckusick 			continue;
22211645Smckusick 		if (ep->e_flags & (NEW|EXTRACT))
22310315Smckusick 			return (start);
22410315Smckusick 	}
22510315Smckusick 	return (start);
22610315Smckusick }
22710315Smckusick 
22810315Smckusick /*
22910315Smckusick  * report on a badly formed entry
23010315Smckusick  */
23110315Smckusick badentry(ep, msg)
23210315Smckusick 	register struct entry *ep;
23310315Smckusick 	char *msg;
23410315Smckusick {
23510315Smckusick 
23610315Smckusick 	fprintf(stderr, "bad entry: %s\n", msg);
23710315Smckusick 	fprintf(stderr, "name: %s\n", myname(ep));
23810315Smckusick 	fprintf(stderr, "parent name %s\n", myname(ep->e_parent));
23910315Smckusick 	if (ep->e_sibling != NIL)
24010315Smckusick 		fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling));
24110315Smckusick 	if (ep->e_entries != NIL)
24210315Smckusick 		fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries));
24310315Smckusick 	if (ep->e_links != NIL)
24410315Smckusick 		fprintf(stderr, "next link name: %s\n", myname(ep->e_links));
24511645Smckusick 	if (ep->e_next != NIL)
24611645Smckusick 		fprintf(stderr, "next hashchain name: %s\n", myname(ep->e_next));
24710315Smckusick 	fprintf(stderr, "entry type: %s\n",
24810315Smckusick 		ep->e_type == NODE ? "NODE" : "LEAF");
24910315Smckusick 	fprintf(stderr, "inode number: %ld\n", ep->e_ino);
25011898Smckusick 	panic("flags: %s\n", flagvalues(ep));
25111898Smckusick }
25211898Smckusick 
25311898Smckusick /*
25411898Smckusick  * Construct a string indicating the active flag bits of an entry.
25511898Smckusick  */
25611898Smckusick char *
25711898Smckusick flagvalues(ep)
25811898Smckusick 	register struct entry *ep;
25911898Smckusick {
26011898Smckusick 	static char flagbuf[BUFSIZ];
26111898Smckusick 
26211898Smckusick 	(void) strcpy(flagbuf, "|NIL");
26310315Smckusick 	flagbuf[0] = '\0';
26410315Smckusick 	if (ep->e_flags & REMOVED)
26511898Smckusick 		(void) strcat(flagbuf, "|REMOVED");
26610315Smckusick 	if (ep->e_flags & TMPNAME)
26711898Smckusick 		(void) strcat(flagbuf, "|TMPNAME");
26810315Smckusick 	if (ep->e_flags & EXTRACT)
26911898Smckusick 		(void) strcat(flagbuf, "|EXTRACT");
27010315Smckusick 	if (ep->e_flags & NEW)
27111898Smckusick 		(void) strcat(flagbuf, "|NEW");
27210315Smckusick 	if (ep->e_flags & KEEP)
27311898Smckusick 		(void) strcat(flagbuf, "|KEEP");
274*18006Smckusick 	if (ep->e_flags & EXISTED)
275*18006Smckusick 		(void) strcat(flagbuf, "|EXISTED");
27611898Smckusick 	return (&flagbuf[1]);
27710315Smckusick }
27810315Smckusick 
27910315Smckusick /*
28011995Smckusick  * Check to see if a name is on a dump tape.
28111321Smckusick  */
28211995Smckusick ino_t
28311995Smckusick dirlookup(name)
28411995Smckusick 	char *name;
28511995Smckusick {
28611995Smckusick 	ino_t ino;
28711995Smckusick 
28811995Smckusick 	ino = psearch(name);
28911995Smckusick 	if (ino == 0 || BIT(ino, dumpmap) == 0)
29011995Smckusick 		fprintf(stderr, "%s is not on tape\n", name);
29111995Smckusick 	return (ino);
29211995Smckusick }
29311995Smckusick 
29411995Smckusick /*
29511995Smckusick  * 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] ");
30512557Smckusick 		(void) fflush(stderr);
30611995Smckusick 		c = getc(terminal);
30711995Smckusick 		while (c != '\n' && getc(terminal) != '\n')
30817711Smckusick 			if (feof(terminal))
30917711Smckusick 				done(1);
31010315Smckusick 	} while (c != 'y' && c != 'n');
31110315Smckusick 	if (c == 'y')
31210315Smckusick 		return (GOOD);
31310315Smckusick 	return (FAIL);
31410315Smckusick }
31511995Smckusick 
31611995Smckusick /*
31711995Smckusick  * handle unexpected inconsistencies
31811995Smckusick  */
31911995Smckusick /* VARARGS1 */
32011995Smckusick panic(msg, d1, d2)
32111995Smckusick 	char *msg;
32211995Smckusick 	long d1, d2;
32311995Smckusick {
32411995Smckusick 
32511995Smckusick 	fprintf(stderr, msg, d1, d2);
32611995Smckusick 	if (reply("abort") == GOOD) {
32711995Smckusick 		if (reply("dump core") == GOOD)
32811995Smckusick 			abort();
32911995Smckusick 		done(1);
33011995Smckusick 	}
33111995Smckusick }
332