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 34 #ifndef lint 35 static const char copyright[] = 36 "@(#) Copyright (c) 1983, 1993\n\ 37 The Regents of the University of California. All rights reserved.\n"; 38 #endif /* not lint */ 39 40 #ifndef lint 41 #if 0 42 static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/4/95"; 43 #endif 44 static const char rcsid[] = 45 "$FreeBSD$"; 46 #endif /* not lint */ 47 48 #include <sys/param.h> 49 #include <sys/stat.h> 50 51 #include <ufs/ufs/dinode.h> 52 #include <protocols/dumprestore.h> 53 54 #include <err.h> 55 #include <limits.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, vflag = 0, yflag = 0; 66 int hflag = 1, mflag = 1, Nflag = 0; 67 int uflag = 0; 68 char command = '\0'; 69 long dumpnum = 1; 70 long volno = 0; 71 long ntrec; 72 char *dumpmap; 73 char *usedinomap; 74 ino_t maxino; 75 time_t dumptime; 76 time_t dumpdate; 77 FILE *terminal; 78 79 static void obsolete(int *, char **[]); 80 static void usage(void) __dead2; 81 82 int 83 main(int argc, char *argv[]) 84 { 85 int ch; 86 ino_t ino; 87 char *inputdev; 88 char *symtbl = "./restoresymtable"; 89 char *p, name[MAXPATHLEN]; 90 91 /* Temp files should *not* be readable. We set permissions later. */ 92 (void) umask(077); 93 94 if (argc < 2) 95 usage(); 96 97 if ((inputdev = getenv("TAPE")) == NULL) 98 inputdev = _PATH_DEFTAPE; 99 obsolete(&argc, &argv); 100 while ((ch = getopt(argc, argv, "b:df:himNRrs:tuvxy")) != -1) 101 switch(ch) { 102 case 'b': 103 /* Change default tape blocksize. */ 104 bflag = 1; 105 ntrec = strtol(optarg, &p, 10); 106 if (*p) 107 errx(1, "illegal blocksize -- %s", optarg); 108 if (ntrec <= 0) 109 errx(1, "block size must be greater than 0"); 110 break; 111 case 'd': 112 dflag = 1; 113 break; 114 case 'f': 115 inputdev = optarg; 116 break; 117 case 'h': 118 hflag = 0; 119 break; 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 (void) signal(SIGINT, SIG_IGN); 165 if (signal(SIGTERM, onintr) == SIG_IGN) 166 (void) 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((char *)0); 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((char *)0); 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((char *)0); 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() 280 { 281 (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n", 282 "restore -i [-cdhmNuvy] [-b blocksize] [-f file] [-s fileno]", 283 "restore -r [-cdNuvy] [-b blocksize] [-f file] [-s fileno]", 284 "restore -R [-cdNuvy] [-b blocksize] [-f file] [-s fileno]", 285 "restore -x [-cdhmNuvy] [-b blocksize] [-f file] [-s fileno] [file ...]", 286 "restore -t [-cdhNuvy] [-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 (void)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