1 /* Copyright (c) 1983 Regents of the University of California */ 2 3 #ifndef lint 4 static char sccsid[] = "@(#)main.c 3.10 (Berkeley) 83/05/15"; 5 #endif 6 7 /* 8 * Modified to recursively extract all files within a subtree 9 * (supressed by the h option) and recreate the heirarchical 10 * structure of that subtree and move extracted files to their 11 * proper homes (supressed by the m option). 12 * Includes the s (skip files) option for use with multiple 13 * dumps on a single tape. 14 * 8/29/80 by Mike Litzkow 15 * 16 * Modified to work on the new file system and to recover from 17 * tape read errors. 18 * 1/19/82 by Kirk McKusick 19 * 20 * Full incremental restore running entirely in user code and 21 * interactive tape browser. 22 * 1/19/83 by Kirk McKusick 23 */ 24 25 #include "restore.h" 26 #include <signal.h> 27 28 int cvtflag = 0, dflag = 0, vflag = 0, yflag = 0; 29 int hflag = 1, mflag = 1; 30 char command = '\0'; 31 long dumpnum = 1; 32 long volno = 0; 33 char *dumpmap; 34 char *clrimap; 35 ino_t maxino; 36 time_t dumptime; 37 time_t dumpdate; 38 FILE *terminal; 39 40 main(argc, argv) 41 int argc; 42 char *argv[]; 43 { 44 register char *cp; 45 ino_t ino; 46 char *inputdev = "/dev/rmt8"; 47 char *symtbl = "./restoresymtable"; 48 char name[MAXPATHLEN]; 49 int (*signal())(); 50 extern int onintr(); 51 52 if (signal(SIGINT, onintr) == SIG_IGN) 53 (void) signal(SIGINT, SIG_IGN); 54 if (signal(SIGTERM, onintr) == SIG_IGN) 55 (void) signal(SIGTERM, SIG_IGN); 56 setlinebuf(stderr); 57 if (argc < 2) { 58 usage: 59 fprintf(stderr, "Usage:\n%s%s%s%s%s", 60 "\trestore tfhsvy [file file ...]\n", 61 "\trestore xfhmsvy [file file ...]\n", 62 "\trestore ifhmsvy\n", 63 "\trestore rfsvy\n", 64 "\trestore Rfsvy\n"); 65 done(1); 66 } 67 argv++; 68 argc -= 2; 69 command = '\0'; 70 for (cp = *argv++; *cp; cp++) { 71 switch (*cp) { 72 case '-': 73 break; 74 case 'c': 75 cvtflag++; 76 break; 77 case 'd': 78 dflag++; 79 break; 80 case 'h': 81 hflag = 0; 82 break; 83 case 'm': 84 mflag = 0; 85 break; 86 case 'v': 87 vflag++; 88 break; 89 case 'y': 90 yflag++; 91 break; 92 case 'f': 93 if (argc < 1) { 94 fprintf(stderr, "missing device specifier\n"); 95 done(1); 96 } 97 inputdev = *argv++; 98 argc--; 99 break; 100 case 's': 101 /* 102 * dumpnum (skip to) for multifile dump tapes 103 */ 104 if (argc < 1) { 105 fprintf(stderr, "missing dump number\n"); 106 done(1); 107 } 108 dumpnum = atoi(*argv++); 109 if (dumpnum <= 0) { 110 fprintf(stderr, "Dump number must be a positive integer\n"); 111 done(1); 112 } 113 argc--; 114 break; 115 case 't': 116 case 'R': 117 case 'r': 118 case 'x': 119 case 'i': 120 if (command != '\0') { 121 fprintf(stderr, 122 "%c and %c are mutually exclusive\n", 123 *cp, command); 124 goto usage; 125 } 126 command = *cp; 127 break; 128 default: 129 fprintf(stderr, "Bad key character %c\n", *cp); 130 goto usage; 131 } 132 } 133 if (command == '\0') { 134 fprintf(stderr, "must specify i, t, r, R, or x\n"); 135 goto usage; 136 } 137 setinput(inputdev); 138 if (argc == 0) { 139 argc = 1; 140 *--argv = "."; 141 } 142 switch (command) { 143 /* 144 * Interactive mode. 145 */ 146 case 'i': 147 setup(); 148 extractdirs(1); 149 initsymtable((char *)0); 150 runcmdshell(); 151 done(0); 152 /* 153 * Incremental restoration of a file system. 154 */ 155 case 'r': 156 setup(); 157 if (dumptime > 0) { 158 /* 159 * This is an incremental dump tape. 160 */ 161 vprintf(stdout, "Begin incremental restore\n"); 162 initsymtable(symtbl); 163 extractdirs(1); 164 removeoldleaves(); 165 vprintf(stdout, "Calculate node updates.\n"); 166 treescan(".", ROOTINO, nodeupdates); 167 findunreflinks(); 168 removeoldnodes(); 169 } else { 170 /* 171 * This is a level zero dump tape. 172 */ 173 vprintf(stdout, "Begin level 0 restore\n"); 174 initsymtable((char *)0); 175 extractdirs(1); 176 vprintf(stdout, "Calculate extraction list.\n"); 177 treescan(".", ROOTINO, nodeupdates); 178 } 179 createleaves(symtbl); 180 createlinks(); 181 setdirmodes(); 182 checkrestore(); 183 if (dflag) { 184 vprintf(stdout, "Verify the directory structure\n"); 185 treescan(".", ROOTINO, verifyfile); 186 } 187 dumpsymtable(symtbl, (long)1); 188 done(0); 189 /* 190 * Resume an incremental file system restoration. 191 */ 192 case 'R': 193 initsymtable(symtbl); 194 skipmaps(); 195 skipdirs(); 196 createleaves(symtbl); 197 createlinks(); 198 setdirmodes(); 199 checkrestore(); 200 dumpsymtable(symtbl, (long)1); 201 done(0); 202 /* 203 * List contents of tape. 204 */ 205 case 't': 206 setup(); 207 extractdirs(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 done(0); 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(); 235 if (dflag) 236 checkrestore(); 237 done(0); 238 } 239 } 240 241 /* 242 * Read and execute commands from the terminal. 243 */ 244 runcmdshell() 245 { 246 register struct entry *np; 247 ino_t ino; 248 char curdir[MAXPATHLEN]; 249 char name[MAXPATHLEN]; 250 char cmd[BUFSIZ]; 251 252 canon("/", curdir); 253 loop: 254 getcmd(curdir, cmd, name); 255 switch (cmd[0]) { 256 /* 257 * Add elements to the extraction list. 258 */ 259 case 'a': 260 ino = dirlookup(name); 261 if (ino == 0) 262 break; 263 if (mflag) 264 pathcheck(name); 265 treescan(name, ino, addfile); 266 break; 267 /* 268 * Change working directory. 269 */ 270 case 'c': 271 ino = dirlookup(name); 272 if (ino == 0) 273 break; 274 if (inodetype(ino) == LEAF) { 275 fprintf(stderr, "%s: not a directory\n", name); 276 break; 277 } 278 (void) strcpy(curdir, name); 279 break; 280 /* 281 * Delete elements from the extraction list. 282 */ 283 case 'd': 284 np = lookupname(name); 285 if (np == NIL || (np->e_flags & NEW) == 0) { 286 fprintf(stderr, "%s: not on extraction list\n", name); 287 break; 288 } 289 treescan(name, np->e_ino, deletefile); 290 break; 291 /* 292 * Extract the requested list. 293 */ 294 case 'e': 295 createfiles(); 296 createlinks(); 297 setdirmodes(); 298 if (dflag) 299 checkrestore(); 300 volno = 0; 301 break; 302 /* 303 * List available commands. 304 */ 305 case 'h': 306 case '?': 307 fprintf(stderr, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", 308 "Available commands are:\n", 309 "\tls [arg] - list directory\n", 310 "\tcd arg - change directory\n", 311 "\tpwd - print current directory\n", 312 "\tadd [arg] - add `arg' to list of", 313 " files to be extracted\n", 314 "\tdelete [arg] - delete `arg' from", 315 " list of files to be extracted\n", 316 "\textract - extract requested files\n", 317 "\tquit - immediately exit program\n", 318 "\tverbose - toggle verbose flag", 319 " (useful with ``ls'')\n", 320 "\thelp or `?' - print this list\n", 321 "If no `arg' is supplied, the current", 322 " directory is used\n"); 323 break; 324 /* 325 * List a directory. 326 */ 327 case 'l': 328 ino = dirlookup(name); 329 if (ino == 0) 330 break; 331 printlist(name, ino); 332 break; 333 /* 334 * Print current directory. 335 */ 336 case 'p': 337 if (curdir[1] == '\0') 338 fprintf(stderr, "/\n"); 339 else 340 fprintf(stderr, "%s\n", &curdir[1]); 341 break; 342 /* 343 * Quit. 344 */ 345 case 'q': 346 return; 347 /* 348 * Toggle verbose mode. 349 */ 350 case 'v': 351 if (vflag) { 352 fprintf(stderr, "verbose mode off\n"); 353 vflag = 0; 354 break; 355 } 356 fprintf(stderr, "verbose mode on\n"); 357 vflag++; 358 break; 359 /* 360 * Turn on debugging. 361 */ 362 case 'D': 363 if (dflag) { 364 fprintf(stderr, "debugging mode off\n"); 365 dflag = 0; 366 break; 367 } 368 fprintf(stderr, "debugging mode on\n"); 369 dflag++; 370 break; 371 /* 372 * Unknown command. 373 */ 374 default: 375 fprintf(stderr, "%s: unknown command; type ? for help\n", cmd); 376 break; 377 } 378 goto loop; 379 } 380