Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / sbin / restore / main.c
blob95d8543c760ad9c6fc4089d11afa5b0999b4a78a
1 /* $NetBSD: main.c,v 1.32 2006/03/20 01:51:54 christos Exp $ */
3 /*
4 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved.
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. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 #ifndef lint
34 __COPYRIGHT("@(#) Copyright (c) 1983, 1993\
35 The Regents of the University of California. All rights reserved.");
36 #endif /* not lint */
38 #ifndef lint
39 #if 0
40 static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/4/95";
41 #else
42 __RCSID("$NetBSD: main.c,v 1.32 2006/03/20 01:51:54 christos Exp $");
43 #endif
44 #endif /* not lint */
46 #include <sys/param.h>
47 #include <sys/time.h>
49 #include <ufs/ufs/dinode.h>
50 #include <ufs/ffs/fs.h>
51 #include <protocols/dumprestore.h>
53 #include <err.h>
54 #include <errno.h>
55 #include <paths.h>
56 #include <signal.h>
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 #include <unistd.h>
62 #include "restore.h"
63 #include "extern.h"
65 int bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0;
66 int hflag = 1, mflag = 1, Dflag = 0, Nflag = 0;
67 char command = '\0';
68 int32_t dumpnum = 1;
69 int32_t volno = 0;
70 int32_t ntrec;
71 char *dumpmap;
72 char *usedinomap;
73 ino_t maxino;
74 time_t dumptime;
75 time_t dumpdate;
76 size_t pagesize;
77 FILE *terminal;
78 const char *tmpdir;
79 int dotflag = 0;
81 FILE *Mtreefile = NULL;
83 static void obsolete(int *, char **[]);
84 static void usage(void);
86 int
87 main(int argc, char *argv[])
89 int ch;
90 ino_t ino;
91 const char *inputdev;
92 const char *symtbl = "./restoresymtable";
93 char *p, name[MAXPATHLEN];
94 static char dot[] = ".";
96 if (argc < 2)
97 usage();
99 if ((inputdev = getenv("TAPE")) == NULL)
100 inputdev = _PATH_DEFTAPE;
101 if ((tmpdir = getenv("TMPDIR")) == NULL)
102 tmpdir = _PATH_TMP;
103 obsolete(&argc, &argv);
104 while ((ch = getopt(argc, argv, "b:cD:df:himM:NRrs:tuvxy")) != -1)
105 switch (ch) {
106 case 'b':
107 /* Change default tape blocksize. */
108 bflag = 1;
109 ntrec = strtol(optarg, &p, 10);
110 if (*p)
111 errx(1, "illegal blocksize -- %s", optarg);
112 if (ntrec <= 0)
113 errx(1, "block size must be greater than 0");
114 break;
115 case 'c':
116 cvtflag = 1;
117 break;
118 case 'D':
119 ddesc = digest_lookup(optarg);
120 if (ddesc == NULL)
121 err(1, "unknown digest algorithm: %s", optarg);
122 Dflag = 1;
123 break;
124 case 'd':
125 dflag = 1;
126 break;
127 case 'f':
128 inputdev = optarg;
129 break;
130 case 'h':
131 hflag = 0;
132 break;
133 case 'i':
134 case 'R':
135 case 'r':
136 case 't':
137 case 'x':
138 if (command != '\0')
139 errx(1,
140 "%c and %c options are mutually exclusive",
141 ch, command);
142 command = ch;
143 break;
144 case 'm':
145 mflag = 0;
146 break;
147 case 'N':
148 Nflag = 1;
149 break;
150 case 'M':
151 Mtreefile = fopen(optarg, "a");
152 if (Mtreefile == NULL)
153 err(1, "can't open %s", optarg);
154 break;
155 case 's':
156 /* Dumpnum (skip to) for multifile dump tapes. */
157 dumpnum = strtol(optarg, &p, 10);
158 if (*p)
159 errx(1, "illegal dump number -- %s", optarg);
160 if (dumpnum <= 0)
161 errx(1, "dump number must be greater than 0");
162 break;
163 case 'u':
164 uflag = 1;
165 break;
166 case 'v':
167 vflag = 1;
168 break;
169 case 'y':
170 yflag = 1;
171 break;
172 default:
173 usage();
175 argc -= optind;
176 argv += optind;
178 if (command == '\0')
179 errx(1, "none of i, R, r, t or x options specified");
181 if (Nflag || command == 't')
182 uflag = 0;
184 if (signal(SIGINT, onintr) == SIG_IGN)
185 (void) signal(SIGINT, SIG_IGN);
186 if (signal(SIGTERM, onintr) == SIG_IGN)
187 (void) signal(SIGTERM, SIG_IGN);
188 setlinebuf(stderr);
189 pagesize = sysconf(_SC_PAGESIZE);
191 atexit(cleanup);
193 setinput(inputdev);
195 if (argc == 0) {
196 argc = 1;
197 *--argv = dot;
200 switch (command) {
202 * Interactive mode.
204 case 'i':
205 setup();
206 extractdirs(1);
207 initsymtable(NULL);
208 runcmdshell();
209 break;
211 * Incremental restoration of a file system.
213 case 'r':
214 setup();
215 if (dumptime > 0) {
217 * This is an incremental dump tape.
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 {
229 * This is a level zero dump tape.
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);
237 createleaves(symtbl);
238 createlinks();
239 setdirmodes(FORCE);
240 checkrestore();
241 if (dflag) {
242 vprintf(stdout, "Verify the directory structure\n");
243 treescan(".", ROOTINO, verifyfile);
245 dumpsymtable(symtbl, (long)1);
246 break;
248 * Resume an incremental file system restoration.
250 case 'R':
251 initsymtable(symtbl);
252 skipmaps();
253 skipdirs();
254 createleaves(symtbl);
255 createlinks();
256 setdirmodes(FORCE);
257 checkrestore();
258 dumpsymtable(symtbl, (long)1);
259 break;
261 * List contents of tape.
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);
274 break;
276 * Batch extraction of tape contents.
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 (ino == ROOTINO)
288 dotflag = 1;
289 if (mflag)
290 pathcheck(name);
291 treescan(name, ino, addfile);
293 createfiles();
294 createlinks();
295 setdirmodes(0);
296 if (dflag)
297 checkrestore();
298 break;
300 exit(0);
301 /* NOTREACHED */
304 static void
305 usage(void)
307 const char *progname = getprogname();
309 (void)fprintf(stderr,
310 "usage: %s -i [-cdhmvyN] [-b bsize] [-D algorithm] "
311 "[-f file] [-M mtreefile] [-s fileno]\n", progname);
312 (void)fprintf(stderr,
313 " %s -R [-cdvyN] [-b bsize] [-D algorithm] [-f file] "
314 "[-M mtreefile] [-s fileno]\n", progname);
315 (void)fprintf(stderr,
316 " %s -r [-cdvyN] [-b bsize] [-D algorithm] [-f file] "
317 "[-M mtreefile] [-s fileno]\n", progname);
318 (void)fprintf(stderr,
319 " %s -t [-cdhvy] [-b bsize] [-D algorithm] [-f file]\n"
320 " [-s fileno] [file ...]\n", progname);
321 (void)fprintf(stderr,
322 " %s -x [-cdhmvyN] [-b bsize] [-D algorithm] [-f file]\n"
323 " [-M mtreefile] [-s fileno] [file ...]\n", progname);
324 exit(1);
328 * obsolete --
329 * Change set of key letters and ordered arguments into something
330 * getopt(3) will like.
332 static void
333 obsolete(int *argcp, char **argvp[])
335 int argc, flags;
336 char *ap, **argv, *flagsp, **nargv, *p;
338 /* Setup. */
339 argv = *argvp;
340 argc = *argcp;
342 /* Return if no arguments or first argument has leading dash. */
343 ap = argv[1];
344 if (argc == 1 || *ap == '-')
345 return;
347 /* Allocate space for new arguments. */
348 if ((*argvp = nargv = malloc((argc + 1) * sizeof(char *))) == NULL ||
349 (p = flagsp = malloc(strlen(ap) + 2)) == NULL)
350 err(1, NULL);
352 *nargv++ = *argv;
353 argv += 2;
355 for (flags = 0; *ap; ++ap) {
356 switch (*ap) {
357 case 'b':
358 case 'f':
359 case 's':
360 if (*argv == NULL) {
361 warnx("option requires an argument -- %c", *ap);
362 usage();
364 if ((nargv[0] = malloc(strlen(*argv) + 2 + 1)) == NULL)
365 err(1, NULL);
366 nargv[0][0] = '-';
367 nargv[0][1] = *ap;
368 (void)strcpy(&nargv[0][2], *argv);
369 ++argv;
370 ++nargv;
371 break;
372 default:
373 if (!flags) {
374 *p++ = '-';
375 flags = 1;
377 *p++ = *ap;
378 break;
382 /* Terminate flags. */
383 if (flags) {
384 *p = '\0';
385 *nargv++ = flagsp;
386 } else {
387 free(flagsp);
390 /* Copy remaining arguments. */
391 while ((*nargv++ = *argv++) != NULL)
394 /* Update argument count. */
395 *argcp = nargv - *argvp - 1;