(gid_to_chars, major_to_chars, minor_to_chars)
(mode_to_chars, off_to_chars, size_to_chars, time_to_chars) (uid_to_chars, uintmax_to_chars): Return bool (to_chars): Return bool (start_header): Check return values of convertion routines. Fail if unable to store data in the header.
This commit is contained in:
199
src/create.c
199
src/create.c
@@ -108,69 +108,18 @@ to_base256 (int negative, uintmax_t value, char *where, size_t size)
|
||||
while (i);
|
||||
}
|
||||
|
||||
/* Convert NEGATIVE VALUE (which was originally of size VALSIZE) to
|
||||
external form, using SUBSTITUTE (...) if VALUE won't fit. Output
|
||||
to buffer WHERE with size SIZE. NEGATIVE is 1 iff VALUE was
|
||||
negative before being cast to uintmax_t; its original bitpattern
|
||||
can be deduced from VALSIZE, its original size before casting.
|
||||
TYPE is the kind of value being output (useful for diagnostics).
|
||||
Prefer the POSIX format of SIZE - 1 octal digits (with leading zero
|
||||
digits), followed by '\0'. If this won't work, and if GNU or
|
||||
OLDGNU format is allowed, use '\200' followed by base-256, or (if
|
||||
NEGATIVE is nonzero) '\377' followed by two's complement base-256.
|
||||
If neither format works, use SUBSTITUTE (...) instead. Pass to
|
||||
SUBSTITUTE the address of an 0-or-1 flag recording whether the
|
||||
substitute value is negative. */
|
||||
|
||||
static void
|
||||
static bool
|
||||
to_chars (int negative, uintmax_t value, size_t valsize,
|
||||
uintmax_t (*substitute) (int *),
|
||||
char *where, size_t size, const char *type);
|
||||
|
||||
static bool
|
||||
to_chars_subst (int negative, int gnu_format, uintmax_t value, size_t valsize,
|
||||
uintmax_t (*substitute) (int *),
|
||||
char *where, size_t size, const char *type)
|
||||
{
|
||||
int base256_allowed = (archive_format == GNU_FORMAT
|
||||
|| archive_format == OLDGNU_FORMAT);
|
||||
|
||||
/* Generate the POSIX octal representation if the number fits. */
|
||||
if (! negative && value <= MAX_VAL_WITH_DIGITS (size - 1, LG_8))
|
||||
{
|
||||
where[size - 1] = '\0';
|
||||
to_octal (value, where, size - 1);
|
||||
}
|
||||
|
||||
/* Otherwise, generate the base-256 representation if we are
|
||||
generating an old or new GNU format and if the number fits. */
|
||||
else if (((negative ? -1 - value : value)
|
||||
<= MAX_VAL_WITH_DIGITS (size - 1, LG_256))
|
||||
&& base256_allowed)
|
||||
{
|
||||
where[0] = negative ? -1 : 1 << (LG_256 - 1);
|
||||
to_base256 (negative, value, where + 1, size - 1);
|
||||
}
|
||||
|
||||
/* Otherwise, if the number is negative, and if it would not cause
|
||||
ambiguity on this host by confusing positive with negative
|
||||
values, then generate the POSIX octal representation of the value
|
||||
modulo 2**(field bits). The resulting tar file is
|
||||
machine-dependent, since it depends on the host word size. Yuck!
|
||||
But this is the traditional behavior. */
|
||||
else if (negative && valsize * CHAR_BIT <= (size - 1) * LG_8)
|
||||
{
|
||||
static int warned_once;
|
||||
if (! warned_once)
|
||||
{
|
||||
warned_once = 1;
|
||||
WARN ((0, 0, _("Generating negative octal headers")));
|
||||
}
|
||||
where[size - 1] = '\0';
|
||||
to_octal (value & MAX_VAL_WITH_DIGITS (valsize * CHAR_BIT, 1),
|
||||
where, size - 1);
|
||||
}
|
||||
|
||||
/* Otherwise, output a substitute value if possible (with a
|
||||
warning), and an error message if not. */
|
||||
else
|
||||
{
|
||||
uintmax_t maxval = (base256_allowed
|
||||
uintmax_t maxval = (gnu_format
|
||||
? MAX_VAL_WITH_DIGITS (size - 1, LG_256)
|
||||
: MAX_VAL_WITH_DIGITS (size - 1, LG_8));
|
||||
char valbuf[UINTMAX_STRSIZE_BOUND + 1];
|
||||
@@ -179,8 +128,9 @@ to_chars (int negative, uintmax_t value, size_t valsize,
|
||||
char const *minval_string;
|
||||
char const *maxval_string = STRINGIFY_BIGINT (maxval, maxbuf);
|
||||
char const *value_string;
|
||||
char *p;
|
||||
|
||||
if (base256_allowed)
|
||||
if (gnu_format)
|
||||
{
|
||||
uintmax_t m = maxval + 1 ? maxval + 1 : maxval / 2 + 1;
|
||||
char *p = STRINGIFY_BIGINT (m, minbuf + 1);
|
||||
@@ -219,6 +169,76 @@ to_chars (int negative, uintmax_t value, size_t valsize,
|
||||
ERROR ((0, 0, _("value %s out of %s range %s..%s"),
|
||||
value_string, type, minval_string, maxval_string));
|
||||
}
|
||||
|
||||
/* Convert NEGATIVE VALUE (which was originally of size VALSIZE) to
|
||||
external form, using SUBSTITUTE (...) if VALUE won't fit. Output
|
||||
to buffer WHERE with size SIZE. NEGATIVE is 1 iff VALUE was
|
||||
negative before being cast to uintmax_t; its original bitpattern
|
||||
can be deduced from VALSIZE, its original size before casting.
|
||||
TYPE is the kind of value being output (useful for diagnostics).
|
||||
Prefer the POSIX format of SIZE - 1 octal digits (with leading zero
|
||||
digits), followed by '\0'. If this won't work, and if GNU or
|
||||
OLDGNU format is allowed, use '\200' followed by base-256, or (if
|
||||
NEGATIVE is nonzero) '\377' followed by two's complement base-256.
|
||||
If neither format works, use SUBSTITUTE (...) instead. Pass to
|
||||
SUBSTITUTE the address of an 0-or-1 flag recording whether the
|
||||
substitute value is negative. */
|
||||
|
||||
static bool
|
||||
to_chars (int negative, uintmax_t value, size_t valsize,
|
||||
uintmax_t (*substitute) (int *),
|
||||
char *where, size_t size, const char *type)
|
||||
{
|
||||
int gnu_format = (archive_format == GNU_FORMAT
|
||||
|| archive_format == OLDGNU_FORMAT);
|
||||
|
||||
/* Generate the POSIX octal representation if the number fits. */
|
||||
if (! negative && value <= MAX_VAL_WITH_DIGITS (size - 1, LG_8))
|
||||
{
|
||||
where[size - 1] = '\0';
|
||||
to_octal (value, where, size - 1);
|
||||
return true;
|
||||
}
|
||||
else if (gnu_format)
|
||||
{
|
||||
/* Try to cope with the number by using traditional GNU format
|
||||
methods */
|
||||
|
||||
/* Generate the base-256 representation if the number fits. */
|
||||
if (((negative ? -1 - value : value)
|
||||
<= MAX_VAL_WITH_DIGITS (size - 1, LG_256)))
|
||||
{
|
||||
where[0] = negative ? -1 : 1 << (LG_256 - 1);
|
||||
to_base256 (negative, value, where + 1, size - 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Otherwise, if the number is negative, and if it would not cause
|
||||
ambiguity on this host by confusing positive with negative
|
||||
values, then generate the POSIX octal representation of the value
|
||||
modulo 2**(field bits). The resulting tar file is
|
||||
machine-dependent, since it depends on the host word size. Yuck!
|
||||
But this is the traditional behavior. */
|
||||
else if (negative && valsize * CHAR_BIT <= (size - 1) * LG_8)
|
||||
{
|
||||
static int warned_once;
|
||||
if (! warned_once)
|
||||
{
|
||||
warned_once = 1;
|
||||
WARN ((0, 0, _("Generating negative octal headers")));
|
||||
}
|
||||
where[size - 1] = '\0';
|
||||
to_octal (value & MAX_VAL_WITH_DIGITS (valsize * CHAR_BIT, 1),
|
||||
where, size - 1);
|
||||
return true;
|
||||
}
|
||||
/* Otherwise fall back to substitution, if possible: */
|
||||
}
|
||||
else
|
||||
substitute = NULL; /* No substitution for formats, other than GNU */
|
||||
|
||||
return to_chars_subst (negative, gnu_format, value, valsize, substitute,
|
||||
where, size, type);
|
||||
}
|
||||
|
||||
static uintmax_t
|
||||
@@ -237,25 +257,25 @@ gid_substitute (int *negative)
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
gid_to_chars (gid_t v, char *p, size_t s)
|
||||
{
|
||||
to_chars (v < 0, (uintmax_t) v, sizeof v, gid_substitute, p, s, "gid_t");
|
||||
return to_chars (v < 0, (uintmax_t) v, sizeof v, gid_substitute, p, s, "gid_t");
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
major_to_chars (major_t v, char *p, size_t s)
|
||||
{
|
||||
to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "major_t");
|
||||
return to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "major_t");
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
minor_to_chars (minor_t v, char *p, size_t s)
|
||||
{
|
||||
to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "minor_t");
|
||||
return to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "minor_t");
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
mode_to_chars (mode_t v, char *p, size_t s)
|
||||
{
|
||||
/* In the common case where the internal and external mode bits are the same,
|
||||
@@ -292,25 +312,25 @@ mode_to_chars (mode_t v, char *p, size_t s)
|
||||
| (v & S_IWOTH ? TOWRITE : 0)
|
||||
| (v & S_IXOTH ? TOEXEC : 0));
|
||||
}
|
||||
to_chars (negative, u, sizeof v, 0, p, s, "mode_t");
|
||||
return to_chars (negative, u, sizeof v, 0, p, s, "mode_t");
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
off_to_chars (off_t v, char *p, size_t s)
|
||||
{
|
||||
to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "off_t");
|
||||
return to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "off_t");
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
size_to_chars (size_t v, char *p, size_t s)
|
||||
{
|
||||
to_chars (0, (uintmax_t) v, sizeof v, 0, p, s, "size_t");
|
||||
return to_chars (0, (uintmax_t) v, sizeof v, 0, p, s, "size_t");
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
time_to_chars (time_t v, char *p, size_t s)
|
||||
{
|
||||
to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "time_t");
|
||||
return to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "time_t");
|
||||
}
|
||||
|
||||
static uintmax_t
|
||||
@@ -329,16 +349,16 @@ uid_substitute (int *negative)
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
uid_to_chars (uid_t v, char *p, size_t s)
|
||||
{
|
||||
to_chars (v < 0, (uintmax_t) v, sizeof v, uid_substitute, p, s, "uid_t");
|
||||
return to_chars (v < 0, (uintmax_t) v, sizeof v, uid_substitute, p, s, "uid_t");
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
uintmax_to_chars (uintmax_t v, char *p, size_t s)
|
||||
{
|
||||
to_chars (0, v, sizeof v, 0, p, s, "uintmax_t");
|
||||
return to_chars (0, v, sizeof v, 0, p, s, "uintmax_t");
|
||||
}
|
||||
|
||||
void
|
||||
@@ -681,7 +701,8 @@ start_header (struct tar_stat_info *st)
|
||||
xheader_store ("uid", st, NULL);
|
||||
uid = 0;
|
||||
}
|
||||
UID_TO_CHARS (uid, header->header.uid);
|
||||
if (!UID_TO_CHARS (uid, header->header.uid))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
{
|
||||
@@ -692,7 +713,8 @@ start_header (struct tar_stat_info *st)
|
||||
xheader_store ("gid", st, NULL);
|
||||
gid = 0;
|
||||
}
|
||||
GID_TO_CHARS (gid, header->header.gid);
|
||||
if (!GID_TO_CHARS (gid, header->header.gid))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
{
|
||||
@@ -703,7 +725,8 @@ start_header (struct tar_stat_info *st)
|
||||
xheader_store ("size", st, NULL);
|
||||
size = 0;
|
||||
}
|
||||
OFF_TO_CHARS (size, header->header.size);
|
||||
if (!OFF_TO_CHARS (size, header->header.size))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
{
|
||||
@@ -716,7 +739,8 @@ start_header (struct tar_stat_info *st)
|
||||
if (MAX_OCTAL_VAL (header->header.mtime) < mtime.tv_sec)
|
||||
mtime.tv_sec = 0;
|
||||
}
|
||||
TIME_TO_CHARS (mtime.tv_sec, header->header.mtime);
|
||||
if (!TIME_TO_CHARS (mtime.tv_sec, header->header.mtime))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* FIXME */
|
||||
@@ -732,7 +756,8 @@ start_header (struct tar_stat_info *st)
|
||||
xheader_store ("devmajor", st, NULL);
|
||||
devmajor = 0;
|
||||
}
|
||||
MAJOR_TO_CHARS (devmajor, header->header.devmajor);
|
||||
if (!MAJOR_TO_CHARS (devmajor, header->header.devmajor))
|
||||
return NULL;
|
||||
|
||||
if (archive_format == POSIX_FORMAT
|
||||
&& MAX_OCTAL_VAL (header->header.devminor) < devminor)
|
||||
@@ -740,12 +765,14 @@ start_header (struct tar_stat_info *st)
|
||||
xheader_store ("devminor", st, NULL);
|
||||
devminor = 0;
|
||||
}
|
||||
MINOR_TO_CHARS (devminor, header->header.devminor);
|
||||
if (!MINOR_TO_CHARS (devminor, header->header.devminor))
|
||||
return NULL;
|
||||
}
|
||||
else if (archive_format != GNU_FORMAT && archive_format != OLDGNU_FORMAT)
|
||||
{
|
||||
MAJOR_TO_CHARS (0, header->header.devmajor);
|
||||
MINOR_TO_CHARS (0, header->header.devminor);
|
||||
if (!(MAJOR_TO_CHARS (0, header->header.devmajor)
|
||||
&& MINOR_TO_CHARS (0, header->header.devminor)))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (archive_format == POSIX_FORMAT)
|
||||
@@ -1289,7 +1316,7 @@ dump_hard_link (struct tar_stat_info *st)
|
||||
st->stat.st_size = 0;
|
||||
blk = start_header (st);
|
||||
if (!blk)
|
||||
return true;
|
||||
return false;
|
||||
tar_copy_str (blk->header.linkname, link_name, NAME_FIELD_SIZE);
|
||||
|
||||
blk->header.typeflag = LNKTYPE;
|
||||
|
||||
Reference in New Issue
Block a user