xref: /csrg-svn/sbin/restore/utilities.c (revision 42489)
121171Sdist /*
236105Sbostic  * Copyright (c) 1983 The Regents of the University of California.
336105Sbostic  * All rights reserved.
436105Sbostic  *
536105Sbostic  * Redistribution and use in source and binary forms are permitted
636105Sbostic  * provided that the above copyright notice and this paragraph are
736105Sbostic  * duplicated in all such forms and that any documentation,
836105Sbostic  * advertising materials, and other materials related to such
936105Sbostic  * distribution and use acknowledge that the software was developed
1036105Sbostic  * by the University of California, Berkeley.  The name of the
1136105Sbostic  * University may not be used to endorse or promote products derived
1236105Sbostic  * from this software without specific prior written permission.
1336105Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1436105Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1536105Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1621171Sdist  */
1721171Sdist 
1810315Smckusick #ifndef lint
19*42489Smckusick static char sccsid[] = "@(#)utilities.c	5.5 (Berkeley) 05/30/90";
2036105Sbostic #endif /* not lint */
2110315Smckusick 
2210315Smckusick #include "restore.h"
2310315Smckusick 
2410315Smckusick /*
2510315Smckusick  * Insure that all the components of a pathname exist.
2610315Smckusick  */
2711645Smckusick pathcheck(name)
2810315Smckusick 	char *name;
2910315Smckusick {
3010315Smckusick 	register char *cp;
3110315Smckusick 	struct entry *ep;
3211312Smckusick 	char *start;
3310315Smckusick 
3410315Smckusick 	start = index(name, '/');
3511312Smckusick 	if (start == 0)
3611645Smckusick 		return;
3710315Smckusick 	for (cp = start; *cp != '\0'; cp++) {
3810315Smckusick 		if (*cp != '/')
3910315Smckusick 			continue;
4010315Smckusick 		*cp = '\0';
4110315Smckusick 		ep = lookupname(name);
4210315Smckusick 		if (ep == NIL) {
4311995Smckusick 			ep = addentry(name, psearch(name), NODE);
4410315Smckusick 			newnode(ep);
4510315Smckusick 		}
4618009Smckusick 		ep->e_flags |= NEW|KEEP;
4710315Smckusick 		*cp = '/';
4810315Smckusick 	}
4910315Smckusick }
5010315Smckusick 
5110315Smckusick /*
5210315Smckusick  * Change a name to a unique temporary name.
5310315Smckusick  */
5410315Smckusick mktempname(ep)
5510315Smckusick 	register struct entry *ep;
5610315Smckusick {
5711645Smckusick 	char oldname[MAXPATHLEN];
5810315Smckusick 
5910315Smckusick 	if (ep->e_flags & TMPNAME)
6010315Smckusick 		badentry(ep, "mktempname: called with TMPNAME");
6110315Smckusick 	ep->e_flags |= TMPNAME;
6211995Smckusick 	(void) strcpy(oldname, myname(ep));
6311645Smckusick 	freename(ep->e_name);
6411645Smckusick 	ep->e_name = savename(gentempname(ep));
6511645Smckusick 	ep->e_namlen = strlen(ep->e_name);
6610315Smckusick 	renameit(oldname, myname(ep));
6710315Smckusick }
6810315Smckusick 
6910315Smckusick /*
7011645Smckusick  * Generate a temporary name for an entry.
7111645Smckusick  */
7211645Smckusick char *
7311645Smckusick gentempname(ep)
7411645Smckusick 	struct entry *ep;
7511645Smckusick {
7611645Smckusick 	static char name[MAXPATHLEN];
7711645Smckusick 	struct entry *np;
7811645Smckusick 	long i = 0;
7911645Smckusick 
8011645Smckusick 	for (np = lookupino(ep->e_ino); np != NIL && np != ep; np = np->e_links)
8111645Smckusick 		i++;
8211645Smckusick 	if (np == NIL)
8311645Smckusick 		badentry(ep, "not on ino list");
8411733Smckusick 	(void) sprintf(name, "%s%d%d", TMPHDR, i, ep->e_ino);
8511645Smckusick 	return (name);
8611645Smckusick }
8711645Smckusick 
8811645Smckusick /*
8910315Smckusick  * Rename a file or directory.
9010315Smckusick  */
9110315Smckusick renameit(from, to)
9210315Smckusick 	char *from, *to;
9310315Smckusick {
9434268Smckusick 	if (!Nflag && rename(from, to) < 0) {
9512557Smckusick 		fprintf(stderr, "Warning: cannot rename %s to %s", from, to);
9612557Smckusick 		(void) fflush(stderr);
9712557Smckusick 		perror("");
9811923Smckusick 		return;
9910315Smckusick 	}
10010315Smckusick 	vprintf(stdout, "rename %s to %s\n", from, to);
10110315Smckusick }
10210315Smckusick 
10310315Smckusick /*
10410315Smckusick  * Create a new node (directory).
10510315Smckusick  */
10610315Smckusick newnode(np)
10710315Smckusick 	struct entry *np;
10810315Smckusick {
10910315Smckusick 	char *cp;
11010315Smckusick 
11110315Smckusick 	if (np->e_type != NODE)
11210315Smckusick 		badentry(np, "newnode: not a node");
11310315Smckusick 	cp = myname(np);
11434268Smckusick 	if (!Nflag && mkdir(cp, 0777) < 0) {
11518006Smckusick 		np->e_flags |= EXISTED;
11611740Smckusick 		fprintf(stderr, "Warning: ");
11711995Smckusick 		(void) fflush(stderr);
11811740Smckusick 		perror(cp);
11911740Smckusick 		return;
12010315Smckusick 	}
12110315Smckusick 	vprintf(stdout, "Make node %s\n", cp);
12210315Smckusick }
12310315Smckusick 
12410315Smckusick /*
12510315Smckusick  * Remove an old node (directory).
12610315Smckusick  */
12710315Smckusick removenode(ep)
12810315Smckusick 	register struct entry *ep;
12910315Smckusick {
13010315Smckusick 	char *cp;
13110315Smckusick 
13210315Smckusick 	if (ep->e_type != NODE)
13310315Smckusick 		badentry(ep, "removenode: not a node");
13410315Smckusick 	if (ep->e_entries != NIL)
13510315Smckusick 		badentry(ep, "removenode: non-empty directory");
13611923Smckusick 	ep->e_flags |= REMOVED;
13711923Smckusick 	ep->e_flags &= ~TMPNAME;
13810315Smckusick 	cp = myname(ep);
13934268Smckusick 	if (!Nflag && rmdir(cp) < 0) {
14011923Smckusick 		fprintf(stderr, "Warning: ");
14111995Smckusick 		(void) fflush(stderr);
14211923Smckusick 		perror(cp);
14311923Smckusick 		return;
14410315Smckusick 	}
14510315Smckusick 	vprintf(stdout, "Remove node %s\n", cp);
14610315Smckusick }
14710315Smckusick 
14810315Smckusick /*
14910315Smckusick  * Remove a leaf.
15010315Smckusick  */
15110315Smckusick removeleaf(ep)
15210315Smckusick 	register struct entry *ep;
15310315Smckusick {
15410315Smckusick 	char *cp;
15510315Smckusick 
15610315Smckusick 	if (ep->e_type != LEAF)
15710315Smckusick 		badentry(ep, "removeleaf: not a leaf");
15811923Smckusick 	ep->e_flags |= REMOVED;
15911923Smckusick 	ep->e_flags &= ~TMPNAME;
16010315Smckusick 	cp = myname(ep);
16134268Smckusick 	if (!Nflag && unlink(cp) < 0) {
16211923Smckusick 		fprintf(stderr, "Warning: ");
16311995Smckusick 		(void) fflush(stderr);
16411923Smckusick 		perror(cp);
16511923Smckusick 		return;
16610315Smckusick 	}
16710315Smckusick 	vprintf(stdout, "Remove leaf %s\n", cp);
16810315Smckusick }
16910315Smckusick 
17010315Smckusick /*
17110315Smckusick  * Create a link.
17210315Smckusick  */
17310315Smckusick linkit(existing, new, type)
17410315Smckusick 	char *existing, *new;
17510315Smckusick 	int type;
17610315Smckusick {
17710315Smckusick 
17810315Smckusick 	if (type == SYMLINK) {
17934268Smckusick 		if (!Nflag && symlink(existing, new) < 0) {
18011923Smckusick 			fprintf(stderr,
18115782Smckusick 				"Warning: cannot create symbolic link %s->%s: ",
18210315Smckusick 				new, existing);
18312557Smckusick 			(void) fflush(stderr);
18412557Smckusick 			perror("");
18515782Smckusick 			return (FAIL);
18610315Smckusick 		}
18710315Smckusick 	} else if (type == HARDLINK) {
18834268Smckusick 		if (!Nflag && link(existing, new) < 0) {
18911923Smckusick 			fprintf(stderr,
19015782Smckusick 				"Warning: cannot create hard link %s->%s: ",
19110315Smckusick 				new, existing);
19212557Smckusick 			(void) fflush(stderr);
19312557Smckusick 			perror("");
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);
21611995Smckusick 		if (ep == NIL || 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);
23511995Smckusick 		if (ep == NIL || 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  */
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));
25410315Smckusick 	if (ep->e_sibling != NIL)
25510315Smckusick 		fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling));
25610315Smckusick 	if (ep->e_entries != NIL)
25710315Smckusick 		fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries));
25810315Smckusick 	if (ep->e_links != NIL)
25910315Smckusick 		fprintf(stderr, "next link name: %s\n", myname(ep->e_links));
26011645Smckusick 	if (ep->e_next != NIL)
26111645Smckusick 		fprintf(stderr, "next hashchain name: %s\n", myname(ep->e_next));
26210315Smckusick 	fprintf(stderr, "entry type: %s\n",
26310315Smckusick 		ep->e_type == NODE ? "NODE" : "LEAF");
26410315Smckusick 	fprintf(stderr, "inode number: %ld\n", ep->e_ino);
26511898Smckusick 	panic("flags: %s\n", flagvalues(ep));
26611898Smckusick }
26711898Smckusick 
26811898Smckusick /*
26911898Smckusick  * Construct a string indicating the active flag bits of an entry.
27011898Smckusick  */
27111898Smckusick char *
27211898Smckusick flagvalues(ep)
27311898Smckusick 	register struct entry *ep;
27411898Smckusick {
27511898Smckusick 	static char flagbuf[BUFSIZ];
27611898Smckusick 
27711898Smckusick 	(void) strcpy(flagbuf, "|NIL");
27810315Smckusick 	flagbuf[0] = '\0';
27910315Smckusick 	if (ep->e_flags & REMOVED)
28011898Smckusick 		(void) strcat(flagbuf, "|REMOVED");
28110315Smckusick 	if (ep->e_flags & TMPNAME)
28211898Smckusick 		(void) strcat(flagbuf, "|TMPNAME");
28310315Smckusick 	if (ep->e_flags & EXTRACT)
28411898Smckusick 		(void) strcat(flagbuf, "|EXTRACT");
28510315Smckusick 	if (ep->e_flags & NEW)
28611898Smckusick 		(void) strcat(flagbuf, "|NEW");
28710315Smckusick 	if (ep->e_flags & KEEP)
28811898Smckusick 		(void) strcat(flagbuf, "|KEEP");
28918006Smckusick 	if (ep->e_flags & EXISTED)
29018006Smckusick 		(void) strcat(flagbuf, "|EXISTED");
29111898Smckusick 	return (&flagbuf[1]);
29210315Smckusick }
29310315Smckusick 
29410315Smckusick /*
29511995Smckusick  * Check to see if a name is on a dump tape.
29611321Smckusick  */
29711995Smckusick ino_t
29811995Smckusick dirlookup(name)
29911995Smckusick 	char *name;
30011995Smckusick {
30111995Smckusick 	ino_t ino;
30211995Smckusick 
30311995Smckusick 	ino = psearch(name);
30411995Smckusick 	if (ino == 0 || BIT(ino, dumpmap) == 0)
30511995Smckusick 		fprintf(stderr, "%s is not on tape\n", name);
30611995Smckusick 	return (ino);
30711995Smckusick }
30811995Smckusick 
30911995Smckusick /*
31011995Smckusick  * Elicit a reply.
31110315Smckusick  */
31210315Smckusick reply(question)
31310315Smckusick 	char *question;
31410315Smckusick {
31510315Smckusick 	char c;
31610315Smckusick 
31710315Smckusick 	do	{
31824185Smckusick 		fprintf(stderr, "%s? [yn] ", question);
31912557Smckusick 		(void) fflush(stderr);
32011995Smckusick 		c = getc(terminal);
32111995Smckusick 		while (c != '\n' && getc(terminal) != '\n')
32217711Smckusick 			if (feof(terminal))
32324185Smckusick 				return (FAIL);
32410315Smckusick 	} while (c != 'y' && c != 'n');
32510315Smckusick 	if (c == 'y')
32610315Smckusick 		return (GOOD);
32710315Smckusick 	return (FAIL);
32810315Smckusick }
32911995Smckusick 
33011995Smckusick /*
33111995Smckusick  * handle unexpected inconsistencies
33211995Smckusick  */
33311995Smckusick /* VARARGS1 */
33411995Smckusick panic(msg, d1, d2)
33511995Smckusick 	char *msg;
33611995Smckusick 	long d1, d2;
33711995Smckusick {
33811995Smckusick 
33911995Smckusick 	fprintf(stderr, msg, d1, d2);
340*42489Smckusick 	if (yflag)
341*42489Smckusick 		return;
34211995Smckusick 	if (reply("abort") == GOOD) {
34311995Smckusick 		if (reply("dump core") == GOOD)
34411995Smckusick 			abort();
34511995Smckusick 		done(1);
34611995Smckusick 	}
34711995Smckusick }
348