Subject: bug#19616: [Bug-tar] dist tarball contains hardlinks

From: Dimitrios Apostolou <[email-masked]>
Date: Mon, 16 Mar 2015 13:29:21 +0100 (CET)

On Fri, 13 Mar 2015, Dimitrios Apostolou wrote:
>
> I believe my only choice at this point is to forbid "make dist" if tar is 
> detected to be old (less than 1.29), and keep doing --hard-dereference. I 
> open to new ideas though. :-)

The attached patch solves the problem in a more elegant manner IMHO, 
so I plan to include this modified tar.m4 in my project.

Review is welcome, and feel free to include to upstream automake.

Dimitris
From 3672979dc4313da1ec1727eadf3284771e9186f8 Mon Sep 17 00:00:00 2001
From: Dimitrios Apostolou <[email-masked]>
Date: Mon, 16 Mar 2015 13:09:06 +0100
Subject: [PATCH 1/1] GNU Tar now uses --hard-dereference when possible

Historically "make dist" tries to store only files inside the tarball,
avoiding all symlinks/hardlinks in order to bypass limitations of the
tar format (for example the "ustar" format allows only 100 characters
filenames for symlinks). For that reason -o (i.e. --dereference) has
been passed to the tar command.

However GNU Tar changed its behaviour since v1.24 and stores symlinks as
hardlinks if --dereference is passed. Thus we now need to pass
--hard-dereference to make sure no links are stored in the
tarball. Unfortunately this option is available since GNU tar v1.28,
which means that for versions 1.24-1.28 "make dist" will create tarballs
containing hardlinks, with all the limitations of the respective format
(see [1]).

[1] http://www.gnu.org/software/tar/manual/html_section/tar_68.html
---
 m4/tar.m4 | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/m4/tar.m4 b/m4/tar.m4
index d8054cb..bca9c3f 100644
--- a/m4/tar.m4
+++ b/m4/tar.m4
@@ -72,18 +72,26 @@ m4_if([$1], [v7],
   _am_tools=${am_cv_prog_tar_$1-$_am_tools}
 
   for _am_tool in $_am_tools; do
     case $_am_tool in
     gnutar)
       for _am_tar in tar gnutar gtar; do
         AM_RUN_LOG([$_am_tar --version]) && break
       done
-      am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
-      am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+      AC_MSG_CHECKING([if GNU tar supports --hard-dereference])
+      AM_RUN_LOG([$_am_tar --hard-dereference])
+      # Exit code 64 means unrecognized option
+      if test "$ac_status" -eq 64; then
+        am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+        am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+      else
+        am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) --hard-dereference -chf - "'"$$tardir"'
+        am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) --hard-dereference -chf - "'"$tardir"'
+      fi
       am__untar="$_am_tar -xf -"
       ;;
     plaintar)
       # Must skip GNU tar: if it does not support --format= it doesn't create
       # ustar tarball either.
       (tar --version) >/dev/null 2>&1 && continue
       am__tar='tar chf - "$$tardir"'
       am__tar_='tar chf - "$tardir"'
-- 
1.9.1