xref: /csrg-svn/sbin/restore/utilities.c (revision 11898)
110315Smckusick /* Copyright (c) 1983 Regents of the University of California */
210315Smckusick 
310315Smckusick #ifndef lint
4*11898Smckusick static char sccsid[] = "@(#)utilities.c	3.9	(Berkeley)	83/04/11";
510315Smckusick #endif
610315Smckusick 
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) {
2811645Smckusick 			ep = addentry(name, ep->e_ino, NODE);
2911645Smckusick 			ep->e_flags |= KEEP;
3010315Smckusick 			newnode(ep);
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;
4710315Smckusick 	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) {
8010315Smckusick 		perror("renameit");
8110315Smckusick 		panic("Cannot rename %s to %s\n", from, to);
8210315Smckusick 	}
8310315Smckusick 	vprintf(stdout, "rename %s to %s\n", from, to);
8410315Smckusick }
8510315Smckusick 
8610315Smckusick /*
8710315Smckusick  * Create a new node (directory).
8810315Smckusick  */
8910315Smckusick newnode(np)
9010315Smckusick 	struct entry *np;
9110315Smckusick {
9210315Smckusick 	char *cp;
9310315Smckusick 
9410315Smckusick 	if (np->e_type != NODE)
9510315Smckusick 		badentry(np, "newnode: not a node");
9610315Smckusick 	cp = myname(np);
9711312Smckusick 	if (mkdir(cp, 0777) < 0) {
9811740Smckusick 		fprintf(stderr, "Warning: ");
9911740Smckusick 		fflush(stderr);
10011740Smckusick 		perror(cp);
10111740Smckusick 		return;
10210315Smckusick 	}
10310315Smckusick 	vprintf(stdout, "Make node %s\n", cp);
10410315Smckusick }
10510315Smckusick 
10610315Smckusick /*
10710315Smckusick  * Remove an old node (directory).
10810315Smckusick  */
10910315Smckusick removenode(ep)
11010315Smckusick 	register struct entry *ep;
11110315Smckusick {
11210315Smckusick 	char *cp;
11310315Smckusick 
11410315Smckusick 	if (ep->e_type != NODE)
11510315Smckusick 		badentry(ep, "removenode: not a node");
11610315Smckusick 	if (ep->e_entries != NIL)
11710315Smckusick 		badentry(ep, "removenode: non-empty directory");
11810315Smckusick 	cp = myname(ep);
11910315Smckusick 	if (rmdir(cp) < 0) {
12010315Smckusick 		perror("removenode");
12110315Smckusick 		panic("Cannot remove node %s\n", cp);
12210315Smckusick 	}
12310315Smckusick 	ep->e_flags |= REMOVED;
12411645Smckusick 	ep->e_flags &= ~TMPNAME;
12510315Smckusick 	vprintf(stdout, "Remove node %s\n", cp);
12610315Smckusick }
12710315Smckusick 
12810315Smckusick /*
12910315Smckusick  * Remove a leaf.
13010315Smckusick  */
13110315Smckusick removeleaf(ep)
13210315Smckusick 	register struct entry *ep;
13310315Smckusick {
13410315Smckusick 	char *cp;
13510315Smckusick 
13610315Smckusick 	if (ep->e_type != LEAF)
13710315Smckusick 		badentry(ep, "removeleaf: not a leaf");
13810315Smckusick 	cp = myname(ep);
13910315Smckusick 	if (unlink(cp) < 0) {
14010315Smckusick 		perror("removeleaf");
14110315Smckusick 		panic("Cannot remove leaf %s\n", cp);
14210315Smckusick 	}
14310315Smckusick 	ep->e_flags |= REMOVED;
14410315Smckusick 	ep->e_flags &= ~TMPNAME;
14510315Smckusick 	vprintf(stdout, "Remove leaf %s\n", cp);
14610315Smckusick }
14710315Smckusick 
14810315Smckusick /*
14910315Smckusick  * Create a link.
15010315Smckusick  */
15110315Smckusick linkit(existing, new, type)
15210315Smckusick 	char *existing, *new;
15310315Smckusick 	int type;
15410315Smckusick {
15510315Smckusick 
15610315Smckusick 	if (type == SYMLINK) {
15710315Smckusick 		if (symlink(existing, new) < 0) {
15810315Smckusick 			perror("linkit");
15910315Smckusick 			panic("Cannot create symbolic link %s->%s\n",
16010315Smckusick 				new, existing);
16110315Smckusick 		}
16210315Smckusick 	} else if (type == HARDLINK) {
16310315Smckusick 		if (link(existing, new) < 0) {
16410315Smckusick 			perror("linkit");
16510315Smckusick 			panic("Cannot create hard link %s->%s\n",
16610315Smckusick 				new, existing);
16710315Smckusick 		}
16810315Smckusick 	} else {
16910315Smckusick 		panic("linkit: unknown type %d\n", type);
17010315Smckusick 	}
17110315Smckusick 	vprintf(stdout, "Create %s link %s->%s\n",
17210315Smckusick 		type == SYMLINK ? "symbolic" : "hard", new, existing);
17310315Smckusick }
17410315Smckusick 
17510315Smckusick /*
17610315Smckusick  * find lowest number file (above "start") that needs to be extracted
17710315Smckusick  */
17810315Smckusick ino_t
17910315Smckusick lowerbnd(start)
18010315Smckusick 	ino_t start;
18110315Smckusick {
18210315Smckusick 	register struct entry *ep;
18310315Smckusick 
18410315Smckusick 	for ( ; start < maxino; start++) {
18510315Smckusick 		ep = lookupino(start);
18610315Smckusick 		if (ep == NIL)
18710315Smckusick 			continue;
18811645Smckusick 		if (ep->e_flags & (NEW|EXTRACT))
18910315Smckusick 			return (start);
19010315Smckusick 	}
19110315Smckusick 	return (start);
19210315Smckusick }
19310315Smckusick 
19410315Smckusick /*
19510315Smckusick  * find highest number file (below "start") that needs to be extracted
19610315Smckusick  */
19710315Smckusick ino_t
19810315Smckusick upperbnd(start)
19910315Smckusick 	ino_t start;
20010315Smckusick {
20110315Smckusick 	register struct entry *ep;
20210315Smckusick 
20310315Smckusick 	for ( ; start > ROOTINO; start--) {
20410315Smckusick 		ep = lookupino(start);
20510315Smckusick 		if (ep == NIL)
20610315Smckusick 			continue;
20711645Smckusick 		if (ep->e_flags & (NEW|EXTRACT))
20810315Smckusick 			return (start);
20910315Smckusick 	}
21010315Smckusick 	return (start);
21110315Smckusick }
21210315Smckusick 
21310315Smckusick /*
21410315Smckusick  * report on a badly formed entry
21510315Smckusick  */
21610315Smckusick badentry(ep, msg)
21710315Smckusick 	register struct entry *ep;
21810315Smckusick 	char *msg;
21910315Smckusick {
22010315Smckusick 
22110315Smckusick 	fprintf(stderr, "bad entry: %s\n", msg);
22210315Smckusick 	fprintf(stderr, "name: %s\n", myname(ep));
22310315Smckusick 	fprintf(stderr, "parent name %s\n", myname(ep->e_parent));
22410315Smckusick 	if (ep->e_sibling != NIL)
22510315Smckusick 		fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling));
22610315Smckusick 	if (ep->e_entries != NIL)
22710315Smckusick 		fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries));
22810315Smckusick 	if (ep->e_links != NIL)
22910315Smckusick 		fprintf(stderr, "next link name: %s\n", myname(ep->e_links));
23011645Smckusick 	if (ep->e_next != NIL)
23111645Smckusick 		fprintf(stderr, "next hashchain name: %s\n", myname(ep->e_next));
23210315Smckusick 	fprintf(stderr, "entry type: %s\n",
23310315Smckusick 		ep->e_type == NODE ? "NODE" : "LEAF");
23410315Smckusick 	fprintf(stderr, "inode number: %ld\n", ep->e_ino);
235*11898Smckusick 	panic("flags: %s\n", flagvalues(ep));
236*11898Smckusick }
237*11898Smckusick 
238*11898Smckusick /*
239*11898Smckusick  * Construct a string indicating the active flag bits of an entry.
240*11898Smckusick  */
241*11898Smckusick char *
242*11898Smckusick flagvalues(ep)
243*11898Smckusick 	register struct entry *ep;
244*11898Smckusick {
245*11898Smckusick 	static char flagbuf[BUFSIZ];
246*11898Smckusick 
247*11898Smckusick 	(void) strcpy(flagbuf, "|NIL");
24810315Smckusick 	flagbuf[0] = '\0';
24910315Smckusick 	if (ep->e_flags & REMOVED)
250*11898Smckusick 		(void) strcat(flagbuf, "|REMOVED");
25110315Smckusick 	if (ep->e_flags & TMPNAME)
252*11898Smckusick 		(void) strcat(flagbuf, "|TMPNAME");
25310315Smckusick 	if (ep->e_flags & EXTRACT)
254*11898Smckusick 		(void) strcat(flagbuf, "|EXTRACT");
25510315Smckusick 	if (ep->e_flags & NEW)
256*11898Smckusick 		(void) strcat(flagbuf, "|NEW");
25710315Smckusick 	if (ep->e_flags & KEEP)
258*11898Smckusick 		(void) strcat(flagbuf, "|KEEP");
259*11898Smckusick 	return (&flagbuf[1]);
26010315Smckusick }
26110315Smckusick 
26210315Smckusick /*
26311321Smckusick  * canonicalize file names to always start with ``./''
26411321Smckusick  */
26511321Smckusick canon(rawname, canonname)
26611321Smckusick 	char *rawname, *canonname;
26711321Smckusick {
26811321Smckusick 	int len;
26911321Smckusick 
27011321Smckusick 	if (strcmp(rawname, ".") == 0 || strncmp(rawname, "./", 2) == 0)
27111645Smckusick 		(void) strcpy(canonname, "");
27211321Smckusick 	else if (rawname[0] == '/')
27311645Smckusick 		(void) strcpy(canonname, ".");
27411321Smckusick 	else
27511645Smckusick 		(void) strcpy(canonname, "./");
27611645Smckusick 	(void) strcat(canonname, rawname);
27711321Smckusick 	len = strlen(canonname) - 1;
27811321Smckusick 	if (canonname[len] == '/')
27911321Smckusick 		canonname[len] = '\0';
28011321Smckusick }
28111321Smckusick 
28211321Smckusick /*
28310315Smckusick  * elicit a reply
28410315Smckusick  */
28510315Smckusick reply(question)
28610315Smckusick 	char *question;
28710315Smckusick {
28810315Smckusick 	char c;
28910315Smckusick 
29010315Smckusick 	fprintf(stderr, "%s? ", question);
29110315Smckusick 	do	{
29210315Smckusick 		fprintf(stderr, "[yn] ");
29310315Smckusick 		c = getchar();
29410315Smckusick 		while (c != '\n' && getchar() != '\n')
29510315Smckusick 			/* void */;
29610315Smckusick 	} while (c != 'y' && c != 'n');
29710315Smckusick 	if (c == 'y')
29810315Smckusick 		return (GOOD);
29910315Smckusick 	return (FAIL);
30010315Smckusick }
301