]> Dogcows Code - chaz/tar/blobdiff - src/tar.c
Automatic detection of seekable archives.
[chaz/tar] / src / tar.c
index 8d23a4faa656f270dee2a3b70838003a035e81ad..583edc90ea6f549e883186d097f10c496a97bd8e 100644 (file)
--- a/src/tar.c
+++ b/src/tar.c
@@ -256,6 +256,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,
@@ -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,
@@ -365,7 +367,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 +426,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 +668,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,
@@ -844,44 +855,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
@@ -1388,7 +1407,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
 
     case 'K':
       starting_file_option = true;
-      addname (arg, 0, NULL);
+      addname (arg, 0, true, NULL);
       break;
 
     case ONE_FILE_SYSTEM_OPTION:
@@ -1446,9 +1465,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 +1675,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 +1711,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:
@@ -2132,6 +2159,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.  */
@@ -2264,18 +2293,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
This page took 0.026733 seconds and 4 git commands to generate.