BSD 4_4 release
[unix-history] / usr / src / sbin / restore / main.c
index e4ef61b..c717410 100644 (file)
@@ -1,35 +1,69 @@
-/* Copyright (c) 1983 Regents of the University of California */
-
-#ifndef lint
-static char sccsid[] = "@(#)main.c     3.10    (Berkeley)      83/05/15";
-#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 and
- *     interactive tape browser.
- *     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;
 long   volno = 0;
 char   command = '\0';
 long   dumpnum = 1;
 long   volno = 0;
+long   ntrec;
 char   *dumpmap;
 char   *clrimap;
 ino_t  maxino;
 char   *dumpmap;
 char   *clrimap;
 ino_t  maxino;
@@ -37,108 +71,99 @@ time_t     dumptime;
 time_t dumpdate;
 FILE   *terminal;
 
 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 name[MAXPATHLEN];
-       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:\n%s%s%s%s%s",
-                       "\trestore tfhsvy [file file ...]\n",
-                       "\trestore xfhmsvy [file file ...]\n",
-                       "\trestore ifhmsvy\n",
-                       "\trestore rfsvy\n",
-                       "\trestore Rfsvy\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':
-               case 'i':
-                       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 i, 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) {
        /*
         * Interactive mode.
        switch (command) {
        /*
         * Interactive mode.
@@ -146,9 +171,9 @@ usage:
        case 'i':
                setup();
                extractdirs(1);
        case 'i':
                setup();
                extractdirs(1);
-               initsymtable((char *)0);
+               initsymtable(NULL);
                runcmdshell();
                runcmdshell();
-               done(0);
+               break;
        /*
         * Incremental restoration of a file system.
         */
        /*
         * Incremental restoration of a file system.
         */
@@ -178,14 +203,14 @@ usage:
                }
                createleaves(symtbl);
                createlinks();
                }
                createleaves(symtbl);
                createlinks();
-               setdirmodes();
+               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.
         */
        /*
         * Resume an incremental file system restoration.
         */
@@ -195,16 +220,17 @@ usage:
                skipdirs();
                createleaves(symtbl);
                createlinks();
                skipdirs();
                createleaves(symtbl);
                createlinks();
-               setdirmodes();
+               setdirmodes(FORCE);
                checkrestore();
                dumpsymtable(symtbl, (long)1);
                checkrestore();
                dumpsymtable(symtbl, (long)1);
-               done(0);
+               break;
        /*
         * List contents of tape.
         */
        case 't':
                setup();
                extractdirs(0);
        /*
         * List contents of tape.
         */
        case 't':
                setup();
                extractdirs(0);
+               initsymtable((char *)0);
                while (argc--) {
                        canon(*argv++, name);
                        ino = dirlookup(name);
                while (argc--) {
                        canon(*argv++, name);
                        ino = dirlookup(name);
@@ -212,7 +238,7 @@ usage:
                                continue;
                        treescan(name, ino, listfile);
                }
                                continue;
                        treescan(name, ino, listfile);
                }
-               done(0);
+               break;
        /*
         * Batch extraction of tape contents.
         */
        /*
         * Batch extraction of tape contents.
         */
@@ -231,149 +257,116 @@ usage:
                }
                createfiles();
                createlinks();
                }
                createfiles();
                createlinks();
-               setdirmodes();
+               setdirmodes(0);
                if (dflag)
                        checkrestore();
                if (dflag)
                        checkrestore();
-               done(0);
+               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);
 }
 
 /*
 }
 
 /*
- * Read and execute commands from the terminal.
+ * obsolete --
+ *     Change set of key letters and ordered arguments into something
+ *     getopt(3) will like.
  */
  */
-runcmdshell()
+static void
+obsolete(argcp, argvp)
+       int *argcp;
+       char **argvp[];
 {
 {
-       register struct entry *np;
-       ino_t ino;
-       char curdir[MAXPATHLEN];
-       char name[MAXPATHLEN];
-       char cmd[BUFSIZ];
+       int argc, flags;
+       char *ap, **argv, *flagsp, **nargv, *p;
 
 
-       canon("/", curdir);
-loop:
-       getcmd(curdir, cmd, name);
-       switch (cmd[0]) {
-       /*
-        * Add elements to the extraction list.
-        */
-       case 'a':
-               ino = dirlookup(name);
-               if (ino == 0)
-                       break;
-               if (mflag)
-                       pathcheck(name);
-               treescan(name, ino, addfile);
-               break;
-       /*
-        * Change working directory.
-        */
-       case 'c':
-               ino = dirlookup(name);
-               if (ino == 0)
-                       break;
-               if (inodetype(ino) == LEAF) {
-                       fprintf(stderr, "%s: not a directory\n", name);
-                       break;
-               }
-               (void) strcpy(curdir, name);
-               break;
-       /*
-        * Delete elements from the extraction list.
-        */
-       case 'd':
-               np = lookupname(name);
-               if (np == NIL || (np->e_flags & NEW) == 0) {
-                       fprintf(stderr, "%s: not on extraction list\n", name);
-                       break;
-               }
-               treescan(name, np->e_ino, deletefile);
-               break;
-       /*
-        * Extract the requested list.
-        */
-       case 'e':
-               createfiles();
-               createlinks();
-               setdirmodes();
-               if (dflag)
-                       checkrestore();
-               volno = 0;
-               break;
-       /*
-        * List available commands.
-        */
-       case 'h':
-       case '?':
-               fprintf(stderr, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
-                       "Available commands are:\n",
-                       "\tls [arg] - list directory\n",
-                       "\tcd arg - change directory\n",
-                       "\tpwd - print current directory\n",
-                       "\tadd [arg] - add `arg' to list of",
-                       " files to be extracted\n",
-                       "\tdelete [arg] - delete `arg' from",
-                       " list of files to be extracted\n",
-                       "\textract - extract requested files\n",
-                       "\tquit - immediately exit program\n",
-                       "\tverbose - toggle verbose flag",
-                       " (useful with ``ls'')\n",
-                       "\thelp or `?' - print this list\n",
-                       "If no `arg' is supplied, the current",
-                       " directory is used\n");
-               break;
-       /*
-        * List a directory.
-        */
-       case 'l':
-               ino = dirlookup(name);
-               if (ino == 0)
-                       break;
-               printlist(name, ino);
-               break;
-       /*
-        * Print current directory.
-        */
-       case 'p':
-               if (curdir[1] == '\0')
-                       fprintf(stderr, "/\n");
-               else
-                       fprintf(stderr, "%s\n", &curdir[1]);
-               break;
-       /*
-        * Quit.
-        */
-       case 'q':
+       /* Setup. */
+       argv = *argvp;
+       argc = *argcp;
+
+       /* Return if no arguments or first argument has leading dash. */
+       ap = argv[1];
+       if (argc == 1 || *ap == '-')
                return;
                return;
-       /*
-        * Toggle verbose mode.
-        */
-       case 'v':
-               if (vflag) {
-                       fprintf(stderr, "verbose mode off\n");
-                       vflag = 0;
+
+       /* 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;
                        break;
-               }
-               fprintf(stderr, "verbose mode on\n");
-               vflag++;
-               break;
-       /*
-        * Turn on debugging.
-        */
-       case 'D':
-               if (dflag) {
-                       fprintf(stderr, "debugging mode off\n");
-                       dflag = 0;
+               default:
+                       if (!flags) {
+                               *p++ = '-';
+                               flags = 1;
+                       }
+                       *p++ = *ap;
                        break;
                }
                        break;
                }
-               fprintf(stderr, "debugging mode on\n");
-               dflag++;
-               break;
-       /*
-        * Unknown command.
-        */
-       default:
-               fprintf(stderr, "%s: unknown command; type ? for help\n", cmd);
-               break;
        }
        }
-       goto loop;
+
+       /* 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 */
 }
 }