]> Dogcows Code - chaz/tar/blobdiff - src/tar.c
Improve command line option handling.
[chaz/tar] / src / tar.c
index 943de847457a558e9d80e927f8a224f6dcea4ad1..d4fda6fad53c8df89902e23b95fc2ef339eb21b9 100644 (file)
--- a/src/tar.c
+++ b/src/tar.c
@@ -25,6 +25,7 @@
 #include <argp.h>
 #include <argp-namefrob.h>
 #include <argp-fmtstream.h>
+#include <argp-version-etc.h>
 
 #include <signal.h>
 #if ! defined SIGCHLD && defined SIGCLD
@@ -256,6 +257,7 @@ enum
   DELAY_DIRECTORY_RESTORE_OPTION,
   HARD_DEREFERENCE_OPTION,
   DELETE_OPTION,
+  EXCLUDE_BACKUPS_OPTION,
   EXCLUDE_CACHES_OPTION,
   EXCLUDE_CACHES_UNDER_OPTION,
   EXCLUDE_CACHES_ALL_OPTION,
@@ -266,7 +268,6 @@ enum
   EXCLUDE_VCS_OPTION,
   FORCE_LOCAL_OPTION,
   GROUP_OPTION,
-  HANG_OPTION,
   IGNORE_CASE_OPTION,
   IGNORE_COMMAND_ERROR_OPTION,
   IGNORE_FAILED_READ_OPTION,
@@ -290,6 +291,7 @@ enum
   NO_RECURSION_OPTION,
   NO_SAME_OWNER_OPTION,
   NO_SAME_PERMISSIONS_OPTION,
+  NO_SEEK_OPTION,
   NO_UNQUOTE_OPTION,
   NO_WILDCARDS_MATCH_SLASH_OPTION,
   NO_WILDCARDS_OPTION,
@@ -325,9 +327,7 @@ enum
   TO_COMMAND_OPTION,
   TRANSFORM_OPTION,
   UNQUOTE_OPTION,
-  USAGE_OPTION,
   UTC_OPTION,
-  VERSION_OPTION,
   VOLNO_FILE_OPTION,
   WARNING_OPTION, 
   WILDCARDS_MATCH_SLASH_OPTION,
@@ -365,7 +365,12 @@ The version control may be set with --backup or VERSION_CONTROL, values are:\n\n
    [q  alias for --occurrence=1 =/= this would better be used for quiet?]
 
    y  per-file gzip compression
-   Y  per-block gzip compression */
+   Y  per-block gzip compression.
+
+   Additionally, the 'n' letter is assigned for option --seek, which
+   is probably not needed and should be marked as deprecated, so that
+   -n may become available in the future.
+*/
 
 static struct argp_option options[] = {
 #define GRID 10
@@ -419,6 +424,8 @@ static struct argp_option options[] = {
       " NUMBER defaults to 1"), GRID+1 },
   {"seek", 'n', NULL, 0,
    N_("archive is seekable"), GRID+1 },
+  {"no-seek", NO_SEEK_OPTION, NULL, 0,
+   N_("archive is not seekable"), GRID+1 },
   {"no-check-device", NO_CHECK_DEVICE_OPTION, NULL, 0,
    N_("do not check device numbers when creating incremental archives"),
    GRID+1 },
@@ -659,6 +666,8 @@ static struct argp_option options[] = {
    N_("exclude directories containing FILE"), GRID+1 },
   {"exclude-vcs", EXCLUDE_VCS_OPTION, NULL, 0,
    N_("exclude version control system directories"), GRID+1 },
+  {"exclude-backups", EXCLUDE_BACKUPS_OPTION, NULL, 0,
+   N_("exclude backup and lock files"), GRID+1 },
   {"no-recursion", NO_RECURSION_OPTION, 0, 0,
    N_("avoid descending automatically in directories"), GRID+1 },
   {"one-file-system", ONE_FILE_SYSTEM_OPTION, 0, 0,
@@ -777,14 +786,6 @@ static struct argp_option options[] = {
 
   {"restrict", RESTRICT_OPTION, 0, 0,
    N_("disable use of some potentially harmful options"), -1 },
-
-  {"help",  '?', 0, 0,  N_("give this help list"), -1},
-  {"usage", USAGE_OPTION, 0, 0,  N_("give a short usage message"), -1},
-  {"version", VERSION_OPTION, 0, 0,  N_("print program version"), -1},
-  /* FIXME -V (--label) conflicts with the default short option for
-     --version */
-  {"HANG",       HANG_OPTION,    "SECS", OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
-   N_("hang for SECS seconds (default 3600)"), 0},
 #undef GRID
 
   {0, 0, 0, 0, 0, 0}
@@ -844,44 +845,52 @@ struct tar_args        /* Variables used during option parsing */
   | (args)->matching_flags \
   | recursion_option)
 
+static char const * const vcs_file_table[] = {
+  /* CVS: */
+  "CVS",
+  ".cvsignore",
+  /* RCS: */
+  "RCS",
+  /* SCCS: */
+  "SCCS",
+  /* SVN: */
+  ".svn",
+  /* git: */
+  ".git",
+  ".gitignore",
+  /* Arch: */
+  ".arch-ids",
+  "{arch}",
+  "=RELEASE-ID",
+  "=meta-update",
+  "=update",
+  /* Bazaar */
+  ".bzr",
+  ".bzrignore",
+  ".bzrtags",
+  /* Mercurial */
+  ".hg",
+  ".hgignore",
+  ".hgtags",
+  /* darcs */
+  "_darcs",
+  NULL
+};
+
+static char const * const backup_file_table[] = {
+  ".#*",
+  "*~",
+  "#*#",
+  NULL
+};
+
 void
-exclude_vcs_files ()
+add_exclude_array (char const * const * fv)
 {
   int i;
-  static char *vcs_file[] = {
-    /* CVS: */
-    "CVS",
-    ".cvsignore",
-    /* RCS: */
-    "RCS",
-    /* SCCS: */
-    "SCCS",
-    /* SVN: */
-    ".svn",
-    /* git: */
-    ".git",
-    ".gitignore",
-    /* Arch: */
-    ".arch-ids",
-    "{arch}",
-    "=RELEASE-ID",
-    "=meta-update",
-    "=update",
-    /* Bazaar */
-    ".bzr",
-    ".bzrignore",
-    ".bzrtags",
-    /* Mercurial */
-    ".hg",
-    ".hgignore",
-    ".hgtags",
-    /* darcs */
-    "_darcs",
-    NULL
-  };
 
-  for (i = 0; vcs_file[i]; i++)
-    add_exclude (excluded, vcs_file[i], 0);
+  for (i = 0; fv[i]; i++)
+    add_exclude (excluded, fv[i], 0);
 }
 
 \f
@@ -1055,7 +1064,6 @@ report_textual_dates (struct tar_args *args)
 }
 
 \f
-static volatile int _argp_hang;
 
 /* Either NL or NUL, as decided by the --null option.  */
 static char filename_terminator;
@@ -1446,9 +1454,13 @@ parse_opt (int key, char *arg, struct argp_state *state)
       break;
 
     case 'n':
-      seekable_archive = true;
+      seek_option = 1;
       break;
 
+    case NO_SEEK_OPTION:
+      seek_option = 0;
+      break;
+      
     case 'N':
       after_date_option = true;
       /* Fall through.  */
@@ -1652,6 +1664,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
       set_subcommand_option (DELETE_SUBCOMMAND);
       break;
 
+    case EXCLUDE_BACKUPS_OPTION:
+      add_exclude_array (backup_file_table);
+      break;
+      
     case EXCLUDE_OPTION:
       add_exclude (excluded, arg, MAKE_EXCL_OPTIONS (args));
       break;
@@ -1684,7 +1700,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
       break;
 
     case EXCLUDE_VCS_OPTION:
-      exclude_vcs_files ();
+      add_exclude_array (vcs_file_table);
       break;
       
     case FORCE_LOCAL_OPTION:
@@ -2034,28 +2050,6 @@ parse_opt (int key, char *arg, struct argp_state *state)
 
 #endif /* not DEVICE_PREFIX */
 
-    case '?':
-      tar_help (state);
-      close_stdout ();
-      exit (0);
-
-    case USAGE_OPTION:
-      argp_state_help (state, state->out_stream, ARGP_HELP_USAGE);
-      close_stdout ();
-      exit (0);
-
-    case VERSION_OPTION:
-      version_etc (state->out_stream, "tar", PACKAGE_NAME, VERSION,
-                  "John Gilmore", "Jay Fenlason", (char *) NULL);
-      close_stdout ();
-      exit (0);
-
-    case HANG_OPTION:
-      _argp_hang = atoi (arg ? arg : "3600");
-      while (_argp_hang-- > 0)
-       sleep (1);
-      break;
-
     default:
       return ARGP_ERR_UNKNOWN;
     }
@@ -2096,12 +2090,20 @@ find_argp_option (struct argp_option *o, int letter)
   return NULL;
 }
 
+static const char *tar_authors[] = {
+  "John Gilmore",
+  "Jay Fenlason",
+  NULL
+};
+
 static void
 decode_options (int argc, char **argv)
 {
   int idx;
   struct tar_args args;
 
+  argp_version_setup ("tar", tar_authors);
+  
   /* Set some default option values.  */
   args.textual_date = NULL;
   args.wildcards = default_wildcards;
@@ -2132,6 +2134,8 @@ decode_options (int argc, char **argv)
   check_device_option = true;
 
   incremental_level = -1;
+
+  seek_option = -1;
   
   /* Convert old-style tar call by exploding option element and rearranging
      options accordingly.  */
@@ -2194,8 +2198,7 @@ decode_options (int argc, char **argv)
 
   prepend_default_options (getenv ("TAR_OPTIONS"), &argc, &argv);
 
-  if (argp_parse (&argp, argc, argv, ARGP_IN_ORDER|ARGP_NO_HELP,
-                 &idx, &args))
+  if (argp_parse (&argp, argc, argv, ARGP_IN_ORDER, &idx, &args))
     exit (TAREXIT_FAILURE);
 
 
@@ -2264,18 +2267,6 @@ decode_options (int argc, char **argv)
                          _("--occurrence cannot be used in the requested operation mode")));
     }
 
-  if (seekable_archive && subcommand_option == DELETE_SUBCOMMAND)
-    {
-      /* The current code in delete.c is based on the assumption that
-        skip_member() reads all data from the archive. So, we should
-        make sure it won't use seeks. On the other hand, the same code
-        depends on the ability to backspace a record in the archive,
-        so setting seekable_archive to false is technically incorrect.
-         However, it is tested only in skip_member(), so it's not a
-        problem. */
-      seekable_archive = false;
-    }
-
   if (archive_names == 0)
     {
       /* If no archive file name given, try TAPE from the environment, or
@@ -2560,7 +2551,7 @@ main (int argc, char **argv)
   if (stdlis == stdout)
     close_stdout ();
   else if (ferror (stderr) || fclose (stderr) != 0)
-    exit_status = TAREXIT_FAILURE;
+    set_exit_status (TAREXIT_FAILURE);
 
   return exit_status;
 }
@@ -2598,3 +2589,13 @@ tar_timespec_cmp (struct timespec a, struct timespec b)
     a.tv_nsec = b.tv_nsec = 0;
   return timespec_cmp (a, b);
 }
+
+/* Set tar exit status to VAL, unless it is already indicating
+   a more serious condition. This relies on the fact that the
+   values of TAREXIT_ constants are ranged by severity. */
+void
+set_exit_status (int val)
+{
+  if (val > exit_status)
+    exit_status = val;
+}
This page took 0.027618 seconds and 4 git commands to generate.