121167Sdist /* 236105Sbostic * Copyright (c) 1983 The Regents of the University of California. 336105Sbostic * All rights reserved. 436105Sbostic * 542708Sbostic * %sccs.include.redist.c% 621167Sdist */ 721167Sdist 86846Smckusick #ifndef lint 921167Sdist char copyright[] = 1036105Sbostic "@(#) Copyright (c) 1983 The Regents of the University of California.\n\ 1121167Sdist All rights reserved.\n"; 1236105Sbostic #endif /* not lint */ 134610Smckusick 1421167Sdist #ifndef lint 15*56567Sbostic static char sccsid[] = "@(#)main.c 5.11 (Berkeley) 10/16/92"; 1636105Sbostic #endif /* not lint */ 1714564Ssam 18*56567Sbostic #include <sys/param.h> 19*56567Sbostic #include <sys/time.h> 204610Smckusick 21*56567Sbostic #include <ufs/ffs/fs.h> 22*56567Sbostic #include <ufs/ufs/dinode.h> 2323547Smckusick #include <protocols/dumprestore.h> 24*56567Sbostic 25*56567Sbostic #include <errno.h> 26*56567Sbostic #include <signal.h> 27*56567Sbostic #include <stdio.h> 28*56567Sbostic #include <stdlib.h> 29*56567Sbostic #include <string.h> 30*56567Sbostic 3137952Sbostic #include "pathnames.h" 32*56567Sbostic #include "restore.h" 33*56567Sbostic #include "extern.h" 344610Smckusick 3518496Smckusick int bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0; 3634269Smckusick int hflag = 1, mflag = 1, Nflag = 0; 3710312Smckusick char command = '\0'; 3810312Smckusick long dumpnum = 1; 3911438Smckusick long volno = 0; 4018496Smckusick long ntrec; 415327Smckusic char *dumpmap; 425327Smckusic char *clrimap; 4310312Smckusick ino_t maxino; 4410312Smckusick time_t dumptime; 4511302Smckusick time_t dumpdate; 4611993Smckusick FILE *terminal; 474610Smckusick 48*56567Sbostic static void err __P((const char *, ...)); 49*56567Sbostic static void obsolete __P((int *, char **[])); 50*56567Sbostic static void usage __P((void)); 51*56567Sbostic 5256428Smckusick int 536846Smckusick main(argc, argv) 544700Smckusic int argc; 554700Smckusic char *argv[]; 564610Smckusick { 57*56567Sbostic int ch; 5811308Smckusick ino_t ino; 5937952Sbostic char *inputdev = _PATH_DEFTAPE; 6011308Smckusick char *symtbl = "./restoresymtable"; 61*56567Sbostic char *p, name[MAXPATHLEN]; 624610Smckusick 6356428Smckusick if (argc < 2) 6456428Smckusick usage(); 65*56567Sbostic 66*56567Sbostic obsolete(&argc, &argv); 67*56567Sbostic while ((ch = getopt(argc, argv, "b:cdf:himNRrs:tvxy")) != EOF) 68*56567Sbostic switch(ch) { 69*56567Sbostic case 'b': 70*56567Sbostic /* Change default tape blocksize. */ 71*56567Sbostic bflag = 1; 72*56567Sbostic ntrec = strtol(optarg, &p, 10); 73*56567Sbostic if (*p) 74*56567Sbostic err("illegal blocksize -- %s", optarg); 75*56567Sbostic if (ntrec <= 0) 76*56567Sbostic err("block size must be greater than 0"); 774610Smckusick break; 788302Smckusick case 'c': 79*56567Sbostic cvtflag = 1; 808302Smckusick break; 8110312Smckusick case 'd': 82*56567Sbostic dflag = 1; 834610Smckusick break; 84*56567Sbostic case 'f': 85*56567Sbostic inputdev = optarg; 86*56567Sbostic break; 874610Smckusick case 'h': 8810202Smckusick hflag = 0; 894610Smckusick break; 90*56567Sbostic case 'i': 91*56567Sbostic case 'R': 92*56567Sbostic case 'r': 93*56567Sbostic case 't': 94*56567Sbostic case 'x': 95*56567Sbostic if (command != '\0') 96*56567Sbostic err("%c and %c options are mutually exclusive", 97*56567Sbostic ch, command); 98*56567Sbostic command = ch; 99*56567Sbostic break; 1004610Smckusick case 'm': 10110202Smckusick mflag = 0; 1024610Smckusick break; 10334269Smckusick case 'N': 104*56567Sbostic Nflag = 1; 10534269Smckusick break; 106*56567Sbostic case 's': 107*56567Sbostic /* Dumpnum (skip to) for multifile dump tapes. */ 108*56567Sbostic dumpnum = strtol(optarg, &p, 10); 109*56567Sbostic if (*p) 110*56567Sbostic err("illegal dump number -- %s", optarg); 111*56567Sbostic if (dumpnum <= 0) 112*56567Sbostic err("dump number must be greater than 0"); 113*56567Sbostic break; 1148374Smckusick case 'v': 115*56567Sbostic vflag = 1; 1168374Smckusick break; 1178374Smckusick case 'y': 118*56567Sbostic yflag = 1; 1198374Smckusick break; 1204610Smckusick default: 12156428Smckusick usage(); 1224610Smckusick } 123*56567Sbostic argc -= optind; 124*56567Sbostic argv += optind; 125*56567Sbostic 126*56567Sbostic if (command == '\0') 127*56567Sbostic err("none of i, R, r, t or x options specified"); 128*56567Sbostic 129*56567Sbostic if (signal(SIGINT, onintr) == SIG_IGN) 130*56567Sbostic (void) signal(SIGINT, SIG_IGN); 131*56567Sbostic if (signal(SIGTERM, onintr) == SIG_IGN) 132*56567Sbostic (void) signal(SIGTERM, SIG_IGN); 133*56567Sbostic setlinebuf(stderr); 134*56567Sbostic 13510312Smckusick setinput(inputdev); 136*56567Sbostic 13710202Smckusick if (argc == 0) { 13810312Smckusick argc = 1; 13910202Smckusick *--argv = "."; 14010202Smckusick } 141*56567Sbostic 14210312Smckusick switch (command) { 14311993Smckusick /* 14411993Smckusick * Interactive mode. 14511993Smckusick */ 14611993Smckusick case 'i': 14710312Smckusick setup(); 14811993Smckusick extractdirs(1); 149*56567Sbostic initsymtable(NULL); 15011993Smckusick runcmdshell(); 151*56567Sbostic break; 15211993Smckusick /* 15311993Smckusick * Incremental restoration of a file system. 15411993Smckusick */ 15510312Smckusick case 'r': 15610312Smckusick setup(); 15710312Smckusick if (dumptime > 0) { 15811438Smckusick /* 15911438Smckusick * This is an incremental dump tape. 16011438Smckusick */ 16111438Smckusick vprintf(stdout, "Begin incremental restore\n"); 16210312Smckusick initsymtable(symtbl); 16311993Smckusick extractdirs(1); 16411438Smckusick removeoldleaves(); 16511438Smckusick vprintf(stdout, "Calculate node updates.\n"); 16611438Smckusick treescan(".", ROOTINO, nodeupdates); 16711438Smckusick findunreflinks(); 16811438Smckusick removeoldnodes(); 16910312Smckusick } else { 17011438Smckusick /* 17111438Smckusick * This is a level zero dump tape. 17211438Smckusick */ 17311438Smckusick vprintf(stdout, "Begin level 0 restore\n"); 17411438Smckusick initsymtable((char *)0); 17511993Smckusick extractdirs(1); 17611438Smckusick vprintf(stdout, "Calculate extraction list.\n"); 17711438Smckusick treescan(".", ROOTINO, nodeupdates); 1784843Smckusic } 17910312Smckusick createleaves(symtbl); 18010312Smckusick createlinks(); 18155880Smckusick setdirmodes(FORCE); 18210312Smckusick checkrestore(); 18310312Smckusick if (dflag) { 18410312Smckusick vprintf(stdout, "Verify the directory structure\n"); 18510312Smckusick treescan(".", ROOTINO, verifyfile); 1864610Smckusick } 18710312Smckusick dumpsymtable(symtbl, (long)1); 188*56567Sbostic break; 18911993Smckusick /* 19011993Smckusick * Resume an incremental file system restoration. 19111993Smckusick */ 19210312Smckusick case 'R': 19310312Smckusick initsymtable(symtbl); 19411320Smckusick skipmaps(); 19511320Smckusick skipdirs(); 19610312Smckusick createleaves(symtbl); 19710312Smckusick createlinks(); 19855880Smckusick setdirmodes(FORCE); 19910312Smckusick checkrestore(); 20010312Smckusick dumpsymtable(symtbl, (long)1); 201*56567Sbostic break; 20211993Smckusick /* 20311993Smckusick * List contents of tape. 20411993Smckusick */ 20511993Smckusick case 't': 20611993Smckusick setup(); 20711993Smckusick extractdirs(0); 20827264Smckusick initsymtable((char *)0); 20911993Smckusick while (argc--) { 21011993Smckusick canon(*argv++, name); 21111993Smckusick ino = dirlookup(name); 21211993Smckusick if (ino == 0) 21311993Smckusick continue; 21411993Smckusick treescan(name, ino, listfile); 21511993Smckusick } 216*56567Sbostic break; 21711993Smckusick /* 21811993Smckusick * Batch extraction of tape contents. 21911993Smckusick */ 22011993Smckusick case 'x': 22111993Smckusick setup(); 22211993Smckusick extractdirs(1); 22311993Smckusick initsymtable((char *)0); 22411993Smckusick while (argc--) { 22511993Smckusick canon(*argv++, name); 22611993Smckusick ino = dirlookup(name); 22711993Smckusick if (ino == 0) 22811993Smckusick continue; 22911993Smckusick if (mflag) 23011993Smckusick pathcheck(name); 23111993Smckusick treescan(name, ino, addfile); 23211993Smckusick } 23311993Smckusick createfiles(); 23411993Smckusick createlinks(); 23555880Smckusick setdirmodes(0); 23611993Smckusick if (dflag) 23711993Smckusick checkrestore(); 238*56567Sbostic break; 2394843Smckusic } 240*56567Sbostic done(0); 241*56567Sbostic /* NOTREACHED */ 2424843Smckusic } 24356428Smckusick 244*56567Sbostic void 24556428Smckusick usage() 24656428Smckusick { 247*56567Sbostic (void)fprintf(stderr, "usage:\t%s%s%s%s%s", 248*56567Sbostic "restore tfhsvy [file ...]\n", 249*56567Sbostic "\trestore xfhmsvy [file ...]\n", 25056428Smckusick "\trestore ifhmsvy\n", 25156428Smckusick "\trestore rfsvy\n", 25256428Smckusick "\trestore Rfsvy\n"); 25356428Smckusick done(1); 25456428Smckusick } 255*56567Sbostic 256*56567Sbostic /* 257*56567Sbostic * obsolete -- 258*56567Sbostic * Change set of key letters and ordered arguments into something 259*56567Sbostic * getopt(3) will like. 260*56567Sbostic */ 261*56567Sbostic static void 262*56567Sbostic obsolete(argcp, argvp) 263*56567Sbostic int *argcp; 264*56567Sbostic char **argvp[]; 265*56567Sbostic { 266*56567Sbostic int argc, flags; 267*56567Sbostic char *ap, **argv, *flagsp, **nargv, *p; 268*56567Sbostic 269*56567Sbostic /* Setup. */ 270*56567Sbostic argv = *argvp; 271*56567Sbostic argc = *argcp; 272*56567Sbostic 273*56567Sbostic /* Return if no arguments or first argument has leading dash. */ 274*56567Sbostic ap = argv[1]; 275*56567Sbostic if (argc == 1 || *ap == '-') 276*56567Sbostic return; 277*56567Sbostic 278*56567Sbostic /* Allocate space for new arguments. */ 279*56567Sbostic if ((*argvp = nargv = malloc((argc + 1) * sizeof(char *))) == NULL || 280*56567Sbostic (p = flagsp = malloc(strlen(ap) + 2)) == NULL) 281*56567Sbostic err("%s", strerror(errno)); 282*56567Sbostic 283*56567Sbostic *nargv++ = *argv; 284*56567Sbostic argv += 2; 285*56567Sbostic 286*56567Sbostic for (flags = 0; *ap; ++ap) { 287*56567Sbostic switch(*ap) { 288*56567Sbostic case 'b': 289*56567Sbostic case 'f': 290*56567Sbostic case 's': 291*56567Sbostic if ((nargv[0] = malloc(strlen(*argv) + 2 + 1)) == NULL) 292*56567Sbostic err("%s", strerror(errno)); 293*56567Sbostic nargv[0][0] = '-'; 294*56567Sbostic nargv[0][1] = *ap; 295*56567Sbostic (void)strcpy(&nargv[0][2], *argv); 296*56567Sbostic if (*argv != NULL) 297*56567Sbostic ++argv; 298*56567Sbostic ++nargv; 299*56567Sbostic break; 300*56567Sbostic default: 301*56567Sbostic if (!flags) { 302*56567Sbostic *p++ = '-'; 303*56567Sbostic flags = 1; 304*56567Sbostic } 305*56567Sbostic *p++ = *ap; 306*56567Sbostic break; 307*56567Sbostic } 308*56567Sbostic } 309*56567Sbostic 310*56567Sbostic /* Terminate flags. */ 311*56567Sbostic if (flags) { 312*56567Sbostic *p = '\0'; 313*56567Sbostic *nargv++ = flagsp; 314*56567Sbostic } 315*56567Sbostic 316*56567Sbostic /* Copy remaining arguments. */ 317*56567Sbostic while (*nargv++ = *argv++); 318*56567Sbostic } 319*56567Sbostic 320*56567Sbostic #if __STDC__ 321*56567Sbostic #include <stdarg.h> 322*56567Sbostic #else 323*56567Sbostic #include <varargs.h> 324*56567Sbostic #endif 325*56567Sbostic 326*56567Sbostic void 327*56567Sbostic #if __STDC__ 328*56567Sbostic err(const char *fmt, ...) 329*56567Sbostic #else 330*56567Sbostic err(fmt, va_alist) 331*56567Sbostic char *fmt; 332*56567Sbostic va_dcl 333*56567Sbostic #endif 334*56567Sbostic { 335*56567Sbostic va_list ap; 336*56567Sbostic #if __STDC__ 337*56567Sbostic va_start(ap, fmt); 338*56567Sbostic #else 339*56567Sbostic va_start(ap); 340*56567Sbostic #endif 341*56567Sbostic (void)fprintf(stderr, "restore: "); 342*56567Sbostic (void)vfprintf(stderr, fmt, ap); 343*56567Sbostic va_end(ap); 344*56567Sbostic (void)fprintf(stderr, "\n"); 345*56567Sbostic exit(1); 346*56567Sbostic /* NOTREACHED */ 347*56567Sbostic } 348