xref: /csrg-svn/sbin/restore/main.c (revision 67775)
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*67775Smckusick static char sccsid[] = "@(#)main.c	8.3 (Berkeley) 09/13/94";
1636105Sbostic #endif /* not lint */
1714564Ssam 
1856567Sbostic #include <sys/param.h>
1956567Sbostic #include <sys/time.h>
204610Smckusick 
2156567Sbostic #include <ufs/ffs/fs.h>
2256567Sbostic #include <ufs/ufs/dinode.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>
3156567Sbostic 
3237952Sbostic #include "pathnames.h"
3356567Sbostic #include "restore.h"
3456567Sbostic #include "extern.h"
354610Smckusick 
3618496Smckusick int	bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0;
3734269Smckusick int	hflag = 1, mflag = 1, Nflag = 0;
3810312Smckusick char	command = '\0';
3910312Smckusick long	dumpnum = 1;
4011438Smckusick long	volno = 0;
4118496Smckusick long	ntrec;
425327Smckusic char	*dumpmap;
43*67775Smckusick char	*usedinomap;
4410312Smckusick ino_t	maxino;
4510312Smckusick time_t	dumptime;
4611302Smckusick time_t	dumpdate;
4711993Smckusick FILE 	*terminal;
484610Smckusick 
4956567Sbostic static void obsolete __P((int *, char **[]));
5056567Sbostic static void usage __P((void));
5156567Sbostic 
5256428Smckusick int
536846Smckusick main(argc, argv)
544700Smckusic 	int argc;
554700Smckusic 	char *argv[];
564610Smckusick {
5756567Sbostic 	int ch;
5811308Smckusick 	ino_t ino;
5937952Sbostic 	char *inputdev = _PATH_DEFTAPE;
6011308Smckusick 	char *symtbl = "./restoresymtable";
6156567Sbostic 	char *p, name[MAXPATHLEN];
624610Smckusick 
6356428Smckusick 	if (argc < 2)
6456428Smckusick 		usage();
6556567Sbostic 
6656567Sbostic 	obsolete(&argc, &argv);
6756567Sbostic 	while ((ch = getopt(argc, argv, "b:cdf:himNRrs:tvxy")) != EOF)
6856567Sbostic 		switch(ch) {
6956567Sbostic 		case 'b':
7056567Sbostic 			/* Change default tape blocksize. */
7156567Sbostic 			bflag = 1;
7256567Sbostic 			ntrec = strtol(optarg, &p, 10);
7356567Sbostic 			if (*p)
7465568Sbostic 				errx(1, "illegal blocksize -- %s", optarg);
7556567Sbostic 			if (ntrec <= 0)
7665568Sbostic 				errx(1, "block size must be greater than 0");
774610Smckusick 			break;
788302Smckusick 		case 'c':
7956567Sbostic 			cvtflag = 1;
808302Smckusick 			break;
8110312Smckusick 		case 'd':
8256567Sbostic 			dflag = 1;
834610Smckusick 			break;
8456567Sbostic 		case 'f':
8556567Sbostic 			inputdev = optarg;
8656567Sbostic 			break;
874610Smckusick 		case 'h':
8810202Smckusick 			hflag = 0;
894610Smckusick 			break;
9056567Sbostic 		case 'i':
9156567Sbostic 		case 'R':
9256567Sbostic 		case 'r':
9356567Sbostic 		case 't':
9456567Sbostic 		case 'x':
9556567Sbostic 			if (command != '\0')
9665568Sbostic 				errx(1,
9765568Sbostic 				    "%c and %c options are mutually exclusive",
9856567Sbostic 				    ch, command);
9956567Sbostic 			command = ch;
10056567Sbostic 			break;
1014610Smckusick 		case 'm':
10210202Smckusick 			mflag = 0;
1034610Smckusick 			break;
10434269Smckusick 		case 'N':
10556567Sbostic 			Nflag = 1;
10634269Smckusick 			break;
10756567Sbostic 		case 's':
10856567Sbostic 			/* Dumpnum (skip to) for multifile dump tapes. */
10956567Sbostic 			dumpnum = strtol(optarg, &p, 10);
11056567Sbostic 			if (*p)
11165568Sbostic 				errx(1, "illegal dump number -- %s", optarg);
11256567Sbostic 			if (dumpnum <= 0)
11365568Sbostic 				errx(1, "dump number must be greater than 0");
11456567Sbostic 			break;
1158374Smckusick 		case 'v':
11656567Sbostic 			vflag = 1;
1178374Smckusick 			break;
1188374Smckusick 		case 'y':
11956567Sbostic 			yflag = 1;
1208374Smckusick 			break;
1214610Smckusick 		default:
12256428Smckusick 			usage();
1234610Smckusick 		}
12456567Sbostic 	argc -= optind;
12556567Sbostic 	argv += optind;
12656567Sbostic 
12756567Sbostic 	if (command == '\0')
12865568Sbostic 		errx(1, "none of i, R, r, t or x options specified");
12956567Sbostic 
13056567Sbostic 	if (signal(SIGINT, onintr) == SIG_IGN)
13156567Sbostic 		(void) signal(SIGINT, SIG_IGN);
13256567Sbostic 	if (signal(SIGTERM, onintr) == SIG_IGN)
13356567Sbostic 		(void) signal(SIGTERM, SIG_IGN);
13456567Sbostic 	setlinebuf(stderr);
13556567Sbostic 
13610312Smckusick 	setinput(inputdev);
13756567Sbostic 
13810202Smckusick 	if (argc == 0) {
13910312Smckusick 		argc = 1;
14010202Smckusick 		*--argv = ".";
14110202Smckusick 	}
14256567Sbostic 
14310312Smckusick 	switch (command) {
14411993Smckusick 	/*
14511993Smckusick 	 * Interactive mode.
14611993Smckusick 	 */
14711993Smckusick 	case 'i':
14810312Smckusick 		setup();
14911993Smckusick 		extractdirs(1);
15056567Sbostic 		initsymtable(NULL);
15111993Smckusick 		runcmdshell();
15256567Sbostic 		break;
15311993Smckusick 	/*
15411993Smckusick 	 * Incremental restoration of a file system.
15511993Smckusick 	 */
15610312Smckusick 	case 'r':
15710312Smckusick 		setup();
15810312Smckusick 		if (dumptime > 0) {
15911438Smckusick 			/*
16011438Smckusick 			 * This is an incremental dump tape.
16111438Smckusick 			 */
16211438Smckusick 			vprintf(stdout, "Begin incremental restore\n");
16310312Smckusick 			initsymtable(symtbl);
16411993Smckusick 			extractdirs(1);
16511438Smckusick 			removeoldleaves();
16611438Smckusick 			vprintf(stdout, "Calculate node updates.\n");
16711438Smckusick 			treescan(".", ROOTINO, nodeupdates);
16811438Smckusick 			findunreflinks();
16911438Smckusick 			removeoldnodes();
17010312Smckusick 		} else {
17111438Smckusick 			/*
17211438Smckusick 			 * This is a level zero dump tape.
17311438Smckusick 			 */
17411438Smckusick 			vprintf(stdout, "Begin level 0 restore\n");
17511438Smckusick 			initsymtable((char *)0);
17611993Smckusick 			extractdirs(1);
17711438Smckusick 			vprintf(stdout, "Calculate extraction list.\n");
17811438Smckusick 			treescan(".", ROOTINO, nodeupdates);
1794843Smckusic 		}
18010312Smckusick 		createleaves(symtbl);
18110312Smckusick 		createlinks();
18255880Smckusick 		setdirmodes(FORCE);
18310312Smckusick 		checkrestore();
18410312Smckusick 		if (dflag) {
18510312Smckusick 			vprintf(stdout, "Verify the directory structure\n");
18610312Smckusick 			treescan(".", ROOTINO, verifyfile);
1874610Smckusick 		}
18810312Smckusick 		dumpsymtable(symtbl, (long)1);
18956567Sbostic 		break;
19011993Smckusick 	/*
19111993Smckusick 	 * Resume an incremental file system restoration.
19211993Smckusick 	 */
19310312Smckusick 	case 'R':
19410312Smckusick 		initsymtable(symtbl);
19511320Smckusick 		skipmaps();
19611320Smckusick 		skipdirs();
19710312Smckusick 		createleaves(symtbl);
19810312Smckusick 		createlinks();
19955880Smckusick 		setdirmodes(FORCE);
20010312Smckusick 		checkrestore();
20110312Smckusick 		dumpsymtable(symtbl, (long)1);
20256567Sbostic 		break;
20311993Smckusick 	/*
20411993Smckusick 	 * List contents of tape.
20511993Smckusick 	 */
20611993Smckusick 	case 't':
20711993Smckusick 		setup();
20811993Smckusick 		extractdirs(0);
20927264Smckusick 		initsymtable((char *)0);
21011993Smckusick 		while (argc--) {
21111993Smckusick 			canon(*argv++, name);
21211993Smckusick 			ino = dirlookup(name);
21311993Smckusick 			if (ino == 0)
21411993Smckusick 				continue;
21511993Smckusick 			treescan(name, ino, listfile);
21611993Smckusick 		}
21756567Sbostic 		break;
21811993Smckusick 	/*
21911993Smckusick 	 * Batch extraction of tape contents.
22011993Smckusick 	 */
22111993Smckusick 	case 'x':
22211993Smckusick 		setup();
22311993Smckusick 		extractdirs(1);
22411993Smckusick 		initsymtable((char *)0);
22511993Smckusick 		while (argc--) {
22611993Smckusick 			canon(*argv++, name);
22711993Smckusick 			ino = dirlookup(name);
22811993Smckusick 			if (ino == 0)
22911993Smckusick 				continue;
23011993Smckusick 			if (mflag)
23111993Smckusick 				pathcheck(name);
23211993Smckusick 			treescan(name, ino, addfile);
23311993Smckusick 		}
23411993Smckusick 		createfiles();
23511993Smckusick 		createlinks();
23655880Smckusick 		setdirmodes(0);
23711993Smckusick 		if (dflag)
23811993Smckusick 			checkrestore();
23956567Sbostic 		break;
2404843Smckusic 	}
24156567Sbostic 	done(0);
24256567Sbostic 	/* NOTREACHED */
2434843Smckusic }
24456428Smckusick 
24559771Shibler static void
24656428Smckusick usage()
24756428Smckusick {
24856567Sbostic 	(void)fprintf(stderr, "usage:\t%s%s%s%s%s",
24956567Sbostic 	    "restore tfhsvy [file ...]\n",
25056567Sbostic 	    "\trestore xfhmsvy [file ...]\n",
25156428Smckusick 	    "\trestore ifhmsvy\n",
25256428Smckusick 	    "\trestore rfsvy\n",
25356428Smckusick 	    "\trestore Rfsvy\n");
25456428Smckusick 	done(1);
25556428Smckusick }
25656567Sbostic 
25756567Sbostic /*
25856567Sbostic  * obsolete --
25956567Sbostic  *	Change set of key letters and ordered arguments into something
26056567Sbostic  *	getopt(3) will like.
26156567Sbostic  */
26256567Sbostic static void
26356567Sbostic obsolete(argcp, argvp)
26456567Sbostic 	int *argcp;
26556567Sbostic 	char **argvp[];
26656567Sbostic {
26756567Sbostic 	int argc, flags;
26856567Sbostic 	char *ap, **argv, *flagsp, **nargv, *p;
26956567Sbostic 
27056567Sbostic 	/* Setup. */
27156567Sbostic 	argv = *argvp;
27256567Sbostic 	argc = *argcp;
27356567Sbostic 
27456567Sbostic 	/* Return if no arguments or first argument has leading dash. */
27556567Sbostic 	ap = argv[1];
27656567Sbostic 	if (argc == 1 || *ap == '-')
27756567Sbostic 		return;
27856567Sbostic 
27956567Sbostic 	/* Allocate space for new arguments. */
28056567Sbostic 	if ((*argvp = nargv = malloc((argc + 1) * sizeof(char *))) == NULL ||
28156567Sbostic 	    (p = flagsp = malloc(strlen(ap) + 2)) == NULL)
28265568Sbostic 		err(1, NULL);
28356567Sbostic 
28456567Sbostic 	*nargv++ = *argv;
28556567Sbostic 	argv += 2;
28656567Sbostic 
28756567Sbostic 	for (flags = 0; *ap; ++ap) {
28856567Sbostic 		switch(*ap) {
28956567Sbostic 		case 'b':
29056567Sbostic 		case 'f':
29156567Sbostic 		case 's':
29256567Sbostic 			if ((nargv[0] = malloc(strlen(*argv) + 2 + 1)) == NULL)
29365568Sbostic 				err(1, NULL);
29456567Sbostic 			nargv[0][0] = '-';
29556567Sbostic 			nargv[0][1] = *ap;
29656567Sbostic 			(void)strcpy(&nargv[0][2], *argv);
29756567Sbostic 			if (*argv != NULL)
29856567Sbostic 				++argv;
29956567Sbostic 			++nargv;
30056567Sbostic 			break;
30156567Sbostic 		default:
30256567Sbostic 			if (!flags) {
30356567Sbostic 				*p++ = '-';
30456567Sbostic 				flags = 1;
30556567Sbostic 			}
30656567Sbostic 			*p++ = *ap;
30756567Sbostic 			break;
30856567Sbostic 		}
30956567Sbostic 	}
31056567Sbostic 
31156567Sbostic 	/* Terminate flags. */
31256567Sbostic 	if (flags) {
31356567Sbostic 		*p = '\0';
31456567Sbostic 		*nargv++ = flagsp;
31556567Sbostic 	}
31656567Sbostic 
31756567Sbostic 	/* Copy remaining arguments. */
31856567Sbostic 	while (*nargv++ = *argv++);
31956567Sbostic }
320