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