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