xref: /csrg-svn/sbin/restore/main.c (revision 56567)
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*56567Sbostic static char sccsid[] = "@(#)main.c	5.11 (Berkeley) 10/16/92";
1636105Sbostic #endif /* not lint */
1714564Ssam 
18*56567Sbostic #include <sys/param.h>
19*56567Sbostic #include <sys/time.h>
204610Smckusick 
21*56567Sbostic #include <ufs/ffs/fs.h>
22*56567Sbostic #include <ufs/ufs/dinode.h>
2323547Smckusick #include <protocols/dumprestore.h>
24*56567Sbostic 
25*56567Sbostic #include <errno.h>
26*56567Sbostic #include <signal.h>
27*56567Sbostic #include <stdio.h>
28*56567Sbostic #include <stdlib.h>
29*56567Sbostic #include <string.h>
30*56567Sbostic 
3137952Sbostic #include "pathnames.h"
32*56567Sbostic #include "restore.h"
33*56567Sbostic #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 
48*56567Sbostic static void err __P((const char *, ...));
49*56567Sbostic static void obsolete __P((int *, char **[]));
50*56567Sbostic static void usage __P((void));
51*56567Sbostic 
5256428Smckusick int
536846Smckusick main(argc, argv)
544700Smckusic 	int argc;
554700Smckusic 	char *argv[];
564610Smckusick {
57*56567Sbostic 	int ch;
5811308Smckusick 	ino_t ino;
5937952Sbostic 	char *inputdev = _PATH_DEFTAPE;
6011308Smckusick 	char *symtbl = "./restoresymtable";
61*56567Sbostic 	char *p, name[MAXPATHLEN];
624610Smckusick 
6356428Smckusick 	if (argc < 2)
6456428Smckusick 		usage();
65*56567Sbostic 
66*56567Sbostic 	obsolete(&argc, &argv);
67*56567Sbostic 	while ((ch = getopt(argc, argv, "b:cdf:himNRrs:tvxy")) != EOF)
68*56567Sbostic 		switch(ch) {
69*56567Sbostic 		case 'b':
70*56567Sbostic 			/* Change default tape blocksize. */
71*56567Sbostic 			bflag = 1;
72*56567Sbostic 			ntrec = strtol(optarg, &p, 10);
73*56567Sbostic 			if (*p)
74*56567Sbostic 				err("illegal blocksize -- %s", optarg);
75*56567Sbostic 			if (ntrec <= 0)
76*56567Sbostic 				err("block size must be greater than 0");
774610Smckusick 			break;
788302Smckusick 		case 'c':
79*56567Sbostic 			cvtflag = 1;
808302Smckusick 			break;
8110312Smckusick 		case 'd':
82*56567Sbostic 			dflag = 1;
834610Smckusick 			break;
84*56567Sbostic 		case 'f':
85*56567Sbostic 			inputdev = optarg;
86*56567Sbostic 			break;
874610Smckusick 		case 'h':
8810202Smckusick 			hflag = 0;
894610Smckusick 			break;
90*56567Sbostic 		case 'i':
91*56567Sbostic 		case 'R':
92*56567Sbostic 		case 'r':
93*56567Sbostic 		case 't':
94*56567Sbostic 		case 'x':
95*56567Sbostic 			if (command != '\0')
96*56567Sbostic 				err("%c and %c options are mutually exclusive",
97*56567Sbostic 				    ch, command);
98*56567Sbostic 			command = ch;
99*56567Sbostic 			break;
1004610Smckusick 		case 'm':
10110202Smckusick 			mflag = 0;
1024610Smckusick 			break;
10334269Smckusick 		case 'N':
104*56567Sbostic 			Nflag = 1;
10534269Smckusick 			break;
106*56567Sbostic 		case 's':
107*56567Sbostic 			/* Dumpnum (skip to) for multifile dump tapes. */
108*56567Sbostic 			dumpnum = strtol(optarg, &p, 10);
109*56567Sbostic 			if (*p)
110*56567Sbostic 				err("illegal dump number -- %s", optarg);
111*56567Sbostic 			if (dumpnum <= 0)
112*56567Sbostic 				err("dump number must be greater than 0");
113*56567Sbostic 			break;
1148374Smckusick 		case 'v':
115*56567Sbostic 			vflag = 1;
1168374Smckusick 			break;
1178374Smckusick 		case 'y':
118*56567Sbostic 			yflag = 1;
1198374Smckusick 			break;
1204610Smckusick 		default:
12156428Smckusick 			usage();
1224610Smckusick 		}
123*56567Sbostic 	argc -= optind;
124*56567Sbostic 	argv += optind;
125*56567Sbostic 
126*56567Sbostic 	if (command == '\0')
127*56567Sbostic 		err("none of i, R, r, t or x options specified");
128*56567Sbostic 
129*56567Sbostic 	if (signal(SIGINT, onintr) == SIG_IGN)
130*56567Sbostic 		(void) signal(SIGINT, SIG_IGN);
131*56567Sbostic 	if (signal(SIGTERM, onintr) == SIG_IGN)
132*56567Sbostic 		(void) signal(SIGTERM, SIG_IGN);
133*56567Sbostic 	setlinebuf(stderr);
134*56567Sbostic 
13510312Smckusick 	setinput(inputdev);
136*56567Sbostic 
13710202Smckusick 	if (argc == 0) {
13810312Smckusick 		argc = 1;
13910202Smckusick 		*--argv = ".";
14010202Smckusick 	}
141*56567Sbostic 
14210312Smckusick 	switch (command) {
14311993Smckusick 	/*
14411993Smckusick 	 * Interactive mode.
14511993Smckusick 	 */
14611993Smckusick 	case 'i':
14710312Smckusick 		setup();
14811993Smckusick 		extractdirs(1);
149*56567Sbostic 		initsymtable(NULL);
15011993Smckusick 		runcmdshell();
151*56567Sbostic 		break;
15211993Smckusick 	/*
15311993Smckusick 	 * Incremental restoration of a file system.
15411993Smckusick 	 */
15510312Smckusick 	case 'r':
15610312Smckusick 		setup();
15710312Smckusick 		if (dumptime > 0) {
15811438Smckusick 			/*
15911438Smckusick 			 * This is an incremental dump tape.
16011438Smckusick 			 */
16111438Smckusick 			vprintf(stdout, "Begin incremental restore\n");
16210312Smckusick 			initsymtable(symtbl);
16311993Smckusick 			extractdirs(1);
16411438Smckusick 			removeoldleaves();
16511438Smckusick 			vprintf(stdout, "Calculate node updates.\n");
16611438Smckusick 			treescan(".", ROOTINO, nodeupdates);
16711438Smckusick 			findunreflinks();
16811438Smckusick 			removeoldnodes();
16910312Smckusick 		} else {
17011438Smckusick 			/*
17111438Smckusick 			 * This is a level zero dump tape.
17211438Smckusick 			 */
17311438Smckusick 			vprintf(stdout, "Begin level 0 restore\n");
17411438Smckusick 			initsymtable((char *)0);
17511993Smckusick 			extractdirs(1);
17611438Smckusick 			vprintf(stdout, "Calculate extraction list.\n");
17711438Smckusick 			treescan(".", ROOTINO, nodeupdates);
1784843Smckusic 		}
17910312Smckusick 		createleaves(symtbl);
18010312Smckusick 		createlinks();
18155880Smckusick 		setdirmodes(FORCE);
18210312Smckusick 		checkrestore();
18310312Smckusick 		if (dflag) {
18410312Smckusick 			vprintf(stdout, "Verify the directory structure\n");
18510312Smckusick 			treescan(".", ROOTINO, verifyfile);
1864610Smckusick 		}
18710312Smckusick 		dumpsymtable(symtbl, (long)1);
188*56567Sbostic 		break;
18911993Smckusick 	/*
19011993Smckusick 	 * Resume an incremental file system restoration.
19111993Smckusick 	 */
19210312Smckusick 	case 'R':
19310312Smckusick 		initsymtable(symtbl);
19411320Smckusick 		skipmaps();
19511320Smckusick 		skipdirs();
19610312Smckusick 		createleaves(symtbl);
19710312Smckusick 		createlinks();
19855880Smckusick 		setdirmodes(FORCE);
19910312Smckusick 		checkrestore();
20010312Smckusick 		dumpsymtable(symtbl, (long)1);
201*56567Sbostic 		break;
20211993Smckusick 	/*
20311993Smckusick 	 * List contents of tape.
20411993Smckusick 	 */
20511993Smckusick 	case 't':
20611993Smckusick 		setup();
20711993Smckusick 		extractdirs(0);
20827264Smckusick 		initsymtable((char *)0);
20911993Smckusick 		while (argc--) {
21011993Smckusick 			canon(*argv++, name);
21111993Smckusick 			ino = dirlookup(name);
21211993Smckusick 			if (ino == 0)
21311993Smckusick 				continue;
21411993Smckusick 			treescan(name, ino, listfile);
21511993Smckusick 		}
216*56567Sbostic 		break;
21711993Smckusick 	/*
21811993Smckusick 	 * Batch extraction of tape contents.
21911993Smckusick 	 */
22011993Smckusick 	case 'x':
22111993Smckusick 		setup();
22211993Smckusick 		extractdirs(1);
22311993Smckusick 		initsymtable((char *)0);
22411993Smckusick 		while (argc--) {
22511993Smckusick 			canon(*argv++, name);
22611993Smckusick 			ino = dirlookup(name);
22711993Smckusick 			if (ino == 0)
22811993Smckusick 				continue;
22911993Smckusick 			if (mflag)
23011993Smckusick 				pathcheck(name);
23111993Smckusick 			treescan(name, ino, addfile);
23211993Smckusick 		}
23311993Smckusick 		createfiles();
23411993Smckusick 		createlinks();
23555880Smckusick 		setdirmodes(0);
23611993Smckusick 		if (dflag)
23711993Smckusick 			checkrestore();
238*56567Sbostic 		break;
2394843Smckusic 	}
240*56567Sbostic 	done(0);
241*56567Sbostic 	/* NOTREACHED */
2424843Smckusic }
24356428Smckusick 
244*56567Sbostic void
24556428Smckusick usage()
24656428Smckusick {
247*56567Sbostic 	(void)fprintf(stderr, "usage:\t%s%s%s%s%s",
248*56567Sbostic 	    "restore tfhsvy [file ...]\n",
249*56567Sbostic 	    "\trestore xfhmsvy [file ...]\n",
25056428Smckusick 	    "\trestore ifhmsvy\n",
25156428Smckusick 	    "\trestore rfsvy\n",
25256428Smckusick 	    "\trestore Rfsvy\n");
25356428Smckusick 	done(1);
25456428Smckusick }
255*56567Sbostic 
256*56567Sbostic /*
257*56567Sbostic  * obsolete --
258*56567Sbostic  *	Change set of key letters and ordered arguments into something
259*56567Sbostic  *	getopt(3) will like.
260*56567Sbostic  */
261*56567Sbostic static void
262*56567Sbostic obsolete(argcp, argvp)
263*56567Sbostic 	int *argcp;
264*56567Sbostic 	char **argvp[];
265*56567Sbostic {
266*56567Sbostic 	int argc, flags;
267*56567Sbostic 	char *ap, **argv, *flagsp, **nargv, *p;
268*56567Sbostic 
269*56567Sbostic 	/* Setup. */
270*56567Sbostic 	argv = *argvp;
271*56567Sbostic 	argc = *argcp;
272*56567Sbostic 
273*56567Sbostic 	/* Return if no arguments or first argument has leading dash. */
274*56567Sbostic 	ap = argv[1];
275*56567Sbostic 	if (argc == 1 || *ap == '-')
276*56567Sbostic 		return;
277*56567Sbostic 
278*56567Sbostic 	/* Allocate space for new arguments. */
279*56567Sbostic 	if ((*argvp = nargv = malloc((argc + 1) * sizeof(char *))) == NULL ||
280*56567Sbostic 	    (p = flagsp = malloc(strlen(ap) + 2)) == NULL)
281*56567Sbostic 		err("%s", strerror(errno));
282*56567Sbostic 
283*56567Sbostic 	*nargv++ = *argv;
284*56567Sbostic 	argv += 2;
285*56567Sbostic 
286*56567Sbostic 	for (flags = 0; *ap; ++ap) {
287*56567Sbostic 		switch(*ap) {
288*56567Sbostic 		case 'b':
289*56567Sbostic 		case 'f':
290*56567Sbostic 		case 's':
291*56567Sbostic 			if ((nargv[0] = malloc(strlen(*argv) + 2 + 1)) == NULL)
292*56567Sbostic 				err("%s", strerror(errno));
293*56567Sbostic 			nargv[0][0] = '-';
294*56567Sbostic 			nargv[0][1] = *ap;
295*56567Sbostic 			(void)strcpy(&nargv[0][2], *argv);
296*56567Sbostic 			if (*argv != NULL)
297*56567Sbostic 				++argv;
298*56567Sbostic 			++nargv;
299*56567Sbostic 			break;
300*56567Sbostic 		default:
301*56567Sbostic 			if (!flags) {
302*56567Sbostic 				*p++ = '-';
303*56567Sbostic 				flags = 1;
304*56567Sbostic 			}
305*56567Sbostic 			*p++ = *ap;
306*56567Sbostic 			break;
307*56567Sbostic 		}
308*56567Sbostic 	}
309*56567Sbostic 
310*56567Sbostic 	/* Terminate flags. */
311*56567Sbostic 	if (flags) {
312*56567Sbostic 		*p = '\0';
313*56567Sbostic 		*nargv++ = flagsp;
314*56567Sbostic 	}
315*56567Sbostic 
316*56567Sbostic 	/* Copy remaining arguments. */
317*56567Sbostic 	while (*nargv++ = *argv++);
318*56567Sbostic }
319*56567Sbostic 
320*56567Sbostic #if __STDC__
321*56567Sbostic #include <stdarg.h>
322*56567Sbostic #else
323*56567Sbostic #include <varargs.h>
324*56567Sbostic #endif
325*56567Sbostic 
326*56567Sbostic void
327*56567Sbostic #if __STDC__
328*56567Sbostic err(const char *fmt, ...)
329*56567Sbostic #else
330*56567Sbostic err(fmt, va_alist)
331*56567Sbostic 	char *fmt;
332*56567Sbostic         va_dcl
333*56567Sbostic #endif
334*56567Sbostic {
335*56567Sbostic 	va_list ap;
336*56567Sbostic #if __STDC__
337*56567Sbostic 	va_start(ap, fmt);
338*56567Sbostic #else
339*56567Sbostic 	va_start(ap);
340*56567Sbostic #endif
341*56567Sbostic 	(void)fprintf(stderr, "restore: ");
342*56567Sbostic 	(void)vfprintf(stderr, fmt, ap);
343*56567Sbostic 	va_end(ap);
344*56567Sbostic 	(void)fprintf(stderr, "\n");
345*56567Sbostic 	exit(1);
346*56567Sbostic 	/* NOTREACHED */
347*56567Sbostic }
348