]> Dogcows Code - chaz/tar/blobdiff - src/tar.c
(decode_options): Adjust to addname's new signature.
[chaz/tar] / src / tar.c
index 24b0f90bf72097c17f9dd5da1ca734397968d49c..61b7bcae2dc00ebf71870a2b7d0c31984b2a2857 100644 (file)
--- a/src/tar.c
+++ b/src/tar.c
@@ -1,5 +1,5 @@
 /* A tar (tape archiver) program.
-   Copyright (C) 1988, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc.
+   Copyright 1988, 92,93,94,95,96,97, 1999 Free Software Foundation, Inc.
    Written by John Gilmore, starting 1985-08-25.
 
    This program is free software; you can redistribute it and/or modify it
 
    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
-   59 Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "system.h"
 
 #include <getopt.h>
 
+#include <signal.h>
+#if ! defined SIGCHLD && defined SIGCLD
+# define SIGCHLD SIGCLD
+#endif
+
 /* The following causes "common.h" to produce definitions of all the global
    variables, rather than just "extern" declarations of them.  GNU tar does
    depend on the system loader to preset all GLOBAL variables to neutral (or
 #define GLOBAL
 #include "common.h"
 
-#include "backupfile.h"
-enum backup_type get_version ();
-
-/* FIXME: We should use a conversion routine that does reasonable error
-   checking -- atoi doesn't.  For now, punt.  */
-#define intconv        atoi
+#include "xstrtol.h"
 
 time_t get_date ();
 
@@ -50,39 +50,6 @@ static void usage PARAMS ((int));
 \f
 /* Miscellaneous.  */
 
-/*------------------------------------------------------------------------.
-| Check if STRING is the decimal representation of number, and return its |
-| value.  If not a decimal number, return -1.                            |
-`------------------------------------------------------------------------*/
-
-static int
-check_decimal (const char *string)
-{
-  int value = -1;
-
-  while (*string)
-    switch (*string)
-      {
-      case '0':
-      case '1':
-      case '2':
-      case '3':
-      case '4':
-      case '5':
-      case '6':
-      case '7':
-      case '8':
-      case '9':
-       value = value < 0 ? *string - '0' : 10 * value + *string - '0';
-       string++;
-       break;
-
-      default:
-       return -1;
-      }
-    return value;
-}
-
 /*----------------------------------------------.
 | Doesn't return if stdin already requested.    |
 `----------------------------------------------*/
@@ -144,39 +111,40 @@ confirm (const char *message_action, const char *message_name)
    do it.  For the others, we share the code for the equivalent short
    named option, the name of which is stored in the otherwise-unused `val'
    field of the `struct option'; for long options that have no equivalent
-   short option, we use nongraphic characters as pseudo short option
-   characters, starting at 2 and going upwards.  */
-
-#define BACKUP_OPTION                  2
-#define DELETE_OPTION                  3
-#define EXCLUDE_OPTION                 4
-#define GROUP_OPTION                   5
-#define MODE_OPTION                    6
-#define NEWER_MTIME_OPTION             7
-#define NO_RECURSE_OPTION              8
-#define NULL_OPTION                    9
-#define OWNER_OPTION                   10
-#define POSIX_OPTION                   11
-#define PRESERVE_OPTION                        12
-#define RECORD_SIZE_OPTION             13
-#define RSH_COMMAND_OPTION             14
-#define SUFFIX_OPTION                  15
-#define USE_COMPRESS_PROGRAM_OPTION    16
-#define VOLNO_FILE_OPTION              17
-
-/* Some cleanup is being made in GNU tar long options.  Using old names is
-   allowed for a while, but will also send a warning to stderr.  Take old
-   names out in 1.14, or in summer 1997, whichever happens last.  We use
-   nongraphic characters as pseudo short option characters, starting at 31
-   and going downwards.  */
-
-#define OBSOLETE_ABSOLUTE_NAMES                31
-#define OBSOLETE_BLOCK_COMPRESS                30
-#define OBSOLETE_BLOCKING_FACTOR       29
-#define OBSOLETE_BLOCK_NUMBER          28
-#define OBSOLETE_READ_FULL_RECORDS     27
-#define OBSOLETE_TOUCH                 26
-#define OBSOLETE_VERSION_CONTROL       25
+   short option, we use non-characters as pseudo short options,
+   starting at CHAR_MAX + 1 and going upwards.  */
+
+enum
+{
+  BACKUP_OPTION = CHAR_MAX + 1,
+  DELETE_OPTION,
+  EXCLUDE_OPTION,
+  GROUP_OPTION,
+  MODE_OPTION,
+  NEWER_MTIME_OPTION,
+  NO_RECURSE_OPTION,
+  NULL_OPTION,
+  OWNER_OPTION,
+  POSIX_OPTION,
+  PRESERVE_OPTION,
+  RECORD_SIZE_OPTION,
+  RSH_COMMAND_OPTION,
+  SUFFIX_OPTION,
+  USE_COMPRESS_PROGRAM_OPTION,
+  VOLNO_FILE_OPTION,
+
+  /* Some cleanup is being made in GNU tar long options.  Using old names is
+     allowed for a while, but will also send a warning to stderr.  Take old
+     names out in 1.14, or in summer 1997, whichever happens last.  */
+
+  OBSOLETE_ABSOLUTE_NAMES,
+  OBSOLETE_BLOCK_COMPRESS,
+  OBSOLETE_BLOCKING_FACTOR,
+  OBSOLETE_BLOCK_NUMBER,
+  OBSOLETE_READ_FULL_RECORDS,
+  OBSOLETE_TOUCH,
+  OBSOLETE_VERSION_CONTROL
+};
 
 /* If nonzero, display usage information and exit.  */
 static int show_help = 0;
@@ -196,6 +164,7 @@ struct option long_options[] =
   {"block-number", no_argument, NULL, 'R'},
   {"block-size", required_argument, NULL, OBSOLETE_BLOCKING_FACTOR},
   {"blocking-factor", required_argument, NULL, 'b'},
+  {"bzip2", no_argument, NULL, 'y'},
   {"catenate", no_argument, NULL, 'A'},
   {"checkpoint", no_argument, &checkpoint_option, 1},
   {"compare", no_argument, NULL, 'd'},
@@ -372,6 +341,7 @@ Archive format selection:\n\
               PATTERN                at list/extract time, a globbing PATTERN\n\
   -o, --old-archive, --portability   write a V7 format archive\n\
       --posix                        write a POSIX conformant archive\n\
+  -y, --bzip2                        filter the archive through bzip2\n\
   -z, --gzip, --ungzip               filter the archive through gzip\n\
   -Z, --compress, --uncompress       filter the archive through compress\n\
       --use-compress-program=PROG    filter through PROG (must accept -d)\n"),
@@ -432,7 +402,7 @@ or a device.  *This* `tar' defaults to `-f%s -b%d'.\n"),
              DEFAULT_ARCHIVE, DEFAULT_BLOCKING);
       fputs (_("\
 \n\
-Report bugs to <tar-bugs@gnu.ai.mit.edu>.\n"),
+Report bugs to <bug-tar@gnu.org>.\n"),
               stdout);
     }
   exit (status);
@@ -448,7 +418,7 @@ Report bugs to <tar-bugs@gnu.ai.mit.edu>.\n"),
    Y  per-block gzip compression */
 
 #define OPTION_STRING \
-  "-01234567ABC:F:GK:L:MN:OPRST:UV:WX:Zb:cdf:g:hiklmoprstuvwxz"
+  "-01234567ABC:F:GK:L:MN:OPRST:UV:WX:Zb:cdf:g:hiklmoprstuvwxyz"
 
 static void
 set_subcommand_option (enum subcommand subcommand)
@@ -470,13 +440,25 @@ set_use_compress_program_option (const char *string)
   use_compress_program_option = string;
 }
 
+/* Ignore DUMMY (which will always be null in practice), and add
+   PATTERN to the proper set of patterns to be excluded -- either
+   patterns with slashes, or patterns without.  */
+static void
+add_filtered_exclude (struct exclude *dummy, char const *pattern)
+{
+  add_exclude ((strchr (pattern, '/')
+               ? excluded_with_slash
+               : excluded_without_slash),
+              pattern);
+}
+
 static void
 decode_options (int argc, char *const *argv)
 {
   int optchar;                 /* option letter */
   int input_files;             /* number of input files */
   const char *backup_suffix_string;
-  const char *version_control_string;
+  const char *version_control_string = NULL;
 
   /* Set some default option values.  */
 
@@ -484,12 +466,14 @@ decode_options (int argc, char *const *argv)
   archive_format = DEFAULT_FORMAT;
   blocking_factor = DEFAULT_BLOCKING;
   record_size = DEFAULT_BLOCKING * BLOCKSIZE;
+  excluded_with_slash = new_exclude ();
+  excluded_without_slash = new_exclude ();
+  newer_mtime_option = TYPE_MINIMUM (time_t);
 
   owner_option = -1;
   group_option = -1;
 
   backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
-  version_control_string = getenv ("VERSION_CONTROL");
 
   /* Convert old-style tar call by exploding option element and rearranging
      options accordingly.  */
@@ -526,11 +510,13 @@ decode_options (int argc, char *const *argv)
          *out++ = xstrdup (buffer);
          cursor = strchr (OPTION_STRING, *letter);
          if (cursor && cursor[1] == ':')
-           if (in < argv + argc)
-             *out++ = *in++;
-           else
-             USAGE_ERROR ((0, 0, _("Old option `%c' requires an argument."),
-                           *letter));
+           {
+             if (in < argv + argc)
+               *out++ = *in++;
+             else
+               USAGE_ERROR ((0, 0, _("Old option `%c' requires an argument."),
+                             *letter));
+           }
        }
 
       /* Copy all remaining options.  */
@@ -579,8 +565,14 @@ decode_options (int argc, char *const *argv)
        /* Fall through.  */
 
       case 'b':
-       blocking_factor = intconv (optarg);
-       record_size = blocking_factor * BLOCKSIZE;
+       {
+         uintmax_t u;
+         if (! (xstrtoumax (optarg, (char **) 0, 10, &u, "") == LONGINT_OK
+                && u == (blocking_factor = u)
+                && 0 < blocking_factor
+                && u == (record_size = u * (size_t) BLOCKSIZE) / BLOCKSIZE))
+           USAGE_ERROR ((0, 0, _("Invalid blocking factor")));
+       }
        break;
 
       case OBSOLETE_READ_FULL_RECORDS:
@@ -633,6 +625,7 @@ decode_options (int argc, char *const *argv)
 
       case 'g':
        listed_incremental_option = optarg;
+       after_date_option = 1;
        /* Fall through.  */
 
       case 'G':
@@ -665,7 +658,7 @@ decode_options (int argc, char *const *argv)
 
       case 'K':
        starting_file_option = 1;
-       addname (optarg);
+       addname (optarg, NULL);
        break;
 
       case 'l':
@@ -676,10 +669,13 @@ decode_options (int argc, char *const *argv)
        break;
 
       case 'L':
-       clear_tarlong (tape_length_option);
-       add_to_tarlong (tape_length_option, intconv (optarg));
-       mult_tarlong (tape_length_option, 1024);
-       multi_volume_option = 1;
+       {
+         uintmax_t u;
+         if (xstrtoumax (optarg, (char **) 0, 10, &u, "") != LONG_MAX)
+           USAGE_ERROR ((0, 0, _("Invalid tape length")));
+         tape_length_option = 1024 * (tarlong) u;
+         multi_volume_option = 1;
+       }
        break;
 
       case OBSOLETE_TOUCH:
@@ -703,7 +699,7 @@ decode_options (int argc, char *const *argv)
        /* Fall through.  */
 
       case NEWER_MTIME_OPTION:
-       if (newer_mtime_option)
+       if (newer_mtime_option != TYPE_MINIMUM (time_t))
          USAGE_ERROR ((0, 0, _("More than one threshold date")));
 
        newer_mtime_option = get_date (optarg, (voidstar) 0);
@@ -803,8 +799,12 @@ decode_options (int argc, char *const *argv)
        break;
 
       case 'X':
-       exclude_option = 1;
-       add_exclude_file (optarg);
+       if (add_exclude_file (add_filtered_exclude, NULL, optarg, '\n') != 0)
+         FATAL_ERROR ((0, errno, "%s", optarg));
+       break;
+
+      case 'y':
+       set_use_compress_program_option ("bzip2");
        break;
 
       case 'z':
@@ -830,16 +830,20 @@ decode_options (int argc, char *const *argv)
        break;
 
       case EXCLUDE_OPTION:
-       exclude_option = 1;
-       add_exclude (optarg);
+       add_filtered_exclude (NULL, optarg);
        break;
 
       case GROUP_OPTION:
-       if (!gname_to_gid (optarg, &group_option))
-         if (!check_decimal (optarg) >= 0)
-           ERROR ((TAREXIT_FAILURE, 0, _("Invalid group given on option")));
-         else
-           group_option = check_decimal (optarg);
+       if (! (strlen (optarg) < GNAME_FIELD_SIZE
+              && gname_to_gid (optarg, &group_option)))
+         {
+           uintmax_t g;
+           if (xstrtoumax (optarg, (char **) 0, 10, &g, "") == LONGINT_OK
+               && g == (gid_t) g)
+             group_option = g;
+           else
+             FATAL_ERROR ((0, 0, _("Invalid group given on option")));
+         }
        break;
 
       case MODE_OPTION:
@@ -847,9 +851,9 @@ decode_options (int argc, char *const *argv)
          = mode_compile (optarg,
                          MODE_MASK_EQUALS | MODE_MASK_PLUS | MODE_MASK_MINUS);
        if (mode_option == MODE_INVALID)
-         ERROR ((TAREXIT_FAILURE, 0, _("Invalid mode given on option")));
+         FATAL_ERROR ((0, 0, _("Invalid mode given on option")));
        if (mode_option == MODE_MEMORY_EXHAUSTED)
-         ERROR ((TAREXIT_FAILURE, 0, _("Memory exhausted")));
+         FATAL_ERROR ((0, 0, _("Memory exhausted")));
        break;
 
       case NO_RECURSE_OPTION:
@@ -861,11 +865,16 @@ decode_options (int argc, char *const *argv)
        break;
 
       case OWNER_OPTION:
-       if (!uname_to_uid (optarg, &owner_option))
-         if (!check_decimal (optarg) >= 0)
-           ERROR ((TAREXIT_FAILURE, 0, _("Invalid owner given on option")));
-         else
-           owner_option = check_decimal (optarg);
+       if (! (strlen (optarg) < UNAME_FIELD_SIZE
+              && uname_to_uid (optarg, &owner_option)))
+         {
+           uintmax_t u;
+           if (xstrtoumax (optarg, (char **) 0, 10, &u, "") == LONGINT_OK
+               && u == (uid_t) u)
+             owner_option = u;
+           else
+             FATAL_ERROR ((0, 0, _("Invalid owner given on option")));
+         }
        break;
 
       case POSIX_OPTION:
@@ -888,11 +897,17 @@ decode_options (int argc, char *const *argv)
        break;
 
       case RECORD_SIZE_OPTION:
-       record_size = intconv (optarg);
-       if (record_size % BLOCKSIZE != 0)
-         USAGE_ERROR ((0, 0, _("Record size must be a multiple of %d."),
-                       BLOCKSIZE));
-       blocking_factor = record_size / BLOCKSIZE;
+       {
+         uintmax_t u;
+         if (! (xstrtoumax (optarg, (char **) 0, 10, &u, "") == LONG_MAX
+                && u == (size_t) u))
+           USAGE_ERROR ((0, 0, _("Invalid record size")));
+         record_size = u;
+         if (record_size % BLOCKSIZE != 0)
+           USAGE_ERROR ((0, 0, _("Record size must be a multiple of %d."),
+                         BLOCKSIZE));
+         blocking_factor = record_size / BLOCKSIZE;
+       }
        break;
 
       case RSH_COMMAND_OPTION:
@@ -998,7 +1013,7 @@ decode_options (int argc, char *const *argv)
       printf ("tar (GNU %s) %s\n", PACKAGE, VERSION);
       fputs (_("\
 \n\
-Copyright (C) 1988, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc.\n"),
+Copyright 1988, 92,93,94,95,96,97,98, 1999 Free Software Foundation, Inc.\n"),
             stdout);
       fputs (_("\
 This is free software; see the source for copying conditions.  There is NO\n\
@@ -1051,6 +1066,11 @@ Written by John Gilmore and Jay Fenlason.\n"),
     USAGE_ERROR ((0, 0,
                  _("Multiple archive files requires `-M' option")));
 
+  if (listed_incremental_option
+      && newer_mtime_option != TYPE_MINIMUM (time_t))
+    USAGE_ERROR ((0, 0,
+                 _("Cannot combine --listed-incremental with --newer")));
+
   /* If ready to unlink hierarchies, so we are for simpler files.  */
   if (recursive_unlink_option)
     unlink_first_option = 1;
@@ -1098,7 +1118,7 @@ Written by John Gilmore and Jay Fenlason.\n"),
     simple_backup_suffix = xstrdup (backup_suffix_string);
 
   if (backup_option)
-    backup_type = get_version (version_control_string);
+    backup_type = xget_version ("--backup", version_control_string);
 }
 \f
 /* Tar proper.  */
@@ -1125,6 +1145,11 @@ main (int argc, char *const *argv)
     xmalloc (sizeof (const char *) * allocated_archive_names);
   archive_names = 0;
 
+#ifdef SIGCHLD
+  /* System V fork+wait does not work if SIGCHLD is ignored.  */
+  signal (SIGCHLD, SIG_DFL);
+#endif
+
   init_names ();
 
   /* Decode options.  */
@@ -1154,9 +1179,6 @@ main (int argc, char *const *argv)
       break;
 
     case CREATE_SUBCOMMAND:
-      if (totals_option)
-       init_total_written ();
-
       create_archive ();
       name_close ();
 
This page took 0.031694 seconds and 4 git commands to generate.