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