]> Dogcows Code - chaz/tar/commitdiff
New option --sort=ORDER
authorSergey Poznyakoff <gray@gnu.org>
Thu, 13 Feb 2014 22:11:57 +0000 (00:11 +0200)
committerSergey Poznyakoff <gray@gnu.org>
Thu, 13 Feb 2014 22:26:49 +0000 (00:26 +0200)
This option makes tar sort the entries of directories that will be
added to an archive according to ORDER (none, name, or order).

Based on proposition by Dick Streefland (https://savannah.gnu.org/patch/?7892).

* src/common.h (savedir_sort_order): New global.
* src/create.c: Pass savedir_sort_order to streamsavedir.
* src/misc.c: Likewise.
* src/tar.c: New option --sort.

* NEWS: Update.
* doc/tar.texi: Document the --sort option.
* doc/tar.1: Likewise.

NEWS
doc/tar.1
doc/tar.texi
src/common.h
src/create.c
src/misc.c
src/tar.c

diff --git a/NEWS b/NEWS
index 5cbd1270ae693d0f2be89719ddb1dd12d4149464..ec9c8a75fb5c994a020e8ff8728d44031269a536 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-GNU tar NEWS - User visible changes. 2014-02-13
+GNU tar NEWS - User visible changes. 2014-02-14
 Please send GNU tar bug reports to <bug-tar@gnu.org>
 
 \f
 Please send GNU tar bug reports to <bug-tar@gnu.org>
 
 \f
@@ -35,6 +35,19 @@ supplied DIRectory.  This ensures that no archive members are
 extracted outside of the specified directory, even if the archive is
 crafted so as to put them elsewhere.
 
 extracted outside of the specified directory, even if the archive is
 crafted so as to put them elsewhere.
 
+* New option --sort
+
+The --sort=ORDER option instructs tar to sort directory entries
+according to ORDER.  It takes effect when creating archives.
+Available ORDERs are: none (the default), name and inode.  The
+latter may be absent, if the underlying system does not provide
+the necessary information.
+
+Using --sort=name ensures the member ordering in the created archive
+is uniform and reproducible.  Using --sort=inode reduces the number
+of disk seeks made when creating the archive and thus can considerably
+speed up archivation.
+
 * Manpages
 
 This release includes official tar(1) and rmt(8) manpages.
 * Manpages
 
 This release includes official tar(1) and rmt(8) manpages.
index 14268ed85a6ab54f7bda11a701f4ecab59c6a997..b33f55b9060e27887fdf6e94c25c60023ddcd347 100644 (file)
--- a/doc/tar.1
+++ b/doc/tar.1
@@ -13,7 +13,7 @@
 .\"
 .\" You should have received a copy of the GNU General Public License
 .\" along with this program.  If not, see <http://www.gnu.org/licenses/>.
 .\"
 .\" You should have received a copy of the GNU General Public License
 .\" along with this program.  If not, see <http://www.gnu.org/licenses/>.
-.TH TAR 1 "January 28, 2014" "TAR" "GNU TAR Manual"
+.TH TAR 1 "February 14, 2014" "TAR" "GNU TAR Manual"
 .SH NAME
 tar \- an archiving utility
 .SH SYNOPSIS
 .SH NAME
 tar \- an archiving utility
 .SH SYNOPSIS
@@ -506,6 +506,24 @@ Try extracting files with the same ownership as exists in the archive
 .TP
 \fB\-s\fR, \fB\-\-preserve\-order\fR, \fB\-\-same\-order\fR
 Sort names to extract to match archive
 .TP
 \fB\-s\fR, \fB\-\-preserve\-order\fR, \fB\-\-same\-order\fR
 Sort names to extract to match archive
+.TP
+\fB\-\-sort=\fIORDER\fR
+When creating an archive, sort directory entries according to
+\fIORDER\fR, which is one of
+.BR none ,
+.BR name ", or"
+.BR inode .
+
+The default is \fB\-\-sort=none\fR, which stores archive members in
+the same order as returned by the operating system.
+
+Using \fB\-\-sort=name\fR ensures the member ordering in the created archive
+is uniform and reproducible.
+
+Using \fB\-\-sort=inode\fR reduces the number of disk seeks made when
+creating the archive and thus can considerably speed up archivation.
+This sorting order is supported only if the underlying system provides
+the necessary information.
 .SS Device selection and switching
 .TP
 \fB\-f\fR, \fB\-\-file\fR=\fIARCHIVE\fR
 .SS Device selection and switching
 .TP
 \fB\-f\fR, \fB\-\-file\fR=\fIARCHIVE\fR
index 2be123ac9751a22f12111d33772b6814edc0819c..9bb5a833c8c4c0d09d6f8012c13c44ab52dfc1d4 100644 (file)
@@ -3319,6 +3319,27 @@ The @option{--warning=existing-file} option can be used together with
 this option to produce warning messages about existing old files
 (@pxref{warnings}).
 
 this option to produce warning messages about existing old files
 (@pxref{warnings}).
 
+@opsummary{sort}
+@item --sort=@var{order}
+Specify the directory sorting order when reading directories.
+@var{Order} may be one of the following:
+
+@table @samp
+@item none
+No directory sorting is performed. This is the default.
+
+@item name
+Sort the directory entries on name. The operating system may deliver
+directory entries in a more or less random order, and sorting them
+makes archive creation reproducible.
+
+@item inode
+Sort the directory entries on inode number. Sorting directories on
+inode number may reduce the amount of disk seek operations when
+creating an archive for some file systems.
+
+@end table
+
 @opsummary{sparse}
 @item --sparse
 @itemx -S
 @opsummary{sparse}
 @item --sparse
 @itemx -S
index 14ae2caddfbb8e3db77bceaa6cef3c4a666fdbe3..4d2c3994181051b6bfa95b537ee3219dfb80e2fe 100644 (file)
@@ -386,6 +386,8 @@ GLOBAL dev_t root_device;
 /* Unquote filenames */
 GLOBAL bool unquote_option;
 
 /* Unquote filenames */
 GLOBAL bool unquote_option;
 
+GLOBAL int savedir_sort_order;
+
 /* Show file or archive names after transformation.
    In particular, when creating archive in verbose mode, list member names
    as stored in the archive */
 /* Show file or archive names after transformation.
    In particular, when creating archive in verbose mode, list member names
    as stored in the archive */
index 24920db37b967b99ea803d1418c7cb02141100cd..3455bddc60c74016bcad238e0e416ee1f2ad5895 100644 (file)
@@ -1288,7 +1288,7 @@ get_directory_entries (struct tar_stat_info *st)
   while (! (st->dirstream = fdopendir (st->fd)))
     if (! open_failure_recover (st))
       return 0;
   while (! (st->dirstream = fdopendir (st->fd)))
     if (! open_failure_recover (st))
       return 0;
-  return streamsavedir (st->dirstream);
+  return streamsavedir (st->dirstream, savedir_sort_order);
 }
 
 /* Dump the directory ST.  Return true if successful, false (emitting
 }
 
 /* Dump the directory ST.  Return true if successful, false (emitting
index e92c8aa830e36fe2fca6cd25aeaf9f107d7b6bac..cc2fef85a6c5781904ea9ca496c6ea26de9b1bb9 100644 (file)
@@ -1239,7 +1239,7 @@ tar_savedir (const char *name, int must_exist)
       open_error (name);
     }
   else if (! ((dir = fdopendir (fd))
       open_error (name);
     }
   else if (! ((dir = fdopendir (fd))
-             && (ret = streamsavedir (dir))))
+             && (ret = streamsavedir (dir, savedir_sort_order))))
     savedir_error (name);
 
   if (dir ? closedir (dir) != 0 : 0 <= fd && close (fd) != 0)
     savedir_error (name);
 
   if (dir ? closedir (dir) != 0 : 0 <= fd && close (fd) != 0)
index 7cd25c0472a27db95fd8b98a200af4ffe851a809..f36e1518455baa8e91abac3473abca73608de25f 100644 (file)
--- a/src/tar.c
+++ b/src/tar.c
@@ -51,6 +51,7 @@
 #include <xstrtol.h>
 #include <stdopen.h>
 #include <priv-set.h>
 #include <xstrtol.h>
 #include <stdopen.h>
 #include <priv-set.h>
+#include <savedir.h>
 
 /* Local declarations.  */
 
 
 /* Local declarations.  */
 
@@ -342,6 +343,7 @@ enum
   SHOW_SNAPSHOT_FIELD_RANGES_OPTION,
   SHOW_TRANSFORMED_NAMES_OPTION,
   SKIP_OLD_FILES_OPTION,
   SHOW_SNAPSHOT_FIELD_RANGES_OPTION,
   SHOW_TRANSFORMED_NAMES_OPTION,
   SKIP_OLD_FILES_OPTION,
+  SORT_OPTION,
   SPARSE_VERSION_OPTION,
   STRIP_COMPONENTS_OPTION,
   SUFFIX_OPTION,
   SPARSE_VERSION_OPTION,
   STRIP_COMPONENTS_OPTION,
   SUFFIX_OPTION,
@@ -551,6 +553,13 @@ static struct argp_option options[] = {
       " directories until the end of extraction"), GRID+1 },
   {"no-delay-directory-restore", NO_DELAY_DIRECTORY_RESTORE_OPTION, 0, 0,
    N_("cancel the effect of --delay-directory-restore option"), GRID+1 },
       " directories until the end of extraction"), GRID+1 },
   {"no-delay-directory-restore", NO_DELAY_DIRECTORY_RESTORE_OPTION, 0, 0,
    N_("cancel the effect of --delay-directory-restore option"), GRID+1 },
+  {"sort", SORT_OPTION, N_("ORDER"), 0,
+#if D_INO_IN_DIRENT
+   N_("directory sorting order: none (default), name or inode"
+#else
+   N_("directory sorting order: none (default) or name"
+#endif
+     ), GRID+1 },
 #undef GRID
 
 #define GRID 55
 #undef GRID
 
 #define GRID 55
@@ -1310,6 +1319,21 @@ parse_owner_group (char *arg, uintmax_t field_max, char const **name_option)
 /* Either NL or NUL, as decided by the --null option.  */
 static char filename_terminator;
 
 /* Either NL or NUL, as decided by the --null option.  */
 static char filename_terminator;
 
+static char const *const sort_mode_arg[] = {
+  "none",
+  "name",
+  "inode",
+  NULL
+};
+
+static int sort_mode_flag[] = {
+    SAVEDIR_SORT_NONE,
+    SAVEDIR_SORT_NAME,
+    SAVEDIR_SORT_INODE
+};
+
+ARGMATCH_VERIFY (sort_mode_arg, sort_mode_flag);
+
 static error_t
 parse_opt (int key, char *arg, struct argp_state *state)
 {
 static error_t
 parse_opt (int key, char *arg, struct argp_state *state)
 {
@@ -1997,6 +2021,11 @@ parse_opt (int key, char *arg, struct argp_state *state)
       show_transformed_names_option = true;
       break;
 
       show_transformed_names_option = true;
       break;
 
+    case SORT_OPTION:
+      savedir_sort_order = XARGMATCH ("--sort", arg,
+                                     sort_mode_arg, sort_mode_flag);
+      break;
+
     case SUFFIX_OPTION:
       backup_option = true;
       args->backup_suffix_string = arg;
     case SUFFIX_OPTION:
       backup_option = true;
       args->backup_suffix_string = arg;
@@ -2274,6 +2303,8 @@ decode_options (int argc, char **argv)
   tar_sparse_major = 1;
   tar_sparse_minor = 0;
 
   tar_sparse_major = 1;
   tar_sparse_minor = 0;
 
+  savedir_sort_order = SAVEDIR_SORT_NONE;
+  
   owner_option = -1; owner_name_option = NULL;
   group_option = -1; group_name_option = NULL;
 
   owner_option = -1; owner_name_option = NULL;
   group_option = -1; group_name_option = NULL;
 
This page took 0.038965 seconds and 4 git commands to generate.