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