xref: /csrg-svn/sbin/restore/utilities.c (revision 56947)
121171Sdist /*
236105Sbostic  * Copyright (c) 1983 The Regents of the University of California.
336105Sbostic  * All rights reserved.
436105Sbostic  *
542709Sbostic  * %sccs.include.redist.c%
621171Sdist  */
721171Sdist 
810315Smckusick #ifndef lint
9*56947Smckusick static char sccsid[] = "@(#)utilities.c	5.10 (Berkeley) 12/02/92";
1036105Sbostic #endif /* not lint */
1110315Smckusick 
1256567Sbostic #include <sys/param.h>
1356567Sbostic #include <sys/stat.h>
1456567Sbostic 
1556567Sbostic #include <ufs/ufs/dinode.h>
16*56947Smckusick #include <ufs/ufs/dir.h>
1756567Sbostic 
1856567Sbostic #include <errno.h>
1956567Sbostic #include <stdio.h>
2056567Sbostic #include <stdlib.h>
2156567Sbostic #include <string.h>
2256567Sbostic #include <unistd.h>
2356567Sbostic 
2410315Smckusick #include "restore.h"
2556567Sbostic #include "extern.h"
2610315Smckusick 
2710315Smckusick /*
2810315Smckusick  * Insure that all the components of a pathname exist.
2910315Smckusick  */
3056567Sbostic void
3111645Smckusick pathcheck(name)
3210315Smckusick 	char *name;
3310315Smckusick {
3410315Smckusick 	register char *cp;
3510315Smckusick 	struct entry *ep;
3611312Smckusick 	char *start;
3710315Smckusick 
3810315Smckusick 	start = index(name, '/');
3911312Smckusick 	if (start == 0)
4011645Smckusick 		return;
4110315Smckusick 	for (cp = start; *cp != '\0'; cp++) {
4210315Smckusick 		if (*cp != '/')
4310315Smckusick 			continue;
4410315Smckusick 		*cp = '\0';
4510315Smckusick 		ep = lookupname(name);
4656567Sbostic 		if (ep == NULL) {
47*56947Smckusick 			ep = addentry(name, pathsearch(name)->d_ino, NODE);
4810315Smckusick 			newnode(ep);
4910315Smckusick 		}
5018009Smckusick 		ep->e_flags |= NEW|KEEP;
5110315Smckusick 		*cp = '/';
5210315Smckusick 	}
5310315Smckusick }
5410315Smckusick 
5510315Smckusick /*
5610315Smckusick  * Change a name to a unique temporary name.
5710315Smckusick  */
5856567Sbostic void
5910315Smckusick mktempname(ep)
6010315Smckusick 	register struct entry *ep;
6110315Smckusick {
6211645Smckusick 	char oldname[MAXPATHLEN];
6310315Smckusick 
6410315Smckusick 	if (ep->e_flags & TMPNAME)
6510315Smckusick 		badentry(ep, "mktempname: called with TMPNAME");
6610315Smckusick 	ep->e_flags |= TMPNAME;
6711995Smckusick 	(void) strcpy(oldname, myname(ep));
6811645Smckusick 	freename(ep->e_name);
6911645Smckusick 	ep->e_name = savename(gentempname(ep));
7011645Smckusick 	ep->e_namlen = strlen(ep->e_name);
7110315Smckusick 	renameit(oldname, myname(ep));
7210315Smckusick }
7310315Smckusick 
7410315Smckusick /*
7511645Smckusick  * Generate a temporary name for an entry.
7611645Smckusick  */
7711645Smckusick char *
7811645Smckusick gentempname(ep)
7911645Smckusick 	struct entry *ep;
8011645Smckusick {
8111645Smckusick 	static char name[MAXPATHLEN];
8211645Smckusick 	struct entry *np;
8311645Smckusick 	long i = 0;
8411645Smckusick 
8556567Sbostic 	for (np = lookupino(ep->e_ino);
8656567Sbostic 	    np != NULL && np != ep; np = np->e_links)
8711645Smckusick 		i++;
8856567Sbostic 	if (np == NULL)
8911645Smckusick 		badentry(ep, "not on ino list");
9011733Smckusick 	(void) sprintf(name, "%s%d%d", TMPHDR, i, ep->e_ino);
9111645Smckusick 	return (name);
9211645Smckusick }
9311645Smckusick 
9411645Smckusick /*
9510315Smckusick  * Rename a file or directory.
9610315Smckusick  */
9756567Sbostic void
9810315Smckusick renameit(from, to)
9910315Smckusick 	char *from, *to;
10010315Smckusick {
10134268Smckusick 	if (!Nflag && rename(from, to) < 0) {
10256567Sbostic 		fprintf(stderr, "warning: cannot rename %s to %s: %s\n",
10356567Sbostic 		    from, to, strerror(errno));
10411923Smckusick 		return;
10510315Smckusick 	}
10610315Smckusick 	vprintf(stdout, "rename %s to %s\n", from, to);
10710315Smckusick }
10810315Smckusick 
10910315Smckusick /*
11010315Smckusick  * Create a new node (directory).
11110315Smckusick  */
11256567Sbostic void
11310315Smckusick newnode(np)
11410315Smckusick 	struct entry *np;
11510315Smckusick {
11610315Smckusick 	char *cp;
11710315Smckusick 
11810315Smckusick 	if (np->e_type != NODE)
11910315Smckusick 		badentry(np, "newnode: not a node");
12010315Smckusick 	cp = myname(np);
12134268Smckusick 	if (!Nflag && mkdir(cp, 0777) < 0) {
12218006Smckusick 		np->e_flags |= EXISTED;
12356567Sbostic 		fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno));
12411740Smckusick 		return;
12510315Smckusick 	}
12610315Smckusick 	vprintf(stdout, "Make node %s\n", cp);
12710315Smckusick }
12810315Smckusick 
12910315Smckusick /*
13010315Smckusick  * Remove an old node (directory).
13110315Smckusick  */
13256567Sbostic void
13310315Smckusick removenode(ep)
13410315Smckusick 	register struct entry *ep;
13510315Smckusick {
13610315Smckusick 	char *cp;
13710315Smckusick 
13810315Smckusick 	if (ep->e_type != NODE)
13910315Smckusick 		badentry(ep, "removenode: not a node");
14056567Sbostic 	if (ep->e_entries != NULL)
14110315Smckusick 		badentry(ep, "removenode: non-empty directory");
14211923Smckusick 	ep->e_flags |= REMOVED;
14311923Smckusick 	ep->e_flags &= ~TMPNAME;
14410315Smckusick 	cp = myname(ep);
14534268Smckusick 	if (!Nflag && rmdir(cp) < 0) {
14656567Sbostic 		fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno));
14711923Smckusick 		return;
14810315Smckusick 	}
14910315Smckusick 	vprintf(stdout, "Remove node %s\n", cp);
15010315Smckusick }
15110315Smckusick 
15210315Smckusick /*
15310315Smckusick  * Remove a leaf.
15410315Smckusick  */
15556567Sbostic void
15610315Smckusick removeleaf(ep)
15710315Smckusick 	register struct entry *ep;
15810315Smckusick {
15910315Smckusick 	char *cp;
16010315Smckusick 
16110315Smckusick 	if (ep->e_type != LEAF)
16210315Smckusick 		badentry(ep, "removeleaf: not a leaf");
16311923Smckusick 	ep->e_flags |= REMOVED;
16411923Smckusick 	ep->e_flags &= ~TMPNAME;
16510315Smckusick 	cp = myname(ep);
16634268Smckusick 	if (!Nflag && unlink(cp) < 0) {
16756567Sbostic 		fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno));
16811923Smckusick 		return;
16910315Smckusick 	}
17010315Smckusick 	vprintf(stdout, "Remove leaf %s\n", cp);
17110315Smckusick }
17210315Smckusick 
17310315Smckusick /*
17410315Smckusick  * Create a link.
17510315Smckusick  */
17656567Sbostic int
17710315Smckusick linkit(existing, new, type)
17810315Smckusick 	char *existing, *new;
17910315Smckusick 	int type;
18010315Smckusick {
18110315Smckusick 
18210315Smckusick 	if (type == SYMLINK) {
18334268Smckusick 		if (!Nflag && symlink(existing, new) < 0) {
18411923Smckusick 			fprintf(stderr,
18556567Sbostic 			    "warning: cannot create symbolic link %s->%s: %s\n",
18656567Sbostic 			    new, existing, strerror(errno));
18715782Smckusick 			return (FAIL);
18810315Smckusick 		}
18910315Smckusick 	} else if (type == HARDLINK) {
19034268Smckusick 		if (!Nflag && link(existing, new) < 0) {
19111923Smckusick 			fprintf(stderr,
19256567Sbostic 			    "warning: cannot create hard link %s->%s: %s\n",
19356567Sbostic 			    new, existing, strerror(errno));
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);
21656567Sbostic 		if (ep == NULL || 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);
23556567Sbostic 		if (ep == NULL || 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  */
24656567Sbostic void
24710315Smckusick badentry(ep, msg)
24810315Smckusick 	register struct entry *ep;
24910315Smckusick 	char *msg;
25010315Smckusick {
25110315Smckusick 
25210315Smckusick 	fprintf(stderr, "bad entry: %s\n", msg);
25310315Smckusick 	fprintf(stderr, "name: %s\n", myname(ep));
25410315Smckusick 	fprintf(stderr, "parent name %s\n", myname(ep->e_parent));
25556567Sbostic 	if (ep->e_sibling != NULL)
25610315Smckusick 		fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling));
25756567Sbostic 	if (ep->e_entries != NULL)
25810315Smckusick 		fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries));
25956567Sbostic 	if (ep->e_links != NULL)
26010315Smckusick 		fprintf(stderr, "next link name: %s\n", myname(ep->e_links));
26156567Sbostic 	if (ep->e_next != NULL)
26256567Sbostic 		fprintf(stderr,
26356567Sbostic 		    "next hashchain name: %s\n", myname(ep->e_next));
26410315Smckusick 	fprintf(stderr, "entry type: %s\n",
26510315Smckusick 		ep->e_type == NODE ? "NODE" : "LEAF");
26610315Smckusick 	fprintf(stderr, "inode number: %ld\n", ep->e_ino);
26711898Smckusick 	panic("flags: %s\n", flagvalues(ep));
26811898Smckusick }
26911898Smckusick 
27011898Smckusick /*
27111898Smckusick  * Construct a string indicating the active flag bits of an entry.
27211898Smckusick  */
27311898Smckusick char *
27411898Smckusick flagvalues(ep)
27511898Smckusick 	register struct entry *ep;
27611898Smckusick {
27711898Smckusick 	static char flagbuf[BUFSIZ];
27811898Smckusick 
27911898Smckusick 	(void) strcpy(flagbuf, "|NIL");
28010315Smckusick 	flagbuf[0] = '\0';
28110315Smckusick 	if (ep->e_flags & REMOVED)
28211898Smckusick 		(void) strcat(flagbuf, "|REMOVED");
28310315Smckusick 	if (ep->e_flags & TMPNAME)
28411898Smckusick 		(void) strcat(flagbuf, "|TMPNAME");
28510315Smckusick 	if (ep->e_flags & EXTRACT)
28611898Smckusick 		(void) strcat(flagbuf, "|EXTRACT");
28710315Smckusick 	if (ep->e_flags & NEW)
28811898Smckusick 		(void) strcat(flagbuf, "|NEW");
28910315Smckusick 	if (ep->e_flags & KEEP)
29011898Smckusick 		(void) strcat(flagbuf, "|KEEP");
29118006Smckusick 	if (ep->e_flags & EXISTED)
29218006Smckusick 		(void) strcat(flagbuf, "|EXISTED");
29311898Smckusick 	return (&flagbuf[1]);
29410315Smckusick }
29510315Smckusick 
29610315Smckusick /*
29711995Smckusick  * Check to see if a name is on a dump tape.
29811321Smckusick  */
29911995Smckusick ino_t
30011995Smckusick dirlookup(name)
30111995Smckusick 	char *name;
30211995Smckusick {
30311995Smckusick 	ino_t ino;
30411995Smckusick 
305*56947Smckusick 	ino = pathsearch(name)->d_ino;
30656427Smckusick 	if (ino == 0 || TSTINO(ino, dumpmap) == 0)
30711995Smckusick 		fprintf(stderr, "%s is not on tape\n", name);
30811995Smckusick 	return (ino);
30911995Smckusick }
31011995Smckusick 
31111995Smckusick /*
31211995Smckusick  * Elicit a reply.
31310315Smckusick  */
31456567Sbostic int
31510315Smckusick reply(question)
31610315Smckusick 	char *question;
31710315Smckusick {
31810315Smckusick 	char c;
31910315Smckusick 
32010315Smckusick 	do	{
32124185Smckusick 		fprintf(stderr, "%s? [yn] ", question);
32212557Smckusick 		(void) fflush(stderr);
32311995Smckusick 		c = getc(terminal);
32411995Smckusick 		while (c != '\n' && getc(terminal) != '\n')
32517711Smckusick 			if (feof(terminal))
32624185Smckusick 				return (FAIL);
32710315Smckusick 	} while (c != 'y' && c != 'n');
32810315Smckusick 	if (c == 'y')
32910315Smckusick 		return (GOOD);
33010315Smckusick 	return (FAIL);
33110315Smckusick }
33211995Smckusick 
33311995Smckusick /*
33411995Smckusick  * handle unexpected inconsistencies
33511995Smckusick  */
33656567Sbostic #if __STDC__
33756567Sbostic #include <stdarg.h>
33856567Sbostic #else
33956567Sbostic #include <varargs.h>
34056567Sbostic #endif
34156567Sbostic 
34256567Sbostic void
34356567Sbostic #if __STDC__
34456567Sbostic panic(const char *fmt, ...)
34556567Sbostic #else
34656567Sbostic panic(fmt, va_alist)
34756567Sbostic 	char *fmt;
34856567Sbostic 	va_dcl
34956567Sbostic #endif
35011995Smckusick {
35156567Sbostic 	va_list ap;
35256567Sbostic #if __STDC__
35356567Sbostic 	va_start(ap, fmt);
35456567Sbostic #else
35556567Sbostic 	va_start(ap);
35656567Sbostic #endif
35711995Smckusick 
35856567Sbostic 	vfprintf(stderr, fmt, ap);
35942489Smckusick 	if (yflag)
36042489Smckusick 		return;
36111995Smckusick 	if (reply("abort") == GOOD) {
36211995Smckusick 		if (reply("dump core") == GOOD)
36311995Smckusick 			abort();
36411995Smckusick 		done(1);
36511995Smckusick 	}
36611995Smckusick }
367