1 /* 2 * Copyright (c) 1983 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1983 The Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)main.c 5.10 (Berkeley) 10/05/92"; 16 #endif /* not lint */ 17 18 /* 19 * Modified to recursively extract all files within a subtree 20 * (supressed by the h option) and recreate the heirarchical 21 * structure of that subtree and move extracted files to their 22 * proper homes (supressed by the m option). 23 * Includes the s (skip files) option for use with multiple 24 * dumps on a single tape. 25 * 8/29/80 by Mike Litzkow 26 * 27 * Modified to work on the new file system and to recover from 28 * tape read errors. 29 * 1/19/82 by Kirk McKusick 30 * 31 * Full incremental restore running entirely in user code and 32 * interactive tape browser. 33 * 1/19/83 by Kirk McKusick 34 */ 35 36 #include "restore.h" 37 #include <protocols/dumprestore.h> 38 #include <sys/signal.h> 39 #include "pathnames.h" 40 41 int bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0; 42 int hflag = 1, mflag = 1, Nflag = 0; 43 char command = '\0'; 44 long dumpnum = 1; 45 long volno = 0; 46 long ntrec; 47 char *dumpmap; 48 char *clrimap; 49 ino_t maxino; 50 time_t dumptime; 51 time_t dumpdate; 52 FILE *terminal; 53 54 int 55 main(argc, argv) 56 int argc; 57 char *argv[]; 58 { 59 register char *cp; 60 ino_t ino; 61 char *inputdev = _PATH_DEFTAPE; 62 char *symtbl = "./restoresymtable"; 63 char name[MAXPATHLEN]; 64 void onintr(); 65 66 if (signal(SIGINT, onintr) == SIG_IGN) 67 (void) signal(SIGINT, SIG_IGN); 68 if (signal(SIGTERM, onintr) == SIG_IGN) 69 (void) signal(SIGTERM, SIG_IGN); 70 setlinebuf(stderr); 71 if (argc < 2) 72 usage(); 73 argv++; 74 argc -= 2; 75 command = '\0'; 76 for (cp = *argv++; *cp; cp++) { 77 switch (*cp) { 78 case '-': 79 break; 80 case 'c': 81 cvtflag++; 82 break; 83 case 'd': 84 dflag++; 85 break; 86 case 'h': 87 hflag = 0; 88 break; 89 case 'm': 90 mflag = 0; 91 break; 92 case 'N': 93 Nflag++; 94 break; 95 case 'v': 96 vflag++; 97 break; 98 case 'y': 99 yflag++; 100 break; 101 case 'f': 102 if (argc < 1) { 103 fprintf(stderr, "missing device specifier\n"); 104 done(1); 105 } 106 inputdev = *argv++; 107 argc--; 108 break; 109 case 'b': 110 /* 111 * change default tape blocksize 112 */ 113 bflag++; 114 if (argc < 1) { 115 fprintf(stderr, "missing block size\n"); 116 done(1); 117 } 118 ntrec = atoi(*argv++); 119 if (ntrec <= 0) { 120 fprintf(stderr, "Block size must be a positive integer\n"); 121 done(1); 122 } 123 argc--; 124 break; 125 case 's': 126 /* 127 * dumpnum (skip to) for multifile dump tapes 128 */ 129 if (argc < 1) { 130 fprintf(stderr, "missing dump number\n"); 131 done(1); 132 } 133 dumpnum = atoi(*argv++); 134 if (dumpnum <= 0) { 135 fprintf(stderr, "Dump number must be a positive integer\n"); 136 done(1); 137 } 138 argc--; 139 break; 140 case 't': 141 case 'R': 142 case 'r': 143 case 'x': 144 case 'i': 145 if (command != '\0') { 146 fprintf(stderr, 147 "%c and %c are mutually exclusive\n", 148 *cp, command); 149 usage(); 150 } 151 command = *cp; 152 break; 153 default: 154 fprintf(stderr, "Bad key character %c\n", *cp); 155 usage(); 156 } 157 } 158 if (command == '\0') { 159 fprintf(stderr, "must specify i, t, r, R, or x\n"); 160 usage(); 161 } 162 setinput(inputdev); 163 if (argc == 0) { 164 argc = 1; 165 *--argv = "."; 166 } 167 switch (command) { 168 /* 169 * Interactive mode. 170 */ 171 case 'i': 172 setup(); 173 extractdirs(1); 174 initsymtable((char *)0); 175 runcmdshell(); 176 done(0); 177 /* 178 * Incremental restoration of a file system. 179 */ 180 case 'r': 181 setup(); 182 if (dumptime > 0) { 183 /* 184 * This is an incremental dump tape. 185 */ 186 vprintf(stdout, "Begin incremental restore\n"); 187 initsymtable(symtbl); 188 extractdirs(1); 189 removeoldleaves(); 190 vprintf(stdout, "Calculate node updates.\n"); 191 treescan(".", ROOTINO, nodeupdates); 192 findunreflinks(); 193 removeoldnodes(); 194 } else { 195 /* 196 * This is a level zero dump tape. 197 */ 198 vprintf(stdout, "Begin level 0 restore\n"); 199 initsymtable((char *)0); 200 extractdirs(1); 201 vprintf(stdout, "Calculate extraction list.\n"); 202 treescan(".", ROOTINO, nodeupdates); 203 } 204 createleaves(symtbl); 205 createlinks(); 206 setdirmodes(FORCE); 207 checkrestore(); 208 if (dflag) { 209 vprintf(stdout, "Verify the directory structure\n"); 210 treescan(".", ROOTINO, verifyfile); 211 } 212 dumpsymtable(symtbl, (long)1); 213 done(0); 214 /* 215 * Resume an incremental file system restoration. 216 */ 217 case 'R': 218 initsymtable(symtbl); 219 skipmaps(); 220 skipdirs(); 221 createleaves(symtbl); 222 createlinks(); 223 setdirmodes(FORCE); 224 checkrestore(); 225 dumpsymtable(symtbl, (long)1); 226 done(0); 227 /* 228 * List contents of tape. 229 */ 230 case 't': 231 setup(); 232 extractdirs(0); 233 initsymtable((char *)0); 234 while (argc--) { 235 canon(*argv++, name); 236 ino = dirlookup(name); 237 if (ino == 0) 238 continue; 239 treescan(name, ino, listfile); 240 } 241 done(0); 242 /* 243 * Batch extraction of tape contents. 244 */ 245 case 'x': 246 setup(); 247 extractdirs(1); 248 initsymtable((char *)0); 249 while (argc--) { 250 canon(*argv++, name); 251 ino = dirlookup(name); 252 if (ino == 0) 253 continue; 254 if (mflag) 255 pathcheck(name); 256 treescan(name, ino, addfile); 257 } 258 createfiles(); 259 createlinks(); 260 setdirmodes(0); 261 if (dflag) 262 checkrestore(); 263 done(0); 264 } 265 } 266 267 usage() 268 { 269 (void)fprintf(stderr, "usage:\n%s%s%s%s%s", 270 "\trestore tfhsvy [file file ...]\n", 271 "\trestore xfhmsvy [file file ...]\n", 272 "\trestore ifhmsvy\n", 273 "\trestore rfsvy\n", 274 "\trestore Rfsvy\n"); 275 done(1); 276 } 277