121167Sdist /* 2*61536Sbostic * Copyright (c) 1983, 1993 3*61536Sbostic * The Regents of the University of California. All rights reserved. 436105Sbostic * 542708Sbostic * %sccs.include.redist.c% 621167Sdist */ 721167Sdist 86846Smckusick #ifndef lint 9*61536Sbostic static char copyright[] = 10*61536Sbostic "@(#) Copyright (c) 1983, 1993\n\ 11*61536Sbostic The Regents of the University of California. All rights reserved.\n"; 1236105Sbostic #endif /* not lint */ 134610Smckusick 1421167Sdist #ifndef lint 15*61536Sbostic static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 06/05/93"; 1636105Sbostic #endif /* not lint */ 1714564Ssam 1856567Sbostic #include <sys/param.h> 1956567Sbostic #include <sys/time.h> 204610Smckusick 2156567Sbostic #include <ufs/ffs/fs.h> 2256567Sbostic #include <ufs/ufs/dinode.h> 2323547Smckusick #include <protocols/dumprestore.h> 2456567Sbostic 2556567Sbostic #include <errno.h> 2656567Sbostic #include <signal.h> 2756567Sbostic #include <stdio.h> 2856567Sbostic #include <stdlib.h> 2956567Sbostic #include <string.h> 3056567Sbostic 3137952Sbostic #include "pathnames.h" 3256567Sbostic #include "restore.h" 3356567Sbostic #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 4856567Sbostic static void obsolete __P((int *, char **[])); 4956567Sbostic static void usage __P((void)); 5056567Sbostic 5156428Smckusick int 526846Smckusick main(argc, argv) 534700Smckusic int argc; 544700Smckusic char *argv[]; 554610Smckusick { 5656567Sbostic int ch; 5711308Smckusick ino_t ino; 5837952Sbostic char *inputdev = _PATH_DEFTAPE; 5911308Smckusick char *symtbl = "./restoresymtable"; 6056567Sbostic char *p, name[MAXPATHLEN]; 614610Smckusick 6256428Smckusick if (argc < 2) 6356428Smckusick usage(); 6456567Sbostic 6556567Sbostic obsolete(&argc, &argv); 6656567Sbostic while ((ch = getopt(argc, argv, "b:cdf:himNRrs:tvxy")) != EOF) 6756567Sbostic switch(ch) { 6856567Sbostic case 'b': 6956567Sbostic /* Change default tape blocksize. */ 7056567Sbostic bflag = 1; 7156567Sbostic ntrec = strtol(optarg, &p, 10); 7256567Sbostic if (*p) 7356567Sbostic err("illegal blocksize -- %s", optarg); 7456567Sbostic if (ntrec <= 0) 7556567Sbostic err("block size must be greater than 0"); 764610Smckusick break; 778302Smckusick case 'c': 7856567Sbostic cvtflag = 1; 798302Smckusick break; 8010312Smckusick case 'd': 8156567Sbostic dflag = 1; 824610Smckusick break; 8356567Sbostic case 'f': 8456567Sbostic inputdev = optarg; 8556567Sbostic break; 864610Smckusick case 'h': 8710202Smckusick hflag = 0; 884610Smckusick break; 8956567Sbostic case 'i': 9056567Sbostic case 'R': 9156567Sbostic case 'r': 9256567Sbostic case 't': 9356567Sbostic case 'x': 9456567Sbostic if (command != '\0') 9556567Sbostic err("%c and %c options are mutually exclusive", 9656567Sbostic ch, command); 9756567Sbostic command = ch; 9856567Sbostic break; 994610Smckusick case 'm': 10010202Smckusick mflag = 0; 1014610Smckusick break; 10234269Smckusick case 'N': 10356567Sbostic Nflag = 1; 10434269Smckusick break; 10556567Sbostic case 's': 10656567Sbostic /* Dumpnum (skip to) for multifile dump tapes. */ 10756567Sbostic dumpnum = strtol(optarg, &p, 10); 10856567Sbostic if (*p) 10956567Sbostic err("illegal dump number -- %s", optarg); 11056567Sbostic if (dumpnum <= 0) 11156567Sbostic err("dump number must be greater than 0"); 11256567Sbostic break; 1138374Smckusick case 'v': 11456567Sbostic vflag = 1; 1158374Smckusick break; 1168374Smckusick case 'y': 11756567Sbostic yflag = 1; 1188374Smckusick break; 1194610Smckusick default: 12056428Smckusick usage(); 1214610Smckusick } 12256567Sbostic argc -= optind; 12356567Sbostic argv += optind; 12456567Sbostic 12556567Sbostic if (command == '\0') 12656567Sbostic err("none of i, R, r, t or x options specified"); 12756567Sbostic 12856567Sbostic if (signal(SIGINT, onintr) == SIG_IGN) 12956567Sbostic (void) signal(SIGINT, SIG_IGN); 13056567Sbostic if (signal(SIGTERM, onintr) == SIG_IGN) 13156567Sbostic (void) signal(SIGTERM, SIG_IGN); 13256567Sbostic setlinebuf(stderr); 13356567Sbostic 13410312Smckusick setinput(inputdev); 13556567Sbostic 13610202Smckusick if (argc == 0) { 13710312Smckusick argc = 1; 13810202Smckusick *--argv = "."; 13910202Smckusick } 14056567Sbostic 14110312Smckusick switch (command) { 14211993Smckusick /* 14311993Smckusick * Interactive mode. 14411993Smckusick */ 14511993Smckusick case 'i': 14610312Smckusick setup(); 14711993Smckusick extractdirs(1); 14856567Sbostic initsymtable(NULL); 14911993Smckusick runcmdshell(); 15056567Sbostic break; 15111993Smckusick /* 15211993Smckusick * Incremental restoration of a file system. 15311993Smckusick */ 15410312Smckusick case 'r': 15510312Smckusick setup(); 15610312Smckusick if (dumptime > 0) { 15711438Smckusick /* 15811438Smckusick * This is an incremental dump tape. 15911438Smckusick */ 16011438Smckusick vprintf(stdout, "Begin incremental restore\n"); 16110312Smckusick initsymtable(symtbl); 16211993Smckusick extractdirs(1); 16311438Smckusick removeoldleaves(); 16411438Smckusick vprintf(stdout, "Calculate node updates.\n"); 16511438Smckusick treescan(".", ROOTINO, nodeupdates); 16611438Smckusick findunreflinks(); 16711438Smckusick removeoldnodes(); 16810312Smckusick } else { 16911438Smckusick /* 17011438Smckusick * This is a level zero dump tape. 17111438Smckusick */ 17211438Smckusick vprintf(stdout, "Begin level 0 restore\n"); 17311438Smckusick initsymtable((char *)0); 17411993Smckusick extractdirs(1); 17511438Smckusick vprintf(stdout, "Calculate extraction list.\n"); 17611438Smckusick treescan(".", ROOTINO, nodeupdates); 1774843Smckusic } 17810312Smckusick createleaves(symtbl); 17910312Smckusick createlinks(); 18055880Smckusick setdirmodes(FORCE); 18110312Smckusick checkrestore(); 18210312Smckusick if (dflag) { 18310312Smckusick vprintf(stdout, "Verify the directory structure\n"); 18410312Smckusick treescan(".", ROOTINO, verifyfile); 1854610Smckusick } 18610312Smckusick dumpsymtable(symtbl, (long)1); 18756567Sbostic break; 18811993Smckusick /* 18911993Smckusick * Resume an incremental file system restoration. 19011993Smckusick */ 19110312Smckusick case 'R': 19210312Smckusick initsymtable(symtbl); 19311320Smckusick skipmaps(); 19411320Smckusick skipdirs(); 19510312Smckusick createleaves(symtbl); 19610312Smckusick createlinks(); 19755880Smckusick setdirmodes(FORCE); 19810312Smckusick checkrestore(); 19910312Smckusick dumpsymtable(symtbl, (long)1); 20056567Sbostic break; 20111993Smckusick /* 20211993Smckusick * List contents of tape. 20311993Smckusick */ 20411993Smckusick case 't': 20511993Smckusick setup(); 20611993Smckusick extractdirs(0); 20727264Smckusick initsymtable((char *)0); 20811993Smckusick while (argc--) { 20911993Smckusick canon(*argv++, name); 21011993Smckusick ino = dirlookup(name); 21111993Smckusick if (ino == 0) 21211993Smckusick continue; 21311993Smckusick treescan(name, ino, listfile); 21411993Smckusick } 21556567Sbostic break; 21611993Smckusick /* 21711993Smckusick * Batch extraction of tape contents. 21811993Smckusick */ 21911993Smckusick case 'x': 22011993Smckusick setup(); 22111993Smckusick extractdirs(1); 22211993Smckusick initsymtable((char *)0); 22311993Smckusick while (argc--) { 22411993Smckusick canon(*argv++, name); 22511993Smckusick ino = dirlookup(name); 22611993Smckusick if (ino == 0) 22711993Smckusick continue; 22811993Smckusick if (mflag) 22911993Smckusick pathcheck(name); 23011993Smckusick treescan(name, ino, addfile); 23111993Smckusick } 23211993Smckusick createfiles(); 23311993Smckusick createlinks(); 23455880Smckusick setdirmodes(0); 23511993Smckusick if (dflag) 23611993Smckusick checkrestore(); 23756567Sbostic break; 2384843Smckusic } 23956567Sbostic done(0); 24056567Sbostic /* NOTREACHED */ 2414843Smckusic } 24256428Smckusick 24359771Shibler static void 24456428Smckusick usage() 24556428Smckusick { 24656567Sbostic (void)fprintf(stderr, "usage:\t%s%s%s%s%s", 24756567Sbostic "restore tfhsvy [file ...]\n", 24856567Sbostic "\trestore xfhmsvy [file ...]\n", 24956428Smckusick "\trestore ifhmsvy\n", 25056428Smckusick "\trestore rfsvy\n", 25156428Smckusick "\trestore Rfsvy\n"); 25256428Smckusick done(1); 25356428Smckusick } 25456567Sbostic 25556567Sbostic /* 25656567Sbostic * obsolete -- 25756567Sbostic * Change set of key letters and ordered arguments into something 25856567Sbostic * getopt(3) will like. 25956567Sbostic */ 26056567Sbostic static void 26156567Sbostic obsolete(argcp, argvp) 26256567Sbostic int *argcp; 26356567Sbostic char **argvp[]; 26456567Sbostic { 26556567Sbostic int argc, flags; 26656567Sbostic char *ap, **argv, *flagsp, **nargv, *p; 26756567Sbostic 26856567Sbostic /* Setup. */ 26956567Sbostic argv = *argvp; 27056567Sbostic argc = *argcp; 27156567Sbostic 27256567Sbostic /* Return if no arguments or first argument has leading dash. */ 27356567Sbostic ap = argv[1]; 27456567Sbostic if (argc == 1 || *ap == '-') 27556567Sbostic return; 27656567Sbostic 27756567Sbostic /* Allocate space for new arguments. */ 27856567Sbostic if ((*argvp = nargv = malloc((argc + 1) * sizeof(char *))) == NULL || 27956567Sbostic (p = flagsp = malloc(strlen(ap) + 2)) == NULL) 28056567Sbostic err("%s", strerror(errno)); 28156567Sbostic 28256567Sbostic *nargv++ = *argv; 28356567Sbostic argv += 2; 28456567Sbostic 28556567Sbostic for (flags = 0; *ap; ++ap) { 28656567Sbostic switch(*ap) { 28756567Sbostic case 'b': 28856567Sbostic case 'f': 28956567Sbostic case 's': 29056567Sbostic if ((nargv[0] = malloc(strlen(*argv) + 2 + 1)) == NULL) 29156567Sbostic err("%s", strerror(errno)); 29256567Sbostic nargv[0][0] = '-'; 29356567Sbostic nargv[0][1] = *ap; 29456567Sbostic (void)strcpy(&nargv[0][2], *argv); 29556567Sbostic if (*argv != NULL) 29656567Sbostic ++argv; 29756567Sbostic ++nargv; 29856567Sbostic break; 29956567Sbostic default: 30056567Sbostic if (!flags) { 30156567Sbostic *p++ = '-'; 30256567Sbostic flags = 1; 30356567Sbostic } 30456567Sbostic *p++ = *ap; 30556567Sbostic break; 30656567Sbostic } 30756567Sbostic } 30856567Sbostic 30956567Sbostic /* Terminate flags. */ 31056567Sbostic if (flags) { 31156567Sbostic *p = '\0'; 31256567Sbostic *nargv++ = flagsp; 31356567Sbostic } 31456567Sbostic 31556567Sbostic /* Copy remaining arguments. */ 31656567Sbostic while (*nargv++ = *argv++); 31756567Sbostic } 31856567Sbostic 31956567Sbostic #if __STDC__ 32056567Sbostic #include <stdarg.h> 32156567Sbostic #else 32256567Sbostic #include <varargs.h> 32356567Sbostic #endif 32456567Sbostic 32557930Sbostic __dead void 32656567Sbostic #if __STDC__ 32756567Sbostic err(const char *fmt, ...) 32856567Sbostic #else 32956567Sbostic err(fmt, va_alist) 33056567Sbostic char *fmt; 33156567Sbostic va_dcl 33256567Sbostic #endif 33356567Sbostic { 33456567Sbostic va_list ap; 33556567Sbostic #if __STDC__ 33656567Sbostic va_start(ap, fmt); 33756567Sbostic #else 33856567Sbostic va_start(ap); 33956567Sbostic #endif 34056567Sbostic (void)fprintf(stderr, "restore: "); 34156567Sbostic (void)vfprintf(stderr, fmt, ap); 34256567Sbostic va_end(ap); 34356567Sbostic (void)fprintf(stderr, "\n"); 34456567Sbostic exit(1); 34556567Sbostic /* NOTREACHED */ 34656567Sbostic } 347