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