New option --sort=ORDER

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.
This commit is contained in:
Sergey Poznyakoff
2014-02-14 00:11:57 +02:00
parent 62497f0e26
commit 29a6964af3
7 changed files with 89 additions and 4 deletions

15
NEWS
View File

@@ -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>
@@ -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.

View File

@@ -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

View 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

View 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 */

View 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

View 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)

View File

@@ -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;