]> 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
@@ -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.
 
+* 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.
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/>.
-.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
@@ -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\-\-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
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}).
 
+@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
index 14ae2caddfbb8e3db77bceaa6cef3c4a666fdbe3..4d2c3994181051b6bfa95b537ee3219dfb80e2fe 100644 (file)
@@ -386,6 +386,8 @@ GLOBAL dev_t root_device;
 /* 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 */
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;
-  return streamsavedir (st->dirstream);
+  return streamsavedir (st->dirstream, savedir_sort_order);
 }
 
 /* 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))
-             && (ret = streamsavedir (dir))))
+             && (ret = streamsavedir (dir, savedir_sort_order))))
     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 <savedir.h>
 
 /* Local declarations.  */
 
@@ -342,6 +343,7 @@ enum
   SHOW_SNAPSHOT_FIELD_RANGES_OPTION,
   SHOW_TRANSFORMED_NAMES_OPTION,
   SKIP_OLD_FILES_OPTION,
+  SORT_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 },
+  {"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
@@ -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;
 
+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)
 {
@@ -1997,6 +2021,11 @@ parse_opt (int key, char *arg, struct argp_state *state)
       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;
@@ -2274,6 +2303,8 @@ decode_options (int argc, char **argv)
   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;
 
This page took 0.034084 seconds and 4 git commands to generate.