From cba0571c626413777448a801735824e7e2a4dcd8 Mon Sep 17 00:00:00 2001 From: Zachary Vance 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 --- 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 address@hidden 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 @address@hidden/@var{name}}, then the extended header file will be -named @address@hidden/@/address@hidden/@/@var{name}}, where address@hidden is an integer number. +named @address@hidden/@/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="address@hidden" # 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