BSD 4_4 release
[unix-history] / usr / src / sbin / restore / main.c
index d883092..c717410 100644 (file)
@@ -1,52 +1,62 @@
 /*
 /*
- * Copyright (c) 1983 The Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley.  The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * 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.
+ *
+ * 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.
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-char copyright[] =
-"@(#) Copyright (c) 1983 The Regents of the University of California.\n\
- All rights reserved.\n";
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1993\n\
      The Regents of the University of California.  All rights reserved.\n";
 #endif /* not lint */
 
 #ifndef lint
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)main.c     5.6 (Berkeley) %G%";
+static char sccsid[] = "@(#)main.c     8.1 (Berkeley) 6/5/93";
 #endif /* not lint */
 
 #endif /* not lint */
 
-/*
- *     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
- *
- *     Modified to work on the new file system and to recover from
- *     tape read errors.
- *     1/19/82         by Kirk McKusick
- *
- *     Full incremental restore running entirely in user code and
- *     interactive tape browser.
- *     1/19/83         by Kirk McKusick
- */
+#include <sys/param.h>
+#include <sys/time.h>
 
 
-#include "restore.h"
+#include <ufs/ffs/fs.h>
+#include <ufs/ufs/dinode.h>
 #include <protocols/dumprestore.h>
 #include <protocols/dumprestore.h>
-#include <sys/signal.h>
+
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
 #include "pathnames.h"
 #include "pathnames.h"
+#include "restore.h"
+#include "extern.h"
 
 int    bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0;
 int    hflag = 1, mflag = 1, Nflag = 0;
 
 int    bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0;
 int    hflag = 1, mflag = 1, Nflag = 0;
@@ -61,127 +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;
        char *inputdev = _PATH_DEFTAPE;
        char *symtbl = "./restoresymtable";
        ino_t ino;
        char *inputdev = _PATH_DEFTAPE;
        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 'N':
                case 'm':
                        mflag = 0;
                        break;
                case 'N':
-                       Nflag++;
+                       Nflag = 1;
+                       break;
+               case 's':
+                       /* 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;
                case 'v':
                        break;
                case 'v':
-                       vflag++;
+                       vflag = 1;
                        break;
                case 'y':
                        break;
                case 'y':
-                       yflag++;
-                       break;
-               case 'f':
-                       if (argc < 1) {
-                               fprintf(stderr, "missing device specifier\n");
-                               done(1);
-                       }
-                       inputdev = *argv++;
-                       argc--;
-                       break;
-               case 'b':
-                       /*
-                        * change default tape blocksize
-                        */
-                       bflag++;
-                       if (argc < 1) {
-                               fprintf(stderr, "missing block size\n");
-                               done(1);
-                       }
-                       ntrec = atoi(*argv++);
-                       if (ntrec <= 0) {
-                               fprintf(stderr, "Block size must be a positive integer\n");
-                               done(1);
-                       }
-                       argc--;
-                       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--;
-                       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;
+                       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.
@@ -189,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.
         */
@@ -221,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.
         */
@@ -238,10 +220,10 @@ 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.
         */
        /*
         * List contents of tape.
         */
@@ -256,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.
         */
@@ -275,9 +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);
+}
+
+/*
+ * 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 */
 }
 }