1*8a16b7a1SPedro F. Giffuni /*- 2*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 3*8a16b7a1SPedro F. Giffuni * 48fae3551SRodney W. Grimes * Copyright (c) 1983, 1993 58fae3551SRodney W. Grimes * The Regents of the University of California. All rights reserved. 68fae3551SRodney W. Grimes * 78fae3551SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 88fae3551SRodney W. Grimes * modification, are permitted provided that the following conditions 98fae3551SRodney W. Grimes * are met: 108fae3551SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 118fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 128fae3551SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 138fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 148fae3551SRodney W. Grimes * documentation and/or other materials provided with the distribution. 15fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 168fae3551SRodney W. Grimes * may be used to endorse or promote products derived from this software 178fae3551SRodney W. Grimes * without specific prior written permission. 188fae3551SRodney W. Grimes * 198fae3551SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 208fae3551SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 218fae3551SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 228fae3551SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 238fae3551SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 248fae3551SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 258fae3551SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 268fae3551SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 278fae3551SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 288fae3551SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 298fae3551SRodney W. Grimes * SUCH DAMAGE. 308fae3551SRodney W. Grimes */ 318fae3551SRodney W. Grimes 328fae3551SRodney W. Grimes #ifndef lint 3391ac32e4SPhilippe Charnier static const char copyright[] = 348fae3551SRodney W. Grimes "@(#) Copyright (c) 1983, 1993\n\ 358fae3551SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 368fae3551SRodney W. Grimes #endif /* not lint */ 378fae3551SRodney W. Grimes 388fae3551SRodney W. Grimes #ifndef lint 3991ac32e4SPhilippe Charnier #if 0 40d87d79aeSPeter Wemm static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/4/95"; 4191ac32e4SPhilippe Charnier #endif 428fae3551SRodney W. Grimes #endif /* not lint */ 438fae3551SRodney W. Grimes 4435a974fdSPhilippe Charnier #include <sys/cdefs.h> 4535a974fdSPhilippe Charnier __FBSDID("$FreeBSD$"); 4635a974fdSPhilippe Charnier 478fae3551SRodney W. Grimes #include <sys/param.h> 4891ac32e4SPhilippe Charnier #include <sys/stat.h> 498fae3551SRodney W. Grimes 508fae3551SRodney W. Grimes #include <ufs/ufs/dinode.h> 518fae3551SRodney W. Grimes #include <protocols/dumprestore.h> 528fae3551SRodney W. Grimes 538fae3551SRodney W. Grimes #include <err.h> 5489fdc4e1SMike Barcroft #include <limits.h> 550407880fSAndrey A. Chernov #include <locale.h> 568454c72cSDavid E. O'Brien #include <paths.h> 578fae3551SRodney W. Grimes #include <stdio.h> 588fae3551SRodney W. Grimes #include <stdlib.h> 59cafefe8cSDima Dorfman #include <string.h> 60d87d79aeSPeter Wemm #include <unistd.h> 618fae3551SRodney W. Grimes 628fae3551SRodney W. Grimes #include "restore.h" 638fae3551SRodney W. Grimes #include "extern.h" 648fae3551SRodney W. Grimes 65cbc8bb98SDavid Malone int bflag = 0, cvtflag = 0, dflag = 0, Dflag = 0, vflag = 0, yflag = 0; 668fae3551SRodney W. Grimes int hflag = 1, mflag = 1, Nflag = 0; 6726408404SJordan K. Hubbard int uflag = 0; 68c51d70c6SBrian Feldman int pipecmd = 0; 698fae3551SRodney W. Grimes char command = '\0'; 708fae3551SRodney W. Grimes long dumpnum = 1; 718fae3551SRodney W. Grimes long volno = 0; 728fae3551SRodney W. Grimes long ntrec; 738fae3551SRodney W. Grimes char *dumpmap; 74d87d79aeSPeter Wemm char *usedinomap; 758fae3551SRodney W. Grimes ino_t maxino; 768fae3551SRodney W. Grimes time_t dumptime; 778fae3551SRodney W. Grimes time_t dumpdate; 788fae3551SRodney W. Grimes FILE *terminal; 798fae3551SRodney W. Grimes 802db673abSWarner Losh static void obsolete(int *, char **[]); 812db673abSWarner Losh static void usage(void) __dead2; 828fae3551SRodney W. Grimes 838fae3551SRodney W. Grimes int 842db673abSWarner Losh main(int argc, char *argv[]) 858fae3551SRodney W. Grimes { 868fae3551SRodney W. Grimes int ch; 878fae3551SRodney W. Grimes ino_t ino; 88335524b9SWarner Losh char *inputdev; 898fae3551SRodney W. Grimes char *symtbl = "./restoresymtable"; 908fae3551SRodney W. Grimes char *p, name[MAXPATHLEN]; 918fae3551SRodney W. Grimes 92335524b9SWarner Losh /* Temp files should *not* be readable. We set permissions later. */ 93335524b9SWarner Losh (void) umask(077); 94335524b9SWarner Losh 958fae3551SRodney W. Grimes if (argc < 2) 968fae3551SRodney W. Grimes usage(); 978fae3551SRodney W. Grimes 980407880fSAndrey A. Chernov (void)setlocale(LC_ALL, ""); 990407880fSAndrey A. Chernov 100c51d70c6SBrian Feldman inputdev = NULL; 1018fae3551SRodney W. Grimes obsolete(&argc, &argv); 102cbc8bb98SDavid Malone while ((ch = getopt(argc, argv, "b:dDf:himNP:Rrs:tuvxy")) != -1) 1038fae3551SRodney W. Grimes switch(ch) { 1048fae3551SRodney W. Grimes case 'b': 1058fae3551SRodney W. Grimes /* Change default tape blocksize. */ 1068fae3551SRodney W. Grimes bflag = 1; 1078fae3551SRodney W. Grimes ntrec = strtol(optarg, &p, 10); 1088fae3551SRodney W. Grimes if (*p) 1098fae3551SRodney W. Grimes errx(1, "illegal blocksize -- %s", optarg); 1108fae3551SRodney W. Grimes if (ntrec <= 0) 1118fae3551SRodney W. Grimes errx(1, "block size must be greater than 0"); 1128fae3551SRodney W. Grimes break; 1138fae3551SRodney W. Grimes case 'd': 1148fae3551SRodney W. Grimes dflag = 1; 1158fae3551SRodney W. Grimes break; 116cbc8bb98SDavid Malone case 'D': 117cbc8bb98SDavid Malone Dflag = 1; 118cbc8bb98SDavid Malone break; 1198fae3551SRodney W. Grimes case 'f': 120c51d70c6SBrian Feldman if (pipecmd) 121c51d70c6SBrian Feldman errx(1, 122c51d70c6SBrian Feldman "-P and -f options are mutually exclusive"); 1238fae3551SRodney W. Grimes inputdev = optarg; 1248fae3551SRodney W. Grimes break; 125c51d70c6SBrian Feldman case 'P': 126c51d70c6SBrian Feldman if (!pipecmd && inputdev) 127c51d70c6SBrian Feldman errx(1, 128c51d70c6SBrian Feldman "-P and -f options are mutually exclusive"); 129c51d70c6SBrian Feldman inputdev = optarg; 130c51d70c6SBrian Feldman pipecmd = 1; 131c51d70c6SBrian Feldman break; 1328fae3551SRodney W. Grimes case 'h': 1338fae3551SRodney W. Grimes hflag = 0; 1348fae3551SRodney W. Grimes break; 1358fae3551SRodney W. Grimes case 'i': 1368fae3551SRodney W. Grimes case 'R': 1378fae3551SRodney W. Grimes case 'r': 1388fae3551SRodney W. Grimes case 't': 1398fae3551SRodney W. Grimes case 'x': 1408fae3551SRodney W. Grimes if (command != '\0') 1418fae3551SRodney W. Grimes errx(1, 1428fae3551SRodney W. Grimes "%c and %c options are mutually exclusive", 1438fae3551SRodney W. Grimes ch, command); 1448fae3551SRodney W. Grimes command = ch; 1458fae3551SRodney W. Grimes break; 1468fae3551SRodney W. Grimes case 'm': 1478fae3551SRodney W. Grimes mflag = 0; 1488fae3551SRodney W. Grimes break; 1498fae3551SRodney W. Grimes case 'N': 1508fae3551SRodney W. Grimes Nflag = 1; 1518fae3551SRodney W. Grimes break; 1528fae3551SRodney W. Grimes case 's': 1538fae3551SRodney W. Grimes /* Dumpnum (skip to) for multifile dump tapes. */ 1548fae3551SRodney W. Grimes dumpnum = strtol(optarg, &p, 10); 1558fae3551SRodney W. Grimes if (*p) 1568fae3551SRodney W. Grimes errx(1, "illegal dump number -- %s", optarg); 1578fae3551SRodney W. Grimes if (dumpnum <= 0) 1588fae3551SRodney W. Grimes errx(1, "dump number must be greater than 0"); 1598fae3551SRodney W. Grimes break; 16026408404SJordan K. Hubbard case 'u': 16126408404SJordan K. Hubbard uflag = 1; 16226408404SJordan K. Hubbard break; 1638fae3551SRodney W. Grimes case 'v': 1648fae3551SRodney W. Grimes vflag = 1; 1658fae3551SRodney W. Grimes break; 1668fae3551SRodney W. Grimes case 'y': 1678fae3551SRodney W. Grimes yflag = 1; 1688fae3551SRodney W. Grimes break; 1698fae3551SRodney W. Grimes default: 1708fae3551SRodney W. Grimes usage(); 1718fae3551SRodney W. Grimes } 1728fae3551SRodney W. Grimes argc -= optind; 1738fae3551SRodney W. Grimes argv += optind; 1748fae3551SRodney W. Grimes 1758fae3551SRodney W. Grimes if (command == '\0') 1768fae3551SRodney W. Grimes errx(1, "none of i, R, r, t or x options specified"); 1778fae3551SRodney W. Grimes 1788fae3551SRodney W. Grimes if (signal(SIGINT, onintr) == SIG_IGN) 1798fae3551SRodney W. Grimes (void) signal(SIGINT, SIG_IGN); 1808fae3551SRodney W. Grimes if (signal(SIGTERM, onintr) == SIG_IGN) 1818fae3551SRodney W. Grimes (void) signal(SIGTERM, SIG_IGN); 1828fae3551SRodney W. Grimes setlinebuf(stderr); 1838fae3551SRodney W. Grimes 184c51d70c6SBrian Feldman if (inputdev == NULL && (inputdev = getenv("TAPE")) == NULL) 185c51d70c6SBrian Feldman inputdev = _PATH_DEFTAPE; 186c51d70c6SBrian Feldman setinput(inputdev, pipecmd); 1878fae3551SRodney W. Grimes 1888fae3551SRodney W. Grimes if (argc == 0) { 1898fae3551SRodney W. Grimes argc = 1; 1908fae3551SRodney W. Grimes *--argv = "."; 1918fae3551SRodney W. Grimes } 1928fae3551SRodney W. Grimes 1938fae3551SRodney W. Grimes switch (command) { 1948fae3551SRodney W. Grimes /* 1958fae3551SRodney W. Grimes * Interactive mode. 1968fae3551SRodney W. Grimes */ 1978fae3551SRodney W. Grimes case 'i': 1988fae3551SRodney W. Grimes setup(); 1998fae3551SRodney W. Grimes extractdirs(1); 2008fae3551SRodney W. Grimes initsymtable(NULL); 2018fae3551SRodney W. Grimes runcmdshell(); 2028fae3551SRodney W. Grimes break; 2038fae3551SRodney W. Grimes /* 2048fae3551SRodney W. Grimes * Incremental restoration of a file system. 2058fae3551SRodney W. Grimes */ 2068fae3551SRodney W. Grimes case 'r': 2078fae3551SRodney W. Grimes setup(); 2088fae3551SRodney W. Grimes if (dumptime > 0) { 2098fae3551SRodney W. Grimes /* 2108fae3551SRodney W. Grimes * This is an incremental dump tape. 2118fae3551SRodney W. Grimes */ 2128fae3551SRodney W. Grimes vprintf(stdout, "Begin incremental restore\n"); 2138fae3551SRodney W. Grimes initsymtable(symtbl); 2148fae3551SRodney W. Grimes extractdirs(1); 2158fae3551SRodney W. Grimes removeoldleaves(); 2168fae3551SRodney W. Grimes vprintf(stdout, "Calculate node updates.\n"); 2171dc349abSEd Maste treescan(".", UFS_ROOTINO, nodeupdates); 2188fae3551SRodney W. Grimes findunreflinks(); 2198fae3551SRodney W. Grimes removeoldnodes(); 2208fae3551SRodney W. Grimes } else { 2218fae3551SRodney W. Grimes /* 2228fae3551SRodney W. Grimes * This is a level zero dump tape. 2238fae3551SRodney W. Grimes */ 2248fae3551SRodney W. Grimes vprintf(stdout, "Begin level 0 restore\n"); 2258fae3551SRodney W. Grimes initsymtable((char *)0); 2268fae3551SRodney W. Grimes extractdirs(1); 2278fae3551SRodney W. Grimes vprintf(stdout, "Calculate extraction list.\n"); 2281dc349abSEd Maste treescan(".", UFS_ROOTINO, nodeupdates); 2298fae3551SRodney W. Grimes } 2308fae3551SRodney W. Grimes createleaves(symtbl); 2318fae3551SRodney W. Grimes createlinks(); 2328fae3551SRodney W. Grimes setdirmodes(FORCE); 2338fae3551SRodney W. Grimes checkrestore(); 2348fae3551SRodney W. Grimes if (dflag) { 2358fae3551SRodney W. Grimes vprintf(stdout, "Verify the directory structure\n"); 2361dc349abSEd Maste treescan(".", UFS_ROOTINO, verifyfile); 2378fae3551SRodney W. Grimes } 2388fae3551SRodney W. Grimes dumpsymtable(symtbl, (long)1); 2398fae3551SRodney W. Grimes break; 2408fae3551SRodney W. Grimes /* 2418fae3551SRodney W. Grimes * Resume an incremental file system restoration. 2428fae3551SRodney W. Grimes */ 2438fae3551SRodney W. Grimes case 'R': 2448fae3551SRodney W. Grimes initsymtable(symtbl); 2458fae3551SRodney W. Grimes skipmaps(); 2468fae3551SRodney W. Grimes skipdirs(); 2478fae3551SRodney W. Grimes createleaves(symtbl); 2488fae3551SRodney W. Grimes createlinks(); 2498fae3551SRodney W. Grimes setdirmodes(FORCE); 2508fae3551SRodney W. Grimes checkrestore(); 2518fae3551SRodney W. Grimes dumpsymtable(symtbl, (long)1); 2528fae3551SRodney W. Grimes break; 2538fae3551SRodney W. Grimes /* 2548fae3551SRodney W. Grimes * List contents of tape. 2558fae3551SRodney W. Grimes */ 2568fae3551SRodney W. Grimes case 't': 2578fae3551SRodney W. Grimes setup(); 2588fae3551SRodney W. Grimes extractdirs(0); 2598fae3551SRodney W. Grimes initsymtable((char *)0); 2608fae3551SRodney W. Grimes while (argc--) { 26164121840SGuido van Rooij canon(*argv++, name, sizeof(name)); 2628fae3551SRodney W. Grimes ino = dirlookup(name); 2638fae3551SRodney W. Grimes if (ino == 0) 2648fae3551SRodney W. Grimes continue; 2658fae3551SRodney W. Grimes treescan(name, ino, listfile); 2668fae3551SRodney W. Grimes } 2678fae3551SRodney W. Grimes break; 2688fae3551SRodney W. Grimes /* 2698fae3551SRodney W. Grimes * Batch extraction of tape contents. 2708fae3551SRodney W. Grimes */ 2718fae3551SRodney W. Grimes case 'x': 2728fae3551SRodney W. Grimes setup(); 2738fae3551SRodney W. Grimes extractdirs(1); 2748fae3551SRodney W. Grimes initsymtable((char *)0); 2758fae3551SRodney W. Grimes while (argc--) { 27664121840SGuido van Rooij canon(*argv++, name, sizeof(name)); 2778fae3551SRodney W. Grimes ino = dirlookup(name); 2788fae3551SRodney W. Grimes if (ino == 0) 2798fae3551SRodney W. Grimes continue; 2808fae3551SRodney W. Grimes if (mflag) 2818fae3551SRodney W. Grimes pathcheck(name); 2828fae3551SRodney W. Grimes treescan(name, ino, addfile); 2838fae3551SRodney W. Grimes } 2848fae3551SRodney W. Grimes createfiles(); 2858fae3551SRodney W. Grimes createlinks(); 2868fae3551SRodney W. Grimes setdirmodes(0); 2878fae3551SRodney W. Grimes if (dflag) 2888fae3551SRodney W. Grimes checkrestore(); 2898fae3551SRodney W. Grimes break; 2908fae3551SRodney W. Grimes } 2918fae3551SRodney W. Grimes done(0); 2928fae3551SRodney W. Grimes /* NOTREACHED */ 2938fae3551SRodney W. Grimes } 2948fae3551SRodney W. Grimes 2958fae3551SRodney W. Grimes static void 2968fae3551SRodney W. Grimes usage() 2978fae3551SRodney W. Grimes { 298c51d70c6SBrian Feldman const char *const common = 2998d646af5SRuslan Ermilov "[-b blocksize] [-f file | -P pipecommand] [-s fileno]"; 300c51d70c6SBrian Feldman const char *const fileell = "[file ...]"; 301c51d70c6SBrian Feldman 302c51d70c6SBrian Feldman (void)fprintf(stderr, "usage:\t%s %s\n\t%s %s\n\t%s %s\n" 303c51d70c6SBrian Feldman "\t%s %s %s\n\t%s %s %s\n", 304ecdd99f8SWarner Losh "restore -i [-dhmNuvy]", common, 305ecdd99f8SWarner Losh "restore -R [-dNuvy]", common, 306ecdd99f8SWarner Losh "restore -r [-dNuvy]", common, 307ecdd99f8SWarner Losh "restore -t [-dhNuvy]", common, fileell, 308ecdd99f8SWarner Losh "restore -x [-dhmNuvy]", common, fileell); 3098fae3551SRodney W. Grimes done(1); 3108fae3551SRodney W. Grimes } 3118fae3551SRodney W. Grimes 3128fae3551SRodney W. Grimes /* 3138fae3551SRodney W. Grimes * obsolete -- 3148fae3551SRodney W. Grimes * Change set of key letters and ordered arguments into something 3158fae3551SRodney W. Grimes * getopt(3) will like. 3168fae3551SRodney W. Grimes */ 3178fae3551SRodney W. Grimes static void 3182db673abSWarner Losh obsolete(int *argcp, char **argvp[]) 3198fae3551SRodney W. Grimes { 3208fae3551SRodney W. Grimes int argc, flags; 3218fae3551SRodney W. Grimes char *ap, **argv, *flagsp, **nargv, *p; 3228fae3551SRodney W. Grimes 3238fae3551SRodney W. Grimes /* Setup. */ 3248fae3551SRodney W. Grimes argv = *argvp; 3258fae3551SRodney W. Grimes argc = *argcp; 3268fae3551SRodney W. Grimes 3278fae3551SRodney W. Grimes /* Return if no arguments or first argument has leading dash. */ 3288fae3551SRodney W. Grimes ap = argv[1]; 3298fae3551SRodney W. Grimes if (argc == 1 || *ap == '-') 3308fae3551SRodney W. Grimes return; 3318fae3551SRodney W. Grimes 3328fae3551SRodney W. Grimes /* Allocate space for new arguments. */ 3338fae3551SRodney W. Grimes if ((*argvp = nargv = malloc((argc + 1) * sizeof(char *))) == NULL || 3348fae3551SRodney W. Grimes (p = flagsp = malloc(strlen(ap) + 2)) == NULL) 3358fae3551SRodney W. Grimes err(1, NULL); 3368fae3551SRodney W. Grimes 3378fae3551SRodney W. Grimes *nargv++ = *argv; 3381eb5b41eSJordan K. Hubbard argv += 2, argc -= 2; 3398fae3551SRodney W. Grimes 3408fae3551SRodney W. Grimes for (flags = 0; *ap; ++ap) { 3418fae3551SRodney W. Grimes switch (*ap) { 3428fae3551SRodney W. Grimes case 'b': 3438fae3551SRodney W. Grimes case 'f': 3448fae3551SRodney W. Grimes case 's': 345d87d79aeSPeter Wemm if (*argv == NULL) { 346d87d79aeSPeter Wemm warnx("option requires an argument -- %c", *ap); 3471eb5b41eSJordan K. Hubbard usage(); 348d87d79aeSPeter Wemm } 3498fae3551SRodney W. Grimes if ((nargv[0] = malloc(strlen(*argv) + 2 + 1)) == NULL) 3508fae3551SRodney W. Grimes err(1, NULL); 3518fae3551SRodney W. Grimes nargv[0][0] = '-'; 3528fae3551SRodney W. Grimes nargv[0][1] = *ap; 3538fae3551SRodney W. Grimes (void)strcpy(&nargv[0][2], *argv); 3548fae3551SRodney W. Grimes ++argv; 3558fae3551SRodney W. Grimes ++nargv; 3568fae3551SRodney W. Grimes break; 3578fae3551SRodney W. Grimes default: 3588fae3551SRodney W. Grimes if (!flags) { 3598fae3551SRodney W. Grimes *p++ = '-'; 3608fae3551SRodney W. Grimes flags = 1; 3618fae3551SRodney W. Grimes } 3628fae3551SRodney W. Grimes *p++ = *ap; 3638fae3551SRodney W. Grimes break; 3648fae3551SRodney W. Grimes } 3658fae3551SRodney W. Grimes } 3668fae3551SRodney W. Grimes 3678fae3551SRodney W. Grimes /* Terminate flags. */ 3688fae3551SRodney W. Grimes if (flags) { 3698fae3551SRodney W. Grimes *p = '\0'; 3708fae3551SRodney W. Grimes *nargv++ = flagsp; 371e451cf5fSPedro F. Giffuni } else 372e451cf5fSPedro F. Giffuni free(flagsp); 3738fae3551SRodney W. Grimes 3748fae3551SRodney W. Grimes /* Copy remaining arguments. */ 37591ac32e4SPhilippe Charnier while ((*nargv++ = *argv++)); 376d87d79aeSPeter Wemm 377d87d79aeSPeter Wemm /* Update argument count. */ 378d87d79aeSPeter Wemm *argcp = nargv - *argvp - 1; 3798fae3551SRodney W. Grimes } 380