xref: /csrg-svn/sbin/restore/main.c (revision 69225)
121167Sdist /*
261536Sbostic  * Copyright (c) 1983, 1993
361536Sbostic  *	The Regents of the University of California.  All rights reserved.
436105Sbostic  *
542708Sbostic  * %sccs.include.redist.c%
621167Sdist  */
721167Sdist 
86846Smckusick #ifndef lint
961536Sbostic static char copyright[] =
1061536Sbostic "@(#) Copyright (c) 1983, 1993\n\
1161536Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1236105Sbostic #endif /* not lint */
134610Smckusick 
1421167Sdist #ifndef lint
15*69225Sbostic static char sccsid[] = "@(#)main.c	8.6 (Berkeley) 05/04/95";
1636105Sbostic #endif /* not lint */
1714564Ssam 
1856567Sbostic #include <sys/param.h>
1956567Sbostic #include <sys/time.h>
204610Smckusick 
2169153Smckusick #include <ufs/ufs/dinode.h>
2256567Sbostic #include <ufs/ffs/fs.h>
2323547Smckusick #include <protocols/dumprestore.h>
2456567Sbostic 
2565568Sbostic #include <err.h>
2656567Sbostic #include <errno.h>
2756567Sbostic #include <signal.h>
2856567Sbostic #include <stdio.h>
2956567Sbostic #include <stdlib.h>
3056567Sbostic #include <string.h>
31*69225Sbostic #include <unistd.h>
3256567Sbostic 
3337952Sbostic #include "pathnames.h"
3456567Sbostic #include "restore.h"
3556567Sbostic #include "extern.h"
364610Smckusick 
3718496Smckusick int	bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0;
3834269Smckusick int	hflag = 1, mflag = 1, Nflag = 0;
3910312Smckusick char	command = '\0';
4010312Smckusick long	dumpnum = 1;
4111438Smckusick long	volno = 0;
4218496Smckusick long	ntrec;
435327Smckusic char	*dumpmap;
4467775Smckusick char	*usedinomap;
4510312Smckusick ino_t	maxino;
4610312Smckusick time_t	dumptime;
4711302Smckusick time_t	dumpdate;
4811993Smckusick FILE 	*terminal;
494610Smckusick 
5056567Sbostic static void obsolete __P((int *, char **[]));
5156567Sbostic static void usage __P((void));
5256567Sbostic 
5356428Smckusick int
main(argc,argv)546846Smckusick main(argc, argv)
554700Smckusic 	int argc;
564700Smckusic 	char *argv[];
574610Smckusick {
5856567Sbostic 	int ch;
5911308Smckusick 	ino_t ino;
6037952Sbostic 	char *inputdev = _PATH_DEFTAPE;
6111308Smckusick 	char *symtbl = "./restoresymtable";
6256567Sbostic 	char *p, name[MAXPATHLEN];
634610Smckusick 
6456428Smckusick 	if (argc < 2)
6556428Smckusick 		usage();
6656567Sbostic 
6756567Sbostic 	obsolete(&argc, &argv);
6856567Sbostic 	while ((ch = getopt(argc, argv, "b:cdf:himNRrs:tvxy")) != EOF)
6956567Sbostic 		switch(ch) {
7056567Sbostic 		case 'b':
7156567Sbostic 			/* Change default tape blocksize. */
7256567Sbostic 			bflag = 1;
7356567Sbostic 			ntrec = strtol(optarg, &p, 10);
7456567Sbostic 			if (*p)
7565568Sbostic 				errx(1, "illegal blocksize -- %s", optarg);
7656567Sbostic 			if (ntrec <= 0)
7765568Sbostic 				errx(1, "block size must be greater than 0");
784610Smckusick 			break;
798302Smckusick 		case 'c':
8056567Sbostic 			cvtflag = 1;
818302Smckusick 			break;
8210312Smckusick 		case 'd':
8356567Sbostic 			dflag = 1;
844610Smckusick 			break;
8556567Sbostic 		case 'f':
8656567Sbostic 			inputdev = optarg;
8756567Sbostic 			break;
884610Smckusick 		case 'h':
8910202Smckusick 			hflag = 0;
904610Smckusick 			break;
9156567Sbostic 		case 'i':
9256567Sbostic 		case 'R':
9356567Sbostic 		case 'r':
9456567Sbostic 		case 't':
9556567Sbostic 		case 'x':
9656567Sbostic 			if (command != '\0')
9765568Sbostic 				errx(1,
9865568Sbostic 				    "%c and %c options are mutually exclusive",
9956567Sbostic 				    ch, command);
10056567Sbostic 			command = ch;
10156567Sbostic 			break;
1024610Smckusick 		case 'm':
10310202Smckusick 			mflag = 0;
1044610Smckusick 			break;
10534269Smckusick 		case 'N':
10656567Sbostic 			Nflag = 1;
10734269Smckusick 			break;
10856567Sbostic 		case 's':
10956567Sbostic 			/* Dumpnum (skip to) for multifile dump tapes. */
11056567Sbostic 			dumpnum = strtol(optarg, &p, 10);
11156567Sbostic 			if (*p)
11265568Sbostic 				errx(1, "illegal dump number -- %s", optarg);
11356567Sbostic 			if (dumpnum <= 0)
11465568Sbostic 				errx(1, "dump number must be greater than 0");
11556567Sbostic 			break;
1168374Smckusick 		case 'v':
11756567Sbostic 			vflag = 1;
1188374Smckusick 			break;
1198374Smckusick 		case 'y':
12056567Sbostic 			yflag = 1;
1218374Smckusick 			break;
1224610Smckusick 		default:
12356428Smckusick 			usage();
1244610Smckusick 		}
12556567Sbostic 	argc -= optind;
12656567Sbostic 	argv += optind;
12756567Sbostic 
12856567Sbostic 	if (command == '\0')
12965568Sbostic 		errx(1, "none of i, R, r, t or x options specified");
13056567Sbostic 
13156567Sbostic 	if (signal(SIGINT, onintr) == SIG_IGN)
13256567Sbostic 		(void) signal(SIGINT, SIG_IGN);
13356567Sbostic 	if (signal(SIGTERM, onintr) == SIG_IGN)
13456567Sbostic 		(void) signal(SIGTERM, SIG_IGN);
13556567Sbostic 	setlinebuf(stderr);
13656567Sbostic 
13710312Smckusick 	setinput(inputdev);
13856567Sbostic 
13910202Smckusick 	if (argc == 0) {
14010312Smckusick 		argc = 1;
14110202Smckusick 		*--argv = ".";
14210202Smckusick 	}
14356567Sbostic 
14410312Smckusick 	switch (command) {
14511993Smckusick 	/*
14611993Smckusick 	 * Interactive mode.
14711993Smckusick 	 */
14811993Smckusick 	case 'i':
14910312Smckusick 		setup();
15011993Smckusick 		extractdirs(1);
15156567Sbostic 		initsymtable(NULL);
15211993Smckusick 		runcmdshell();
15356567Sbostic 		break;
15411993Smckusick 	/*
15511993Smckusick 	 * Incremental restoration of a file system.
15611993Smckusick 	 */
15710312Smckusick 	case 'r':
15810312Smckusick 		setup();
15910312Smckusick 		if (dumptime > 0) {
16011438Smckusick 			/*
16111438Smckusick 			 * This is an incremental dump tape.
16211438Smckusick 			 */
16311438Smckusick 			vprintf(stdout, "Begin incremental restore\n");
16410312Smckusick 			initsymtable(symtbl);
16511993Smckusick 			extractdirs(1);
16611438Smckusick 			removeoldleaves();
16711438Smckusick 			vprintf(stdout, "Calculate node updates.\n");
16811438Smckusick 			treescan(".", ROOTINO, nodeupdates);
16911438Smckusick 			findunreflinks();
17011438Smckusick 			removeoldnodes();
17110312Smckusick 		} else {
17211438Smckusick 			/*
17311438Smckusick 			 * This is a level zero dump tape.
17411438Smckusick 			 */
17511438Smckusick 			vprintf(stdout, "Begin level 0 restore\n");
17611438Smckusick 			initsymtable((char *)0);
17711993Smckusick 			extractdirs(1);
17811438Smckusick 			vprintf(stdout, "Calculate extraction list.\n");
17911438Smckusick 			treescan(".", ROOTINO, nodeupdates);
1804843Smckusic 		}
18110312Smckusick 		createleaves(symtbl);
18210312Smckusick 		createlinks();
18355880Smckusick 		setdirmodes(FORCE);
18410312Smckusick 		checkrestore();
18510312Smckusick 		if (dflag) {
18610312Smckusick 			vprintf(stdout, "Verify the directory structure\n");
18710312Smckusick 			treescan(".", ROOTINO, verifyfile);
1884610Smckusick 		}
18910312Smckusick 		dumpsymtable(symtbl, (long)1);
19056567Sbostic 		break;
19111993Smckusick 	/*
19211993Smckusick 	 * Resume an incremental file system restoration.
19311993Smckusick 	 */
19410312Smckusick 	case 'R':
19510312Smckusick 		initsymtable(symtbl);
19611320Smckusick 		skipmaps();
19711320Smckusick 		skipdirs();
19810312Smckusick 		createleaves(symtbl);
19910312Smckusick 		createlinks();
20055880Smckusick 		setdirmodes(FORCE);
20110312Smckusick 		checkrestore();
20210312Smckusick 		dumpsymtable(symtbl, (long)1);
20356567Sbostic 		break;
20411993Smckusick 	/*
20511993Smckusick 	 * List contents of tape.
20611993Smckusick 	 */
20711993Smckusick 	case 't':
20811993Smckusick 		setup();
20911993Smckusick 		extractdirs(0);
21027264Smckusick 		initsymtable((char *)0);
21111993Smckusick 		while (argc--) {
21211993Smckusick 			canon(*argv++, name);
21311993Smckusick 			ino = dirlookup(name);
21411993Smckusick 			if (ino == 0)
21511993Smckusick 				continue;
21611993Smckusick 			treescan(name, ino, listfile);
21711993Smckusick 		}
21856567Sbostic 		break;
21911993Smckusick 	/*
22011993Smckusick 	 * Batch extraction of tape contents.
22111993Smckusick 	 */
22211993Smckusick 	case 'x':
22311993Smckusick 		setup();
22411993Smckusick 		extractdirs(1);
22511993Smckusick 		initsymtable((char *)0);
22611993Smckusick 		while (argc--) {
22711993Smckusick 			canon(*argv++, name);
22811993Smckusick 			ino = dirlookup(name);
22911993Smckusick 			if (ino == 0)
23011993Smckusick 				continue;
23111993Smckusick 			if (mflag)
23211993Smckusick 				pathcheck(name);
23311993Smckusick 			treescan(name, ino, addfile);
23411993Smckusick 		}
23511993Smckusick 		createfiles();
23611993Smckusick 		createlinks();
23755880Smckusick 		setdirmodes(0);
23811993Smckusick 		if (dflag)
23911993Smckusick 			checkrestore();
24056567Sbostic 		break;
2414843Smckusic 	}
24256567Sbostic 	done(0);
24356567Sbostic 	/* NOTREACHED */
2444843Smckusic }
24556428Smckusick 
24659771Shibler static void
usage()24756428Smckusick usage()
24856428Smckusick {
24969154Smckusick 	(void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n",
25069154Smckusick 	  "restore -i [-chmvy] [-b blocksize] [-f file] [-s fileno]",
25169154Smckusick 	  "restore -r [-cvy] [-b blocksize] [-f file] [-s fileno]",
25269154Smckusick 	  "restore -R [-cvy] [-b blocksize] [-f file] [-s fileno]",
25369154Smckusick 	  "restore -x [-chmvy] [-b blocksize] [-f file] [-s fileno] [file ...]",
25469154Smckusick 	  "restore -t [-chvy] [-b blocksize] [-f file] [-s fileno] [file ...]");
25556428Smckusick 	done(1);
25656428Smckusick }
25756567Sbostic 
25856567Sbostic /*
25956567Sbostic  * obsolete --
26056567Sbostic  *	Change set of key letters and ordered arguments into something
26156567Sbostic  *	getopt(3) will like.
26256567Sbostic  */
26356567Sbostic static void
obsolete(argcp,argvp)26456567Sbostic obsolete(argcp, argvp)
26556567Sbostic 	int *argcp;
26656567Sbostic 	char **argvp[];
26756567Sbostic {
26856567Sbostic 	int argc, flags;
26956567Sbostic 	char *ap, **argv, *flagsp, **nargv, *p;
27056567Sbostic 
27156567Sbostic 	/* Setup. */
27256567Sbostic 	argv = *argvp;
27356567Sbostic 	argc = *argcp;
27456567Sbostic 
27556567Sbostic 	/* Return if no arguments or first argument has leading dash. */
27656567Sbostic 	ap = argv[1];
27756567Sbostic 	if (argc == 1 || *ap == '-')
27856567Sbostic 		return;
27956567Sbostic 
28056567Sbostic 	/* Allocate space for new arguments. */
28156567Sbostic 	if ((*argvp = nargv = malloc((argc + 1) * sizeof(char *))) == NULL ||
28256567Sbostic 	    (p = flagsp = malloc(strlen(ap) + 2)) == NULL)
28365568Sbostic 		err(1, NULL);
28456567Sbostic 
28556567Sbostic 	*nargv++ = *argv;
28656567Sbostic 	argv += 2;
28756567Sbostic 
28856567Sbostic 	for (flags = 0; *ap; ++ap) {
28969153Smckusick 		switch (*ap) {
29056567Sbostic 		case 'b':
29156567Sbostic 		case 'f':
29256567Sbostic 		case 's':
29369153Smckusick 			if (*argv == NULL) {
29469153Smckusick 				warnx("option requires an argument -- %c", *ap);
29569153Smckusick 				usage();
29669153Smckusick 			}
29756567Sbostic 			if ((nargv[0] = malloc(strlen(*argv) + 2 + 1)) == NULL)
29865568Sbostic 				err(1, NULL);
29956567Sbostic 			nargv[0][0] = '-';
30056567Sbostic 			nargv[0][1] = *ap;
30156567Sbostic 			(void)strcpy(&nargv[0][2], *argv);
30269153Smckusick 			++argv;
30356567Sbostic 			++nargv;
30456567Sbostic 			break;
30556567Sbostic 		default:
30656567Sbostic 			if (!flags) {
30756567Sbostic 				*p++ = '-';
30856567Sbostic 				flags = 1;
30956567Sbostic 			}
31056567Sbostic 			*p++ = *ap;
31156567Sbostic 			break;
31256567Sbostic 		}
31356567Sbostic 	}
31456567Sbostic 
31556567Sbostic 	/* Terminate flags. */
31656567Sbostic 	if (flags) {
31756567Sbostic 		*p = '\0';
31856567Sbostic 		*nargv++ = flagsp;
31956567Sbostic 	}
32056567Sbostic 
32156567Sbostic 	/* Copy remaining arguments. */
32256567Sbostic 	while (*nargv++ = *argv++);
32369153Smckusick 
32469153Smckusick 	/* Update argument count. */
32569153Smckusick 	*argcp = nargv - *argvp - 1;
32656567Sbostic }
327