mirror of
https://git.savannah.gnu.org/git/tar.git
synced 2026-05-31 03:56:45 +00:00
(from_header): Do not issue a diagnostic if TYPE is zero.
However, check for error even for '-' or '+' case. (print_header): Try parsing uids and gids as unsigned integers first, and as a uid_t or gid_t only if that fails. This adds support for listing positive uids and gids that are greater than UID_MAX and GID_MAX.
This commit is contained in:
173
src/list.c
173
src/list.c
@@ -1,5 +1,8 @@
|
||||
/* List a tar archive, with support routines for reading a tar archive.
|
||||
Copyright 1988,92,93,94,96,97,98,99,2000,2001 Free Software Foundation, Inc.
|
||||
|
||||
Copyright 1988, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000,
|
||||
2001 Free Software Foundation, Inc.
|
||||
|
||||
Written by John Gilmore, on 1985-08-26.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
@@ -484,7 +487,8 @@ decode_header (union block *header, struct stat *stat_info,
|
||||
/* Convert buffer at WHERE0 of size DIGS from external format to
|
||||
uintmax_t. The data is of type TYPE. The buffer must represent a
|
||||
value in the range -MINUS_MINVAL through MAXVAL. DIGS must be
|
||||
positive. */
|
||||
positive. Return -1 on error, diagnosing the error if TYPE is
|
||||
nonzero. */
|
||||
static uintmax_t
|
||||
from_header (char const *where0, size_t digs, char const *type,
|
||||
uintmax_t minus_minval, uintmax_t maxval)
|
||||
@@ -534,7 +538,7 @@ from_header (char const *where0, size_t digs, char const *type,
|
||||
nonzero digit is 1, we can't recover the original value
|
||||
reliably; so do this only if the digit is 2 or more. This
|
||||
catches the common case of 32-bit negative time stamps. */
|
||||
if ((overflow || maxval < value) && '2' <= *where1)
|
||||
if ((overflow || maxval < value) && '2' <= *where1 && type)
|
||||
{
|
||||
/* Compute the negative of the input value, assuming two's
|
||||
complement. */
|
||||
@@ -566,79 +570,76 @@ from_header (char const *where0, size_t digs, char const *type,
|
||||
|
||||
if (overflow)
|
||||
{
|
||||
ERROR ((0, 0,
|
||||
_("Archive octal value %.*s is out of %s range"),
|
||||
(int) (where - where1), where1, type));
|
||||
if (type)
|
||||
ERROR ((0, 0,
|
||||
_("Archive octal value %.*s is out of %s range"),
|
||||
(int) (where - where1), where1, type));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (type)
|
||||
else if (*where == '-' || *where == '+')
|
||||
{
|
||||
/* The following forms cannot appear as checksums, so we don't
|
||||
check for them if TYPE is null. */
|
||||
|
||||
if (*where == '-' || *where == '+')
|
||||
/* Parse base-64 output produced only by tar test versions
|
||||
1.13.6 (1999-08-11) through 1.13.11 (1999-08-23).
|
||||
Support for this will be withdrawn in future releases. */
|
||||
int dig;
|
||||
static int warned_once;
|
||||
if (! warned_once)
|
||||
{
|
||||
/* Parse base-64 output produced only by tar test versions
|
||||
1.13.6 (1999-08-11) through 1.13.11 (1999-08-23).
|
||||
Support for this will be withdrawn in future releases. */
|
||||
int dig;
|
||||
static int warned_once;
|
||||
if (! warned_once)
|
||||
warned_once = 1;
|
||||
WARN ((0, 0,
|
||||
_("Archive contains obsolescent base-64 headers")));
|
||||
}
|
||||
negative = *where++ == '-';
|
||||
while (where != lim
|
||||
&& (dig = base64_map[(unsigned char) *where]) < 64)
|
||||
{
|
||||
if (value << LG_64 >> LG_64 != value)
|
||||
{
|
||||
warned_once = 1;
|
||||
WARN ((0, 0,
|
||||
_("Archive contains obsolescent base-64 headers")));
|
||||
char *string = alloca (digs + 1);
|
||||
memcpy (string, where0, digs);
|
||||
string[digs] = '\0';
|
||||
if (type)
|
||||
ERROR ((0, 0,
|
||||
_("Archive signed base-64 string %s is out of %s range"),
|
||||
quote (string), type));
|
||||
return -1;
|
||||
}
|
||||
negative = *where++ == '-';
|
||||
while (where != lim
|
||||
&& (dig = base64_map[(unsigned char) *where]) < 64)
|
||||
value = (value << LG_64) | dig;
|
||||
where++;
|
||||
}
|
||||
}
|
||||
else if (*where == '\200' /* positive base-256 */
|
||||
|| *where == '\377' /* negative base-256 */)
|
||||
{
|
||||
/* Parse base-256 output. A nonnegative number N is
|
||||
represented as (256**DIGS)/2 + N; a negative number -N is
|
||||
represented as (256**DIGS) - N, i.e. as two's complement.
|
||||
The representation guarantees that the leading bit is
|
||||
always on, so that we don't confuse this format with the
|
||||
others (assuming ASCII bytes of 8 bits or more). */
|
||||
int signbit = *where & (1 << (LG_256 - 2));
|
||||
uintmax_t topbits = (((uintmax_t) - signbit)
|
||||
<< (CHAR_BIT * sizeof (uintmax_t)
|
||||
- LG_256 - (LG_256 - 2)));
|
||||
value = (*where++ & ((1 << (LG_256 - 2)) - 1)) - signbit;
|
||||
for (;;)
|
||||
{
|
||||
value = (value << LG_256) + (unsigned char) *where++;
|
||||
if (where == lim)
|
||||
break;
|
||||
if (((value << LG_256 >> LG_256) | topbits) != value)
|
||||
{
|
||||
if (value << LG_64 >> LG_64 != value)
|
||||
{
|
||||
char *string = alloca (digs + 1);
|
||||
memcpy (string, where0, digs);
|
||||
string[digs] = '\0';
|
||||
ERROR ((0, 0,
|
||||
_("Archive signed base-64 string %s is out of %s range"),
|
||||
quote (string), type));
|
||||
return -1;
|
||||
}
|
||||
value = (value << LG_64) | dig;
|
||||
where++;
|
||||
if (type)
|
||||
ERROR ((0, 0,
|
||||
_("Archive base-256 value is out of %s range"),
|
||||
type));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (*where == '\200' /* positive base-256 */
|
||||
|| *where == '\377' /* negative base-256 */)
|
||||
{
|
||||
/* Parse base-256 output. A nonnegative number N is
|
||||
represented as (256**DIGS)/2 + N; a negative number -N is
|
||||
represented as (256**DIGS) - N, i.e. as two's complement.
|
||||
The representation guarantees that the leading bit is
|
||||
always on, so that we don't confuse this format with the
|
||||
others (assuming ASCII bytes of 8 bits or more). */
|
||||
int signbit = *where & (1 << (LG_256 - 2));
|
||||
uintmax_t topbits = (((uintmax_t) - signbit)
|
||||
<< (CHAR_BIT * sizeof (uintmax_t)
|
||||
- LG_256 - (LG_256 - 2)));
|
||||
value = (*where++ & ((1 << (LG_256 - 2)) - 1)) - signbit;
|
||||
for (;;)
|
||||
{
|
||||
value = (value << LG_256) + (unsigned char) *where++;
|
||||
if (where == lim)
|
||||
break;
|
||||
if (((value << LG_256 >> LG_256) | topbits) != value)
|
||||
{
|
||||
ERROR ((0, 0,
|
||||
_("Archive base-256 value is out of %s range"),
|
||||
type));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
negative = signbit;
|
||||
if (negative)
|
||||
value = -value;
|
||||
}
|
||||
negative = signbit;
|
||||
if (negative)
|
||||
value = -value;
|
||||
}
|
||||
|
||||
if (where != lim && *where && !ISSPACE ((unsigned char) *where))
|
||||
@@ -947,17 +948,45 @@ print_header (void)
|
||||
&& !numeric_owner_option)
|
||||
user = current_header->header.uname;
|
||||
else
|
||||
user = STRINGIFY_BIGINT (UINTMAX_FROM_HEADER
|
||||
(current_header->header.uid),
|
||||
uform);
|
||||
{
|
||||
/* Try parsing it as an unsigned integer first, and as a
|
||||
uid_t if that fails. This method can list positive user
|
||||
ids that are too large to fit in a uid_t. */
|
||||
uintmax_t u = from_header (current_header->header.uid,
|
||||
sizeof current_header->header.uid, 0,
|
||||
(uintmax_t) 0,
|
||||
(uintmax_t) TYPE_MAXIMUM (uintmax_t));
|
||||
if (u != -1)
|
||||
user = STRINGIFY_BIGINT (u, uform);
|
||||
else
|
||||
{
|
||||
sprintf (uform, "%ld",
|
||||
(long) UID_FROM_HEADER (current_header->header.uid));
|
||||
user = uform;
|
||||
}
|
||||
}
|
||||
|
||||
if (*current_header->header.gname && current_format != V7_FORMAT
|
||||
&& !numeric_owner_option)
|
||||
group = current_header->header.gname;
|
||||
else
|
||||
group = STRINGIFY_BIGINT (UINTMAX_FROM_HEADER
|
||||
(current_header->header.gid),
|
||||
gform);
|
||||
{
|
||||
/* Try parsing it as an unsigned integer first, and as a
|
||||
gid_t if that fails. This method can list positive group
|
||||
ids that are too large to fit in a gid_t. */
|
||||
uintmax_t g = from_header (current_header->header.gid,
|
||||
sizeof current_header->header.gid, 0,
|
||||
(uintmax_t) 0,
|
||||
(uintmax_t) TYPE_MAXIMUM (uintmax_t));
|
||||
if (g != -1)
|
||||
group = STRINGIFY_BIGINT (g, gform);
|
||||
else
|
||||
{
|
||||
sprintf (gform, "%ld",
|
||||
(long) GID_FROM_HEADER (current_header->header.gid));
|
||||
group = gform;
|
||||
}
|
||||
}
|
||||
|
||||
/* Format the file size or major/minor device numbers. */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user