+
+ /* 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)
+ {
+ where[size - 1] = '\0';
+ to_base (value & MAX_VAL_WITH_DIGITS (valsize * CHAR_BIT, 1),
+ LG_8, base_8_digits, where, size - 1);
+ }
+
+ /* Otherwise, output a substitute value if possible (with a
+ warning), and an error message if not. */
+ else
+ {
+ uintmax_t maxval = (archive_format == GNU_FORMAT
+ ? MAX_VAL_WITH_DIGITS (size - 1, LG_64)
+ : MAX_VAL_WITH_DIGITS (size - 1, LG_8));
+ char buf1[UINTMAX_STRSIZE_BOUND + 1];
+ char buf2[UINTMAX_STRSIZE_BOUND + 1];
+ char buf3[UINTMAX_STRSIZE_BOUND + 1];
+ char *value_string = STRINGIFY_BIGINT (v, buf1 + 1);
+ char *maxval_string = STRINGIFY_BIGINT (maxval, buf2 + 1);
+ char const *minval_string =
+ (archive_format == GNU_FORMAT
+ ? "0"
+ : (maxval_string[-1] = '-', maxval_string - 1));
+ if (negative)
+ *--value_string = '-';
+ if (substitute)
+ {
+ int negsub;
+ uintmax_t sub = substitute (&negsub) & maxval;
+ uintmax_t s = (negsub &= archive_format == GNU_FORMAT) ? -sub : sub;
+ char *sub_string = STRINGIFY_BIGINT (s, buf3 + 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));
+ }
+}
+
+static uintmax_t
+gid_substitute (int *negative)
+{
+ gid_t r;
+#ifdef GID_NOBODY
+ r = GID_NOBODY;
+#else
+ static gid_t gid_nobody;
+ if (!gid_nobody && !gname_to_gid ("nobody", &gid_nobody))
+ gid_nobody = -2;
+ r = gid_nobody;
+#endif
+ *negative = r < 0;
+ return r;