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