xref: /original-bsd/sbin/restore/main.c (revision 3708840b)
1 /* Copyright (c) 1983 Regents of the University of California */
2 
3 #ifndef lint
4 static char sccsid[] = "@(#)main.c	3.10	(Berkeley)	83/05/15";
5 #endif
6 
7 /*
8  *	Modified to recursively extract all files within a subtree
9  *	(supressed by the h option) and recreate the heirarchical
10  *	structure of that subtree and move extracted files to their
11  *	proper homes (supressed by the m option).
12  *	Includes the s (skip files) option for use with multiple
13  *	dumps on a single tape.
14  *	8/29/80		by Mike Litzkow
15  *
16  *	Modified to work on the new file system and to recover from
17  *	tape read errors.
18  *	1/19/82		by Kirk McKusick
19  *
20  *	Full incremental restore running entirely in user code and
21  *	interactive tape browser.
22  *	1/19/83		by Kirk McKusick
23  */
24 
25 #include "restore.h"
26 #include <signal.h>
27 
28 int	cvtflag = 0, dflag = 0, vflag = 0, yflag = 0;
29 int	hflag = 1, mflag = 1;
30 char	command = '\0';
31 long	dumpnum = 1;
32 long	volno = 0;
33 char	*dumpmap;
34 char	*clrimap;
35 ino_t	maxino;
36 time_t	dumptime;
37 time_t	dumpdate;
38 FILE 	*terminal;
39 
40 main(argc, argv)
41 	int argc;
42 	char *argv[];
43 {
44 	register char *cp;
45 	ino_t ino;
46 	char *inputdev = "/dev/rmt8";
47 	char *symtbl = "./restoresymtable";
48 	char name[MAXPATHLEN];
49 	int (*signal())();
50 	extern int onintr();
51 
52 	if (signal(SIGINT, onintr) == SIG_IGN)
53 		(void) signal(SIGINT, SIG_IGN);
54 	if (signal(SIGTERM, onintr) == SIG_IGN)
55 		(void) signal(SIGTERM, SIG_IGN);
56 	setlinebuf(stderr);
57 	if (argc < 2) {
58 usage:
59 		fprintf(stderr, "Usage:\n%s%s%s%s%s",
60 			"\trestore tfhsvy [file file ...]\n",
61 			"\trestore xfhmsvy [file file ...]\n",
62 			"\trestore ifhmsvy\n",
63 			"\trestore rfsvy\n",
64 			"\trestore Rfsvy\n");
65 		done(1);
66 	}
67 	argv++;
68 	argc -= 2;
69 	command = '\0';
70 	for (cp = *argv++; *cp; cp++) {
71 		switch (*cp) {
72 		case '-':
73 			break;
74 		case 'c':
75 			cvtflag++;
76 			break;
77 		case 'd':
78 			dflag++;
79 			break;
80 		case 'h':
81 			hflag = 0;
82 			break;
83 		case 'm':
84 			mflag = 0;
85 			break;
86 		case 'v':
87 			vflag++;
88 			break;
89 		case 'y':
90 			yflag++;
91 			break;
92 		case 'f':
93 			if (argc < 1) {
94 				fprintf(stderr, "missing device specifier\n");
95 				done(1);
96 			}
97 			inputdev = *argv++;
98 			argc--;
99 			break;
100 		case 's':
101 			/*
102 			 * dumpnum (skip to) for multifile dump tapes
103 			 */
104 			if (argc < 1) {
105 				fprintf(stderr, "missing dump number\n");
106 				done(1);
107 			}
108 			dumpnum = atoi(*argv++);
109 			if (dumpnum <= 0) {
110 				fprintf(stderr, "Dump number must be a positive integer\n");
111 				done(1);
112 			}
113 			argc--;
114 			break;
115 		case 't':
116 		case 'R':
117 		case 'r':
118 		case 'x':
119 		case 'i':
120 			if (command != '\0') {
121 				fprintf(stderr,
122 					"%c and %c are mutually exclusive\n",
123 					*cp, command);
124 				goto usage;
125 			}
126 			command = *cp;
127 			break;
128 		default:
129 			fprintf(stderr, "Bad key character %c\n", *cp);
130 			goto usage;
131 		}
132 	}
133 	if (command == '\0') {
134 		fprintf(stderr, "must specify i, t, r, R, or x\n");
135 		goto usage;
136 	}
137 	setinput(inputdev);
138 	if (argc == 0) {
139 		argc = 1;
140 		*--argv = ".";
141 	}
142 	switch (command) {
143 	/*
144 	 * Interactive mode.
145 	 */
146 	case 'i':
147 		setup();
148 		extractdirs(1);
149 		initsymtable((char *)0);
150 		runcmdshell();
151 		done(0);
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();
182 		checkrestore();
183 		if (dflag) {
184 			vprintf(stdout, "Verify the directory structure\n");
185 			treescan(".", ROOTINO, verifyfile);
186 		}
187 		dumpsymtable(symtbl, (long)1);
188 		done(0);
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();
199 		checkrestore();
200 		dumpsymtable(symtbl, (long)1);
201 		done(0);
202 	/*
203 	 * List contents of tape.
204 	 */
205 	case 't':
206 		setup();
207 		extractdirs(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 		done(0);
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();
235 		if (dflag)
236 			checkrestore();
237 		done(0);
238 	}
239 }
240 
241 /*
242  * Read and execute commands from the terminal.
243  */
244 runcmdshell()
245 {
246 	register struct entry *np;
247 	ino_t ino;
248 	char curdir[MAXPATHLEN];
249 	char name[MAXPATHLEN];
250 	char cmd[BUFSIZ];
251 
252 	canon("/", curdir);
253 loop:
254 	getcmd(curdir, cmd, name);
255 	switch (cmd[0]) {
256 	/*
257 	 * Add elements to the extraction list.
258 	 */
259 	case 'a':
260 		ino = dirlookup(name);
261 		if (ino == 0)
262 			break;
263 		if (mflag)
264 			pathcheck(name);
265 		treescan(name, ino, addfile);
266 		break;
267 	/*
268 	 * Change working directory.
269 	 */
270 	case 'c':
271 		ino = dirlookup(name);
272 		if (ino == 0)
273 			break;
274 		if (inodetype(ino) == LEAF) {
275 			fprintf(stderr, "%s: not a directory\n", name);
276 			break;
277 		}
278 		(void) strcpy(curdir, name);
279 		break;
280 	/*
281 	 * Delete elements from the extraction list.
282 	 */
283 	case 'd':
284 		np = lookupname(name);
285 		if (np == NIL || (np->e_flags & NEW) == 0) {
286 			fprintf(stderr, "%s: not on extraction list\n", name);
287 			break;
288 		}
289 		treescan(name, np->e_ino, deletefile);
290 		break;
291 	/*
292 	 * Extract the requested list.
293 	 */
294 	case 'e':
295 		createfiles();
296 		createlinks();
297 		setdirmodes();
298 		if (dflag)
299 			checkrestore();
300 		volno = 0;
301 		break;
302 	/*
303 	 * List available commands.
304 	 */
305 	case 'h':
306 	case '?':
307 		fprintf(stderr, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
308 			"Available commands are:\n",
309 			"\tls [arg] - list directory\n",
310 			"\tcd arg - change directory\n",
311 			"\tpwd - print current directory\n",
312 			"\tadd [arg] - add `arg' to list of",
313 			" files to be extracted\n",
314 			"\tdelete [arg] - delete `arg' from",
315 			" list of files to be extracted\n",
316 			"\textract - extract requested files\n",
317 			"\tquit - immediately exit program\n",
318 			"\tverbose - toggle verbose flag",
319 			" (useful with ``ls'')\n",
320 			"\thelp or `?' - print this list\n",
321 			"If no `arg' is supplied, the current",
322 			" directory is used\n");
323 		break;
324 	/*
325 	 * List a directory.
326 	 */
327 	case 'l':
328 		ino = dirlookup(name);
329 		if (ino == 0)
330 			break;
331 		printlist(name, ino);
332 		break;
333 	/*
334 	 * Print current directory.
335 	 */
336 	case 'p':
337 		if (curdir[1] == '\0')
338 			fprintf(stderr, "/\n");
339 		else
340 			fprintf(stderr, "%s\n", &curdir[1]);
341 		break;
342 	/*
343 	 * Quit.
344 	 */
345 	case 'q':
346 		return;
347 	/*
348 	 * Toggle verbose mode.
349 	 */
350 	case 'v':
351 		if (vflag) {
352 			fprintf(stderr, "verbose mode off\n");
353 			vflag = 0;
354 			break;
355 		}
356 		fprintf(stderr, "verbose mode on\n");
357 		vflag++;
358 		break;
359 	/*
360 	 * Turn on debugging.
361 	 */
362 	case 'D':
363 		if (dflag) {
364 			fprintf(stderr, "debugging mode off\n");
365 			dflag = 0;
366 			break;
367 		}
368 		fprintf(stderr, "debugging mode on\n");
369 		dflag++;
370 		break;
371 	/*
372 	 * Unknown command.
373 	 */
374 	default:
375 		fprintf(stderr, "%s: unknown command; type ? for help\n", cmd);
376 		break;
377 	}
378 	goto loop;
379 }
380