121167Sdist /* 261536Sbostic * Copyright (c) 1983, 1993 361536Sbostic * The Regents of the University of California. All rights reserved. 436105Sbostic * 542708Sbostic * %sccs.include.redist.c% 621167Sdist */ 721167Sdist 86846Smckusick #ifndef lint 961536Sbostic static char copyright[] = 1061536Sbostic "@(#) Copyright (c) 1983, 1993\n\ 1161536Sbostic The Regents of the University of California. All rights reserved.\n"; 1236105Sbostic #endif /* not lint */ 134610Smckusick 1421167Sdist #ifndef lint 15*65568Sbostic static char sccsid[] = "@(#)main.c 8.2 (Berkeley) 01/07/94"; 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 25*65568Sbostic #include <err.h> 2656567Sbostic #include <errno.h> 2756567Sbostic #include <signal.h> 2856567Sbostic #include <stdio.h> 2956567Sbostic #include <stdlib.h> 3056567Sbostic #include <string.h> 3156567Sbostic 3237952Sbostic #include "pathnames.h" 3356567Sbostic #include "restore.h" 3456567Sbostic #include "extern.h" 354610Smckusick 3618496Smckusick int bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0; 3734269Smckusick int hflag = 1, mflag = 1, Nflag = 0; 3810312Smckusick char command = '\0'; 3910312Smckusick long dumpnum = 1; 4011438Smckusick long volno = 0; 4118496Smckusick long ntrec; 425327Smckusic char *dumpmap; 435327Smckusic char *clrimap; 4410312Smckusick ino_t maxino; 4510312Smckusick time_t dumptime; 4611302Smckusick time_t dumpdate; 4711993Smckusick FILE *terminal; 484610Smckusick 4956567Sbostic static void obsolete __P((int *, char **[])); 5056567Sbostic static void usage __P((void)); 5156567Sbostic 5256428Smckusick int 536846Smckusick main(argc, argv) 544700Smckusic int argc; 554700Smckusic char *argv[]; 564610Smckusick { 5756567Sbostic int ch; 5811308Smckusick ino_t ino; 5937952Sbostic char *inputdev = _PATH_DEFTAPE; 6011308Smckusick char *symtbl = "./restoresymtable"; 6156567Sbostic char *p, name[MAXPATHLEN]; 624610Smckusick 6356428Smckusick if (argc < 2) 6456428Smckusick usage(); 6556567Sbostic 6656567Sbostic obsolete(&argc, &argv); 6756567Sbostic while ((ch = getopt(argc, argv, "b:cdf:himNRrs:tvxy")) != EOF) 6856567Sbostic switch(ch) { 6956567Sbostic case 'b': 7056567Sbostic /* Change default tape blocksize. */ 7156567Sbostic bflag = 1; 7256567Sbostic ntrec = strtol(optarg, &p, 10); 7356567Sbostic if (*p) 74*65568Sbostic errx(1, "illegal blocksize -- %s", optarg); 7556567Sbostic if (ntrec <= 0) 76*65568Sbostic errx(1, "block size must be greater than 0"); 774610Smckusick break; 788302Smckusick case 'c': 7956567Sbostic cvtflag = 1; 808302Smckusick break; 8110312Smckusick case 'd': 8256567Sbostic dflag = 1; 834610Smckusick break; 8456567Sbostic case 'f': 8556567Sbostic inputdev = optarg; 8656567Sbostic break; 874610Smckusick case 'h': 8810202Smckusick hflag = 0; 894610Smckusick break; 9056567Sbostic case 'i': 9156567Sbostic case 'R': 9256567Sbostic case 'r': 9356567Sbostic case 't': 9456567Sbostic case 'x': 9556567Sbostic if (command != '\0') 96*65568Sbostic errx(1, 97*65568Sbostic "%c and %c options are mutually exclusive", 9856567Sbostic ch, command); 9956567Sbostic command = ch; 10056567Sbostic break; 1014610Smckusick case 'm': 10210202Smckusick mflag = 0; 1034610Smckusick break; 10434269Smckusick case 'N': 10556567Sbostic Nflag = 1; 10634269Smckusick break; 10756567Sbostic case 's': 10856567Sbostic /* Dumpnum (skip to) for multifile dump tapes. */ 10956567Sbostic dumpnum = strtol(optarg, &p, 10); 11056567Sbostic if (*p) 111*65568Sbostic errx(1, "illegal dump number -- %s", optarg); 11256567Sbostic if (dumpnum <= 0) 113*65568Sbostic errx(1, "dump number must be greater than 0"); 11456567Sbostic break; 1158374Smckusick case 'v': 11656567Sbostic vflag = 1; 1178374Smckusick break; 1188374Smckusick case 'y': 11956567Sbostic yflag = 1; 1208374Smckusick break; 1214610Smckusick default: 12256428Smckusick usage(); 1234610Smckusick } 12456567Sbostic argc -= optind; 12556567Sbostic argv += optind; 12656567Sbostic 12756567Sbostic if (command == '\0') 128*65568Sbostic errx(1, "none of i, R, r, t or x options specified"); 12956567Sbostic 13056567Sbostic if (signal(SIGINT, onintr) == SIG_IGN) 13156567Sbostic (void) signal(SIGINT, SIG_IGN); 13256567Sbostic if (signal(SIGTERM, onintr) == SIG_IGN) 13356567Sbostic (void) signal(SIGTERM, SIG_IGN); 13456567Sbostic setlinebuf(stderr); 13556567Sbostic 13610312Smckusick setinput(inputdev); 13756567Sbostic 13810202Smckusick if (argc == 0) { 13910312Smckusick argc = 1; 14010202Smckusick *--argv = "."; 14110202Smckusick } 14256567Sbostic 14310312Smckusick switch (command) { 14411993Smckusick /* 14511993Smckusick * Interactive mode. 14611993Smckusick */ 14711993Smckusick case 'i': 14810312Smckusick setup(); 14911993Smckusick extractdirs(1); 15056567Sbostic initsymtable(NULL); 15111993Smckusick runcmdshell(); 15256567Sbostic break; 15311993Smckusick /* 15411993Smckusick * Incremental restoration of a file system. 15511993Smckusick */ 15610312Smckusick case 'r': 15710312Smckusick setup(); 15810312Smckusick if (dumptime > 0) { 15911438Smckusick /* 16011438Smckusick * This is an incremental dump tape. 16111438Smckusick */ 16211438Smckusick vprintf(stdout, "Begin incremental restore\n"); 16310312Smckusick initsymtable(symtbl); 16411993Smckusick extractdirs(1); 16511438Smckusick removeoldleaves(); 16611438Smckusick vprintf(stdout, "Calculate node updates.\n"); 16711438Smckusick treescan(".", ROOTINO, nodeupdates); 16811438Smckusick findunreflinks(); 16911438Smckusick removeoldnodes(); 17010312Smckusick } else { 17111438Smckusick /* 17211438Smckusick * This is a level zero dump tape. 17311438Smckusick */ 17411438Smckusick vprintf(stdout, "Begin level 0 restore\n"); 17511438Smckusick initsymtable((char *)0); 17611993Smckusick extractdirs(1); 17711438Smckusick vprintf(stdout, "Calculate extraction list.\n"); 17811438Smckusick treescan(".", ROOTINO, nodeupdates); 1794843Smckusic } 18010312Smckusick createleaves(symtbl); 18110312Smckusick createlinks(); 18255880Smckusick setdirmodes(FORCE); 18310312Smckusick checkrestore(); 18410312Smckusick if (dflag) { 18510312Smckusick vprintf(stdout, "Verify the directory structure\n"); 18610312Smckusick treescan(".", ROOTINO, verifyfile); 1874610Smckusick } 18810312Smckusick dumpsymtable(symtbl, (long)1); 18956567Sbostic break; 19011993Smckusick /* 19111993Smckusick * Resume an incremental file system restoration. 19211993Smckusick */ 19310312Smckusick case 'R': 19410312Smckusick initsymtable(symtbl); 19511320Smckusick skipmaps(); 19611320Smckusick skipdirs(); 19710312Smckusick createleaves(symtbl); 19810312Smckusick createlinks(); 19955880Smckusick setdirmodes(FORCE); 20010312Smckusick checkrestore(); 20110312Smckusick dumpsymtable(symtbl, (long)1); 20256567Sbostic break; 20311993Smckusick /* 20411993Smckusick * List contents of tape. 20511993Smckusick */ 20611993Smckusick case 't': 20711993Smckusick setup(); 20811993Smckusick extractdirs(0); 20927264Smckusick initsymtable((char *)0); 21011993Smckusick while (argc--) { 21111993Smckusick canon(*argv++, name); 21211993Smckusick ino = dirlookup(name); 21311993Smckusick if (ino == 0) 21411993Smckusick continue; 21511993Smckusick treescan(name, ino, listfile); 21611993Smckusick } 21756567Sbostic break; 21811993Smckusick /* 21911993Smckusick * Batch extraction of tape contents. 22011993Smckusick */ 22111993Smckusick case 'x': 22211993Smckusick setup(); 22311993Smckusick extractdirs(1); 22411993Smckusick initsymtable((char *)0); 22511993Smckusick while (argc--) { 22611993Smckusick canon(*argv++, name); 22711993Smckusick ino = dirlookup(name); 22811993Smckusick if (ino == 0) 22911993Smckusick continue; 23011993Smckusick if (mflag) 23111993Smckusick pathcheck(name); 23211993Smckusick treescan(name, ino, addfile); 23311993Smckusick } 23411993Smckusick createfiles(); 23511993Smckusick createlinks(); 23655880Smckusick setdirmodes(0); 23711993Smckusick if (dflag) 23811993Smckusick checkrestore(); 23956567Sbostic break; 2404843Smckusic } 24156567Sbostic done(0); 24256567Sbostic /* NOTREACHED */ 2434843Smckusic } 24456428Smckusick 24559771Shibler static void 24656428Smckusick usage() 24756428Smckusick { 24856567Sbostic (void)fprintf(stderr, "usage:\t%s%s%s%s%s", 24956567Sbostic "restore tfhsvy [file ...]\n", 25056567Sbostic "\trestore xfhmsvy [file ...]\n", 25156428Smckusick "\trestore ifhmsvy\n", 25256428Smckusick "\trestore rfsvy\n", 25356428Smckusick "\trestore Rfsvy\n"); 25456428Smckusick done(1); 25556428Smckusick } 25656567Sbostic 25756567Sbostic /* 25856567Sbostic * obsolete -- 25956567Sbostic * Change set of key letters and ordered arguments into something 26056567Sbostic * getopt(3) will like. 26156567Sbostic */ 26256567Sbostic static void 26356567Sbostic obsolete(argcp, argvp) 26456567Sbostic int *argcp; 26556567Sbostic char **argvp[]; 26656567Sbostic { 26756567Sbostic int argc, flags; 26856567Sbostic char *ap, **argv, *flagsp, **nargv, *p; 26956567Sbostic 27056567Sbostic /* Setup. */ 27156567Sbostic argv = *argvp; 27256567Sbostic argc = *argcp; 27356567Sbostic 27456567Sbostic /* Return if no arguments or first argument has leading dash. */ 27556567Sbostic ap = argv[1]; 27656567Sbostic if (argc == 1 || *ap == '-') 27756567Sbostic return; 27856567Sbostic 27956567Sbostic /* Allocate space for new arguments. */ 28056567Sbostic if ((*argvp = nargv = malloc((argc + 1) * sizeof(char *))) == NULL || 28156567Sbostic (p = flagsp = malloc(strlen(ap) + 2)) == NULL) 282*65568Sbostic err(1, NULL); 28356567Sbostic 28456567Sbostic *nargv++ = *argv; 28556567Sbostic argv += 2; 28656567Sbostic 28756567Sbostic for (flags = 0; *ap; ++ap) { 28856567Sbostic switch(*ap) { 28956567Sbostic case 'b': 29056567Sbostic case 'f': 29156567Sbostic case 's': 29256567Sbostic if ((nargv[0] = malloc(strlen(*argv) + 2 + 1)) == NULL) 293*65568Sbostic err(1, NULL); 29456567Sbostic nargv[0][0] = '-'; 29556567Sbostic nargv[0][1] = *ap; 29656567Sbostic (void)strcpy(&nargv[0][2], *argv); 29756567Sbostic if (*argv != NULL) 29856567Sbostic ++argv; 29956567Sbostic ++nargv; 30056567Sbostic break; 30156567Sbostic default: 30256567Sbostic if (!flags) { 30356567Sbostic *p++ = '-'; 30456567Sbostic flags = 1; 30556567Sbostic } 30656567Sbostic *p++ = *ap; 30756567Sbostic break; 30856567Sbostic } 30956567Sbostic } 31056567Sbostic 31156567Sbostic /* Terminate flags. */ 31256567Sbostic if (flags) { 31356567Sbostic *p = '\0'; 31456567Sbostic *nargv++ = flagsp; 31556567Sbostic } 31656567Sbostic 31756567Sbostic /* Copy remaining arguments. */ 31856567Sbostic while (*nargv++ = *argv++); 31956567Sbostic } 320