xref: /csrg-svn/sbin/restore/utilities.c (revision 11321)
110315Smckusick /* Copyright (c) 1983 Regents of the University of California */
210315Smckusick 
310315Smckusick #ifndef lint
4*11321Smckusick static char sccsid[] = "@(#)utilities.c	3.4	(Berkeley)	83/02/28";
510315Smckusick #endif
610315Smckusick 
710315Smckusick #include "restore.h"
810315Smckusick 
910315Smckusick /*
1011131Smckusick  * Move the contents of a directory to a new directory.
1111131Smckusick  */
1211131Smckusick movecontents(from, to)
1311131Smckusick 	struct entry *from, *to;
1411131Smckusick {
1511131Smckusick 	register struct entry *ep;
1611131Smckusick 	struct entry *np;
1711131Smckusick 	register char *targetp;
1811131Smckusick 	char target[BUFSIZ];
1911131Smckusick 
2011131Smckusick 	strcpy(target, myname(to));
2111131Smckusick 	targetp = &target[strlen(target)];
2211131Smckusick 	*targetp++ = '/';
2311131Smckusick 	for (ep = from->e_entries; ep != NIL; ) {
2411131Smckusick 		strcpy(targetp, ep->e_name);
2511131Smckusick 		if (ep->e_flags & TMPNAME)
2611131Smckusick 			badentry(ep, "movecontents: found TMPNAME");
2711131Smckusick 		np = lookupname(target);
2811131Smckusick 		if (np != NIL)
2911131Smckusick 			mktempname(np);
3011131Smckusick 		renameit(myname(ep), target);
3111131Smckusick 		np = ep->e_sibling;
3211131Smckusick 		moveentry(ep, target);
3311131Smckusick 		ep = np;
3411131Smckusick 	}
3511131Smckusick }
3611131Smckusick 
3711131Smckusick /*
3810315Smckusick  * Insure that all the components of a pathname exist.
3910315Smckusick  */
4011131Smckusick struct entry *
4111131Smckusick pathcheck(name, type)
4210315Smckusick 	char *name;
4311131Smckusick 	char type;
4410315Smckusick {
4510315Smckusick 	register char *cp;
4610315Smckusick 	struct entry *ep;
4711312Smckusick 	char *start;
4810315Smckusick 
4910315Smckusick 	start = index(name, '/');
5011312Smckusick 	if (start == 0)
5111131Smckusick 		return (lookupino(ROOTINO));
5210315Smckusick 	for (cp = start; *cp != '\0'; cp++) {
5310315Smckusick 		if (*cp != '/')
5410315Smckusick 			continue;
5510315Smckusick 		*cp = '\0';
5610315Smckusick 		ep = lookupname(name);
5710315Smckusick 		if (ep == NIL) {
5811131Smckusick 			ep = addentry(name, (ino_t)0, NODE);
5911131Smckusick 			ep->e_flags |= type;
6010315Smckusick 			newnode(ep);
6110315Smckusick 		}
6210315Smckusick 		*cp = '/';
6310315Smckusick 	}
6411131Smckusick 	return (ep);
6510315Smckusick }
6610315Smckusick 
6710315Smckusick /*
6810315Smckusick  * Change a name to a unique temporary name.
6910315Smckusick  */
7010315Smckusick mktempname(ep)
7110315Smckusick 	register struct entry *ep;
7210315Smckusick {
7310315Smckusick 	char oldname[BUFSIZ];
7410315Smckusick 
7510315Smckusick 	if (ep->e_flags & TMPNAME)
7610315Smckusick 		badentry(ep, "mktempname: called with TMPNAME");
7710315Smckusick 	ep->e_flags |= TMPNAME;
7810315Smckusick 	strcpy(oldname, myname(ep));
7910315Smckusick 	ep->e_name[ep->e_namlen++] = TMPCHAR;
8010315Smckusick 	ep->e_name[ep->e_namlen] = '\0';
8110315Smckusick 	renameit(oldname, myname(ep));
8210315Smckusick }
8310315Smckusick 
8410315Smckusick /*
8510315Smckusick  * Rename a file or directory.
8610315Smckusick  */
8710315Smckusick renameit(from, to)
8810315Smckusick 	char *from, *to;
8910315Smckusick {
9010315Smckusick 	if (rename(from, to) < 0) {
9110315Smckusick 		perror("renameit");
9210315Smckusick 		panic("Cannot rename %s to %s\n", from, to);
9310315Smckusick 	}
9410315Smckusick 	vprintf(stdout, "rename %s to %s\n", from, to);
9510315Smckusick }
9610315Smckusick 
9710315Smckusick /*
9810315Smckusick  * Create a new node (directory).
9910315Smckusick  */
10010315Smckusick newnode(np)
10110315Smckusick 	struct entry *np;
10210315Smckusick {
10310315Smckusick 	char *cp;
10410315Smckusick 
10510315Smckusick 	if (np->e_type != NODE)
10610315Smckusick 		badentry(np, "newnode: not a node");
10710315Smckusick 	cp = myname(np);
10811312Smckusick 	if (mkdir(cp, 0777) < 0) {
10911314Smckusick 		if (command == 'x') {
11011314Smckusick 			perror(cp);
11111314Smckusick 			return;
11211314Smckusick 		}
11310315Smckusick 		perror("newnode");
11410315Smckusick 		panic("Cannot make node %s\n", cp);
11510315Smckusick 	}
11610315Smckusick 	vprintf(stdout, "Make node %s\n", cp);
11710315Smckusick }
11810315Smckusick 
11910315Smckusick /*
12010315Smckusick  * Remove an old node (directory).
12110315Smckusick  */
12210315Smckusick removenode(ep)
12310315Smckusick 	register struct entry *ep;
12410315Smckusick {
12510315Smckusick 	char *cp;
12610315Smckusick 
12710315Smckusick 	if (ep->e_type != NODE)
12810315Smckusick 		badentry(ep, "removenode: not a node");
12910315Smckusick 	if (ep->e_entries != NIL)
13010315Smckusick 		badentry(ep, "removenode: non-empty directory");
13110315Smckusick 	cp = myname(ep);
13210315Smckusick 	if (rmdir(cp) < 0) {
13310315Smckusick 		perror("removenode");
13410315Smckusick 		panic("Cannot remove node %s\n", cp);
13510315Smckusick 	}
13610315Smckusick 	ep->e_flags |= REMOVED;
13711131Smckusick 	ep->e_flags &= ~(TMPNAME|TMPNODE);
13810315Smckusick 	vprintf(stdout, "Remove node %s\n", cp);
13910315Smckusick }
14010315Smckusick 
14110315Smckusick /*
14210315Smckusick  * Remove a leaf.
14310315Smckusick  */
14410315Smckusick removeleaf(ep)
14510315Smckusick 	register struct entry *ep;
14610315Smckusick {
14710315Smckusick 	char *cp;
14810315Smckusick 
14910315Smckusick 	if (ep->e_type != LEAF)
15010315Smckusick 		badentry(ep, "removeleaf: not a leaf");
15110315Smckusick 	cp = myname(ep);
15210315Smckusick 	if (unlink(cp) < 0) {
15310315Smckusick 		perror("removeleaf");
15410315Smckusick 		panic("Cannot remove leaf %s\n", cp);
15510315Smckusick 	}
15610315Smckusick 	ep->e_flags |= REMOVED;
15710315Smckusick 	ep->e_flags &= ~TMPNAME;
15810315Smckusick 	vprintf(stdout, "Remove leaf %s\n", cp);
15910315Smckusick }
16010315Smckusick 
16110315Smckusick /*
16210315Smckusick  * Create a link.
16310315Smckusick  */
16410315Smckusick linkit(existing, new, type)
16510315Smckusick 	char *existing, *new;
16610315Smckusick 	int type;
16710315Smckusick {
16810315Smckusick 
16910315Smckusick 	if (type == SYMLINK) {
17010315Smckusick 		if (symlink(existing, new) < 0) {
17110315Smckusick 			perror("linkit");
17210315Smckusick 			panic("Cannot create symbolic link %s->%s\n",
17310315Smckusick 				new, existing);
17410315Smckusick 		}
17510315Smckusick 	} else if (type == HARDLINK) {
17610315Smckusick 		if (link(existing, new) < 0) {
17710315Smckusick 			perror("linkit");
17810315Smckusick 			panic("Cannot create hard link %s->%s\n",
17910315Smckusick 				new, existing);
18010315Smckusick 		}
18110315Smckusick 	} else {
18210315Smckusick 		panic("linkit: unknown type %d\n", type);
18310315Smckusick 	}
18410315Smckusick 	vprintf(stdout, "Create %s link %s->%s\n",
18510315Smckusick 		type == SYMLINK ? "symbolic" : "hard", new, existing);
18610315Smckusick }
18710315Smckusick 
18810315Smckusick /*
18910315Smckusick  * find lowest number file (above "start") that needs to be extracted
19010315Smckusick  */
19110315Smckusick ino_t
19210315Smckusick lowerbnd(start)
19310315Smckusick 	ino_t start;
19410315Smckusick {
19510315Smckusick 	register struct entry *ep;
19610315Smckusick 
19710315Smckusick 	for ( ; start < maxino; start++) {
19810315Smckusick 		ep = lookupino(start);
19910315Smckusick 		if (ep == NIL)
20010315Smckusick 			continue;
20111131Smckusick 		if (ep->e_flags & (NEW|EXTRACT|CHANGE))
20210315Smckusick 			return (start);
20310315Smckusick 	}
20410315Smckusick 	return (start);
20510315Smckusick }
20610315Smckusick 
20710315Smckusick /*
20810315Smckusick  * find highest number file (below "start") that needs to be extracted
20910315Smckusick  */
21010315Smckusick ino_t
21110315Smckusick upperbnd(start)
21210315Smckusick 	ino_t start;
21310315Smckusick {
21410315Smckusick 	register struct entry *ep;
21510315Smckusick 
21610315Smckusick 	for ( ; start > ROOTINO; start--) {
21710315Smckusick 		ep = lookupino(start);
21810315Smckusick 		if (ep == NIL)
21910315Smckusick 			continue;
22011131Smckusick 		if (ep->e_flags & (NEW|EXTRACT|CHANGE))
22110315Smckusick 			return (start);
22210315Smckusick 	}
22310315Smckusick 	return (start);
22410315Smckusick }
22510315Smckusick 
22610315Smckusick /*
22710315Smckusick  * report on a badly formed entry
22810315Smckusick  */
22910315Smckusick badentry(ep, msg)
23010315Smckusick 	register struct entry *ep;
23110315Smckusick 	char *msg;
23210315Smckusick {
23310315Smckusick 	char flagbuf[BUFSIZ];
23410315Smckusick 
23510315Smckusick 	fprintf(stderr, "bad entry: %s\n", msg);
23610315Smckusick 	fprintf(stderr, "name: %s\n", myname(ep));
23711131Smckusick 	if (ep->e_newname != NULL)
23811131Smckusick 		fprintf(stderr, "new name: %s\n", ep->e_newname);
23910315Smckusick 	fprintf(stderr, "parent name %s\n", myname(ep->e_parent));
24010315Smckusick 	if (ep->e_sibling != NIL)
24110315Smckusick 		fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling));
24210315Smckusick 	if (ep->e_entries != NIL)
24310315Smckusick 		fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries));
24410315Smckusick 	if (ep->e_links != NIL)
24510315Smckusick 		fprintf(stderr, "next link name: %s\n", myname(ep->e_links));
24610315Smckusick 	fprintf(stderr, "entry type: %s\n",
24710315Smckusick 		ep->e_type == NODE ? "NODE" : "LEAF");
24810315Smckusick 	fprintf(stderr, "inode number: %ld\n", ep->e_ino);
24910315Smckusick 	strcpy(flagbuf, "|NIL");
25010315Smckusick 	flagbuf[0] = '\0';
25111131Smckusick 	if (ep->e_flags & REMOVE)
25211131Smckusick 		strcat(flagbuf, "|REMOVE");
25310315Smckusick 	if (ep->e_flags & REMOVED)
25410315Smckusick 		strcat(flagbuf, "|REMOVED");
25511131Smckusick 	if (ep->e_flags & RENAME)
25611131Smckusick 		strcat(flagbuf, "|RENAME");
25710315Smckusick 	if (ep->e_flags & TMPNAME)
25810315Smckusick 		strcat(flagbuf, "|TMPNAME");
25911131Smckusick 	if (ep->e_flags & TMPNODE)
26011131Smckusick 		strcat(flagbuf, "|TMPNODE");
26110315Smckusick 	if (ep->e_flags & EXTRACT)
26210315Smckusick 		strcat(flagbuf, "|EXTRACT");
26311131Smckusick 	if (ep->e_flags & RENUMBER)
26411131Smckusick 		strcat(flagbuf, "|RENUMBER");
26511131Smckusick 	if (ep->e_flags & CHANGE)
26611131Smckusick 		strcat(flagbuf, "|CHANGE");
26710315Smckusick 	if (ep->e_flags & NEW)
26810315Smckusick 		strcat(flagbuf, "|NEW");
26910315Smckusick 	if (ep->e_flags & KEEP)
27010315Smckusick 		strcat(flagbuf, "|KEEP");
27110315Smckusick 	panic("flags: %s\n", &flagbuf[1]);
27210315Smckusick }
27310315Smckusick 
27410315Smckusick /*
275*11321Smckusick  * canonicalize file names to always start with ``./''
276*11321Smckusick  */
277*11321Smckusick canon(rawname, canonname)
278*11321Smckusick 	char *rawname, *canonname;
279*11321Smckusick {
280*11321Smckusick 	int len;
281*11321Smckusick 
282*11321Smckusick 	if (strcmp(rawname, ".") == 0 || strncmp(rawname, "./", 2) == 0)
283*11321Smckusick 		strcpy(canonname, "");
284*11321Smckusick 	else if (rawname[0] == '/')
285*11321Smckusick 		strcpy(canonname, ".");
286*11321Smckusick 	else
287*11321Smckusick 		strcpy(canonname, "./");
288*11321Smckusick 	strcat(canonname, rawname);
289*11321Smckusick 	len = strlen(canonname) - 1;
290*11321Smckusick 	if (canonname[len] == '/')
291*11321Smckusick 		canonname[len] = '\0';
292*11321Smckusick }
293*11321Smckusick 
294*11321Smckusick /*
29510315Smckusick  * 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] ");
30510315Smckusick 		c = getchar();
30610315Smckusick 		while (c != '\n' && getchar() != '\n')
30710315Smckusick 			/* void */;
30810315Smckusick 	} while (c != 'y' && c != 'n');
30910315Smckusick 	if (c == 'y')
31010315Smckusick 		return (GOOD);
31110315Smckusick 	return (FAIL);
31210315Smckusick }
313