xref: /csrg-svn/sbin/restore/utilities.c (revision 42709)
121171Sdist /*
236105Sbostic  * Copyright (c) 1983 The Regents of the University of California.
336105Sbostic  * All rights reserved.
436105Sbostic  *
5*42709Sbostic  * %sccs.include.redist.c%
621171Sdist  */
721171Sdist 
810315Smckusick #ifndef lint
9*42709Sbostic static char sccsid[] = "@(#)utilities.c	5.6 (Berkeley) 06/01/90";
1036105Sbostic #endif /* not lint */
1110315Smckusick 
1210315Smckusick #include "restore.h"
1310315Smckusick 
1410315Smckusick /*
1510315Smckusick  * Insure that all the components of a pathname exist.
1610315Smckusick  */
1711645Smckusick pathcheck(name)
1810315Smckusick 	char *name;
1910315Smckusick {
2010315Smckusick 	register char *cp;
2110315Smckusick 	struct entry *ep;
2211312Smckusick 	char *start;
2310315Smckusick 
2410315Smckusick 	start = index(name, '/');
2511312Smckusick 	if (start == 0)
2611645Smckusick 		return;
2710315Smckusick 	for (cp = start; *cp != '\0'; cp++) {
2810315Smckusick 		if (*cp != '/')
2910315Smckusick 			continue;
3010315Smckusick 		*cp = '\0';
3110315Smckusick 		ep = lookupname(name);
3210315Smckusick 		if (ep == NIL) {
3311995Smckusick 			ep = addentry(name, psearch(name), NODE);
3410315Smckusick 			newnode(ep);
3510315Smckusick 		}
3618009Smckusick 		ep->e_flags |= NEW|KEEP;
3710315Smckusick 		*cp = '/';
3810315Smckusick 	}
3910315Smckusick }
4010315Smckusick 
4110315Smckusick /*
4210315Smckusick  * Change a name to a unique temporary name.
4310315Smckusick  */
4410315Smckusick mktempname(ep)
4510315Smckusick 	register struct entry *ep;
4610315Smckusick {
4711645Smckusick 	char oldname[MAXPATHLEN];
4810315Smckusick 
4910315Smckusick 	if (ep->e_flags & TMPNAME)
5010315Smckusick 		badentry(ep, "mktempname: called with TMPNAME");
5110315Smckusick 	ep->e_flags |= TMPNAME;
5211995Smckusick 	(void) strcpy(oldname, myname(ep));
5311645Smckusick 	freename(ep->e_name);
5411645Smckusick 	ep->e_name = savename(gentempname(ep));
5511645Smckusick 	ep->e_namlen = strlen(ep->e_name);
5610315Smckusick 	renameit(oldname, myname(ep));
5710315Smckusick }
5810315Smckusick 
5910315Smckusick /*
6011645Smckusick  * Generate a temporary name for an entry.
6111645Smckusick  */
6211645Smckusick char *
6311645Smckusick gentempname(ep)
6411645Smckusick 	struct entry *ep;
6511645Smckusick {
6611645Smckusick 	static char name[MAXPATHLEN];
6711645Smckusick 	struct entry *np;
6811645Smckusick 	long i = 0;
6911645Smckusick 
7011645Smckusick 	for (np = lookupino(ep->e_ino); np != NIL && np != ep; np = np->e_links)
7111645Smckusick 		i++;
7211645Smckusick 	if (np == NIL)
7311645Smckusick 		badentry(ep, "not on ino list");
7411733Smckusick 	(void) sprintf(name, "%s%d%d", TMPHDR, i, ep->e_ino);
7511645Smckusick 	return (name);
7611645Smckusick }
7711645Smckusick 
7811645Smckusick /*
7910315Smckusick  * Rename a file or directory.
8010315Smckusick  */
8110315Smckusick renameit(from, to)
8210315Smckusick 	char *from, *to;
8310315Smckusick {
8434268Smckusick 	if (!Nflag && rename(from, to) < 0) {
8512557Smckusick 		fprintf(stderr, "Warning: cannot rename %s to %s", from, to);
8612557Smckusick 		(void) fflush(stderr);
8712557Smckusick 		perror("");
8811923Smckusick 		return;
8910315Smckusick 	}
9010315Smckusick 	vprintf(stdout, "rename %s to %s\n", from, to);
9110315Smckusick }
9210315Smckusick 
9310315Smckusick /*
9410315Smckusick  * Create a new node (directory).
9510315Smckusick  */
9610315Smckusick newnode(np)
9710315Smckusick 	struct entry *np;
9810315Smckusick {
9910315Smckusick 	char *cp;
10010315Smckusick 
10110315Smckusick 	if (np->e_type != NODE)
10210315Smckusick 		badentry(np, "newnode: not a node");
10310315Smckusick 	cp = myname(np);
10434268Smckusick 	if (!Nflag && mkdir(cp, 0777) < 0) {
10518006Smckusick 		np->e_flags |= EXISTED;
10611740Smckusick 		fprintf(stderr, "Warning: ");
10711995Smckusick 		(void) fflush(stderr);
10811740Smckusick 		perror(cp);
10911740Smckusick 		return;
11010315Smckusick 	}
11110315Smckusick 	vprintf(stdout, "Make node %s\n", cp);
11210315Smckusick }
11310315Smckusick 
11410315Smckusick /*
11510315Smckusick  * Remove an old node (directory).
11610315Smckusick  */
11710315Smckusick removenode(ep)
11810315Smckusick 	register struct entry *ep;
11910315Smckusick {
12010315Smckusick 	char *cp;
12110315Smckusick 
12210315Smckusick 	if (ep->e_type != NODE)
12310315Smckusick 		badentry(ep, "removenode: not a node");
12410315Smckusick 	if (ep->e_entries != NIL)
12510315Smckusick 		badentry(ep, "removenode: non-empty directory");
12611923Smckusick 	ep->e_flags |= REMOVED;
12711923Smckusick 	ep->e_flags &= ~TMPNAME;
12810315Smckusick 	cp = myname(ep);
12934268Smckusick 	if (!Nflag && rmdir(cp) < 0) {
13011923Smckusick 		fprintf(stderr, "Warning: ");
13111995Smckusick 		(void) fflush(stderr);
13211923Smckusick 		perror(cp);
13311923Smckusick 		return;
13410315Smckusick 	}
13510315Smckusick 	vprintf(stdout, "Remove node %s\n", cp);
13610315Smckusick }
13710315Smckusick 
13810315Smckusick /*
13910315Smckusick  * Remove a leaf.
14010315Smckusick  */
14110315Smckusick removeleaf(ep)
14210315Smckusick 	register struct entry *ep;
14310315Smckusick {
14410315Smckusick 	char *cp;
14510315Smckusick 
14610315Smckusick 	if (ep->e_type != LEAF)
14710315Smckusick 		badentry(ep, "removeleaf: not a leaf");
14811923Smckusick 	ep->e_flags |= REMOVED;
14911923Smckusick 	ep->e_flags &= ~TMPNAME;
15010315Smckusick 	cp = myname(ep);
15134268Smckusick 	if (!Nflag && unlink(cp) < 0) {
15211923Smckusick 		fprintf(stderr, "Warning: ");
15311995Smckusick 		(void) fflush(stderr);
15411923Smckusick 		perror(cp);
15511923Smckusick 		return;
15610315Smckusick 	}
15710315Smckusick 	vprintf(stdout, "Remove leaf %s\n", cp);
15810315Smckusick }
15910315Smckusick 
16010315Smckusick /*
16110315Smckusick  * Create a link.
16210315Smckusick  */
16310315Smckusick linkit(existing, new, type)
16410315Smckusick 	char *existing, *new;
16510315Smckusick 	int type;
16610315Smckusick {
16710315Smckusick 
16810315Smckusick 	if (type == SYMLINK) {
16934268Smckusick 		if (!Nflag && symlink(existing, new) < 0) {
17011923Smckusick 			fprintf(stderr,
17115782Smckusick 				"Warning: cannot create symbolic link %s->%s: ",
17210315Smckusick 				new, existing);
17312557Smckusick 			(void) fflush(stderr);
17412557Smckusick 			perror("");
17515782Smckusick 			return (FAIL);
17610315Smckusick 		}
17710315Smckusick 	} else if (type == HARDLINK) {
17834268Smckusick 		if (!Nflag && link(existing, new) < 0) {
17911923Smckusick 			fprintf(stderr,
18015782Smckusick 				"Warning: cannot create hard link %s->%s: ",
18110315Smckusick 				new, existing);
18212557Smckusick 			(void) fflush(stderr);
18312557Smckusick 			perror("");
18415782Smckusick 			return (FAIL);
18510315Smckusick 		}
18610315Smckusick 	} else {
18710315Smckusick 		panic("linkit: unknown type %d\n", type);
18815782Smckusick 		return (FAIL);
18910315Smckusick 	}
19010315Smckusick 	vprintf(stdout, "Create %s link %s->%s\n",
19110315Smckusick 		type == SYMLINK ? "symbolic" : "hard", new, existing);
19215782Smckusick 	return (GOOD);
19310315Smckusick }
19410315Smckusick 
19510315Smckusick /*
19610315Smckusick  * find lowest number file (above "start") that needs to be extracted
19710315Smckusick  */
19810315Smckusick ino_t
19910315Smckusick lowerbnd(start)
20010315Smckusick 	ino_t start;
20110315Smckusick {
20210315Smckusick 	register struct entry *ep;
20310315Smckusick 
20410315Smckusick 	for ( ; start < maxino; start++) {
20510315Smckusick 		ep = lookupino(start);
20611995Smckusick 		if (ep == NIL || ep->e_type == NODE)
20710315Smckusick 			continue;
20811645Smckusick 		if (ep->e_flags & (NEW|EXTRACT))
20910315Smckusick 			return (start);
21010315Smckusick 	}
21110315Smckusick 	return (start);
21210315Smckusick }
21310315Smckusick 
21410315Smckusick /*
21510315Smckusick  * find highest number file (below "start") that needs to be extracted
21610315Smckusick  */
21710315Smckusick ino_t
21810315Smckusick upperbnd(start)
21910315Smckusick 	ino_t start;
22010315Smckusick {
22110315Smckusick 	register struct entry *ep;
22210315Smckusick 
22310315Smckusick 	for ( ; start > ROOTINO; start--) {
22410315Smckusick 		ep = lookupino(start);
22511995Smckusick 		if (ep == NIL || ep->e_type == NODE)
22610315Smckusick 			continue;
22711645Smckusick 		if (ep->e_flags & (NEW|EXTRACT))
22810315Smckusick 			return (start);
22910315Smckusick 	}
23010315Smckusick 	return (start);
23110315Smckusick }
23210315Smckusick 
23310315Smckusick /*
23410315Smckusick  * report on a badly formed entry
23510315Smckusick  */
23610315Smckusick badentry(ep, msg)
23710315Smckusick 	register struct entry *ep;
23810315Smckusick 	char *msg;
23910315Smckusick {
24010315Smckusick 
24110315Smckusick 	fprintf(stderr, "bad entry: %s\n", msg);
24210315Smckusick 	fprintf(stderr, "name: %s\n", myname(ep));
24310315Smckusick 	fprintf(stderr, "parent name %s\n", myname(ep->e_parent));
24410315Smckusick 	if (ep->e_sibling != NIL)
24510315Smckusick 		fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling));
24610315Smckusick 	if (ep->e_entries != NIL)
24710315Smckusick 		fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries));
24810315Smckusick 	if (ep->e_links != NIL)
24910315Smckusick 		fprintf(stderr, "next link name: %s\n", myname(ep->e_links));
25011645Smckusick 	if (ep->e_next != NIL)
25111645Smckusick 		fprintf(stderr, "next hashchain name: %s\n", myname(ep->e_next));
25210315Smckusick 	fprintf(stderr, "entry type: %s\n",
25310315Smckusick 		ep->e_type == NODE ? "NODE" : "LEAF");
25410315Smckusick 	fprintf(stderr, "inode number: %ld\n", ep->e_ino);
25511898Smckusick 	panic("flags: %s\n", flagvalues(ep));
25611898Smckusick }
25711898Smckusick 
25811898Smckusick /*
25911898Smckusick  * Construct a string indicating the active flag bits of an entry.
26011898Smckusick  */
26111898Smckusick char *
26211898Smckusick flagvalues(ep)
26311898Smckusick 	register struct entry *ep;
26411898Smckusick {
26511898Smckusick 	static char flagbuf[BUFSIZ];
26611898Smckusick 
26711898Smckusick 	(void) strcpy(flagbuf, "|NIL");
26810315Smckusick 	flagbuf[0] = '\0';
26910315Smckusick 	if (ep->e_flags & REMOVED)
27011898Smckusick 		(void) strcat(flagbuf, "|REMOVED");
27110315Smckusick 	if (ep->e_flags & TMPNAME)
27211898Smckusick 		(void) strcat(flagbuf, "|TMPNAME");
27310315Smckusick 	if (ep->e_flags & EXTRACT)
27411898Smckusick 		(void) strcat(flagbuf, "|EXTRACT");
27510315Smckusick 	if (ep->e_flags & NEW)
27611898Smckusick 		(void) strcat(flagbuf, "|NEW");
27710315Smckusick 	if (ep->e_flags & KEEP)
27811898Smckusick 		(void) strcat(flagbuf, "|KEEP");
27918006Smckusick 	if (ep->e_flags & EXISTED)
28018006Smckusick 		(void) strcat(flagbuf, "|EXISTED");
28111898Smckusick 	return (&flagbuf[1]);
28210315Smckusick }
28310315Smckusick 
28410315Smckusick /*
28511995Smckusick  * Check to see if a name is on a dump tape.
28611321Smckusick  */
28711995Smckusick ino_t
28811995Smckusick dirlookup(name)
28911995Smckusick 	char *name;
29011995Smckusick {
29111995Smckusick 	ino_t ino;
29211995Smckusick 
29311995Smckusick 	ino = psearch(name);
29411995Smckusick 	if (ino == 0 || BIT(ino, dumpmap) == 0)
29511995Smckusick 		fprintf(stderr, "%s is not on tape\n", name);
29611995Smckusick 	return (ino);
29711995Smckusick }
29811995Smckusick 
29911995Smckusick /*
30011995Smckusick  * Elicit a reply.
30110315Smckusick  */
30210315Smckusick reply(question)
30310315Smckusick 	char *question;
30410315Smckusick {
30510315Smckusick 	char c;
30610315Smckusick 
30710315Smckusick 	do	{
30824185Smckusick 		fprintf(stderr, "%s? [yn] ", question);
30912557Smckusick 		(void) fflush(stderr);
31011995Smckusick 		c = getc(terminal);
31111995Smckusick 		while (c != '\n' && getc(terminal) != '\n')
31217711Smckusick 			if (feof(terminal))
31324185Smckusick 				return (FAIL);
31410315Smckusick 	} while (c != 'y' && c != 'n');
31510315Smckusick 	if (c == 'y')
31610315Smckusick 		return (GOOD);
31710315Smckusick 	return (FAIL);
31810315Smckusick }
31911995Smckusick 
32011995Smckusick /*
32111995Smckusick  * handle unexpected inconsistencies
32211995Smckusick  */
32311995Smckusick /* VARARGS1 */
32411995Smckusick panic(msg, d1, d2)
32511995Smckusick 	char *msg;
32611995Smckusick 	long d1, d2;
32711995Smckusick {
32811995Smckusick 
32911995Smckusick 	fprintf(stderr, msg, d1, d2);
33042489Smckusick 	if (yflag)
33142489Smckusick 		return;
33211995Smckusick 	if (reply("abort") == GOOD) {
33311995Smckusick 		if (reply("dump core") == GOOD)
33411995Smckusick 			abort();
33511995Smckusick 		done(1);
33611995Smckusick 	}
33711995Smckusick }
338