while (i);
}
+
+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)
+{
+ 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];
+ char maxbuf[UINTMAX_STRSIZE_BOUND];
+ char minbuf[UINTMAX_STRSIZE_BOUND + 1];
+ char const *minval_string;
+ char const *maxval_string = STRINGIFY_BIGINT (maxval, maxbuf);
+ char const *value_string;
+ char *p;
+
+ if (gnu_format)
+ {
+ uintmax_t m = maxval + 1 ? maxval + 1 : maxval / 2 + 1;
+ char *p = STRINGIFY_BIGINT (m, minbuf + 1);
+ *--p = '-';
+ minval_string = p;
+ }
+ else
+ minval_string = "0";
+
+ if (negative)
+ {
+ char *p = STRINGIFY_BIGINT (- value, valbuf + 1);
+ *--p = '-';
+ value_string = p;
+ }
+ else
+ value_string = STRINGIFY_BIGINT (value, valbuf);
+
+ if (substitute)
+ {
+ int negsub;
+ uintmax_t sub = substitute (&negsub) & maxval;
+ /* FIXME: This is the only place where GNU_FORMAT differs from
+ OLDGNU_FORMAT. Apart from this they are completely identical. */
+ uintmax_t s = (negsub &= archive_format == GNU_FORMAT) ? - sub : sub;
+ char subbuf[UINTMAX_STRSIZE_BOUND + 1];
+ char *sub_string = STRINGIFY_BIGINT (s, subbuf + 1);
+ if (negsub)
+ *--sub_string = '-';
+ WARN ((0, 0, _("value %s out of %s range %s..%s; substituting %s"),
+ value_string, type, minval_string, maxval_string,
+ sub_string));
+ to_chars (negsub, s, valsize, 0, where, size, type);
+ }
+ else
+ 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
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)
{
- int base256_allowed = (archive_format == GNU_FORMAT
- || archive_format == OLDGNU_FORMAT);
+ 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;
}
-
- /* 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
+ else if (gnu_format)
{
- uintmax_t maxval = (base256_allowed
- ? MAX_VAL_WITH_DIGITS (size - 1, LG_256)
- : MAX_VAL_WITH_DIGITS (size - 1, LG_8));
- char valbuf[UINTMAX_STRSIZE_BOUND + 1];
- char maxbuf[UINTMAX_STRSIZE_BOUND];
- char minbuf[UINTMAX_STRSIZE_BOUND + 1];
- char const *minval_string;
- char const *maxval_string = STRINGIFY_BIGINT (maxval, maxbuf);
- char const *value_string;
-
- if (base256_allowed)
- {
- uintmax_t m = maxval + 1 ? maxval + 1 : maxval / 2 + 1;
- char *p = STRINGIFY_BIGINT (m, minbuf + 1);
- *--p = '-';
- minval_string = p;
- }
- else
- minval_string = "0";
+ /* Try to cope with the number by using traditional GNU format
+ methods */
- if (negative)
+ /* Generate the base-256 representation if the number fits. */
+ if (((negative ? -1 - value : value)
+ <= MAX_VAL_WITH_DIGITS (size - 1, LG_256)))
{
- char *p = STRINGIFY_BIGINT (- value, valbuf + 1);
- *--p = '-';
- value_string = p;
+ where[0] = negative ? -1 : 1 << (LG_256 - 1);
+ to_base256 (negative, value, where + 1, size - 1);
+ return true;
}
- else
- value_string = STRINGIFY_BIGINT (value, valbuf);
- if (substitute)
+ /* 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)
{
- int negsub;
- uintmax_t sub = substitute (&negsub) & maxval;
- /* FIXME: This is the only place where GNU_FORMAT differs from
- OLDGNU_FORMAT. Apart from this they are completely identical. */
- uintmax_t s = (negsub &= archive_format == GNU_FORMAT) ? - sub : sub;
- char subbuf[UINTMAX_STRSIZE_BOUND + 1];
- char *sub_string = STRINGIFY_BIGINT (s, subbuf + 1);
- if (negsub)
- *--sub_string = '-';
- WARN ((0, 0, _("value %s out of %s range %s..%s; substituting %s"),
- value_string, type, minval_string, maxval_string,
- sub_string));
- to_chars (negsub, s, valsize, 0, where, size, type);
+ 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;
}
- else
- ERROR ((0, 0, _("value %s out of %s range %s..%s"),
- value_string, type, minval_string, maxval_string));
+ /* 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
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,
| (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
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
xheader_store ("uid", st, NULL);
uid = 0;
}
- UID_TO_CHARS (uid, header->header.uid);
+ if (!UID_TO_CHARS (uid, header->header.uid))
+ return NULL;
}
{
xheader_store ("gid", st, NULL);
gid = 0;
}
- GID_TO_CHARS (gid, header->header.gid);
+ if (!GID_TO_CHARS (gid, header->header.gid))
+ return NULL;
}
{
xheader_store ("size", st, NULL);
size = 0;
}
- OFF_TO_CHARS (size, header->header.size);
+ if (!OFF_TO_CHARS (size, header->header.size))
+ return NULL;
}
{
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 */
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)
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)
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;