]> git.wh0rd.org - dump.git/blob - restore/main.c
7460d7dd3903075bcff685e49565a4f9e7e0c739
[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.4 1999/10/11 13:08:09 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 <compaterr.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 char *tmpdir;
99 int compare_ignore_not_found;
100 char *filesys = NULL;
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(int argc, char *argv[])
111 {
112 int ch;
113 ino_t ino;
114 char *inputdev = _PATH_DEFTAPE;
115 char *symtbl = "./restoresymtable";
116 char *p, name[MAXPATHLEN];
117
118 /* Temp files should *not* be readable. We set permissions later. */
119 (void) umask(077);
120
121 #ifdef __linux__
122 __progname = argv[0];
123 #endif
124
125 if (argc < 2)
126 usage();
127
128 if ((inputdev = getenv("TAPE")) == NULL)
129 inputdev = _PATH_DEFTAPE;
130 if ((tmpdir = getenv("TMPDIR")) == NULL)
131 tmpdir = _PATH_TMP;
132 if ((tmpdir = strdup(tmpdir)) == NULL)
133 err(1, "malloc tmpdir");
134 for (p = tmpdir + strlen(tmpdir) - 1; p >= tmpdir && *p == '/'; p--)
135 ;
136 obsolete(&argc, &argv);
137 #ifdef KERBEROS
138 #define optlist "b:CcdD:f:hikmNRrs:tT:uvxy"
139 #else
140 #define optlist "b:CcdD:f:himNRrs:tT:uvxy"
141 #endif
142 while ((ch = getopt(argc, argv, optlist)) != -1)
143 switch(ch) {
144 case 'b':
145 /* Change default tape blocksize. */
146 bflag = 1;
147 ntrec = strtol(optarg, &p, 10);
148 if (*p)
149 errx(1, "illegal blocksize -- %s", optarg);
150 if (ntrec <= 0)
151 errx(1, "block size must be greater than 0");
152 break;
153 case 'c':
154 cvtflag = 1;
155 break;
156 case 'D':
157 filesys = optarg;
158 break;
159 case 'T':
160 tmpdir = optarg;
161 break;
162 case 'd':
163 dflag = 1;
164 break;
165 case 'f':
166 inputdev = optarg;
167 break;
168 case 'h':
169 hflag = 0;
170 break;
171 #ifdef KERBEROS
172 case 'k':
173 dokerberos = 1;
174 break;
175 #endif
176 case 'C':
177 case 'i':
178 case 'R':
179 case 'r':
180 case 't':
181 case 'x':
182 if (command != '\0')
183 errx(1,
184 "%c and %c options are mutually exclusive",
185 ch, command);
186 command = ch;
187 break;
188 case 'm':
189 mflag = 0;
190 break;
191 case 'N':
192 Nflag = 1;
193 break;
194 case 's':
195 /* Dumpnum (skip to) for multifile dump tapes. */
196 dumpnum = strtol(optarg, &p, 10);
197 if (*p)
198 errx(1, "illegal dump number -- %s", optarg);
199 if (dumpnum <= 0)
200 errx(1, "dump number must be greater than 0");
201 break;
202 case 'u':
203 uflag = 1;
204 break;
205 case 'v':
206 vflag = 1;
207 break;
208 case 'y':
209 yflag = 1;
210 break;
211 default:
212 usage();
213 }
214 argc -= optind;
215 argv += optind;
216
217 if (command == '\0')
218 errx(1, "none of C, i, R, r, t or x options specified");
219
220 if (signal(SIGINT, onintr) == SIG_IGN)
221 (void) signal(SIGINT, SIG_IGN);
222 if (signal(SIGTERM, onintr) == SIG_IGN)
223 (void) signal(SIGTERM, SIG_IGN);
224 setlinebuf(stderr);
225
226 atexit(cleanup);
227
228 setinput(inputdev);
229
230 if (argc == 0) {
231 argc = 1;
232 *--argv = ".";
233 }
234
235 switch (command) {
236 /*
237 * Compare contents of tape.
238 */
239 case 'C': {
240 struct stat stbuf;
241
242 Vprintf(stdout, "Begin compare restore\n");
243 compare_ignore_not_found = 0;
244 setup();
245 printf("filesys = %s\n", filesys);
246 if (stat(filesys, &stbuf) < 0)
247 err(1, "cannot stat directory %s", filesys);
248 if (chdir(filesys) < 0)
249 err(1, "cannot cd to %s", filesys);
250 compare_ignore_not_found = dumptime > 0;
251 initsymtable((char *)0);
252 extractdirs(0);
253 treescan(".", ROOTINO, nodeupdates);
254 compareleaves();
255 checkrestore();
256 break;
257 }
258
259 /*
260 * Interactive mode.
261 */
262 case 'i':
263 setup();
264 extractdirs(1);
265 initsymtable(NULL);
266 runcmdshell();
267 break;
268 /*
269 * Incremental restoration of a file system.
270 */
271 case 'r':
272 setup();
273 if (dumptime > 0) {
274 /*
275 * This is an incremental dump tape.
276 */
277 Vprintf(stdout, "Begin incremental restore\n");
278 initsymtable(symtbl);
279 extractdirs(1);
280 removeoldleaves();
281 Vprintf(stdout, "Calculate node updates.\n");
282 treescan(".", ROOTINO, nodeupdates);
283 findunreflinks();
284 removeoldnodes();
285 } else {
286 /*
287 * This is a level zero dump tape.
288 */
289 Vprintf(stdout, "Begin level 0 restore\n");
290 initsymtable((char *)0);
291 extractdirs(1);
292 Vprintf(stdout, "Calculate extraction list.\n");
293 treescan(".", ROOTINO, nodeupdates);
294 }
295 createleaves(symtbl);
296 createlinks();
297 setdirmodes(FORCE);
298 checkrestore();
299 if (dflag) {
300 Vprintf(stdout, "Verify the directory structure\n");
301 treescan(".", ROOTINO, verifyfile);
302 }
303 dumpsymtable(symtbl, (long)1);
304 break;
305 /*
306 * Resume an incremental file system restoration.
307 */
308 case 'R':
309 initsymtable(symtbl);
310 skipmaps();
311 skipdirs();
312 createleaves(symtbl);
313 createlinks();
314 setdirmodes(FORCE);
315 checkrestore();
316 dumpsymtable(symtbl, (long)1);
317 break;
318 /*
319 * List contents of tape.
320 */
321 case 't':
322 setup();
323 extractdirs(0);
324 initsymtable((char *)0);
325 while (argc--) {
326 canon(*argv++, name, sizeof(name));
327 ino = dirlookup(name);
328 if (ino == 0)
329 continue;
330 treescan(name, ino, listfile);
331 }
332 break;
333 /*
334 * Batch extraction of tape contents.
335 */
336 case 'x':
337 setup();
338 extractdirs(1);
339 initsymtable((char *)0);
340 while (argc--) {
341 canon(*argv++, name, sizeof(name));
342 ino = dirlookup(name);
343 if (ino == 0)
344 continue;
345 if (mflag)
346 pathcheck(name);
347 treescan(name, ino, addfile);
348 }
349 createfiles();
350 createlinks();
351 setdirmodes(0);
352 if (dflag)
353 checkrestore();
354 break;
355 }
356 exit(0);
357 /* NOTREACHED */
358 return 0; /* gcc shut up */
359 }
360
361 static void
362 usage(void)
363 {
364 #ifdef KERBEROS
365 #define kerbflag "k"
366 #else
367 #define kerbflag
368 #endif
369 (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n",
370 "restore -i [-ch" kerbflag "muvy] [-b blocksize] [-f file] [-s fileno]",
371 "restore -r [-c" kerbflag "uvy] [-b blocksize] [-f file] [-s fileno]",
372 "restore -R [-c" kerbflag "uvy] [-b blocksize] [-f file] [-s fileno]",
373 "restore -x [-ch" kerbflag "muvy] [-b blocksize] [-f file] [-s fileno] [file ...]",
374 "restore -t [-ch" kerbflag "kuvy] [-b blocksize] [-f file] [-s fileno] [file ...]");
375 exit(1);
376 }
377
378 /*
379 * obsolete --
380 * Change set of key letters and ordered arguments into something
381 * getopt(3) will like.
382 */
383 static void
384 obsolete(int *argcp, char **argvp[])
385 {
386 int argc, flags;
387 char *ap, **argv, *flagsp = NULL, **nargv, *p = NULL;
388
389 /* Setup. */
390 argv = *argvp;
391 argc = *argcp;
392
393 /* Return if no arguments or first argument has leading dash. */
394 ap = argv[1];
395 if (argc == 1 || *ap == '-')
396 return;
397
398 /* Allocate space for new arguments. */
399 if ((*argvp = nargv = malloc((argc + 1) * sizeof(char *))) == NULL ||
400 (p = flagsp = malloc(strlen(ap) + 2)) == NULL)
401 err(1, "malloc args");
402
403 *nargv++ = *argv;
404 argv += 2, argc -= 2;
405
406 for (flags = 0; *ap; ++ap) {
407 switch (*ap) {
408 case 'b':
409 case 'f':
410 case 's':
411 if (*argv == NULL) {
412 warnx("option requires an argument -- %c", *ap);
413 usage();
414 }
415 if ((nargv[0] = malloc(strlen(*argv) + 2 + 1)) == NULL)
416 err(1, "malloc arg");
417 nargv[0][0] = '-';
418 nargv[0][1] = *ap;
419 (void)strcpy(&nargv[0][2], *argv);
420 ++argv;
421 ++nargv;
422 break;
423 default:
424 if (!flags) {
425 *p++ = '-';
426 flags = 1;
427 }
428 *p++ = *ap;
429 break;
430 }
431 }
432
433 /* Terminate flags. */
434 if (flags) {
435 *p = '\0';
436 *nargv++ = flagsp;
437 }
438
439 /* Copy remaining arguments. */
440 while ((*nargv++ = *argv++));
441
442 /* Update argument count. */
443 *argcp = nargv - *argvp - 1;
444 }