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