(xheader_format_name): Bugfix.

(xheader_xhdr_name): Changed the default extended header name
to '%d/PaxHeaders.%p/%f', as POSIX requires.
(xheader_ghdr_name): Removed unused argument.
(xheader_write,xheader_write_global): New function.
(xheader_decode): Modified to honor overrides whatever
the current archive format is.
This commit is contained in:
Sergey Poznyakoff
2004-02-20 15:34:12 +00:00
parent eff25ef359
commit f038194718

View File

@@ -31,8 +31,23 @@
bool xheader_protected_pattern_p (const char *pattern);
bool xheader_protected_keyword_p (const char *keyword);
/* Number of the global headers written so far. Not used yet */
/* Used by xheader_finish() */
static void code_string (char const *string, char const *keyword,
struct xheader *xhdr);
static void extended_header_init ();
/* Number of global headers written so far. */
static size_t global_header_count;
/* FIXME: Possibly it should be reset after changing the volume.
POSIX %n specification says that it is expanded to the sequence
number of current global header in *the* archive. However, for
multi-volume archives this will yield duplicate header names
in different volumes, which I'd like to avoid. The best way
to solve this would be to use per-archive header count as required
by POSIX *and* set globexthdr.name to, say,
$TMPDIR/GlobalHead.%p.$NUMVOLUME.%n.
However it should wait until buffer.c is finally rewritten */
/* Keyword options */
@@ -173,7 +188,7 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n)
char pidbuf[64];
char nbuf[64];
for (p = exthdr_name; *p && (p = strchr (p, '%')); )
for (p = fmt; *p && (p = strchr (p, '%')); )
{
switch (p[1])
{
@@ -182,13 +197,20 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n)
break;
case 'd':
dirname = safer_name_suffix (dir_name (st->orig_file_name), false);
len += strlen (dirname) - 1;
if (st)
{
dirname = safer_name_suffix (dir_name (st->orig_file_name),
false);
len += strlen (dirname) - 1;
}
break;
case 'f':
basename = base_name (st->orig_file_name);
len += strlen (basename) - 1;
if (st)
{
basename = base_name (st->orig_file_name);
len += strlen (basename) - 1;
}
break;
case 'p':
@@ -222,12 +244,14 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n)
break;
case 'd':
q = stpcpy (q, dirname);
if (dirname)
q = stpcpy (q, dirname);
p += 2;
break;
case 'f':
q = stpcpy (q, basename);
if (basename)
q = stpcpy (q, basename);
p += 2;
break;
@@ -264,16 +288,15 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n)
char *
xheader_xhdr_name (struct tar_stat_info *st)
{
/* FIXME: POSIX requires the default name to be '%d/PaxHeaders.%p/%f' */
if (!exthdr_name)
return xstrdup ("././@PaxHeader");
assign_string (&exthdr_name, "%d/PaxHeaders.%p/%f");
return xheader_format_name (st, exthdr_name, false);
}
#define GLOBAL_HEADER_TEMPLATE "/GlobalHead.%p.%n"
char *
xheader_ghdr_name (struct tar_stat_info *st)
xheader_ghdr_name ()
{
if (!globexthdr_name)
{
@@ -287,16 +310,65 @@ xheader_ghdr_name (struct tar_stat_info *st)
strcat(globexthdr_name, GLOBAL_HEADER_TEMPLATE);
}
return xheader_format_name (st, globexthdr_name, true);
return xheader_format_name (NULL, globexthdr_name, true);
}
void
xheader_write (char type, char *name, struct xheader *xhdr)
{
union block *header;
size_t size;
char *p;
size = xhdr->size;
header = start_private_header (name, size);
header->header.typeflag = type;
simple_finish_header (header);
p = xhdr->buffer;
do
{
size_t len;
header = find_next_block ();
len = BLOCKSIZE;
if (len > size)
len = size;
memcpy (header->buffer, p, len);
if (len < BLOCKSIZE)
memset (header->buffer + len, 0, BLOCKSIZE - len);
p += len;
size -= len;
set_next_block_after (header);
}
while (size > 0);
xheader_destroy (xhdr);
}
void
xheader_write_global ()
{
char *name;
struct keyword_list *kp;
if (!keyword_global_override_list)
return;
extended_header_init ();
for (kp = keyword_global_override_list; kp; kp = kp->next)
code_string (kp->value, kp->pattern, &extended_header);
xheader_finish (&extended_header);
xheader_write (XGLTYPE, name = xheader_ghdr_name (),
&extended_header);
free (name);
global_header_count++;
}
/* General Interface */
/* Used by xheader_finish() */
static void code_string (char const *string, char const *keyword,
struct xheader *xhdr);
struct xhdr_tab
{
char const *keyword;
@@ -419,18 +491,30 @@ run_override_list (struct keyword_list *kp, struct tar_stat_info *st)
void
xheader_decode (struct tar_stat_info *st)
{
char *p = extended_header.buffer + BLOCKSIZE;
char *endp = &extended_header.buffer[extended_header.size-1];
run_override_list (keyword_global_override_list, st);
while (p < endp)
if (!decode_record (&p, st))
break;
if (extended_header.size)
{
char *p = extended_header.buffer + BLOCKSIZE;
char *endp = &extended_header.buffer[extended_header.size-1];
while (p < endp)
if (!decode_record (&p, st))
break;
}
run_override_list (keyword_override_list, st);
}
static void
extended_header_init ()
{
if (!extended_header.stk)
{
extended_header.stk = xmalloc (sizeof *extended_header.stk);
obstack_init (extended_header.stk);
}
}
void
xheader_store (char const *keyword, struct tar_stat_info const *st, void *data)
{
@@ -445,11 +529,7 @@ xheader_store (char const *keyword, struct tar_stat_info const *st, void *data)
if (xheader_keyword_deleted_p (keyword)
|| xheader_keyword_override_p (keyword))
return;
if (!extended_header.stk)
{
extended_header.stk = xmalloc (sizeof *extended_header.stk);
obstack_init (extended_header.stk);
}
extended_header_init ();
t->coder (st, keyword, &extended_header, data);
}