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