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