xref: /csrg-svn/sbin/restore/main.c (revision 59771)
121167Sdist /*
236105Sbostic  * Copyright (c) 1983 The Regents of the University of California.
336105Sbostic  * All rights reserved.
436105Sbostic  *
542708Sbostic  * %sccs.include.redist.c%
621167Sdist  */
721167Sdist 
86846Smckusick #ifndef lint
921167Sdist char copyright[] =
1036105Sbostic "@(#) Copyright (c) 1983 The Regents of the University of California.\n\
1121167Sdist  All rights reserved.\n";
1236105Sbostic #endif /* not lint */
134610Smckusick 
1421167Sdist #ifndef lint
15*59771Shibler static char sccsid[] = "@(#)main.c	5.13 (Berkeley) 05/06/93";
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 
2556567Sbostic #include <errno.h>
2656567Sbostic #include <signal.h>
2756567Sbostic #include <stdio.h>
2856567Sbostic #include <stdlib.h>
2956567Sbostic #include <string.h>
3056567Sbostic 
3137952Sbostic #include "pathnames.h"
3256567Sbostic #include "restore.h"
3356567Sbostic #include "extern.h"
344610Smckusick 
3518496Smckusick int	bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0;
3634269Smckusick int	hflag = 1, mflag = 1, Nflag = 0;
3710312Smckusick char	command = '\0';
3810312Smckusick long	dumpnum = 1;
3911438Smckusick long	volno = 0;
4018496Smckusick long	ntrec;
415327Smckusic char	*dumpmap;
425327Smckusic char	*clrimap;
4310312Smckusick ino_t	maxino;
4410312Smckusick time_t	dumptime;
4511302Smckusick time_t	dumpdate;
4611993Smckusick FILE 	*terminal;
474610Smckusick 
4856567Sbostic static void obsolete __P((int *, char **[]));
4956567Sbostic static void usage __P((void));
5056567Sbostic 
5156428Smckusick int
526846Smckusick main(argc, argv)
534700Smckusic 	int argc;
544700Smckusic 	char *argv[];
554610Smckusick {
5656567Sbostic 	int ch;
5711308Smckusick 	ino_t ino;
5837952Sbostic 	char *inputdev = _PATH_DEFTAPE;
5911308Smckusick 	char *symtbl = "./restoresymtable";
6056567Sbostic 	char *p, name[MAXPATHLEN];
614610Smckusick 
6256428Smckusick 	if (argc < 2)
6356428Smckusick 		usage();
6456567Sbostic 
6556567Sbostic 	obsolete(&argc, &argv);
6656567Sbostic 	while ((ch = getopt(argc, argv, "b:cdf:himNRrs:tvxy")) != EOF)
6756567Sbostic 		switch(ch) {
6856567Sbostic 		case 'b':
6956567Sbostic 			/* Change default tape blocksize. */
7056567Sbostic 			bflag = 1;
7156567Sbostic 			ntrec = strtol(optarg, &p, 10);
7256567Sbostic 			if (*p)
7356567Sbostic 				err("illegal blocksize -- %s", optarg);
7456567Sbostic 			if (ntrec <= 0)
7556567Sbostic 				err("block size must be greater than 0");
764610Smckusick 			break;
778302Smckusick 		case 'c':
7856567Sbostic 			cvtflag = 1;
798302Smckusick 			break;
8010312Smckusick 		case 'd':
8156567Sbostic 			dflag = 1;
824610Smckusick 			break;
8356567Sbostic 		case 'f':
8456567Sbostic 			inputdev = optarg;
8556567Sbostic 			break;
864610Smckusick 		case 'h':
8710202Smckusick 			hflag = 0;
884610Smckusick 			break;
8956567Sbostic 		case 'i':
9056567Sbostic 		case 'R':
9156567Sbostic 		case 'r':
9256567Sbostic 		case 't':
9356567Sbostic 		case 'x':
9456567Sbostic 			if (command != '\0')
9556567Sbostic 				err("%c and %c options are mutually exclusive",
9656567Sbostic 				    ch, command);
9756567Sbostic 			command = ch;
9856567Sbostic 			break;
994610Smckusick 		case 'm':
10010202Smckusick 			mflag = 0;
1014610Smckusick 			break;
10234269Smckusick 		case 'N':
10356567Sbostic 			Nflag = 1;
10434269Smckusick 			break;
10556567Sbostic 		case 's':
10656567Sbostic 			/* Dumpnum (skip to) for multifile dump tapes. */
10756567Sbostic 			dumpnum = strtol(optarg, &p, 10);
10856567Sbostic 			if (*p)
10956567Sbostic 				err("illegal dump number -- %s", optarg);
11056567Sbostic 			if (dumpnum <= 0)
11156567Sbostic 				err("dump number must be greater than 0");
11256567Sbostic 			break;
1138374Smckusick 		case 'v':
11456567Sbostic 			vflag = 1;
1158374Smckusick 			break;
1168374Smckusick 		case 'y':
11756567Sbostic 			yflag = 1;
1188374Smckusick 			break;
1194610Smckusick 		default:
12056428Smckusick 			usage();
1214610Smckusick 		}
12256567Sbostic 	argc -= optind;
12356567Sbostic 	argv += optind;
12456567Sbostic 
12556567Sbostic 	if (command == '\0')
12656567Sbostic 		err("none of i, R, r, t or x options specified");
12756567Sbostic 
12856567Sbostic 	if (signal(SIGINT, onintr) == SIG_IGN)
12956567Sbostic 		(void) signal(SIGINT, SIG_IGN);
13056567Sbostic 	if (signal(SIGTERM, onintr) == SIG_IGN)
13156567Sbostic 		(void) signal(SIGTERM, SIG_IGN);
13256567Sbostic 	setlinebuf(stderr);
13356567Sbostic 
13410312Smckusick 	setinput(inputdev);
13556567Sbostic 
13610202Smckusick 	if (argc == 0) {
13710312Smckusick 		argc = 1;
13810202Smckusick 		*--argv = ".";
13910202Smckusick 	}
14056567Sbostic 
14110312Smckusick 	switch (command) {
14211993Smckusick 	/*
14311993Smckusick 	 * Interactive mode.
14411993Smckusick 	 */
14511993Smckusick 	case 'i':
14610312Smckusick 		setup();
14711993Smckusick 		extractdirs(1);
14856567Sbostic 		initsymtable(NULL);
14911993Smckusick 		runcmdshell();
15056567Sbostic 		break;
15111993Smckusick 	/*
15211993Smckusick 	 * Incremental restoration of a file system.
15311993Smckusick 	 */
15410312Smckusick 	case 'r':
15510312Smckusick 		setup();
15610312Smckusick 		if (dumptime > 0) {
15711438Smckusick 			/*
15811438Smckusick 			 * This is an incremental dump tape.
15911438Smckusick 			 */
16011438Smckusick 			vprintf(stdout, "Begin incremental restore\n");
16110312Smckusick 			initsymtable(symtbl);
16211993Smckusick 			extractdirs(1);
16311438Smckusick 			removeoldleaves();
16411438Smckusick 			vprintf(stdout, "Calculate node updates.\n");
16511438Smckusick 			treescan(".", ROOTINO, nodeupdates);
16611438Smckusick 			findunreflinks();
16711438Smckusick 			removeoldnodes();
16810312Smckusick 		} else {
16911438Smckusick 			/*
17011438Smckusick 			 * This is a level zero dump tape.
17111438Smckusick 			 */
17211438Smckusick 			vprintf(stdout, "Begin level 0 restore\n");
17311438Smckusick 			initsymtable((char *)0);
17411993Smckusick 			extractdirs(1);
17511438Smckusick 			vprintf(stdout, "Calculate extraction list.\n");
17611438Smckusick 			treescan(".", ROOTINO, nodeupdates);
1774843Smckusic 		}
17810312Smckusick 		createleaves(symtbl);
17910312Smckusick 		createlinks();
18055880Smckusick 		setdirmodes(FORCE);
18110312Smckusick 		checkrestore();
18210312Smckusick 		if (dflag) {
18310312Smckusick 			vprintf(stdout, "Verify the directory structure\n");
18410312Smckusick 			treescan(".", ROOTINO, verifyfile);
1854610Smckusick 		}
18610312Smckusick 		dumpsymtable(symtbl, (long)1);
18756567Sbostic 		break;
18811993Smckusick 	/*
18911993Smckusick 	 * Resume an incremental file system restoration.
19011993Smckusick 	 */
19110312Smckusick 	case 'R':
19210312Smckusick 		initsymtable(symtbl);
19311320Smckusick 		skipmaps();
19411320Smckusick 		skipdirs();
19510312Smckusick 		createleaves(symtbl);
19610312Smckusick 		createlinks();
19755880Smckusick 		setdirmodes(FORCE);
19810312Smckusick 		checkrestore();
19910312Smckusick 		dumpsymtable(symtbl, (long)1);
20056567Sbostic 		break;
20111993Smckusick 	/*
20211993Smckusick 	 * List contents of tape.
20311993Smckusick 	 */
20411993Smckusick 	case 't':
20511993Smckusick 		setup();
20611993Smckusick 		extractdirs(0);
20727264Smckusick 		initsymtable((char *)0);
20811993Smckusick 		while (argc--) {
20911993Smckusick 			canon(*argv++, name);
21011993Smckusick 			ino = dirlookup(name);
21111993Smckusick 			if (ino == 0)
21211993Smckusick 				continue;
21311993Smckusick 			treescan(name, ino, listfile);
21411993Smckusick 		}
21556567Sbostic 		break;
21611993Smckusick 	/*
21711993Smckusick 	 * Batch extraction of tape contents.
21811993Smckusick 	 */
21911993Smckusick 	case 'x':
22011993Smckusick 		setup();
22111993Smckusick 		extractdirs(1);
22211993Smckusick 		initsymtable((char *)0);
22311993Smckusick 		while (argc--) {
22411993Smckusick 			canon(*argv++, name);
22511993Smckusick 			ino = dirlookup(name);
22611993Smckusick 			if (ino == 0)
22711993Smckusick 				continue;
22811993Smckusick 			if (mflag)
22911993Smckusick 				pathcheck(name);
23011993Smckusick 			treescan(name, ino, addfile);
23111993Smckusick 		}
23211993Smckusick 		createfiles();
23311993Smckusick 		createlinks();
23455880Smckusick 		setdirmodes(0);
23511993Smckusick 		if (dflag)
23611993Smckusick 			checkrestore();
23756567Sbostic 		break;
2384843Smckusic 	}
23956567Sbostic 	done(0);
24056567Sbostic 	/* NOTREACHED */
2414843Smckusic }
24256428Smckusick 
243*59771Shibler static void
24456428Smckusick usage()
24556428Smckusick {
24656567Sbostic 	(void)fprintf(stderr, "usage:\t%s%s%s%s%s",
24756567Sbostic 	    "restore tfhsvy [file ...]\n",
24856567Sbostic 	    "\trestore xfhmsvy [file ...]\n",
24956428Smckusick 	    "\trestore ifhmsvy\n",
25056428Smckusick 	    "\trestore rfsvy\n",
25156428Smckusick 	    "\trestore Rfsvy\n");
25256428Smckusick 	done(1);
25356428Smckusick }
25456567Sbostic 
25556567Sbostic /*
25656567Sbostic  * obsolete --
25756567Sbostic  *	Change set of key letters and ordered arguments into something
25856567Sbostic  *	getopt(3) will like.
25956567Sbostic  */
26056567Sbostic static void
26156567Sbostic obsolete(argcp, argvp)
26256567Sbostic 	int *argcp;
26356567Sbostic 	char **argvp[];
26456567Sbostic {
26556567Sbostic 	int argc, flags;
26656567Sbostic 	char *ap, **argv, *flagsp, **nargv, *p;
26756567Sbostic 
26856567Sbostic 	/* Setup. */
26956567Sbostic 	argv = *argvp;
27056567Sbostic 	argc = *argcp;
27156567Sbostic 
27256567Sbostic 	/* Return if no arguments or first argument has leading dash. */
27356567Sbostic 	ap = argv[1];
27456567Sbostic 	if (argc == 1 || *ap == '-')
27556567Sbostic 		return;
27656567Sbostic 
27756567Sbostic 	/* Allocate space for new arguments. */
27856567Sbostic 	if ((*argvp = nargv = malloc((argc + 1) * sizeof(char *))) == NULL ||
27956567Sbostic 	    (p = flagsp = malloc(strlen(ap) + 2)) == NULL)
28056567Sbostic 		err("%s", strerror(errno));
28156567Sbostic 
28256567Sbostic 	*nargv++ = *argv;
28356567Sbostic 	argv += 2;
28456567Sbostic 
28556567Sbostic 	for (flags = 0; *ap; ++ap) {
28656567Sbostic 		switch(*ap) {
28756567Sbostic 		case 'b':
28856567Sbostic 		case 'f':
28956567Sbostic 		case 's':
29056567Sbostic 			if ((nargv[0] = malloc(strlen(*argv) + 2 + 1)) == NULL)
29156567Sbostic 				err("%s", strerror(errno));
29256567Sbostic 			nargv[0][0] = '-';
29356567Sbostic 			nargv[0][1] = *ap;
29456567Sbostic 			(void)strcpy(&nargv[0][2], *argv);
29556567Sbostic 			if (*argv != NULL)
29656567Sbostic 				++argv;
29756567Sbostic 			++nargv;
29856567Sbostic 			break;
29956567Sbostic 		default:
30056567Sbostic 			if (!flags) {
30156567Sbostic 				*p++ = '-';
30256567Sbostic 				flags = 1;
30356567Sbostic 			}
30456567Sbostic 			*p++ = *ap;
30556567Sbostic 			break;
30656567Sbostic 		}
30756567Sbostic 	}
30856567Sbostic 
30956567Sbostic 	/* Terminate flags. */
31056567Sbostic 	if (flags) {
31156567Sbostic 		*p = '\0';
31256567Sbostic 		*nargv++ = flagsp;
31356567Sbostic 	}
31456567Sbostic 
31556567Sbostic 	/* Copy remaining arguments. */
31656567Sbostic 	while (*nargv++ = *argv++);
31756567Sbostic }
31856567Sbostic 
31956567Sbostic #if __STDC__
32056567Sbostic #include <stdarg.h>
32156567Sbostic #else
32256567Sbostic #include <varargs.h>
32356567Sbostic #endif
32456567Sbostic 
32557930Sbostic __dead void
32656567Sbostic #if __STDC__
32756567Sbostic err(const char *fmt, ...)
32856567Sbostic #else
32956567Sbostic err(fmt, va_alist)
33056567Sbostic 	char *fmt;
33156567Sbostic         va_dcl
33256567Sbostic #endif
33356567Sbostic {
33456567Sbostic 	va_list ap;
33556567Sbostic #if __STDC__
33656567Sbostic 	va_start(ap, fmt);
33756567Sbostic #else
33856567Sbostic 	va_start(ap);
33956567Sbostic #endif
34056567Sbostic 	(void)fprintf(stderr, "restore: ");
34156567Sbostic 	(void)vfprintf(stderr, fmt, ap);
34256567Sbostic 	va_end(ap);
34356567Sbostic 	(void)fprintf(stderr, "\n");
34456567Sbostic 	exit(1);
34556567Sbostic 	/* NOTREACHED */
34656567Sbostic }
347