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