xref: /original-bsd/sbin/restore/main.c (revision 3b6250d9)
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.8 (Berkeley) 06/01/90";
16 #endif /* not lint */
17 
18 /*
19  *	Modified to recursively extract all files within a subtree
20  *	(supressed by the h option) and recreate the heirarchical
21  *	structure of that subtree and move extracted files to their
22  *	proper homes (supressed by the m option).
23  *	Includes the s (skip files) option for use with multiple
24  *	dumps on a single tape.
25  *	8/29/80		by Mike Litzkow
26  *
27  *	Modified to work on the new file system and to recover from
28  *	tape read errors.
29  *	1/19/82		by Kirk McKusick
30  *
31  *	Full incremental restore running entirely in user code and
32  *	interactive tape browser.
33  *	1/19/83		by Kirk McKusick
34  */
35 
36 #include "restore.h"
37 #include <protocols/dumprestore.h>
38 #include <sys/signal.h>
39 #include "pathnames.h"
40 
41 int	bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0;
42 int	hflag = 1, mflag = 1, Nflag = 0;
43 char	command = '\0';
44 long	dumpnum = 1;
45 long	volno = 0;
46 long	ntrec;
47 char	*dumpmap;
48 char	*clrimap;
49 ino_t	maxino;
50 time_t	dumptime;
51 time_t	dumpdate;
52 FILE 	*terminal;
53 
54 main(argc, argv)
55 	int argc;
56 	char *argv[];
57 {
58 	register char *cp;
59 	ino_t ino;
60 	char *inputdev = _PATH_DEFTAPE;
61 	char *symtbl = "./restoresymtable";
62 	char name[MAXPATHLEN];
63 	void onintr();
64 
65 	if (signal(SIGINT, onintr) == SIG_IGN)
66 		(void) signal(SIGINT, SIG_IGN);
67 	if (signal(SIGTERM, onintr) == SIG_IGN)
68 		(void) signal(SIGTERM, SIG_IGN);
69 	setlinebuf(stderr);
70 	if (argc < 2) {
71 usage:
72 		fprintf(stderr, "Usage:\n%s%s%s%s%s",
73 			"\trestore tfhsvy [file file ...]\n",
74 			"\trestore xfhmsvy [file file ...]\n",
75 			"\trestore ifhmsvy\n",
76 			"\trestore rfsvy\n",
77 			"\trestore Rfsvy\n");
78 		done(1);
79 	}
80 	argv++;
81 	argc -= 2;
82 	command = '\0';
83 	for (cp = *argv++; *cp; cp++) {
84 		switch (*cp) {
85 		case '-':
86 			break;
87 		case 'c':
88 			cvtflag++;
89 			break;
90 		case 'd':
91 			dflag++;
92 			break;
93 		case 'h':
94 			hflag = 0;
95 			break;
96 		case 'm':
97 			mflag = 0;
98 			break;
99 		case 'N':
100 			Nflag++;
101 			break;
102 		case 'v':
103 			vflag++;
104 			break;
105 		case 'y':
106 			yflag++;
107 			break;
108 		case 'f':
109 			if (argc < 1) {
110 				fprintf(stderr, "missing device specifier\n");
111 				done(1);
112 			}
113 			inputdev = *argv++;
114 			argc--;
115 			break;
116 		case 'b':
117 			/*
118 			 * change default tape blocksize
119 			 */
120 			bflag++;
121 			if (argc < 1) {
122 				fprintf(stderr, "missing block size\n");
123 				done(1);
124 			}
125 			ntrec = atoi(*argv++);
126 			if (ntrec <= 0) {
127 				fprintf(stderr, "Block size must be a positive integer\n");
128 				done(1);
129 			}
130 			argc--;
131 			break;
132 		case 's':
133 			/*
134 			 * dumpnum (skip to) for multifile dump tapes
135 			 */
136 			if (argc < 1) {
137 				fprintf(stderr, "missing dump number\n");
138 				done(1);
139 			}
140 			dumpnum = atoi(*argv++);
141 			if (dumpnum <= 0) {
142 				fprintf(stderr, "Dump number must be a positive integer\n");
143 				done(1);
144 			}
145 			argc--;
146 			break;
147 		case 't':
148 		case 'R':
149 		case 'r':
150 		case 'x':
151 		case 'i':
152 			if (command != '\0') {
153 				fprintf(stderr,
154 					"%c and %c are mutually exclusive\n",
155 					*cp, command);
156 				goto usage;
157 			}
158 			command = *cp;
159 			break;
160 		default:
161 			fprintf(stderr, "Bad key character %c\n", *cp);
162 			goto usage;
163 		}
164 	}
165 	if (command == '\0') {
166 		fprintf(stderr, "must specify i, t, r, R, or x\n");
167 		goto usage;
168 	}
169 	setinput(inputdev);
170 	if (argc == 0) {
171 		argc = 1;
172 		*--argv = ".";
173 	}
174 	switch (command) {
175 	/*
176 	 * Interactive mode.
177 	 */
178 	case 'i':
179 		setup();
180 		extractdirs(1);
181 		initsymtable((char *)0);
182 		runcmdshell();
183 		done(0);
184 	/*
185 	 * Incremental restoration of a file system.
186 	 */
187 	case 'r':
188 		setup();
189 		if (dumptime > 0) {
190 			/*
191 			 * This is an incremental dump tape.
192 			 */
193 			vprintf(stdout, "Begin incremental restore\n");
194 			initsymtable(symtbl);
195 			extractdirs(1);
196 			removeoldleaves();
197 			vprintf(stdout, "Calculate node updates.\n");
198 			treescan(".", ROOTINO, nodeupdates);
199 			findunreflinks();
200 			removeoldnodes();
201 		} else {
202 			/*
203 			 * This is a level zero dump tape.
204 			 */
205 			vprintf(stdout, "Begin level 0 restore\n");
206 			initsymtable((char *)0);
207 			extractdirs(1);
208 			vprintf(stdout, "Calculate extraction list.\n");
209 			treescan(".", ROOTINO, nodeupdates);
210 		}
211 		createleaves(symtbl);
212 		createlinks();
213 		setdirmodes();
214 		checkrestore();
215 		if (dflag) {
216 			vprintf(stdout, "Verify the directory structure\n");
217 			treescan(".", ROOTINO, verifyfile);
218 		}
219 		dumpsymtable(symtbl, (long)1);
220 		done(0);
221 	/*
222 	 * Resume an incremental file system restoration.
223 	 */
224 	case 'R':
225 		initsymtable(symtbl);
226 		skipmaps();
227 		skipdirs();
228 		createleaves(symtbl);
229 		createlinks();
230 		setdirmodes();
231 		checkrestore();
232 		dumpsymtable(symtbl, (long)1);
233 		done(0);
234 	/*
235 	 * List contents of tape.
236 	 */
237 	case 't':
238 		setup();
239 		extractdirs(0);
240 		initsymtable((char *)0);
241 		while (argc--) {
242 			canon(*argv++, name);
243 			ino = dirlookup(name);
244 			if (ino == 0)
245 				continue;
246 			treescan(name, ino, listfile);
247 		}
248 		done(0);
249 	/*
250 	 * Batch extraction of tape contents.
251 	 */
252 	case 'x':
253 		setup();
254 		extractdirs(1);
255 		initsymtable((char *)0);
256 		while (argc--) {
257 			canon(*argv++, name);
258 			ino = dirlookup(name);
259 			if (ino == 0)
260 				continue;
261 			if (mflag)
262 				pathcheck(name);
263 			treescan(name, ino, addfile);
264 		}
265 		createfiles();
266 		createlinks();
267 		setdirmodes();
268 		if (dflag)
269 			checkrestore();
270 		done(0);
271 	}
272 }
273