xref: /386bsd/usr/src/sbin/restore/main.c (revision a2142627)
1 /*
2  * Copyright (c) 1983 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #ifndef lint
35 char copyright[] =
36 "@(#) Copyright (c) 1983 The Regents of the University of California.\n\
37  All rights reserved.\n";
38 #endif /* not lint */
39 
40 #ifndef lint
41 static char sccsid[] = "@(#)main.c	5.8 (Berkeley) 6/1/90";
42 #endif /* not lint */
43 
44 /*
45  *	Modified to recursively extract all files within a subtree
46  *	(supressed by the h option) and recreate the heirarchical
47  *	structure of that subtree and move extracted files to their
48  *	proper homes (supressed by the m option).
49  *	Includes the s (skip files) option for use with multiple
50  *	dumps on a single tape.
51  *	8/29/80		by Mike Litzkow
52  *
53  *	Modified to work on the new file system and to recover from
54  *	tape read errors.
55  *	1/19/82		by Kirk McKusick
56  *
57  *	Full incremental restore running entirely in user code and
58  *	interactive tape browser.
59  *	1/19/83		by Kirk McKusick
60  */
61 
62 #include "restore.h"
63 #include <protocols/dumprestore.h>
64 #include <sys/signal.h>
65 #include "pathnames.h"
66 
67 int	bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0;
68 int	hflag = 1, mflag = 1, Nflag = 0;
69 char	command = '\0';
70 long	dumpnum = 1;
71 long	volno = 0;
72 long	ntrec;
73 char	*dumpmap;
74 char	*clrimap;
75 ino_t	maxino;
76 time_t	dumptime;
77 time_t	dumpdate;
78 FILE 	*terminal;
79 
main(argc,argv)80 main(argc, argv)
81 	int argc;
82 	char *argv[];
83 {
84 	register char *cp;
85 	ino_t ino;
86 	char *inputdev = _PATH_DEFTAPE;
87 	char *symtbl = "./restoresymtable";
88 	char name[MAXPATHLEN];
89 	void onintr();
90 
91 	if (signal(SIGINT, onintr) == SIG_IGN)
92 		(void) signal(SIGINT, SIG_IGN);
93 	if (signal(SIGTERM, onintr) == SIG_IGN)
94 		(void) signal(SIGTERM, SIG_IGN);
95 	setlinebuf(stderr);
96 	if (argc < 2) {
97 usage:
98 		fprintf(stderr, "Usage:\n%s%s%s%s%s",
99 			"\trestore tfhsvy [file file ...]\n",
100 			"\trestore xfhmsvy [file file ...]\n",
101 			"\trestore ifhmsvy\n",
102 			"\trestore rfsvy\n",
103 			"\trestore Rfsvy\n");
104 		done(1);
105 	}
106 	argv++;
107 	argc -= 2;
108 	command = '\0';
109 	for (cp = *argv++; *cp; cp++) {
110 		switch (*cp) {
111 		case '-':
112 			break;
113 		case 'c':
114 			cvtflag++;
115 			break;
116 		case 'd':
117 			dflag++;
118 			break;
119 		case 'h':
120 			hflag = 0;
121 			break;
122 		case 'm':
123 			mflag = 0;
124 			break;
125 		case 'N':
126 			Nflag++;
127 			break;
128 		case 'v':
129 			vflag++;
130 			break;
131 		case 'y':
132 			yflag++;
133 			break;
134 		case 'f':
135 			if (argc < 1) {
136 				fprintf(stderr, "missing device specifier\n");
137 				done(1);
138 			}
139 			inputdev = *argv++;
140 			argc--;
141 			break;
142 		case 'b':
143 			/*
144 			 * change default tape blocksize
145 			 */
146 			bflag++;
147 			if (argc < 1) {
148 				fprintf(stderr, "missing block size\n");
149 				done(1);
150 			}
151 			ntrec = atoi(*argv++);
152 			if (ntrec <= 0) {
153 				fprintf(stderr, "Block size must be a positive integer\n");
154 				done(1);
155 			}
156 			argc--;
157 			break;
158 		case 's':
159 			/*
160 			 * dumpnum (skip to) for multifile dump tapes
161 			 */
162 			if (argc < 1) {
163 				fprintf(stderr, "missing dump number\n");
164 				done(1);
165 			}
166 			dumpnum = atoi(*argv++);
167 			if (dumpnum <= 0) {
168 				fprintf(stderr, "Dump number must be a positive integer\n");
169 				done(1);
170 			}
171 			argc--;
172 			break;
173 		case 't':
174 		case 'R':
175 		case 'r':
176 		case 'x':
177 		case 'i':
178 			if (command != '\0') {
179 				fprintf(stderr,
180 					"%c and %c are mutually exclusive\n",
181 					*cp, command);
182 				goto usage;
183 			}
184 			command = *cp;
185 			break;
186 		default:
187 			fprintf(stderr, "Bad key character %c\n", *cp);
188 			goto usage;
189 		}
190 	}
191 	if (command == '\0') {
192 		fprintf(stderr, "must specify i, t, r, R, or x\n");
193 		goto usage;
194 	}
195 	setinput(inputdev);
196 	if (argc == 0) {
197 		argc = 1;
198 		*--argv = ".";
199 	}
200 	switch (command) {
201 	/*
202 	 * Interactive mode.
203 	 */
204 	case 'i':
205 		setup();
206 		extractdirs(1);
207 		initsymtable((char *)0);
208 		runcmdshell();
209 		done(0);
210 	/*
211 	 * Incremental restoration of a file system.
212 	 */
213 	case 'r':
214 		setup();
215 		if (dumptime > 0) {
216 			/*
217 			 * This is an incremental dump tape.
218 			 */
219 			vprintf(stdout, "Begin incremental restore\n");
220 			initsymtable(symtbl);
221 			extractdirs(1);
222 			removeoldleaves();
223 			vprintf(stdout, "Calculate node updates.\n");
224 			treescan(".", ROOTINO, nodeupdates);
225 			findunreflinks();
226 			removeoldnodes();
227 		} else {
228 			/*
229 			 * This is a level zero dump tape.
230 			 */
231 			vprintf(stdout, "Begin level 0 restore\n");
232 			initsymtable((char *)0);
233 			extractdirs(1);
234 			vprintf(stdout, "Calculate extraction list.\n");
235 			treescan(".", ROOTINO, nodeupdates);
236 		}
237 		createleaves(symtbl);
238 		createlinks();
239 		setdirmodes();
240 		checkrestore();
241 		if (dflag) {
242 			vprintf(stdout, "Verify the directory structure\n");
243 			treescan(".", ROOTINO, verifyfile);
244 		}
245 		dumpsymtable(symtbl, (long)1);
246 		done(0);
247 	/*
248 	 * Resume an incremental file system restoration.
249 	 */
250 	case 'R':
251 		initsymtable(symtbl);
252 		skipmaps();
253 		skipdirs();
254 		createleaves(symtbl);
255 		createlinks();
256 		setdirmodes();
257 		checkrestore();
258 		dumpsymtable(symtbl, (long)1);
259 		done(0);
260 	/*
261 	 * List contents of tape.
262 	 */
263 	case 't':
264 		setup();
265 		extractdirs(0);
266 		initsymtable((char *)0);
267 		while (argc--) {
268 			canon(*argv++, name);
269 			ino = dirlookup(name);
270 			if (ino == 0)
271 				continue;
272 			treescan(name, ino, listfile);
273 		}
274 		done(0);
275 	/*
276 	 * Batch extraction of tape contents.
277 	 */
278 	case 'x':
279 		setup();
280 		extractdirs(1);
281 		initsymtable((char *)0);
282 		while (argc--) {
283 			canon(*argv++, name);
284 			ino = dirlookup(name);
285 			if (ino == 0)
286 				continue;
287 			if (mflag)
288 				pathcheck(name);
289 			treescan(name, ino, addfile);
290 		}
291 		createfiles();
292 		createlinks();
293 		setdirmodes();
294 		if (dflag)
295 			checkrestore();
296 		done(0);
297 	}
298 }
299