main.c revision 37906
1/*
2 * Copyright (c) 1983, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static const char copyright[] =
36"@(#) Copyright (c) 1983, 1993\n\
37	The Regents of the University of California.  All rights reserved.\n";
38#endif /* not lint */
39
40#ifndef lint
41#if 0
42static char sccsid[] = "@(#)main.c	8.6 (Berkeley) 5/4/95";
43#endif
44static const char rcsid[] =
45	"$Id$";
46#endif /* not lint */
47
48#include <sys/param.h>
49#include <sys/stat.h>
50
51#include <ufs/ufs/dinode.h>
52#include <protocols/dumprestore.h>
53
54#include <err.h>
55#include <stdio.h>
56#include <stdlib.h>
57#include <unistd.h>
58
59#include "pathnames.h"
60#include "restore.h"
61#include "extern.h"
62
63int	bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0;
64int	hflag = 1, mflag = 1, Nflag = 0;
65int	uflag = 0;
66int	dokerberos = 0;
67char	command = '\0';
68long	dumpnum = 1;
69long	volno = 0;
70long	ntrec;
71char	*dumpmap;
72char	*usedinomap;
73ino_t	maxino;
74time_t	dumptime;
75time_t	dumpdate;
76FILE 	*terminal;
77
78static void obsolete __P((int *, char **[]));
79static void usage __P((void));
80
81int
82main(argc, argv)
83	int argc;
84	char *argv[];
85{
86	int ch;
87	ino_t ino;
88	char *inputdev;
89	char *symtbl = "./restoresymtable";
90	char *p, name[MAXPATHLEN];
91
92	/* Temp files should *not* be readable.  We set permissions later. */
93	(void) umask(077);
94
95	if (argc < 2)
96		usage();
97
98	if ((inputdev = getenv("TAPE")) == NULL)
99		inputdev = _PATH_DEFTAPE;
100	obsolete(&argc, &argv);
101#ifdef KERBEROS
102#define	optlist "b:cdf:hikmNRrs:tuvxy"
103#else
104#define	optlist "b:cdf:himNRrs:tuvxy"
105#endif
106	while ((ch = getopt(argc, argv, optlist)) != -1)
107		switch(ch) {
108		case 'b':
109			/* Change default tape blocksize. */
110			bflag = 1;
111			ntrec = strtol(optarg, &p, 10);
112			if (*p)
113				errx(1, "illegal blocksize -- %s", optarg);
114			if (ntrec <= 0)
115				errx(1, "block size must be greater than 0");
116			break;
117		case 'c':
118			cvtflag = 1;
119			break;
120		case 'd':
121			dflag = 1;
122			break;
123		case 'f':
124			inputdev = optarg;
125			break;
126		case 'h':
127			hflag = 0;
128			break;
129#ifdef KERBEROS
130		case 'k':
131			dokerberos = 1;
132			break;
133#endif
134		case 'i':
135		case 'R':
136		case 'r':
137		case 't':
138		case 'x':
139			if (command != '\0')
140				errx(1,
141				    "%c and %c options are mutually exclusive",
142				    ch, command);
143			command = ch;
144			break;
145		case 'm':
146			mflag = 0;
147			break;
148		case 'N':
149			Nflag = 1;
150			break;
151		case 's':
152			/* Dumpnum (skip to) for multifile dump tapes. */
153			dumpnum = strtol(optarg, &p, 10);
154			if (*p)
155				errx(1, "illegal dump number -- %s", optarg);
156			if (dumpnum <= 0)
157				errx(1, "dump number must be greater than 0");
158			break;
159		case 'u':
160			uflag = 1;
161			break;
162		case 'v':
163			vflag = 1;
164			break;
165		case 'y':
166			yflag = 1;
167			break;
168		default:
169			usage();
170		}
171	argc -= optind;
172	argv += optind;
173
174	if (command == '\0')
175		errx(1, "none of i, R, r, t or x options specified");
176
177	if (signal(SIGINT, onintr) == SIG_IGN)
178		(void) signal(SIGINT, SIG_IGN);
179	if (signal(SIGTERM, onintr) == SIG_IGN)
180		(void) signal(SIGTERM, SIG_IGN);
181	setlinebuf(stderr);
182
183	setinput(inputdev);
184
185	if (argc == 0) {
186		argc = 1;
187		*--argv = ".";
188	}
189
190	switch (command) {
191	/*
192	 * Interactive mode.
193	 */
194	case 'i':
195		setup();
196		extractdirs(1);
197		initsymtable(NULL);
198		runcmdshell();
199		break;
200	/*
201	 * Incremental restoration of a file system.
202	 */
203	case 'r':
204		setup();
205		if (dumptime > 0) {
206			/*
207			 * This is an incremental dump tape.
208			 */
209			vprintf(stdout, "Begin incremental restore\n");
210			initsymtable(symtbl);
211			extractdirs(1);
212			removeoldleaves();
213			vprintf(stdout, "Calculate node updates.\n");
214			treescan(".", ROOTINO, nodeupdates);
215			findunreflinks();
216			removeoldnodes();
217		} else {
218			/*
219			 * This is a level zero dump tape.
220			 */
221			vprintf(stdout, "Begin level 0 restore\n");
222			initsymtable((char *)0);
223			extractdirs(1);
224			vprintf(stdout, "Calculate extraction list.\n");
225			treescan(".", ROOTINO, nodeupdates);
226		}
227		createleaves(symtbl);
228		createlinks();
229		setdirmodes(FORCE);
230		checkrestore();
231		if (dflag) {
232			vprintf(stdout, "Verify the directory structure\n");
233			treescan(".", ROOTINO, verifyfile);
234		}
235		dumpsymtable(symtbl, (long)1);
236		break;
237	/*
238	 * Resume an incremental file system restoration.
239	 */
240	case 'R':
241		initsymtable(symtbl);
242		skipmaps();
243		skipdirs();
244		createleaves(symtbl);
245		createlinks();
246		setdirmodes(FORCE);
247		checkrestore();
248		dumpsymtable(symtbl, (long)1);
249		break;
250	/*
251	 * List contents of tape.
252	 */
253	case 't':
254		setup();
255		extractdirs(0);
256		initsymtable((char *)0);
257		while (argc--) {
258			canon(*argv++, name, sizeof(name));
259			ino = dirlookup(name);
260			if (ino == 0)
261				continue;
262			treescan(name, ino, listfile);
263		}
264		break;
265	/*
266	 * Batch extraction of tape contents.
267	 */
268	case 'x':
269		setup();
270		extractdirs(1);
271		initsymtable((char *)0);
272		while (argc--) {
273			canon(*argv++, name, sizeof(name));
274			ino = dirlookup(name);
275			if (ino == 0)
276				continue;
277			if (mflag)
278				pathcheck(name);
279			treescan(name, ino, addfile);
280		}
281		createfiles();
282		createlinks();
283		setdirmodes(0);
284		if (dflag)
285			checkrestore();
286		break;
287	}
288	done(0);
289	/* NOTREACHED */
290}
291
292static void
293usage()
294{
295	(void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n",
296	  "restore -i [-chkmuvy] [-b blocksize] [-f file] [-s fileno]",
297	  "restore -r [-ckuvy] [-b blocksize] [-f file] [-s fileno]",
298	  "restore -R [-ckuvy] [-b blocksize] [-f file] [-s fileno]",
299	  "restore -x [-chkmuvy] [-b blocksize] [-f file] [-s fileno] [file ...]",
300	  "restore -t [-chkuvy] [-b blocksize] [-f file] [-s fileno] [file ...]");
301	done(1);
302}
303
304/*
305 * obsolete --
306 *	Change set of key letters and ordered arguments into something
307 *	getopt(3) will like.
308 */
309static void
310obsolete(argcp, argvp)
311	int *argcp;
312	char **argvp[];
313{
314	int argc, flags;
315	char *ap, **argv, *flagsp, **nargv, *p;
316
317	/* Setup. */
318	argv = *argvp;
319	argc = *argcp;
320
321	/* Return if no arguments or first argument has leading dash. */
322	ap = argv[1];
323	if (argc == 1 || *ap == '-')
324		return;
325
326	/* Allocate space for new arguments. */
327	if ((*argvp = nargv = malloc((argc + 1) * sizeof(char *))) == NULL ||
328	    (p = flagsp = malloc(strlen(ap) + 2)) == NULL)
329		err(1, NULL);
330
331	*nargv++ = *argv;
332	argv += 2, argc -= 2;
333
334	for (flags = 0; *ap; ++ap) {
335		switch (*ap) {
336		case 'b':
337		case 'f':
338		case 's':
339			if (*argv == NULL) {
340				warnx("option requires an argument -- %c", *ap);
341				usage();
342			}
343			if ((nargv[0] = malloc(strlen(*argv) + 2 + 1)) == NULL)
344				err(1, NULL);
345			nargv[0][0] = '-';
346			nargv[0][1] = *ap;
347			(void)strcpy(&nargv[0][2], *argv);
348			++argv;
349			++nargv;
350			break;
351		default:
352			if (!flags) {
353				*p++ = '-';
354				flags = 1;
355			}
356			*p++ = *ap;
357			break;
358		}
359	}
360
361	/* Terminate flags. */
362	if (flags) {
363		*p = '\0';
364		*nargv++ = flagsp;
365	}
366
367	/* Copy remaining arguments. */
368	while ((*nargv++ = *argv++));
369
370	/* Update argument count. */
371	*argcp = nargv - *argvp - 1;
372}
373