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*69225Sbostic static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 05/04/95";
1636105Sbostic #endif /* not lint */
1714564Ssam
1856567Sbostic #include <sys/param.h>
1956567Sbostic #include <sys/time.h>
204610Smckusick
2169153Smckusick #include <ufs/ufs/dinode.h>
2256567Sbostic #include <ufs/ffs/fs.h>
2323547Smckusick #include <protocols/dumprestore.h>
2456567Sbostic
2565568Sbostic #include <err.h>
2656567Sbostic #include <errno.h>
2756567Sbostic #include <signal.h>
2856567Sbostic #include <stdio.h>
2956567Sbostic #include <stdlib.h>
3056567Sbostic #include <string.h>
31*69225Sbostic #include <unistd.h>
3256567Sbostic
3337952Sbostic #include "pathnames.h"
3456567Sbostic #include "restore.h"
3556567Sbostic #include "extern.h"
364610Smckusick
3718496Smckusick int bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0;
3834269Smckusick int hflag = 1, mflag = 1, Nflag = 0;
3910312Smckusick char command = '\0';
4010312Smckusick long dumpnum = 1;
4111438Smckusick long volno = 0;
4218496Smckusick long ntrec;
435327Smckusic char *dumpmap;
4467775Smckusick char *usedinomap;
4510312Smckusick ino_t maxino;
4610312Smckusick time_t dumptime;
4711302Smckusick time_t dumpdate;
4811993Smckusick FILE *terminal;
494610Smckusick
5056567Sbostic static void obsolete __P((int *, char **[]));
5156567Sbostic static void usage __P((void));
5256567Sbostic
5356428Smckusick int
main(argc,argv)546846Smckusick main(argc, argv)
554700Smckusic int argc;
564700Smckusic char *argv[];
574610Smckusick {
5856567Sbostic int ch;
5911308Smckusick ino_t ino;
6037952Sbostic char *inputdev = _PATH_DEFTAPE;
6111308Smckusick char *symtbl = "./restoresymtable";
6256567Sbostic char *p, name[MAXPATHLEN];
634610Smckusick
6456428Smckusick if (argc < 2)
6556428Smckusick usage();
6656567Sbostic
6756567Sbostic obsolete(&argc, &argv);
6856567Sbostic while ((ch = getopt(argc, argv, "b:cdf:himNRrs:tvxy")) != EOF)
6956567Sbostic switch(ch) {
7056567Sbostic case 'b':
7156567Sbostic /* Change default tape blocksize. */
7256567Sbostic bflag = 1;
7356567Sbostic ntrec = strtol(optarg, &p, 10);
7456567Sbostic if (*p)
7565568Sbostic errx(1, "illegal blocksize -- %s", optarg);
7656567Sbostic if (ntrec <= 0)
7765568Sbostic errx(1, "block size must be greater than 0");
784610Smckusick break;
798302Smckusick case 'c':
8056567Sbostic cvtflag = 1;
818302Smckusick break;
8210312Smckusick case 'd':
8356567Sbostic dflag = 1;
844610Smckusick break;
8556567Sbostic case 'f':
8656567Sbostic inputdev = optarg;
8756567Sbostic break;
884610Smckusick case 'h':
8910202Smckusick hflag = 0;
904610Smckusick break;
9156567Sbostic case 'i':
9256567Sbostic case 'R':
9356567Sbostic case 'r':
9456567Sbostic case 't':
9556567Sbostic case 'x':
9656567Sbostic if (command != '\0')
9765568Sbostic errx(1,
9865568Sbostic "%c and %c options are mutually exclusive",
9956567Sbostic ch, command);
10056567Sbostic command = ch;
10156567Sbostic break;
1024610Smckusick case 'm':
10310202Smckusick mflag = 0;
1044610Smckusick break;
10534269Smckusick case 'N':
10656567Sbostic Nflag = 1;
10734269Smckusick break;
10856567Sbostic case 's':
10956567Sbostic /* Dumpnum (skip to) for multifile dump tapes. */
11056567Sbostic dumpnum = strtol(optarg, &p, 10);
11156567Sbostic if (*p)
11265568Sbostic errx(1, "illegal dump number -- %s", optarg);
11356567Sbostic if (dumpnum <= 0)
11465568Sbostic errx(1, "dump number must be greater than 0");
11556567Sbostic break;
1168374Smckusick case 'v':
11756567Sbostic vflag = 1;
1188374Smckusick break;
1198374Smckusick case 'y':
12056567Sbostic yflag = 1;
1218374Smckusick break;
1224610Smckusick default:
12356428Smckusick usage();
1244610Smckusick }
12556567Sbostic argc -= optind;
12656567Sbostic argv += optind;
12756567Sbostic
12856567Sbostic if (command == '\0')
12965568Sbostic errx(1, "none of i, R, r, t or x options specified");
13056567Sbostic
13156567Sbostic if (signal(SIGINT, onintr) == SIG_IGN)
13256567Sbostic (void) signal(SIGINT, SIG_IGN);
13356567Sbostic if (signal(SIGTERM, onintr) == SIG_IGN)
13456567Sbostic (void) signal(SIGTERM, SIG_IGN);
13556567Sbostic setlinebuf(stderr);
13656567Sbostic
13710312Smckusick setinput(inputdev);
13856567Sbostic
13910202Smckusick if (argc == 0) {
14010312Smckusick argc = 1;
14110202Smckusick *--argv = ".";
14210202Smckusick }
14356567Sbostic
14410312Smckusick switch (command) {
14511993Smckusick /*
14611993Smckusick * Interactive mode.
14711993Smckusick */
14811993Smckusick case 'i':
14910312Smckusick setup();
15011993Smckusick extractdirs(1);
15156567Sbostic initsymtable(NULL);
15211993Smckusick runcmdshell();
15356567Sbostic break;
15411993Smckusick /*
15511993Smckusick * Incremental restoration of a file system.
15611993Smckusick */
15710312Smckusick case 'r':
15810312Smckusick setup();
15910312Smckusick if (dumptime > 0) {
16011438Smckusick /*
16111438Smckusick * This is an incremental dump tape.
16211438Smckusick */
16311438Smckusick vprintf(stdout, "Begin incremental restore\n");
16410312Smckusick initsymtable(symtbl);
16511993Smckusick extractdirs(1);
16611438Smckusick removeoldleaves();
16711438Smckusick vprintf(stdout, "Calculate node updates.\n");
16811438Smckusick treescan(".", ROOTINO, nodeupdates);
16911438Smckusick findunreflinks();
17011438Smckusick removeoldnodes();
17110312Smckusick } else {
17211438Smckusick /*
17311438Smckusick * This is a level zero dump tape.
17411438Smckusick */
17511438Smckusick vprintf(stdout, "Begin level 0 restore\n");
17611438Smckusick initsymtable((char *)0);
17711993Smckusick extractdirs(1);
17811438Smckusick vprintf(stdout, "Calculate extraction list.\n");
17911438Smckusick treescan(".", ROOTINO, nodeupdates);
1804843Smckusic }
18110312Smckusick createleaves(symtbl);
18210312Smckusick createlinks();
18355880Smckusick setdirmodes(FORCE);
18410312Smckusick checkrestore();
18510312Smckusick if (dflag) {
18610312Smckusick vprintf(stdout, "Verify the directory structure\n");
18710312Smckusick treescan(".", ROOTINO, verifyfile);
1884610Smckusick }
18910312Smckusick dumpsymtable(symtbl, (long)1);
19056567Sbostic break;
19111993Smckusick /*
19211993Smckusick * Resume an incremental file system restoration.
19311993Smckusick */
19410312Smckusick case 'R':
19510312Smckusick initsymtable(symtbl);
19611320Smckusick skipmaps();
19711320Smckusick skipdirs();
19810312Smckusick createleaves(symtbl);
19910312Smckusick createlinks();
20055880Smckusick setdirmodes(FORCE);
20110312Smckusick checkrestore();
20210312Smckusick dumpsymtable(symtbl, (long)1);
20356567Sbostic break;
20411993Smckusick /*
20511993Smckusick * List contents of tape.
20611993Smckusick */
20711993Smckusick case 't':
20811993Smckusick setup();
20911993Smckusick extractdirs(0);
21027264Smckusick initsymtable((char *)0);
21111993Smckusick while (argc--) {
21211993Smckusick canon(*argv++, name);
21311993Smckusick ino = dirlookup(name);
21411993Smckusick if (ino == 0)
21511993Smckusick continue;
21611993Smckusick treescan(name, ino, listfile);
21711993Smckusick }
21856567Sbostic break;
21911993Smckusick /*
22011993Smckusick * Batch extraction of tape contents.
22111993Smckusick */
22211993Smckusick case 'x':
22311993Smckusick setup();
22411993Smckusick extractdirs(1);
22511993Smckusick initsymtable((char *)0);
22611993Smckusick while (argc--) {
22711993Smckusick canon(*argv++, name);
22811993Smckusick ino = dirlookup(name);
22911993Smckusick if (ino == 0)
23011993Smckusick continue;
23111993Smckusick if (mflag)
23211993Smckusick pathcheck(name);
23311993Smckusick treescan(name, ino, addfile);
23411993Smckusick }
23511993Smckusick createfiles();
23611993Smckusick createlinks();
23755880Smckusick setdirmodes(0);
23811993Smckusick if (dflag)
23911993Smckusick checkrestore();
24056567Sbostic break;
2414843Smckusic }
24256567Sbostic done(0);
24356567Sbostic /* NOTREACHED */
2444843Smckusic }
24556428Smckusick
24659771Shibler static void
usage()24756428Smckusick usage()
24856428Smckusick {
24969154Smckusick (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n",
25069154Smckusick "restore -i [-chmvy] [-b blocksize] [-f file] [-s fileno]",
25169154Smckusick "restore -r [-cvy] [-b blocksize] [-f file] [-s fileno]",
25269154Smckusick "restore -R [-cvy] [-b blocksize] [-f file] [-s fileno]",
25369154Smckusick "restore -x [-chmvy] [-b blocksize] [-f file] [-s fileno] [file ...]",
25469154Smckusick "restore -t [-chvy] [-b blocksize] [-f file] [-s fileno] [file ...]");
25556428Smckusick done(1);
25656428Smckusick }
25756567Sbostic
25856567Sbostic /*
25956567Sbostic * obsolete --
26056567Sbostic * Change set of key letters and ordered arguments into something
26156567Sbostic * getopt(3) will like.
26256567Sbostic */
26356567Sbostic static void
obsolete(argcp,argvp)26456567Sbostic obsolete(argcp, argvp)
26556567Sbostic int *argcp;
26656567Sbostic char **argvp[];
26756567Sbostic {
26856567Sbostic int argc, flags;
26956567Sbostic char *ap, **argv, *flagsp, **nargv, *p;
27056567Sbostic
27156567Sbostic /* Setup. */
27256567Sbostic argv = *argvp;
27356567Sbostic argc = *argcp;
27456567Sbostic
27556567Sbostic /* Return if no arguments or first argument has leading dash. */
27656567Sbostic ap = argv[1];
27756567Sbostic if (argc == 1 || *ap == '-')
27856567Sbostic return;
27956567Sbostic
28056567Sbostic /* Allocate space for new arguments. */
28156567Sbostic if ((*argvp = nargv = malloc((argc + 1) * sizeof(char *))) == NULL ||
28256567Sbostic (p = flagsp = malloc(strlen(ap) + 2)) == NULL)
28365568Sbostic err(1, NULL);
28456567Sbostic
28556567Sbostic *nargv++ = *argv;
28656567Sbostic argv += 2;
28756567Sbostic
28856567Sbostic for (flags = 0; *ap; ++ap) {
28969153Smckusick switch (*ap) {
29056567Sbostic case 'b':
29156567Sbostic case 'f':
29256567Sbostic case 's':
29369153Smckusick if (*argv == NULL) {
29469153Smckusick warnx("option requires an argument -- %c", *ap);
29569153Smckusick usage();
29669153Smckusick }
29756567Sbostic if ((nargv[0] = malloc(strlen(*argv) + 2 + 1)) == NULL)
29865568Sbostic err(1, NULL);
29956567Sbostic nargv[0][0] = '-';
30056567Sbostic nargv[0][1] = *ap;
30156567Sbostic (void)strcpy(&nargv[0][2], *argv);
30269153Smckusick ++argv;
30356567Sbostic ++nargv;
30456567Sbostic break;
30556567Sbostic default:
30656567Sbostic if (!flags) {
30756567Sbostic *p++ = '-';
30856567Sbostic flags = 1;
30956567Sbostic }
31056567Sbostic *p++ = *ap;
31156567Sbostic break;
31256567Sbostic }
31356567Sbostic }
31456567Sbostic
31556567Sbostic /* Terminate flags. */
31656567Sbostic if (flags) {
31756567Sbostic *p = '\0';
31856567Sbostic *nargv++ = flagsp;
31956567Sbostic }
32056567Sbostic
32156567Sbostic /* Copy remaining arguments. */
32256567Sbostic while (*nargv++ = *argv++);
32369153Smckusick
32469153Smckusick /* Update argument count. */
32569153Smckusick *argcp = nargv - *argvp - 1;
32656567Sbostic }
327