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