main.c revision 1.21 1 /* $NetBSD: main.c,v 1.21 2001/02/19 22:56:22 cgd Exp $ */
2
3 /*
4 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #include <sys/cdefs.h>
37 #ifndef lint
38 __COPYRIGHT("@(#) Copyright (c) 1983, 1993\n\
39 The Regents of the University of California. All rights reserved.\n");
40 #endif /* not lint */
41
42 #ifndef lint
43 #if 0
44 static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/4/95";
45 #else
46 __RCSID("$NetBSD: main.c,v 1.21 2001/02/19 22:56:22 cgd Exp $");
47 #endif
48 #endif /* not lint */
49
50 #include <sys/param.h>
51 #include <sys/time.h>
52
53 #include <ufs/ufs/dinode.h>
54 #include <ufs/ffs/fs.h>
55 #include <protocols/dumprestore.h>
56
57 #include <err.h>
58 #include <errno.h>
59 #include <paths.h>
60 #include <signal.h>
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <string.h>
64 #include <unistd.h>
65
66 #include "restore.h"
67 #include "extern.h"
68
69 int bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0;
70 int hflag = 1, mflag = 1, Nflag = 0;
71 char command = '\0';
72 int32_t dumpnum = 1;
73 int32_t volno = 0;
74 int32_t ntrec;
75 char *dumpmap;
76 char *usedinomap;
77 ino_t maxino;
78 time_t dumptime;
79 time_t dumpdate;
80 FILE *terminal;
81 char *tmpdir;
82
83 int main __P((int, char *[]));
84 static void obsolete __P((int *, char **[]));
85 static void usage __P((void));
86
87 int
88 main(argc, argv)
89 int argc;
90 char *argv[];
91 {
92 int ch;
93 ino_t ino;
94 char *inputdev;
95 char *symtbl = "./restoresymtable";
96 char *p, name[MAXPATHLEN];
97
98 if (argc < 2)
99 usage();
100
101 if ((inputdev = getenv("TAPE")) == NULL)
102 inputdev = _PATH_DEFTAPE;
103 if ((tmpdir = getenv("TMPDIR")) == NULL)
104 tmpdir = _PATH_TMP;
105 obsolete(&argc, &argv);
106 while ((ch = getopt(argc, argv, "b:cdf:himNRrs:tuvxy")) != -1)
107 switch(ch) {
108 case 'b':
109 /* Change default tape blocksize. */
110 bflag = 1;
111 ntrec = strtol(optarg, &p, 10);
112 if (*p)
113 errx(1, "illegal blocksize -- %s", optarg);
114 if (ntrec <= 0)
115 errx(1, "block size must be greater than 0");
116 break;
117 case 'c':
118 cvtflag = 1;
119 break;
120 case 'd':
121 dflag = 1;
122 break;
123 case 'f':
124 inputdev = optarg;
125 break;
126 case 'h':
127 hflag = 0;
128 break;
129 case 'i':
130 case 'R':
131 case 'r':
132 case 't':
133 case 'x':
134 if (command != '\0')
135 errx(1,
136 "%c and %c options are mutually exclusive",
137 ch, command);
138 command = ch;
139 break;
140 case 'm':
141 mflag = 0;
142 break;
143 case 'N':
144 Nflag = 1;
145 break;
146 case 's':
147 /* Dumpnum (skip to) for multifile dump tapes. */
148 dumpnum = strtol(optarg, &p, 10);
149 if (*p)
150 errx(1, "illegal dump number -- %s", optarg);
151 if (dumpnum <= 0)
152 errx(1, "dump number must be greater than 0");
153 break;
154 case 'u':
155 uflag = 1;
156 break;
157 case 'v':
158 vflag = 1;
159 break;
160 case 'y':
161 yflag = 1;
162 break;
163 default:
164 usage();
165 }
166 argc -= optind;
167 argv += optind;
168
169 if (command == '\0')
170 errx(1, "none of i, R, r, t or x options specified");
171
172 if (Nflag || command == 't')
173 uflag = 0;
174
175 if (signal(SIGINT, onintr) == SIG_IGN)
176 (void) signal(SIGINT, SIG_IGN);
177 if (signal(SIGTERM, onintr) == SIG_IGN)
178 (void) signal(SIGTERM, SIG_IGN);
179 setlinebuf(stderr);
180
181 atexit(cleanup);
182
183 setinput(inputdev);
184
185 if (argc == 0) {
186 argc = 1;
187 *--argv = ".";
188 }
189
190 switch (command) {
191 /*
192 * Interactive mode.
193 */
194 case 'i':
195 setup();
196 extractdirs(1);
197 initsymtable(NULL);
198 runcmdshell();
199 break;
200 /*
201 * Incremental restoration of a file system.
202 */
203 case 'r':
204 setup();
205 if (dumptime > 0) {
206 /*
207 * This is an incremental dump tape.
208 */
209 vprintf(stdout, "Begin incremental restore\n");
210 initsymtable(symtbl);
211 extractdirs(1);
212 removeoldleaves();
213 vprintf(stdout, "Calculate node updates.\n");
214 treescan(".", ROOTINO, nodeupdates);
215 findunreflinks();
216 removeoldnodes();
217 } else {
218 /*
219 * This is a level zero dump tape.
220 */
221 vprintf(stdout, "Begin level 0 restore\n");
222 initsymtable((char *)0);
223 extractdirs(1);
224 vprintf(stdout, "Calculate extraction list.\n");
225 treescan(".", ROOTINO, nodeupdates);
226 }
227 createleaves(symtbl);
228 createlinks();
229 setdirmodes(FORCE);
230 checkrestore();
231 if (dflag) {
232 vprintf(stdout, "Verify the directory structure\n");
233 treescan(".", ROOTINO, verifyfile);
234 }
235 dumpsymtable(symtbl, (long)1);
236 break;
237 /*
238 * Resume an incremental file system restoration.
239 */
240 case 'R':
241 initsymtable(symtbl);
242 skipmaps();
243 skipdirs();
244 createleaves(symtbl);
245 createlinks();
246 setdirmodes(FORCE);
247 checkrestore();
248 dumpsymtable(symtbl, (long)1);
249 break;
250 /*
251 * List contents of tape.
252 */
253 case 't':
254 setup();
255 extractdirs(0);
256 initsymtable((char *)0);
257 while (argc--) {
258 canon(*argv++, name);
259 ino = dirlookup(name);
260 if (ino == 0)
261 continue;
262 treescan(name, ino, listfile);
263 }
264 break;
265 /*
266 * Batch extraction of tape contents.
267 */
268 case 'x':
269 setup();
270 extractdirs(1);
271 initsymtable((char *)0);
272 while (argc--) {
273 canon(*argv++, name);
274 ino = dirlookup(name);
275 if (ino == 0)
276 continue;
277 if (mflag)
278 pathcheck(name);
279 treescan(name, ino, addfile);
280 }
281 createfiles();
282 createlinks();
283 setdirmodes(0);
284 if (dflag)
285 checkrestore();
286 break;
287 }
288 exit(0);
289 /* NOTREACHED */
290 }
291
292 static void
293 usage()
294 {
295 const char *progname = getprogname();
296
297 (void)fprintf(stderr,
298 "usage: %s -i [-cdhmvyN] [-b blocksize] [-f file] [-s fileno]\n",
299 progname);
300 (void)fprintf(stderr,
301 "\t%s -R [-cdvyN] [-b blocksize] [-f file] [-s fileno]\n",
302 progname);
303 (void)fprintf(stderr,
304 "\t%s -r [-cdvyN] [-b blocksize] [-f file] [-s fileno]\n",
305 progname);
306 (void)fprintf(stderr,
307 "\t%s -t [-cdhvy] [-b blocksize] [-f file] [-s fileno] [file ...]\n",
308 progname);
309 (void)fprintf(stderr,
310 "\t%s -x [-cdhmvyN] [-b blocksize] [-f file] [-s fileno] [file ...]\n",
311 progname);
312 exit(1);
313 }
314
315 /*
316 * obsolete --
317 * Change set of key letters and ordered arguments into something
318 * getopt(3) will like.
319 */
320 static void
321 obsolete(argcp, argvp)
322 int *argcp;
323 char **argvp[];
324 {
325 int argc, flags;
326 char *ap, **argv, *flagsp, **nargv, *p;
327
328 /* Setup. */
329 argv = *argvp;
330 argc = *argcp;
331
332 /* Return if no arguments or first argument has leading dash. */
333 ap = argv[1];
334 if (argc == 1 || *ap == '-')
335 return;
336
337 /* Allocate space for new arguments. */
338 if ((*argvp = nargv = malloc((argc + 1) * sizeof(char *))) == NULL ||
339 (p = flagsp = malloc(strlen(ap) + 2)) == NULL)
340 err(1, NULL);
341
342 *nargv++ = *argv;
343 argv += 2;
344
345 for (flags = 0; *ap; ++ap) {
346 switch (*ap) {
347 case 'b':
348 case 'f':
349 case 's':
350 if (*argv == NULL) {
351 warnx("option requires an argument -- %c", *ap);
352 usage();
353 }
354 if ((nargv[0] = malloc(strlen(*argv) + 2 + 1)) == NULL)
355 err(1, NULL);
356 nargv[0][0] = '-';
357 nargv[0][1] = *ap;
358 (void)strcpy(&nargv[0][2], *argv);
359 ++argv;
360 ++nargv;
361 break;
362 default:
363 if (!flags) {
364 *p++ = '-';
365 flags = 1;
366 }
367 *p++ = *ap;
368 break;
369 }
370 }
371
372 /* Terminate flags. */
373 if (flags) {
374 *p = '\0';
375 *nargv++ = flagsp;
376 }
377
378 /* Copy remaining arguments. */
379 while ((*nargv++ = *argv++) != NULL)
380 ;
381
382 /* Update argument count. */
383 *argcp = nargv - *argvp - 1;
384 }
385