Thanks for the feedback Sergei. This new version does only one env variable check, and I've updated the documentation.

Feel free to ask for any other changes or to change anything!
From cba0571c626413777448a801735824e7e2a4dcd8 Mon Sep 17 00:00:00 2001
From: Zachary Vance <z...@za3k.com>
Date: Sun, 10 Mar 2019 19:12:19 -0700
Subject: [PATCH] PAX format will default to omitting PID

The intent is to make binary-equivalent PAX archives easy to create.  If
POSIXLY_CORRECT is set, the POSIX standard default is used, which embeds
the pid.

* src/buffer.c (add_chunk_header): Change filenames of multipart files to
   omit the pid.
* src/common.h: Add posixly_correct global boolean.
* src/tar.c (decode_options): Detect the POSIXLY_CORRECT environment variable
* src/xheader.c (xheader_xhdr_name, xheader_ghdr_name): Change default form
   at of PAX headers unless POSIXLY_CORRECT is set.

Signed-off-by: Zachary Vance <z...@za3k.com>
---
 doc/tar.texi      | 43 +++++++++++++++++++++++++------------------
 src/buffer.c      |  2 +-
 src/common.h      |  3 +++
 src/tar.c         |  2 ++
 src/xheader.c     | 23 ++++++++++++++++++-----
 tests/append02.at |  2 +-
 6 files changed, 50 insertions(+), 25 deletions(-)

diff --git a/doc/tar.texi b/doc/tar.texi
index 71318f3..32d919a 100644
--- a/doc/tar.texi
+++ b/doc/tar.texi
@@ -10458,9 +10458,13 @@ If no option @samp{exthdr.name=string} is specified, @command{tar}
 will use the following default value:
 
 @smallexample
-%d/PaxHeaders.%p/%f
+%d/PaxHeaders/%f
 @end smallexample
 
+This default does not not match @acronym{POSIX} standards.  To turn on
+strict @acronym{POSIX} compliance, pass a template to this option or
+set the environment variable @env{POSIXLY_CORRECT}.
+
 @item exthdr.mtime=@var{value}
 
 This keyword defines the value of the @samp{mtime} field that
@@ -10490,9 +10494,13 @@ If no option @samp{globexthdr.name=string} is specified, @command{tar}
 will use the following default value:
 
 @smallexample
-$TMPDIR/GlobalHead.%p.%n
+$TMPDIR/GlobalHead.%n
 @end smallexample
 
+This default does not not match @acronym{POSIX} standards.  To turn on
+strict @acronym{POSIX} compliance, pass a template to this option or
+set the environment variable @env{POSIXLY_CORRECT}.
+
 @noindent
 where @samp{$TMPDIR} represents the value of the @var{TMPDIR}
 environment variable.  If @var{TMPDIR} is not set, @command{tar}
@@ -10557,7 +10565,7 @@ archives created using it, will be binary equivalent if they have the
 same contents:
 
 @smallexample
---pax-option=exthdr.name=%d/PaxHeaders/%f,atime:=0
+--pax-option=atime:=0
 @end smallexample
 
 @noindent
@@ -10566,14 +10574,14 @@ from them, you will also need to eliminate changes due to ctime, as
 shown in examples below:
 
 @smallexample
---pax-option=exthdr.name=%d/PaxHeaders/%f,atime:=0,ctime:=0
+--pax-option=atime:=0,ctime:=0
 @end smallexample
 
 @noindent
 or
 
 @smallexample
---pax-option=exthdr.name=%d/PaxHeaders/%f,atime:=0,delete=ctime
+--pax-option=atime:=0,delete=ctime
 @end smallexample
 
 @node Checksumming
@@ -10699,7 +10707,7 @@ GNU extensions.  More specifically, the very first part retains its
 original name, and all subsequent parts are named using the pattern:
 
 @smallexample
-%d/GNUFileParts.%p/%f.%n
+%d/GNUFileParts/%f.%n
 @end smallexample
 
 @noindent
@@ -10723,8 +10731,8 @@ had process @acronym{ID} @samp{27962}, then the member names will be:
 
 @smallexample
 var/longfile
-var/GNUFileParts.27962/longfile.1
-var/GNUFileParts.27962/longfile.2
+var/GNUFileParts/longfile.1
+var/GNUFileParts/longfile.2
 @end smallexample
 
 When you extract your archive using a third-party @command{tar}, these
@@ -10735,9 +10743,9 @@ the proper order, for example:
 @smallexample
 @group
 $ @kbd{cd var}
-$ @kbd{cat GNUFileParts.27962/longfile.1 \
-  GNUFileParts.27962/longfile.2 >> longfile}
-$ rm -f GNUFileParts.27962
+$ @kbd{cat GNUFileParts/longfile.1 \
+  GNUFileParts/longfile.2 >> longfile}
+$ rm -f GNUFileParts
 @end group
 @end smallexample
 
@@ -10763,12 +10771,12 @@ more warnings and more files generated on your disk, e.g.:
 @smallexample
 @group
 $ @kbd{tar xf vol-1.tar}
-var/PaxHeaders.27962/longfile: Unknown file type 'x', extracted as
+var/PaxHeaders/longfile: Unknown file type 'x', extracted as
 normal file
 Unexpected EOF in archive
 $ @kbd{tar xf vol-2.tar}
-tmp/GlobalHead.27962.1: Unknown file type 'g', extracted as normal file
-GNUFileParts.27962/PaxHeaders.27962/sparsefile.1: Unknown file type
+tmp/GlobalHead.1: Unknown file type 'g', extracted as normal file
+GNUFileParts/PaxHeaders/sparsefile.1: Unknown file type
 'x', extracted as normal file
 @end group
 @end smallexample
@@ -10884,8 +10892,8 @@ use.  Continuing our example:
 
 @smallexample
 @group
-$ @kbd{xsparse -v -x /home/gray/PaxHeaders.6058/sparsefile \
-  /home/gray/GNUSparseFile.6058/sparsefile}
+$ @kbd{xsparse -v -x /home/gray/PaxHeaders/sparsefile \
+  /home/gray/GNUSparseFile/sparsefile}
 Reading extended header file
 Found variable GNU.sparse.major = 1
 Found variable GNU.sparse.minor = 0
@@ -10915,8 +10923,7 @@ If you use a @command{tar} implementation that does not support PAX
 format, extended headers for each member will be extracted as a
 separate file.  If we represent the member name as
 @file{@var{dir}/@var{name}}, then the extended header file will be
-named @file{@var{dir}/@/PaxHeaders.@var{n}/@/@var{name}}, where
-@var{n} is an integer number.
+named @file{@var{dir}/@/PaxHeaders/@/@var{name}}.
 
 Things become more difficult if your @command{tar} implementation
 does support PAX headers, because in this case you will have to
diff --git a/src/buffer.c b/src/buffer.c
index 7781009..151710c 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -1731,7 +1731,7 @@ add_chunk_header (struct bufmap *map)
       st.stat.st_uid = getuid ();
       st.stat.st_gid = getgid ();
       st.orig_file_name = xheader_format_name (&st,
-                                               "%d/GNUFileParts.%p/%f.%n",
+                                               "%d/GNUFileParts/%f.%n",
                                                volno);
       st.file_name = st.orig_file_name;
       st.archive_file_size = st.stat.st_size = map->sizeleft;
diff --git a/src/common.h b/src/common.h
index 501e0d3..363c8e3 100644
--- a/src/common.h
+++ b/src/common.h
@@ -340,6 +340,9 @@ GLOBAL const char *volume_label_option;
 
 /* Other global variables.  */
 
+/* POSIXLY_CORRECT: set to force braindead POSIX compliance */
+GLOBAL bool posixly_correct;
+
 /* File descriptor for archive file.  */
 GLOBAL int archive;
 
diff --git a/src/tar.c b/src/tar.c
index d66fed8..cdc5b77 100644
--- a/src/tar.c
+++ b/src/tar.c
@@ -2230,6 +2230,8 @@ decode_options (int argc, char **argv)
   args.version_control_string = 0;
   args.compress_autodetect = false;
 
+  posixly_correct = getenv ("POSIXLY_CORRECT");
+
   subcommand_option = UNKNOWN_SUBCOMMAND;
   archive_format = DEFAULT_FORMAT;
   blocking_factor = DEFAULT_BLOCKING;
diff --git a/src/xheader.c b/src/xheader.c
index 46bf4bb..aef3876 100644
--- a/src/xheader.c
+++ b/src/xheader.c
@@ -369,29 +369,42 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, size_t n)
   return buf;
 }
 
+static const char *header_template[][2] = {
+  /* Individual header templates */
+  { "%d/PaxHeaders/%f", "%d/PaxHeaders.%p/%f" },
+  /* Global header templates */
+  { "/GlobalHead.%n", "/GlobalHead.%p.%n" }
+};
+/* Indices to the above table */
+enum {
+  pax_file_header,
+  pax_global_header
+};
+
+#define HEADER_TEMPLATE(t) header_template[t][posixly_correct]
+
 char *
 xheader_xhdr_name (struct tar_stat_info *st)
 {
   if (!exthdr_name)
-    assign_string (&exthdr_name, "%d/PaxHeaders.%p/%f");
+    assign_string (&exthdr_name, HEADER_TEMPLATE(pax_file_header));
   return xheader_format_name (st, exthdr_name, 0);
 }
 
-#define GLOBAL_HEADER_TEMPLATE "/GlobalHead.%p.%n"
-
 char *
 xheader_ghdr_name (void)
 {
   if (!globexthdr_name)
     {
       size_t len;
+      const char *global_header_template = HEADER_TEMPLATE(pax_global_header);
       const char *tmp = getenv ("TMPDIR");
       if (!tmp)
 	tmp = "/tmp";
-      len = strlen (tmp) + sizeof (GLOBAL_HEADER_TEMPLATE); /* Includes nul */
+      len = strlen (tmp) + strlen (global_header_template) + 1; /* Includes nul */
       globexthdr_name = xmalloc (len);
       strcpy(globexthdr_name, tmp);
-      strcat(globexthdr_name, GLOBAL_HEADER_TEMPLATE);
+      strcat(globexthdr_name, global_header_template);
     }
 
   return xheader_format_name (NULL, globexthdr_name, global_header_count + 1);
diff --git a/tests/append02.at b/tests/append02.at
index 3cd7760..96b4eff 100644
--- a/tests/append02.at
+++ b/tests/append02.at
@@ -64,7 +64,7 @@ MTIME="--mtime=@0"
 # For PAX archives, we need to make sure extended header names are
 # reproducible and that their contents won't change with time
 if test $[]TEST_TAR_FORMAT = posix; then
-  TAR_OPTIONS="$TAR_OPTIONS --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=mtime,delete=atime,delete=ctime"
+  TAR_OPTIONS="$TAR_OPTIONS --pax-option=delete=mtime,delete=atime,delete=ctime"
 fi
 
 echo Creating archive.1
-- 
2.21.0

Reply via email to