1 /*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #ifndef lint
9 static char copyright[] =
10 "@(#) Copyright (c) 1983, 1993\n\
11 The Regents of the University of California. All rights reserved.\n";
12 #endif /* not lint */
13
14 #ifndef lint
15 static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 05/04/95";
16 #endif /* not lint */
17
18 #include <sys/param.h>
19 #include <sys/time.h>
20
21 #include <ufs/ufs/dinode.h>
22 #include <ufs/ffs/fs.h>
23 #include <protocols/dumprestore.h>
24
25 #include <err.h>
26 #include <errno.h>
27 #include <signal.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32
33 #include "pathnames.h"
34 #include "restore.h"
35 #include "extern.h"
36
37 int bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0;
38 int hflag = 1, mflag = 1, Nflag = 0;
39 char command = '\0';
40 long dumpnum = 1;
41 long volno = 0;
42 long ntrec;
43 char *dumpmap;
44 char *usedinomap;
45 ino_t maxino;
46 time_t dumptime;
47 time_t dumpdate;
48 FILE *terminal;
49
50 static void obsolete __P((int *, char **[]));
51 static void usage __P((void));
52
53 int
main(argc,argv)54 main(argc, argv)
55 int argc;
56 char *argv[];
57 {
58 int ch;
59 ino_t ino;
60 char *inputdev = _PATH_DEFTAPE;
61 char *symtbl = "./restoresymtable";
62 char *p, name[MAXPATHLEN];
63
64 if (argc < 2)
65 usage();
66
67 obsolete(&argc, &argv);
68 while ((ch = getopt(argc, argv, "b:cdf:himNRrs:tvxy")) != EOF)
69 switch(ch) {
70 case 'b':
71 /* Change default tape blocksize. */
72 bflag = 1;
73 ntrec = strtol(optarg, &p, 10);
74 if (*p)
75 errx(1, "illegal blocksize -- %s", optarg);
76 if (ntrec <= 0)
77 errx(1, "block size must be greater than 0");
78 break;
79 case 'c':
80 cvtflag = 1;
81 break;
82 case 'd':
83 dflag = 1;
84 break;
85 case 'f':
86 inputdev = optarg;
87 break;
88 case 'h':
89 hflag = 0;
90 break;
91 case 'i':
92 case 'R':
93 case 'r':
94 case 't':
95 case 'x':
96 if (command != '\0')
97 errx(1,
98 "%c and %c options are mutually exclusive",
99 ch, command);
100 command = ch;
101 break;
102 case 'm':
103 mflag = 0;
104 break;
105 case 'N':
106 Nflag = 1;
107 break;
108 case 's':
109 /* Dumpnum (skip to) for multifile dump tapes. */
110 dumpnum = strtol(optarg, &p, 10);
111 if (*p)
112 errx(1, "illegal dump number -- %s", optarg);
113 if (dumpnum <= 0)
114 errx(1, "dump number must be greater than 0");
115 break;
116 case 'v':
117 vflag = 1;
118 break;
119 case 'y':
120 yflag = 1;
121 break;
122 default:
123 usage();
124 }
125 argc -= optind;
126 argv += optind;
127
128 if (command == '\0')
129 errx(1, "none of i, R, r, t or x options specified");
130
131 if (signal(SIGINT, onintr) == SIG_IGN)
132 (void) signal(SIGINT, SIG_IGN);
133 if (signal(SIGTERM, onintr) == SIG_IGN)
134 (void) signal(SIGTERM, SIG_IGN);
135 setlinebuf(stderr);
136
137 setinput(inputdev);
138
139 if (argc == 0) {
140 argc = 1;
141 *--argv = ".";
142 }
143
144 switch (command) {
145 /*
146 * Interactive mode.
147 */
148 case 'i':
149 setup();
150 extractdirs(1);
151 initsymtable(NULL);
152 runcmdshell();
153 break;
154 /*
155 * Incremental restoration of a file system.
156 */
157 case 'r':
158 setup();
159 if (dumptime > 0) {
160 /*
161 * This is an incremental dump tape.
162 */
163 vprintf(stdout, "Begin incremental restore\n");
164 initsymtable(symtbl);
165 extractdirs(1);
166 removeoldleaves();
167 vprintf(stdout, "Calculate node updates.\n");
168 treescan(".", ROOTINO, nodeupdates);
169 findunreflinks();
170 removeoldnodes();
171 } else {
172 /*
173 * This is a level zero dump tape.
174 */
175 vprintf(stdout, "Begin level 0 restore\n");
176 initsymtable((char *)0);
177 extractdirs(1);
178 vprintf(stdout, "Calculate extraction list.\n");
179 treescan(".", ROOTINO, nodeupdates);
180 }
181 createleaves(symtbl);
182 createlinks();
183 setdirmodes(FORCE);
184 checkrestore();
185 if (dflag) {
186 vprintf(stdout, "Verify the directory structure\n");
187 treescan(".", ROOTINO, verifyfile);
188 }
189 dumpsymtable(symtbl, (long)1);
190 break;
191 /*
192 * Resume an incremental file system restoration.
193 */
194 case 'R':
195 initsymtable(symtbl);
196 skipmaps();
197 skipdirs();
198 createleaves(symtbl);
199 createlinks();
200 setdirmodes(FORCE);
201 checkrestore();
202 dumpsymtable(symtbl, (long)1);
203 break;
204 /*
205 * List contents of tape.
206 */
207 case 't':
208 setup();
209 extractdirs(0);
210 initsymtable((char *)0);
211 while (argc--) {
212 canon(*argv++, name);
213 ino = dirlookup(name);
214 if (ino == 0)
215 continue;
216 treescan(name, ino, listfile);
217 }
218 break;
219 /*
220 * Batch extraction of tape contents.
221 */
222 case 'x':
223 setup();
224 extractdirs(1);
225 initsymtable((char *)0);
226 while (argc--) {
227 canon(*argv++, name);
228 ino = dirlookup(name);
229 if (ino == 0)
230 continue;
231 if (mflag)
232 pathcheck(name);
233 treescan(name, ino, addfile);
234 }
235 createfiles();
236 createlinks();
237 setdirmodes(0);
238 if (dflag)
239 checkrestore();
240 break;
241 }
242 done(0);
243 /* NOTREACHED */
244 }
245
246 static void
usage()247 usage()
248 {
249 (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n",
250 "restore -i [-chmvy] [-b blocksize] [-f file] [-s fileno]",
251 "restore -r [-cvy] [-b blocksize] [-f file] [-s fileno]",
252 "restore -R [-cvy] [-b blocksize] [-f file] [-s fileno]",
253 "restore -x [-chmvy] [-b blocksize] [-f file] [-s fileno] [file ...]",
254 "restore -t [-chvy] [-b blocksize] [-f file] [-s fileno] [file ...]");
255 done(1);
256 }
257
258 /*
259 * obsolete --
260 * Change set of key letters and ordered arguments into something
261 * getopt(3) will like.
262 */
263 static void
obsolete(argcp,argvp)264 obsolete(argcp, argvp)
265 int *argcp;
266 char **argvp[];
267 {
268 int argc, flags;
269 char *ap, **argv, *flagsp, **nargv, *p;
270
271 /* Setup. */
272 argv = *argvp;
273 argc = *argcp;
274
275 /* Return if no arguments or first argument has leading dash. */
276 ap = argv[1];
277 if (argc == 1 || *ap == '-')
278 return;
279
280 /* Allocate space for new arguments. */
281 if ((*argvp = nargv = malloc((argc + 1) * sizeof(char *))) == NULL ||
282 (p = flagsp = malloc(strlen(ap) + 2)) == NULL)
283 err(1, NULL);
284
285 *nargv++ = *argv;
286 argv += 2;
287
288 for (flags = 0; *ap; ++ap) {
289 switch (*ap) {
290 case 'b':
291 case 'f':
292 case 's':
293 if (*argv == NULL) {
294 warnx("option requires an argument -- %c", *ap);
295 usage();
296 }
297 if ((nargv[0] = malloc(strlen(*argv) + 2 + 1)) == NULL)
298 err(1, NULL);
299 nargv[0][0] = '-';
300 nargv[0][1] = *ap;
301 (void)strcpy(&nargv[0][2], *argv);
302 ++argv;
303 ++nargv;
304 break;
305 default:
306 if (!flags) {
307 *p++ = '-';
308 flags = 1;
309 }
310 *p++ = *ap;
311 break;
312 }
313 }
314
315 /* Terminate flags. */
316 if (flags) {
317 *p = '\0';
318 *nargv++ = flagsp;
319 }
320
321 /* Copy remaining arguments. */
322 while (*nargv++ = *argv++);
323
324 /* Update argument count. */
325 *argcp = nargv - *argvp - 1;
326 }
327