main.c revision 1558
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 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
41static char sccsid[] = "@(#)main.c	8.2 (Berkeley) 1/7/94";
42#endif /* not lint */
43
44#include <sys/param.h>
45#include <sys/time.h>
46
47#include <ufs/ffs/fs.h>
48#include <ufs/ufs/dinode.h>
49#include <protocols/dumprestore.h>
50
51#include <err.h>
52#include <errno.h>
53#include <signal.h>
54#include <stdio.h>
55#include <stdlib.h>
56#include <string.h>
57
58#include "pathnames.h"
59#include "restore.h"
60#include "extern.h"
61
62int	bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0;
63int	hflag = 1, mflag = 1, Nflag = 0;
64char	command = '\0';
65long	dumpnum = 1;
66long	volno = 0;
67long	ntrec;
68char	*dumpmap;
69char	*clrimap;
70ino_t	maxino;
71time_t	dumptime;
72time_t	dumpdate;
73FILE 	*terminal;
74
75static void obsolete __P((int *, char **[]));
76static void usage __P((void));
77
78int
79main(argc, argv)
80	int argc;
81	char *argv[];
82{
83	int ch;
84	ino_t ino;
85	char *inputdev = _PATH_DEFTAPE;
86	char *symtbl = "./restoresymtable";
87	char *p, name[MAXPATHLEN];
88
89	if (argc < 2)
90		usage();
91
92	obsolete(&argc, &argv);
93	while ((ch = getopt(argc, argv, "b:cdf:himNRrs:tvxy")) != EOF)
94		switch(ch) {
95		case 'b':
96			/* Change default tape blocksize. */
97			bflag = 1;
98			ntrec = strtol(optarg, &p, 10);
99			if (*p)
100				errx(1, "illegal blocksize -- %s", optarg);
101			if (ntrec <= 0)
102				errx(1, "block size must be greater than 0");
103			break;
104		case 'c':
105			cvtflag = 1;
106			break;
107		case 'd':
108			dflag = 1;
109			break;
110		case 'f':
111			inputdev = optarg;
112			break;
113		case 'h':
114			hflag = 0;
115			break;
116		case 'i':
117		case 'R':
118		case 'r':
119		case 't':
120		case 'x':
121			if (command != '\0')
122				errx(1,
123				    "%c and %c options are mutually exclusive",
124				    ch, command);
125			command = ch;
126			break;
127		case 'm':
128			mflag = 0;
129			break;
130		case 'N':
131			Nflag = 1;
132			break;
133		case 's':
134			/* Dumpnum (skip to) for multifile dump tapes. */
135			dumpnum = strtol(optarg, &p, 10);
136			if (*p)
137				errx(1, "illegal dump number -- %s", optarg);
138			if (dumpnum <= 0)
139				errx(1, "dump number must be greater than 0");
140			break;
141		case 'v':
142			vflag = 1;
143			break;
144		case 'y':
145			yflag = 1;
146			break;
147		default:
148			usage();
149		}
150	argc -= optind;
151	argv += optind;
152
153	if (command == '\0')
154		errx(1, "none of i, R, r, t or x options specified");
155
156	if (signal(SIGINT, onintr) == SIG_IGN)
157		(void) signal(SIGINT, SIG_IGN);
158	if (signal(SIGTERM, onintr) == SIG_IGN)
159		(void) signal(SIGTERM, SIG_IGN);
160	setlinebuf(stderr);
161
162	setinput(inputdev);
163
164	if (argc == 0) {
165		argc = 1;
166		*--argv = ".";
167	}
168
169	switch (command) {
170	/*
171	 * Interactive mode.
172	 */
173	case 'i':
174		setup();
175		extractdirs(1);
176		initsymtable(NULL);
177		runcmdshell();
178		break;
179	/*
180	 * Incremental restoration of a file system.
181	 */
182	case 'r':
183		setup();
184		if (dumptime > 0) {
185			/*
186			 * This is an incremental dump tape.
187			 */
188			vprintf(stdout, "Begin incremental restore\n");
189			initsymtable(symtbl);
190			extractdirs(1);
191			removeoldleaves();
192			vprintf(stdout, "Calculate node updates.\n");
193			treescan(".", ROOTINO, nodeupdates);
194			findunreflinks();
195			removeoldnodes();
196		} else {
197			/*
198			 * This is a level zero dump tape.
199			 */
200			vprintf(stdout, "Begin level 0 restore\n");
201			initsymtable((char *)0);
202			extractdirs(1);
203			vprintf(stdout, "Calculate extraction list.\n");
204			treescan(".", ROOTINO, nodeupdates);
205		}
206		createleaves(symtbl);
207		createlinks();
208		setdirmodes(FORCE);
209		checkrestore();
210		if (dflag) {
211			vprintf(stdout, "Verify the directory structure\n");
212			treescan(".", ROOTINO, verifyfile);
213		}
214		dumpsymtable(symtbl, (long)1);
215		break;
216	/*
217	 * Resume an incremental file system restoration.
218	 */
219	case 'R':
220		initsymtable(symtbl);
221		skipmaps();
222		skipdirs();
223		createleaves(symtbl);
224		createlinks();
225		setdirmodes(FORCE);
226		checkrestore();
227		dumpsymtable(symtbl, (long)1);
228		break;
229	/*
230	 * List contents of tape.
231	 */
232	case 't':
233		setup();
234		extractdirs(0);
235		initsymtable((char *)0);
236		while (argc--) {
237			canon(*argv++, name);
238			ino = dirlookup(name);
239			if (ino == 0)
240				continue;
241			treescan(name, ino, listfile);
242		}
243		break;
244	/*
245	 * Batch extraction of tape contents.
246	 */
247	case 'x':
248		setup();
249		extractdirs(1);
250		initsymtable((char *)0);
251		while (argc--) {
252			canon(*argv++, name);
253			ino = dirlookup(name);
254			if (ino == 0)
255				continue;
256			if (mflag)
257				pathcheck(name);
258			treescan(name, ino, addfile);
259		}
260		createfiles();
261		createlinks();
262		setdirmodes(0);
263		if (dflag)
264			checkrestore();
265		break;
266	}
267	done(0);
268	/* NOTREACHED */
269}
270
271static void
272usage()
273{
274	(void)fprintf(stderr, "usage:\t%s%s%s%s%s",
275	    "restore tfhsvy [file ...]\n",
276	    "\trestore xfhmsvy [file ...]\n",
277	    "\trestore ifhmsvy\n",
278	    "\trestore rfsvy\n",
279	    "\trestore Rfsvy\n");
280	done(1);
281}
282
283/*
284 * obsolete --
285 *	Change set of key letters and ordered arguments into something
286 *	getopt(3) will like.
287 */
288static void
289obsolete(argcp, argvp)
290	int *argcp;
291	char **argvp[];
292{
293	int argc, flags;
294	char *ap, **argv, *flagsp, **nargv, *p;
295
296	/* Setup. */
297	argv = *argvp;
298	argc = *argcp;
299
300	/* Return if no arguments or first argument has leading dash. */
301	ap = argv[1];
302	if (argc == 1 || *ap == '-')
303		return;
304
305	/* Allocate space for new arguments. */
306	if ((*argvp = nargv = malloc((argc + 1) * sizeof(char *))) == NULL ||
307	    (p = flagsp = malloc(strlen(ap) + 2)) == NULL)
308		err(1, NULL);
309
310	*nargv++ = *argv;
311	argv += 2;
312
313	for (flags = 0; *ap; ++ap) {
314		switch(*ap) {
315		case 'b':
316		case 'f':
317		case 's':
318			if ((nargv[0] = malloc(strlen(*argv) + 2 + 1)) == NULL)
319				err(1, NULL);
320			nargv[0][0] = '-';
321			nargv[0][1] = *ap;
322			(void)strcpy(&nargv[0][2], *argv);
323			if (*argv != NULL)
324				++argv;
325			++nargv;
326			break;
327		default:
328			if (!flags) {
329				*p++ = '-';
330				flags = 1;
331			}
332			*p++ = *ap;
333			break;
334		}
335	}
336
337	/* Terminate flags. */
338	if (flags) {
339		*p = '\0';
340		*nargv++ = flagsp;
341	}
342
343	/* Copy remaining arguments. */
344	while (*nargv++ = *argv++);
345}
346