diff -uNr tar-1.26a/lib/Makefile.in tar-1.26b/lib/Makefile.in
--- tar-1.26a/lib/Makefile.in 2011-03-12 10:49:46.000000000 +0059
+++ tar-1.26b/lib/Makefile.in 2012-07-11 10:40:56.033513700 +0159
@@ -179,7 +179,7 @@
am__v_at_0 = @
libtar_a_AR = $(AR) $(ARFLAGS)
libtar_a_LIBADD =
-am_libtar_a_OBJECTS = paxerror.$(OBJEXT) paxexit-status.$(OBJEXT) \
+am_libtar_a_OBJECTS = mpsort.$(OBJEXT) paxerror.$(OBJEXT) paxexit-status.$(OBJEXT) \
paxnames.$(OBJEXT) prepargs.$(OBJEXT) rtapelib.$(OBJEXT) \
stdopen.$(OBJEXT)
libtar_a_OBJECTS = $(am_libtar_a_OBJECTS)
@@ -973,6 +973,7 @@
INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu
noinst_HEADERS = system.h system-ioctl.h rmt.h paxlib.h stdopen.h
libtar_a_SOURCES = \
+ mpsort.c mpsort.h \
paxerror.c paxexit-status.c paxlib.h paxnames.c \
prepargs.c prepargs.h \
rtapelib.c \
@@ -1029,6 +1030,7 @@
distclean-compile:
-rm -f *.tab.c
address@hidden@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
@AMDEP_TRUE@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
@AMDEP_TRUE@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
@AMDEP_TRUE@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
diff -uNr tar-1.26a/lib/mpsort.c tar-1.26b/lib/mpsort.c
--- tar-1.26a/lib/mpsort.c 1970-01-01 01:00:00.000000000 +0100
+++ tar-1.26b/lib/mpsort.c 2012-01-06 08:20:26.000000000 +0059
@@ -0,0 +1,156 @@
+/* Sort a vector of pointers to data.
+
+ Copyright (C) 2007, 2009-2012 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see . */
+
+/* Written by Paul Eggert. */
+
+#include
+
+#include "mpsort.h"
+
+#include
+
+/* The type of qsort-style comparison functions. */
+
+typedef int (*comparison_function) (void const *, void const *);
+
+static void mpsort_with_tmp (void const **restrict, size_t,
+ void const **restrict, comparison_function);
+
+/* Sort a vector BASE containing N pointers, placing the sorted array
+ into TMP. Compare pointers with CMP. N must be at least 2. */
+
+static void
+mpsort_into_tmp (void const **restrict base, size_t n,
+ void const **restrict tmp,
+ comparison_function cmp)
+{
+ size_t n1 = n / 2;
+ size_t n2 = n - n1;
+ size_t a = 0;
+ size_t alim = n1;
+ size_t b = n1;
+ size_t blim = n;
+ void const *ba;
+ void const *bb;
+
+ mpsort_with_tmp (base + n1, n2, tmp, cmp);
+ mpsort_with_tmp (base, n1, tmp, cmp);
+
+ ba = base[a];
+ bb = base[b];
+
+ for (;;)
+ if (cmp (ba, bb) <= 0)
+ {
+ *tmp++ = ba;
+ a++;
+ if (a == alim)
+ {
+ a = b;
+ alim = blim;
+ break;
+ }
+ ba = base[a];
+ }
+ else
+ {
+ *tmp++ = bb;
+ b++;
+ if (b == blim)
+ break;
+ bb = base[b];
+ }
+
+ memcpy (tmp, base + a, (alim - a) * sizeof *base);
+}
+
+/* Sort a vector BASE containing N pointers, in place. Use TMP
+ (containing N / 2 pointers) for temporary storage. Compare
+ pointers with CMP. */
+
+static void
+mpsort_with_tmp (void const **restrict base, size_t n,
+ void const **restrict tmp,
+ comparison_function cmp)
+{
+ if (n <= 2)
+ {
+ if (n == 2)
+ {
+ void const *p0 = base[0];
+ void const *p1 = base[1];
+ if (! (cmp (p0, p1) <= 0))
+ {
+ base[0] = p1;
+ base[1] = p0;
+ }
+ }
+ }
+ else
+ {
+ size_t n1 = n / 2;
+ size_t n2 = n - n1;
+ size_t i;
+ size_t t = 0;
+ size_t tlim = n1;
+ size_t b = n1;
+ size_t blim = n;
+ void const *bb;
+ void const *tt;
+
+ mpsort_with_tmp (base + n1, n2, tmp, cmp);
+
+ if (n1 < 2)
+ tmp[0] = base[0];
+ else
+ mpsort_into_tmp (base, n1, tmp, cmp);
+
+ tt = tmp[t];
+ bb = base[b];
+
+ for (i = 0; ; )
+ if (cmp (tt, bb) <= 0)
+ {
+ base[i++] = tt;
+ t++;
+ if (t == tlim)
+ break;
+ tt = tmp[t];
+ }
+ else
+ {
+ base[i++] = bb;
+ b++;
+ if (b == blim)
+ {
+ memcpy (base + i, tmp + t, (tlim - t) * sizeof *base);
+ break;
+ }
+ bb = base[b];
+ }
+ }
+}
+
+/* Sort a vector BASE containing N pointers, in place. BASE must
+ contain enough storage to hold N + N / 2 vectors; the trailing
+ vectors are used for temporaries. Compare pointers with CMP. */
+
+void
+mpsort (void const **base, size_t n, comparison_function cmp)
+{
+ mpsort_with_tmp (base, n, base + n, cmp);
+}
diff -uNr tar-1.26a/lib/mpsort.h tar-1.26b/lib/mpsort.h
--- tar-1.26a/lib/mpsort.h 1970-01-01 01:00:00.000000000 +0100
+++ tar-1.26b/lib/mpsort.h 2011-04-24 19:21:21.000000000 +0159
@@ -0,0 +1,2 @@
+#include
+void mpsort (void const **, size_t, int (*) (void const *, void const *));
diff -uNr tar-1.26a/src/common.h tar-1.26b/src/common.h
--- tar-1.26a/src/common.h 2011-02-11 12:55:49.000000000 +0059
+++ tar-1.26b/src/common.h 2012-07-11 10:40:55.533510500 +0159
@@ -225,6 +225,11 @@
/* Zero if there is no recursion, otherwise FNM_LEADING_DIR. */
GLOBAL int recursion_option;
+#ifdef ORIGINAL
+#else
+GLOBAL int sort_directory_entries_option;
+
+#endif
GLOBAL bool numeric_owner_option;
GLOBAL bool one_file_system_option;
diff -uNr tar-1.26a/src/create.c tar-1.26b/src/create.c
--- tar-1.26a/src/create.c 2011-03-12 10:09:09.000000000 +0059
+++ tar-1.26b/src/create.c 2012-07-11 10:40:55.611636000 +0159
@@ -1,3 +1,11 @@
+#ifdef ORIGINAL
+#else
+/* #define exactly one among USE_QSORT and USE_MPSORT */
+#define USE_QSORT
+#undef USE_QSORT
+#undef USE_MPSORT
+#define USE_MPSORT
+#endif
/* Create a tar archive.
Copyright (C) 1985, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
@@ -20,6 +28,13 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#include
+#ifdef ORIGINAL
+#else
+#include
+#ifdef USE_MPSORT
+#include
+#endif
+#endif
#include
@@ -1074,6 +1089,48 @@
}
return dump_status_ok;
}
+#ifdef ORIGINAL
+#else
+
+/* setjmp/longjmp/xstrcoll code borrowed from coreutils/src/ls.c */
+static jmp_buf failed_strcoll;
+
+typedef int (*qsortFunc)(void const *a, void const *b);
+
+static int
+xstrcoll (char const *a, char const *b)
+{
+ int diff;
+ errno = 0;
+ diff = strcoll (a, b);
+ if (errno)
+ {
+ error (0, errno, _("cannot compare file names %s and %s"),
+ quote_n (0, a), quote_n (1, b));
+ set_exit_status (TAREXIT_FAILURE);
+ longjmp (failed_strcoll, 1);
+ }
+ return diff;
+}
+#ifdef USE_QSORT
+
+static int
+xstrcoll_for_qsort (void const *ps1, void const *ps2)
+{
+ char const *const *xs1 = ps1;
+ char const *const *xs2 = ps2;
+ return xstrcoll (*xs1, *xs2);
+}
+
+static int
+strcmp_for_qsort (void const *ps1, void const *ps2)
+{
+ char const *const *xs1 = ps1;
+ char const *const *xs2 = ps2;
+ return strcmp (*xs1, *xs2);
+}
+#endif
+#endif
/* Copy info from the directory identified by ST into the archive.
@@ -1181,6 +1238,17 @@
name_size = name_len = strlen (name_buf);
/* Now output all the files in the directory. */
+#ifdef ORIGINAL
+#else
+ size_t nb_entry = 0;
+ if (sort_directory_entries_option) {
+ for (entry = directory; (entry_len = strlen (entry)) != 0;
+ entry += entry_len + 1) {
+ ++nb_entry;
+ };
+ };
+ if (!sort_directory_entries_option || nb_entry < 2) {
+#endif
for (entry = directory; (entry_len = strlen (entry)) != 0;
entry += entry_len + 1)
{
@@ -1193,6 +1261,53 @@
if (!excluded_name (name_buf))
dump_file (st, entry, name_buf);
}
+#ifdef ORIGINAL
+#else
+ } else {
+#ifdef USE_QSORT
+ char const **entry_table = xmalloc ((nb_entry + 1) * sizeof (char const *));
+#endif
+#ifdef USE_MPSORT
+ /* since nb_entry is here >= 2, the extra slot needed is the first from nb_entry / 2 */
+ char const **entry_table = xmalloc ((nb_entry + nb_entry / 2) * sizeof (char const *));
+#endif
+ /* setjmp/longjmp/xstrcoll code borrowed from coreutils/src/ls.c */
+#ifdef USE_QSORT
+ qsortFunc compar_for_qsort = setjmp (failed_strcoll) ? strcmp_for_qsort : xstrcoll_for_qsort;
+#endif
+#ifdef USE_MPSORT
+ qsortFunc compar_for_mpsort = setjmp (failed_strcoll) ? (qsortFunc)strcmp : (qsortFunc)xstrcoll;
+#endif
+ char const **p = entry_table;
+ for (entry = directory; (entry_len = strlen (entry)) != 0;
+ entry += entry_len + 1) {
+ *p++ = entry;
+ };
+#ifdef USE_QSORT
+ qsort (entry_table, nb_entry, sizeof (char const *), compar_for_qsort);
+#endif
+#ifdef USE_MPSORT
+ mpsort ((void const **)entry_table, nb_entry, compar_for_mpsort);
+#endif
+ *p = (char const *)NULL;
+ p = entry_table;
+ while ((entry = *p++)) {
+ entry_len = strlen (entry);
+ /* below 10 lines copied verbatim from above */
+ {
+ if (name_size < name_len + entry_len)
+ {
+ name_size = name_len + entry_len;
+ name_buf = xrealloc (name_buf, name_size + 1);
+ }
+ strcpy (name_buf + name_len, entry);
+ if (!excluded_name (name_buf))
+ dump_file (st, entry, name_buf);
+ }
+ };
+ free (entry_table);
+ };
+#endif
free (name_buf);
}
diff -uNr tar-1.26a/src/tar.c tar-1.26b/src/tar.c
--- tar-1.26a/src/tar.c 2010-10-24 20:07:31.000000000 +0159
+++ tar-1.26b/src/tar.c 2012-07-11 10:40:55.799137200 +0159
@@ -298,6 +298,11 @@
NO_OVERWRITE_DIR_OPTION,
NO_QUOTE_CHARS_OPTION,
NO_RECURSION_OPTION,
+#ifdef ORIGINAL
+#else
+ SORT_DIRECTORY_ENTRIES_OPTION,
+ NO_SORT_DIRECTORY_ENTRIES_OPTION,
+#endif
NO_SAME_OWNER_OPTION,
NO_SAME_PERMISSIONS_OPTION,
NO_SEEK_OPTION,
@@ -675,6 +680,13 @@
N_("exclude backup and lock files"), GRID+1 },
{"no-recursion", NO_RECURSION_OPTION, 0, 0,
N_("avoid descending automatically in directories"), GRID+1 },
+#ifdef ORIGINAL
+#else
+ {"sort-directory-entries", SORT_DIRECTORY_ENTRIES_OPTION, 0, 0,
+ N_("store directory entries as sorted"), GRID+1 },
+ {"no-sort-directory-entries", NO_SORT_DIRECTORY_ENTRIES_OPTION, 0, 0,
+ N_("store directory entries iaw directory order (default)"), GRID+1 },
+#endif
{"one-file-system", ONE_FILE_SYSTEM_OPTION, 0, 0,
N_("stay in local file system when creating archive"), GRID+1 },
{"recursion", RECURSION_OPTION, 0, 0,
@@ -2071,6 +2083,17 @@
recursion_option = 0;
break;
+#ifdef ORIGINAL
+#else
+ case SORT_DIRECTORY_ENTRIES_OPTION:
+ sort_directory_entries_option = 1;
+ break;
+
+ case NO_SORT_DIRECTORY_ENTRIES_OPTION:
+ sort_directory_entries_option = 0;
+ break;
+
+#endif
case NO_SAME_OWNER_OPTION:
same_owner_option = -1;
break;
@@ -2237,6 +2260,10 @@
newer_mtime_option.tv_sec = TYPE_MINIMUM (time_t);
newer_mtime_option.tv_nsec = -1;
recursion_option = FNM_LEADING_DIR;
+#ifdef ORIGINAL
+#else
+ sort_directory_entries_option = 0;
+#endif
unquote_option = true;
tar_sparse_major = 1;
tar_sparse_minor = 0;