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