BSD 4_4 release
[unix-history] / usr / src / sbin / restore / main.c
index 5f5dc46..c717410 100644 (file)
-/* Copyright (c) 1983 Regents of the University of California */
-
-#ifndef lint
-static char sccsid[] = "@(#)main.c     3.6     (Berkeley)      83/01/16";
-#endif
-
 /*
 /*
- *     Modified to recursively extract all files within a subtree
- *     (supressed by the h option) and recreate the heirarchical
- *     structure of that subtree and move extracted files to their
- *     proper homes (supressed by the m option).
- *     Includes the s (skip files) option for use with multiple
- *     dumps on a single tape.
- *     8/29/80         by Mike Litzkow
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  *
- *     Modified to work on the new file system and to recover from
- *     tape read errors.
- *     1/19/82         by Kirk McKusick
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
  *
- *     Full incremental restore running entirely in user code.
- *     1/19/83         by Kirk McKusick
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
 
  */
 
-#include "restore.h"
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)main.c     8.1 (Berkeley) 6/5/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/time.h>
+
+#include <ufs/ffs/fs.h>
+#include <ufs/ufs/dinode.h>
+#include <protocols/dumprestore.h>
+
+#include <errno.h>
 #include <signal.h>
 #include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pathnames.h"
+#include "restore.h"
+#include "extern.h"
 
 
-int    cvtflag = 0, dflag = 0, vflag = 0, yflag = 0;
-int    hflag = 1, mflag = 1;
+int    bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0;
+int    hflag = 1, mflag = 1, Nflag = 0;
 char   command = '\0';
 long   dumpnum = 1;
 char   command = '\0';
 long   dumpnum = 1;
-long   volno = 1;
+long   volno = 0;
+long   ntrec;
 char   *dumpmap;
 char   *clrimap;
 ino_t  maxino;
 time_t dumptime;
 time_t dumpdate;
 char   *dumpmap;
 char   *clrimap;
 ino_t  maxino;
 time_t dumptime;
 time_t dumpdate;
+FILE   *terminal;
 
 
+static void obsolete __P((int *, char **[]));
+static void usage __P((void));
+
+int
 main(argc, argv)
        int argc;
        char *argv[];
 {
 main(argc, argv)
        int argc;
        char *argv[];
 {
-       register char *cp;
+       int ch;
        ino_t ino;
        ino_t ino;
-       char *inputdev = "/dev/rmt8";
+       char *inputdev = _PATH_DEFTAPE;
        char *symtbl = "./restoresymtable";
        char *symtbl = "./restoresymtable";
-       char *dirmodefile = "./dirmodes";
-       char name[BUFSIZ];
-       int (*signal())();
-       extern int onintr();
+       char *p, name[MAXPATHLEN];
 
 
-       if (signal(SIGINT, onintr) == SIG_IGN)
-               (void) signal(SIGINT, SIG_IGN);
-       if (signal(SIGTERM, onintr) == SIG_IGN)
-               (void) signal(SIGTERM, SIG_IGN);
-       setlinebuf(stderr);
-       if (argc < 2) {
-usage:
-               fprintf(stderr, "Usage: restor xtfhmsvy file file... or restor rRfsvy\n");
-               done(1);
-       }
-       argv++;
-       argc -= 2;
-       command = '\0';
-       for (cp = *argv++; *cp; cp++) {
-               switch (*cp) {
-               case '-':
+       if (argc < 2)
+               usage();
+
+       obsolete(&argc, &argv);
+       while ((ch = getopt(argc, argv, "b:cdf:himNRrs:tvxy")) != EOF)
+               switch(ch) {
+               case 'b':
+                       /* Change default tape blocksize. */
+                       bflag = 1;
+                       ntrec = strtol(optarg, &p, 10);
+                       if (*p)
+                               err("illegal blocksize -- %s", optarg);
+                       if (ntrec <= 0)
+                               err("block size must be greater than 0");
                        break;
                case 'c':
                        break;
                case 'c':
-                       cvtflag++;
+                       cvtflag = 1;
                        break;
                case 'd':
                        break;
                case 'd':
-                       dflag++;
+                       dflag = 1;
+                       break;
+               case 'f':
+                       inputdev = optarg;
                        break;
                case 'h':
                        hflag = 0;
                        break;
                        break;
                case 'h':
                        hflag = 0;
                        break;
+               case 'i':
+               case 'R':
+               case 'r':
+               case 't':
+               case 'x':
+                       if (command != '\0')
+                               err("%c and %c options are mutually exclusive",
+                                   ch, command);
+                       command = ch;
+                       break;
                case 'm':
                        mflag = 0;
                        break;
                case 'm':
                        mflag = 0;
                        break;
-               case 'v':
-                       vflag++;
-                       break;
-               case 'y':
-                       yflag++;
-                       break;
-               case 'f':
-                       if (argc < 1) {
-                               fprintf(stderr, "missing device specifier\n");
-                               done(1);
-                       }
-                       inputdev = *argv++;
-                       argc--;
+               case 'N':
+                       Nflag = 1;
                        break;
                case 's':
                        break;
                case 's':
-                       /*
-                        * dumpnum (skip to) for multifile dump tapes
-                        */
-                       if (argc < 1) {
-                               fprintf(stderr, "missing dump number\n");
-                               done(1);
-                       }
-                       dumpnum = atoi(*argv++);
-                       if (dumpnum <= 0) {
-                               fprintf(stderr, "Dump number must be a positive integer\n");
-                               done(1);
-                       }
-                       argc--;
+                       /* Dumpnum (skip to) for multifile dump tapes. */
+                       dumpnum = strtol(optarg, &p, 10);
+                       if (*p)
+                               err("illegal dump number -- %s", optarg);
+                       if (dumpnum <= 0)
+                               err("dump number must be greater than 0");
                        break;
                        break;
-               case 't':
-               case 'R':
-               case 'r':
-               case 'x':
-                       if (command != '\0') {
-                               fprintf(stderr,
-                                       "%c and %c are mutually exclusive\n",
-                                       *cp, command);
-                               goto usage;
-                       }
-                       command = *cp;
+               case 'v':
+                       vflag = 1;
+                       break;
+               case 'y':
+                       yflag = 1;
                        break;
                default:
                        break;
                default:
-                       fprintf(stderr, "Bad key character %c\n", *cp);
-                       goto usage;
+                       usage();
                }
                }
-       }
-       if (command == '\0') {
-               fprintf(stderr, "must specify t, r, R, or x\n");
-               goto usage;
-       }
+       argc -= optind;
+       argv += optind;
+
+       if (command == '\0')
+               err("none of i, R, r, t or x options specified");
+
+       if (signal(SIGINT, onintr) == SIG_IGN)
+               (void) signal(SIGINT, SIG_IGN);
+       if (signal(SIGTERM, onintr) == SIG_IGN)
+               (void) signal(SIGTERM, SIG_IGN);
+       setlinebuf(stderr);
+
        setinput(inputdev);
        setinput(inputdev);
+
        if (argc == 0) {
                argc = 1;
                *--argv = ".";
        }
        if (argc == 0) {
                argc = 1;
                *--argv = ".";
        }
-       switch (command) {
-
-       case 't':
-               setup();
-               extractdirs((char *)0);
-               while (argc--) {
-                       canon(*argv++, name);
-                       if ((ino = psearch(name)) == 0 ||
-                           BIT(ino, dumpmap) == 0) {
-                               fprintf(stderr, "%s: not on tape\n", name);
-                               continue;
-                       }
-                       if (hflag)
-                               treescan(name, ino, listfile);
-                       else
-                               listfile(name, ino, inodetype(ino));
-               }
-               done(0);
 
 
-       case 'x':
+       switch (command) {
+       /*
+        * Interactive mode.
+        */
+       case 'i':
                setup();
                setup();
-               extractdirs(dirmodefile);
-               initsymtable((char *)0);
-               while (argc--) {
-                       canon(*argv++, name);
-                       if ((ino = psearch(name)) == 0 ||
-                           BIT(ino, dumpmap) == 0) {
-                               fprintf(stderr, "%s: not on tape\n", name);
-                               continue;
-                       }
-                       if (mflag)
-                               pathcheck(name);
-                       if (hflag)
-                               treescan(name, ino, addfile);
-                       else
-                               addfile(name, ino, inodetype(ino));
-               }
-               createfiles();
-               createlinks();
-               setdirmodes(dirmodefile);
-               if (dflag)
-                       checkrestore();
-               done(0);
-
+               extractdirs(1);
+               initsymtable(NULL);
+               runcmdshell();
+               break;
+       /*
+        * Incremental restoration of a file system.
+        */
        case 'r':
                setup();
                if (dumptime > 0) {
        case 'r':
                setup();
                if (dumptime > 0) {
@@ -184,7 +185,7 @@ usage:
                         */
                        vprintf(stdout, "Begin incremental restore\n");
                        initsymtable(symtbl);
                         */
                        vprintf(stdout, "Begin incremental restore\n");
                        initsymtable(symtbl);
-                       extractdirs(dirmodefile);
+                       extractdirs(1);
                        removeoldleaves();
                        vprintf(stdout, "Calculate node updates.\n");
                        treescan(".", ROOTINO, nodeupdates);
                        removeoldleaves();
                        vprintf(stdout, "Calculate node updates.\n");
                        treescan(".", ROOTINO, nodeupdates);
@@ -196,30 +197,176 @@ usage:
                         */
                        vprintf(stdout, "Begin level 0 restore\n");
                        initsymtable((char *)0);
                         */
                        vprintf(stdout, "Begin level 0 restore\n");
                        initsymtable((char *)0);
-                       extractdirs(dirmodefile);
+                       extractdirs(1);
                        vprintf(stdout, "Calculate extraction list.\n");
                        treescan(".", ROOTINO, nodeupdates);
                }
                createleaves(symtbl);
                createlinks();
                        vprintf(stdout, "Calculate extraction list.\n");
                        treescan(".", ROOTINO, nodeupdates);
                }
                createleaves(symtbl);
                createlinks();
-               setdirmodes(dirmodefile);
+               setdirmodes(FORCE);
                checkrestore();
                if (dflag) {
                        vprintf(stdout, "Verify the directory structure\n");
                        treescan(".", ROOTINO, verifyfile);
                }
                dumpsymtable(symtbl, (long)1);
                checkrestore();
                if (dflag) {
                        vprintf(stdout, "Verify the directory structure\n");
                        treescan(".", ROOTINO, verifyfile);
                }
                dumpsymtable(symtbl, (long)1);
-               done(0);
-
+               break;
+       /*
+        * Resume an incremental file system restoration.
+        */
        case 'R':
                initsymtable(symtbl);
                skipmaps();
                skipdirs();
                createleaves(symtbl);
                createlinks();
        case 'R':
                initsymtable(symtbl);
                skipmaps();
                skipdirs();
                createleaves(symtbl);
                createlinks();
-               setdirmodes(dirmodefile);
+               setdirmodes(FORCE);
                checkrestore();
                dumpsymtable(symtbl, (long)1);
                checkrestore();
                dumpsymtable(symtbl, (long)1);
-               done(0);
+               break;
+       /*
+        * List contents of tape.
+        */
+       case 't':
+               setup();
+               extractdirs(0);
+               initsymtable((char *)0);
+               while (argc--) {
+                       canon(*argv++, name);
+                       ino = dirlookup(name);
+                       if (ino == 0)
+                               continue;
+                       treescan(name, ino, listfile);
+               }
+               break;
+       /*
+        * Batch extraction of tape contents.
+        */
+       case 'x':
+               setup();
+               extractdirs(1);
+               initsymtable((char *)0);
+               while (argc--) {
+                       canon(*argv++, name);
+                       ino = dirlookup(name);
+                       if (ino == 0)
+                               continue;
+                       if (mflag)
+                               pathcheck(name);
+                       treescan(name, ino, addfile);
+               }
+               createfiles();
+               createlinks();
+               setdirmodes(0);
+               if (dflag)
+                       checkrestore();
+               break;
        }
        }
+       done(0);
+       /* NOTREACHED */
+}
+
+static void
+usage()
+{
+       (void)fprintf(stderr, "usage:\t%s%s%s%s%s",
+           "restore tfhsvy [file ...]\n",
+           "\trestore xfhmsvy [file ...]\n",
+           "\trestore ifhmsvy\n",
+           "\trestore rfsvy\n",
+           "\trestore Rfsvy\n");
+       done(1);
+}
+
+/*
+ * obsolete --
+ *     Change set of key letters and ordered arguments into something
+ *     getopt(3) will like.
+ */
+static void
+obsolete(argcp, argvp)
+       int *argcp;
+       char **argvp[];
+{
+       int argc, flags;
+       char *ap, **argv, *flagsp, **nargv, *p;
+
+       /* Setup. */
+       argv = *argvp;
+       argc = *argcp;
+
+       /* Return if no arguments or first argument has leading dash. */
+       ap = argv[1];
+       if (argc == 1 || *ap == '-')
+               return;
+
+       /* Allocate space for new arguments. */
+       if ((*argvp = nargv = malloc((argc + 1) * sizeof(char *))) == NULL ||
+           (p = flagsp = malloc(strlen(ap) + 2)) == NULL)
+               err("%s", strerror(errno));
+
+       *nargv++ = *argv;
+       argv += 2;
+
+       for (flags = 0; *ap; ++ap) {
+               switch(*ap) {
+               case 'b':
+               case 'f':
+               case 's':
+                       if ((nargv[0] = malloc(strlen(*argv) + 2 + 1)) == NULL)
+                               err("%s", strerror(errno));
+                       nargv[0][0] = '-';
+                       nargv[0][1] = *ap;
+                       (void)strcpy(&nargv[0][2], *argv);
+                       if (*argv != NULL)
+                               ++argv;
+                       ++nargv;
+                       break;
+               default:
+                       if (!flags) {
+                               *p++ = '-';
+                               flags = 1;
+                       }
+                       *p++ = *ap;
+                       break;
+               }
+       }
+
+       /* Terminate flags. */
+       if (flags) {
+               *p = '\0';
+               *nargv++ = flagsp;
+       }
+
+       /* Copy remaining arguments. */
+       while (*nargv++ = *argv++);
+}
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+__dead void
+#if __STDC__
+err(const char *fmt, ...)
+#else
+err(fmt, va_alist)
+       char *fmt;
+        va_dcl
+#endif
+{
+       va_list ap;
+#if __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+       (void)fprintf(stderr, "restore: ");
+       (void)vfprintf(stderr, fmt, ap);
+       va_end(ap);
+       (void)fprintf(stderr, "\n");
+       exit(1);
+       /* NOTREACHED */
 }
 }