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