will use the following default value:
@smallexample
-%d/PaxHeaders.%p/%f
+%d/PaxHeaders/%f
@end smallexample
+This default is selected to ensure the reproducibility of the
+archive. @acronym{POSIX} standard recommends to use
+@samp{%d/PaxHeaders.%p/%f} instead, which means the two archives
+created with the same set of options and containing the same set
+of files will be byte-to-byte different. This default will be used
+if the environment variable @env{POSIXLY_CORRECT} is set.
+
@item exthdr.mtime=@var{value}
This keyword defines the value of the @samp{mtime} field that
If no option @samp{globexthdr.name=string} is specified, @command{tar}
will use the following default value:
+@smallexample
+$TMPDIR/GlobalHead.%n
+@end smallexample
+
+If the environment variable @env{POSIXLY_CORRECT} is set, the
+following value is used instead:
+
@smallexample
$TMPDIR/GlobalHead.%p.%n
@end smallexample
-@noindent
-where @samp{$TMPDIR} represents the value of the @var{TMPDIR}
+In both cases, @samp{$TMPDIR} stands for the value of the @var{TMPDIR}
environment variable. If @var{TMPDIR} is not set, @command{tar}
uses @samp{/tmp}.
same contents:
@smallexample
---pax-option=exthdr.name=%d/PaxHeaders/%f,atime:=0
+--pax-option=atime:=0
@end smallexample
@noindent
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
+
+Notice, that if you create an archive in POSIX format (@pxref{posix})
+and the environment variable @env{POSIXLY_CORRECT} is set, then the
+two archives created using the same options on the same set of files
+will not be byte-to-byte equivalent even with the above option. This
+is because the posix default for extended header names includes the
+PID of the tar process, which is different at each run. To produce
+byte-to-byte equivalent archives in this case, either unset
+@env{POSIXLY_CORRECT}, or use the following option:
+
+@smallexample
+---pax-option=exthdr.name=%d/PaxHeaders/%f,atime:=0,ctime:=0
@end smallexample
@node Checksumming
original name, and all subsequent parts are named using the pattern:
@smallexample
-%d/GNUFileParts.%p/%f.%n
+%d/GNUFileParts/%f.%n
@end smallexample
@noindent
@end multitable
For example, if the file @file{var/longfile} was split during archive
-creation between three volumes, and the creator @command{tar} process
-had process @acronym{ID} @samp{27962}, then the member names will be:
+creation between three volumes, 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
@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
@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
@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
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
return buf;
}
+/* Table of templates for the names of POSIX extended headers.
+ Indexed by the the type of the header (per-file or global)
+ and POSIX compliance mode (0 or q depending on whether
+ POSIXLY_CORRECT environment variable is set. */
+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
+};
+/* Return the name for the POSIX extended header T */
+#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;
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);