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