From c26111742a3a63effd02ff225d79a0e6507e94bd Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Thu, 1 Aug 2024 19:31:50 -0700 Subject: [PATCH] Prefer C99 formats like %jd to doing it by hand MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit It’s now safe to assume support for C99 formats like %jd, so remove some of the longwinded formatting code put in only to be portable to pre-C99 platforms. * gnulib.modules: Add intprops. * src/buffer.c (format_total_stats, try_new_volume) (write_volume_label): * src/checkpoint.c (format_checkpoint_string): * src/compare.c (verify_volume): * src/create.c (to_chars_subst, dump_regular_file): * src/incremen.c (read_num): * src/list.c (read_and, from_header, simple_print_header) (print_for_mkdir): * src/sparse.c (sparse_dump_region): * src/system.c (dec_to_env, sys_exec_info_script) (sys_exec_checkpoint_script): * src/xheader.c (out_of_range_header): Prefer C99 formats like %jd and %ju to STRINGIFY_BIGINT. * src/common.h: Sort includes. Include intprops.h, verify.h. All other includes of verify.h removed. (intmax, uintmax): New functions and macros. (STRINGIFY_BIGINT): Remove; no longer used. (TIMESPEC_STRSIZE_BOUND): Make it 1 byte bigger, for negatives. * src/create.c (MAX_VAL_WITH_DIGITS, to_base256): Use *_WIDTH macros rather than assuming no padding bits. Prefer UINTMAX_MAX to (uintmax_t) -1. * src/list.c (tartime): Use strftime result rather than running strlen later. * src/misc.c (timetostr): New function. Prefer it when printing time_t values. --- gnulib.modules | 1 + src/buffer.c | 57 ++++++++++------------------ src/checkpoint.c | 5 +-- src/common.h | 40 +++++++++++++++----- src/compare.c | 6 +-- src/create.c | 59 ++++++++++------------------- src/incremen.c | 48 +++++++++--------------- src/list.c | 98 ++++++++++++++++++------------------------------ src/misc.c | 24 ++++++++---- src/sparse.c | 9 ++--- src/system.c | 34 ++++++++--------- src/tar.c | 1 - src/xheader.c | 9 +---- 13 files changed, 164 insertions(+), 227 deletions(-) diff --git a/gnulib.modules b/gnulib.modules index 8c4e8e8e..4dc35be4 100644 --- a/gnulib.modules +++ b/gnulib.modules @@ -63,6 +63,7 @@ gitlog-to-changelog hash human idx +intprops inttostr inttypes largefile diff --git a/src/buffer.c b/src/buffer.c index b55a132c..e76ee9b7 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -28,7 +28,6 @@ #include #include #include -#include #include "common.h" #include @@ -543,7 +542,6 @@ format_total_stats (FILE *fp, char const *const *formats, int eor, int eol) case DELETE_SUBCOMMAND: { - char buf[UINTMAX_STRSIZE_BOUND]; n = print_stats (fp, formats[TF_READ], records_read * record_size); @@ -553,15 +551,10 @@ format_total_stats (FILE *fp, char const *const *formats, int eor, int eol) n += print_stats (fp, formats[TF_WRITE], prev_written + bytes_written); - fputc (eor, fp); - n++; - - if (formats[TF_DELETED] && formats[TF_DELETED][0]) - n += fprintf (fp, "%s: ", gettext (formats[TF_DELETED])); - n += fprintf (fp, "%s", - STRINGIFY_BIGINT ((records_read - records_skipped) - * record_size - - (prev_written + bytes_written), buf)); + intmax_t deleted = ((records_read - records_skipped) * record_size + - (prev_written + bytes_written)); + n += fprintf (fp, "%c%s: %jd", eor, gettext (formats[TF_DELETED]), + deleted); } break; @@ -1528,7 +1521,6 @@ try_new_volume (void) if (bufmap_head) { - uintmax_t s; if (!continued_file_name) { WARN ((0, 0, _("%s is not continued on this volume"), @@ -1553,34 +1545,25 @@ try_new_volume (void) } } - s = continued_file_size + continued_file_offset; - - if (bufmap_head->sizetotal != s || s < continued_file_offset) + uintmax_t s; + if (ckd_add (&s, continued_file_size, continued_file_offset) + || s != bufmap_head->sizetotal) { - char totsizebuf[UINTMAX_STRSIZE_BOUND]; - char s1buf[UINTMAX_STRSIZE_BOUND]; - char s2buf[UINTMAX_STRSIZE_BOUND]; - - WARN ((0, 0, _("%s is the wrong size (%s != %s + %s)"), + WARN ((0, 0, _("%s is the wrong size (%jd != %ju + %ju)"), quote (continued_file_name), - STRINGIFY_BIGINT (bufmap_head->sizetotal, totsizebuf), - STRINGIFY_BIGINT (continued_file_size, s1buf), - STRINGIFY_BIGINT (continued_file_offset, s2buf))); + intmax (bufmap_head->sizetotal), + uintmax (continued_file_size), + uintmax (continued_file_offset))); return false; } - if (bufmap_head->sizetotal - bufmap_head->sizeleft != - continued_file_offset) + if (bufmap_head->sizetotal - bufmap_head->sizeleft + != continued_file_offset) { - char totsizebuf[UINTMAX_STRSIZE_BOUND]; - char s1buf[UINTMAX_STRSIZE_BOUND]; - char s2buf[UINTMAX_STRSIZE_BOUND]; - - WARN ((0, 0, _("This volume is out of sequence (%s - %s != %s)"), - STRINGIFY_BIGINT (bufmap_head->sizetotal, totsizebuf), - STRINGIFY_BIGINT (bufmap_head->sizeleft, s1buf), - STRINGIFY_BIGINT (continued_file_offset, s2buf))); - + WARN ((0, 0, _("This volume is out of sequence (%jd - %jd != %ju)"), + intmax (bufmap_head->sizetotal), + intmax (bufmap_head->sizeleft), + uintmax (continued_file_offset))); return false; } } @@ -1700,11 +1683,9 @@ _write_volume_label (const char *str) static void add_volume_label (void) { - char buf[UINTMAX_STRSIZE_BOUND]; - char *p = STRINGIFY_BIGINT (volno, buf); char *s = xmalloc (strlen (volume_label_option) + sizeof VOL_SUFFIX - + strlen (p) + 2); - sprintf (s, "%s %s %s", volume_label_option, VOL_SUFFIX, p); + + INT_BUFSIZE_BOUND (int) + 2); + sprintf (s, "%s %s %d", volume_label_option, VOL_SUFFIX, volno); _write_volume_label (s); free (s); } diff --git a/src/checkpoint.c b/src/checkpoint.c index 8194463e..1a658cad 100644 --- a/src/checkpoint.c +++ b/src/checkpoint.c @@ -234,8 +234,6 @@ format_checkpoint_string (FILE *fp, size_t len, unsigned cpn) { const char *opstr = do_write ? gettext ("write") : gettext ("read"); - char uintbuf[UINTMAX_STRSIZE_BOUND]; - char *cps = STRINGIFY_BIGINT (cpn, uintbuf); const char *ip; static char *argbuf = NULL; @@ -281,8 +279,7 @@ format_checkpoint_string (FILE *fp, size_t len, break; case 'u': - fputs (cps, fp); - len += strlen (cps); + len += fprintf (fp, "%u", cpn); break; case 's': diff --git a/src/common.h b/src/common.h index c65e64d6..c2c22fc3 100644 --- a/src/common.h +++ b/src/common.h @@ -39,26 +39,29 @@ #include "arith.h" + +#define obstack_chunk_alloc xmalloc +#define obstack_chunk_free free +#include + #include #include #include +#include #include #include +#include #include #include +#include +#include #include #include -#include #include #include -#define obstack_chunk_alloc xmalloc -#define obstack_chunk_free free -#include -#include +#include #include -#include - /* Log base 2 of common values. */ #define LG_8 3 #define LG_64 6 @@ -661,6 +664,23 @@ char *namebuf_name (namebuf_t buf, const char *name); const char *tar_dirname (void); +/* intmax (N) is like ((intmax_t) (N)) except without a cast so + that it is an error if N is a pointer. Similarly for uintmax. */ +COMMON_INLINE intmax_t +intmax (intmax_t n) +{ + return n; +} +COMMON_INLINE uintmax_t +uintmax (uintmax_t n) +{ + return n; +} +/* intmax should be used only with signed types, and uintmax for unsigned. + To bypass this check parenthesize the function, e.g., (intmax) (n). */ +#define intmax(n) verify_expr (EXPR_SIGNED (n), (intmax) (n)) +#define uintmax(n) verify_expr (!EXPR_SIGNED (n), (uintmax) (n)) + /* Represent N using a signed integer I such that (uintmax_t) I == N. With a good optimizing compiler, this is equivalent to (intmax_t) i and requires zero machine instructions. */ @@ -679,18 +699,18 @@ represent_uintmax (uintmax_t n) } } -#define STRINGIFY_BIGINT(i, b) umaxtostr (i, b) enum { UINTMAX_STRSIZE_BOUND = INT_BUFSIZE_BOUND (intmax_t) }; enum { SYSINT_BUFSIZE = max (UINTMAX_STRSIZE_BOUND, INT_BUFSIZE_BOUND (intmax_t)) }; char *sysinttostr (uintmax_t, intmax_t, uintmax_t, char buf[SYSINT_BUFSIZE]); intmax_t strtosysint (char const *, char **, intmax_t, uintmax_t); +char *timetostr (time_t, char buf[SYSINT_BUFSIZE]); void code_ns_fraction (int ns, char *p); enum { BILLION = 1000000000, LOG10_BILLION = 9 }; enum { TIMESPEC_STRSIZE_BOUND = - UINTMAX_STRSIZE_BOUND + LOG10_BILLION + sizeof "-." - 1 }; + SYSINT_BUFSIZE + LOG10_BILLION + sizeof "." - 1 }; char const *code_timespec (struct timespec ts, - char sbuf[TIMESPEC_STRSIZE_BOUND]); + char tsbuf[TIMESPEC_STRSIZE_BOUND]); struct timespec decode_timespec (char const *, char **, bool); /* Return true if T does not represent an out-of-range or invalid value. */ diff --git a/src/compare.c b/src/compare.c index 4c3162d0..deb9b92e 100644 --- a/src/compare.c +++ b/src/compare.c @@ -607,15 +607,13 @@ verify_volume (void) set_next_block_after (current_header); if (!ignore_zeros_option) { - char buf[UINTMAX_STRSIZE_BOUND]; - status = read_header (¤t_header, ¤t_stat_info, read_header_auto); if (status == HEADER_ZERO_BLOCK) break; WARNOPT (WARN_ALONE_ZERO_BLOCK, - (0, 0, _("A lone zero block at %s"), - STRINGIFY_BIGINT (current_block_ordinal (), buf))); + (0, 0, _("A lone zero block at %jd"), + intmax (current_block_ordinal ()))); } continue; } diff --git a/src/create.c b/src/create.c index 344bd6d3..c3d88d6c 100644 --- a/src/create.c +++ b/src/create.c @@ -125,9 +125,9 @@ cachedir_file_p (int fd) /* The maximum uintmax_t value that can be represented with DIGITS digits, assuming that each digit is BITS_PER_DIGIT wide. */ #define MAX_VAL_WITH_DIGITS(digits, bits_per_digit) \ - ((digits) * (bits_per_digit) < sizeof (uintmax_t) * CHAR_BIT \ + ((digits) * (bits_per_digit) < UINTMAX_WIDTH \ ? ((uintmax_t) 1 << ((digits) * (bits_per_digit))) - 1 \ - : (uintmax_t) -1) + : UINTMAX_MAX) /* The maximum uintmax_t value that can be represented with octal digits and a trailing NUL in BUFFER. */ @@ -185,7 +185,7 @@ to_base256 (bool negative, uintmax_t value, char *where, size_t size) { uintmax_t v = value; uintmax_t propagated_sign_bits = - ((uintmax_t) - negative << (CHAR_BIT * sizeof v - LG_256)); + ((uintmax_t) - negative << (UINTMAX_WIDTH - LG_256)); size_t i = size; do @@ -218,31 +218,12 @@ to_chars_subst (bool negative, bool gnu_format, uintmax_t value, size_t valsize, 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; - - 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"; - + intmax_t minval = (!gnu_format ? 0 + : ckd_sub (&minval, -1, maxval) ? INTMAX_MIN + : minval); + char const *valuesign = &"-"[!negative]; if (negative) - { - char *p = STRINGIFY_BIGINT (- value, valbuf + 1); - *--p = '-'; - value_string = p; - } - else - value_string = STRINGIFY_BIGINT (value, valbuf); + value = -value; if (substitute) { @@ -256,18 +237,15 @@ to_chars_subst (bool negative, bool gnu_format, uintmax_t value, size_t valsize, 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)); + char const *ssign = &"-"[!negsub]; + WARN ((0, 0, _("value %s%ju out of %s range %jd..%ju;" + " substituting %s%ju"), + valuesign, value, type, minval, maxval, ssign, s)); return 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)); + ERROR ((0, 0, _("value %s%ju out of %s range %jd..%ju"), + valuesign, value, type, minval, maxval)); return false; } @@ -1097,15 +1075,16 @@ dump_regular_file (int fd, struct tar_stat_info *st) if (count != bufsize) { - char buf[UINTMAX_STRSIZE_BOUND]; memset (blk->buffer + count, 0, bufsize - count); WARNOPT (WARN_FILE_SHRANK, (0, 0, - ngettext ("%s: File shrank by %s byte; padding with zeros", - "%s: File shrank by %s bytes; padding with zeros", + ngettext (("%s: File shrank by %jd byte;" + " padding with zeros"), + ("%s: File shrank by %jd bytes;" + " padding with zeros"), size_left), quotearg_colon (st->orig_file_name), - STRINGIFY_BIGINT (size_left, buf))); + intmax (size_left))); if (! ignore_failed_read_option) set_exit_status (TAREXIT_DIFFERS); pad_archive (size_left - (bufsize - count)); diff --git a/src/incremen.c b/src/incremen.c index 11b0f546..41dc8b10 100644 --- a/src/incremen.c +++ b/src/incremen.c @@ -1126,9 +1126,6 @@ read_num (FILE *fp, char const *fieldname, { int i; char buf[INT_BUFSIZE_BOUND (intmax_t)]; - char offbuf[INT_BUFSIZE_BOUND (off_t)]; - char minbuf[INT_BUFSIZE_BOUND (intmax_t)]; - char maxbuf[INT_BUFSIZE_BOUND (intmax_t)]; int conversion_errno; int c = getc (fp); bool negative = c == '-'; @@ -1138,9 +1135,9 @@ read_num (FILE *fp, char const *fieldname, buf[i] = c; if (i == sizeof buf - 1) FATAL_ERROR ((0, 0, - _("%s: byte %s: %s %.*s... too long"), + _("%s: byte %jd: %s %.*s... too long"), quotearg_colon (listed_incremental_option), - offtostr (ftello (fp), offbuf), + intmax (ftello (fp)), fieldname, i + 1, buf)); c = getc (fp); } @@ -1162,9 +1159,9 @@ read_num (FILE *fp, char const *fieldname, { unsigned uc = c; FATAL_ERROR ((0, 0, - _("%s: byte %s: %s %s followed by invalid byte 0x%02x"), + _("%s: byte %jd: %s %s followed by invalid byte 0x%02x"), quotearg_colon (listed_incremental_option), - offtostr (ftello (fp), offbuf), + intmax (ftello (fp)), fieldname, buf, uc)); } @@ -1175,16 +1172,14 @@ read_num (FILE *fp, char const *fieldname, { case ERANGE: FATAL_ERROR ((0, conversion_errno, - _("%s: byte %s: (valid range %s..%s)\n\t%s %s"), + _("%s: byte %jd: (valid range %jd..%ju)\n\t%s %s"), quotearg_colon (listed_incremental_option), - offtostr (ftello (fp), offbuf), - imaxtostr (min_val, minbuf), - umaxtostr (max_val, maxbuf), fieldname, buf)); + intmax (ftello (fp)), min_val, max_val, fieldname, buf)); default: FATAL_ERROR ((0, conversion_errno, - _("%s: byte %s: %s %s"), + _("%s: byte %jd: %s %s"), quotearg_colon (listed_incremental_option), - offtostr (ftello (fp), offbuf), fieldname, buf)); + intmax (ftello (fp)), fieldname, buf)); case 0: break; } @@ -1420,11 +1415,10 @@ write_directory_file_entry (void *entry, void *data) s = DIR_IS_NFS (directory) ? "1" : "0"; fwrite (s, 2, 1, fp); - s = sysinttostr (directory->mtime.tv_sec, TYPE_MINIMUM (time_t), - TYPE_MAXIMUM (time_t), buf); - fwrite (s, strlen (s) + 1, 1, fp); - s = imaxtostr (directory->mtime.tv_nsec, buf); + s = timetostr (directory->mtime.tv_sec, buf); fwrite (s, strlen (s) + 1, 1, fp); + int ns = directory->mtime.tv_nsec; + fprintf (fp, "%d%c", ns, 0); s = sysinttostr (directory->device_number, TYPE_MINIMUM (dev_t), TYPE_MAXIMUM (dev_t), buf); fwrite (s, strlen (s) + 1, 1, fp); @@ -1454,26 +1448,20 @@ void write_directory_file (void) { FILE *fp = listed_incremental_stream; - char buf[UINTMAX_STRSIZE_BOUND]; - char *s; - if (! fp) return; - if (fseeko (fp, 0L, SEEK_SET) != 0) + if (fseeko (fp, 0, SEEK_SET) != 0) seek_error (listed_incremental_option); if (sys_truncate (fileno (fp)) != 0) truncate_error (listed_incremental_option); - fprintf (fp, "%s-%s-%d\n", PACKAGE_NAME, PACKAGE_VERSION, - TAR_INCREMENTAL_VERSION); - - s = (TYPE_SIGNED (time_t) - ? imaxtostr (start_time.tv_sec, buf) - : umaxtostr (start_time.tv_sec, buf)); - fwrite (s, strlen (s) + 1, 1, fp); - s = umaxtostr (start_time.tv_nsec, buf); - fwrite (s, strlen (s) + 1, 1, fp); + int nsec = start_time.tv_nsec; + char buf[SYSINT_BUFSIZE]; + fprintf (fp, "%s-%s-%d\n%s%c%d%c", + PACKAGE_NAME, PACKAGE_VERSION, TAR_INCREMENTAL_VERSION, + timetostr (start_time.tv_sec, buf), + 0, nsec, 0); if (! ferror (fp) && directory_table) hash_do_for_each (directory_table, write_directory_file_entry, fp); diff --git a/src/list.c b/src/list.c index f829f1b8..f7f22c98 100644 --- a/src/list.c +++ b/src/list.c @@ -232,25 +232,20 @@ read_and (void (*do_something) (void)) case HEADER_ZERO_BLOCK: if (block_number_option) - { - char buf[UINTMAX_STRSIZE_BOUND]; - fprintf (stdlis, _("block %s: ** Block of NULs **\n"), - STRINGIFY_BIGINT (current_block_ordinal (), buf)); - } + fprintf (stdlis, _("block %jd: ** Block of NULs **\n"), + intmax (current_block_ordinal ())); set_next_block_after (current_header); if (!ignore_zeros_option) { - char buf[UINTMAX_STRSIZE_BOUND]; - status = read_header (¤t_header, ¤t_stat_info, read_header_auto); if (status == HEADER_ZERO_BLOCK) break; WARNOPT (WARN_ALONE_ZERO_BLOCK, - (0, 0, _("A lone zero block at %s"), - STRINGIFY_BIGINT (current_block_ordinal (), buf))); + (0, 0, _("A lone zero block at %jd"), + intmax (current_block_ordinal ()))); break; } status = prev_status; @@ -258,18 +253,12 @@ read_and (void (*do_something) (void)) case HEADER_END_OF_FILE: if (!ignore_zeros_option) - { - char buf[UINTMAX_STRSIZE_BOUND]; - WARNOPT (WARN_MISSING_ZERO_BLOCKS, - (0, 0, _("Terminating zero blocks missing at %s"), - STRINGIFY_BIGINT (current_block_ordinal (), buf))); - } + WARNOPT (WARN_MISSING_ZERO_BLOCKS, + (0, 0, _("Terminating zero blocks missing at %jd"), + intmax (current_block_ordinal ()))); if (block_number_option) - { - char buf[UINTMAX_STRSIZE_BOUND]; - fprintf (stdlis, _("block %s: ** End of File **\n"), - STRINGIFY_BIGINT (current_block_ordinal (), buf)); - } + fprintf (stdlis, _("block %jd: ** End of File **\n"), + intmax (current_block_ordinal ())); break; case HEADER_FAILURE: @@ -285,12 +274,11 @@ read_and (void (*do_something) (void)) case HEADER_SUCCESS: if (block_number_option) { - char buf[UINTMAX_STRSIZE_BOUND]; off_t block_ordinal = current_block_ordinal (); block_ordinal -= recent_long_name_blocks; block_ordinal -= recent_long_link_blocks; - fprintf (stdlis, _("block %s: "), - STRINGIFY_BIGINT (block_ordinal, buf)); + fprintf (stdlis, _("block %jd: "), + intmax (block_ordinal)); } ERROR ((0, 0, _("Skipping to next header"))); break; @@ -942,19 +930,10 @@ from_header (char const *where0, size_t digs, char const *type, if (type && !silent) { - char minval_buf[UINTMAX_STRSIZE_BOUND + 1]; - char maxval_buf[UINTMAX_STRSIZE_BOUND]; - char value_buf[UINTMAX_STRSIZE_BOUND + 1]; - char *minval_string = STRINGIFY_BIGINT (minus_minval, minval_buf + 1); - char *value_string = STRINGIFY_BIGINT (value, value_buf + 1); - if (negative) - *--value_string = '-'; - if (minus_minval) - *--minval_string = '-'; + char const *value_sign = &"-"[!negative]; /* TRANSLATORS: Second %s is type name (gid_t,uid_t,etc.) */ - ERROR ((0, 0, _("Archive value %s is out of %s range %s..%s"), - value_string, type, - minval_string, STRINGIFY_BIGINT (maxval, maxval_buf))); + ERROR ((0, 0, _("Archive value %s%ju is out of %s range %jd..%ju"), + value_sign, value, type, minval, maxval)); } return -1; @@ -1070,8 +1049,8 @@ tartime (struct timespec t, bool full_time) { if (full_time) { - strftime (buffer, sizeof buffer, "%Y-%m-%d %H:%M:%S", tm); - code_ns_fraction (ns, buffer + strlen (buffer)); + size_t n = strftime (buffer, sizeof buffer, "%Y-%m-%d %H:%M:%S", tm); + code_ns_fraction (ns, buffer + n); } else strftime (buffer, sizeof buffer, "%Y-%m-%d %H:%M", tm); @@ -1129,12 +1108,11 @@ simple_print_header (struct tar_stat_info *st, union block *blk, char *temp_name; /* These hold formatted ints. */ - char uform[max (INT_BUFSIZE_BOUND (intmax_t), UINTMAX_STRSIZE_BOUND)]; - char gform[sizeof uform]; + char uform[SYSINT_BUFSIZE]; + char gform[SYSINT_BUFSIZE]; char *user, *group; char size[2 * UINTMAX_STRSIZE_BOUND]; /* holds formatted size or major,minor */ - char uintbuf[UINTMAX_STRSIZE_BOUND]; int pad; int sizelen; @@ -1145,13 +1123,11 @@ simple_print_header (struct tar_stat_info *st, union block *blk, if (block_number_option) { - char buf[UINTMAX_STRSIZE_BOUND]; if (block_ordinal < 0) block_ordinal = current_block_ordinal (); block_ordinal -= recent_long_name_blocks; block_ordinal -= recent_long_link_blocks; - fprintf (stdlis, _("block %s: "), - STRINGIFY_BIGINT (block_ordinal, buf)); + fprintf (stdlis, _("block %jd: "), intmax (block_ordinal)); } if (verbose_option <= 1) @@ -1235,7 +1211,8 @@ simple_print_header (struct tar_stat_info *st, union block *blk, && !numeric_owner_option) user = st->uname; else - user = STRINGIFY_BIGINT (st->stat.st_uid, uform); + user = sysinttostr (st->stat.st_uid, TYPE_MINIMUM (uid_t), + TYPE_MAXIMUM (uid_t), uform); if (st->gname && st->gname[0] @@ -1243,7 +1220,8 @@ simple_print_header (struct tar_stat_info *st, union block *blk, && !numeric_owner_option) group = st->gname; else - group = STRINGIFY_BIGINT (st->stat.st_gid, gform); + group = sysinttostr (st->stat.st_gid, TYPE_MINIMUM (gid_t), + TYPE_MAXIMUM (gid_t), gform); /* Format the file size or major/minor device numbers. */ @@ -1251,22 +1229,24 @@ simple_print_header (struct tar_stat_info *st, union block *blk, { case CHRTYPE: case BLKTYPE: - strcpy (size, - STRINGIFY_BIGINT (major (st->stat.st_rdev), uintbuf)); - strcat (size, ","); - strcat (size, - STRINGIFY_BIGINT (minor (st->stat.st_rdev), uintbuf)); + sizelen = ((EXPR_SIGNED (major (st->stat.st_rdev)) + && EXPR_SIGNED (minor (st->stat.st_rdev))) + ? sprintf (size, "%jd,%jd", + (intmax) (major (st->stat.st_rdev)), + (intmax) (minor (st->stat.st_rdev))) + : sprintf (size, "%ju,%ju", + (uintmax) (major (st->stat.st_rdev)), + (uintmax) (minor (st->stat.st_rdev)))); break; default: /* st->stat.st_size keeps stored file size */ - strcpy (size, STRINGIFY_BIGINT (st->stat.st_size, uintbuf)); + sizelen = sprintf (size, "%jd", intmax (st->stat.st_size)); break; } /* Figure out padding and print the whole line. */ - sizelen = strlen (size); pad = strlen (user) + 1 + strlen (group) + 1 + sizelen; if (pad > ugswidth) ugswidth = pad; @@ -1324,11 +1304,8 @@ simple_print_header (struct tar_stat_info *st, union block *blk, break; case GNUTYPE_MULTIVOL: - strcpy (size, - STRINGIFY_BIGINT - (UINTMAX_FROM_HEADER (blk->oldgnu_header.offset), - uintbuf)); - fprintf (stdlis, _("--Continued at byte %s--\n"), size); + fprintf (stdlis, _("--Continued at byte %ju--\n"), + UINTMAX_FROM_HEADER (blk->oldgnu_header.offset)); break; } } @@ -1384,11 +1361,8 @@ print_for_mkdir (char *dirname, mode_t mode) pax_decode_mode (mode, modes + 1); if (block_number_option) - { - char buf[UINTMAX_STRSIZE_BOUND]; - fprintf (stdlis, _("block %s: "), - STRINGIFY_BIGINT (current_block_ordinal (), buf)); - } + fprintf (stdlis, _("block %jd: "), + intmax (current_block_ordinal ())); fprintf (stdlis, "%s %*s %s\n", modes, ugswidth + 1 + datewidth, _("Creating directory:"), quotearg (dirname)); diff --git a/src/misc.c b/src/misc.c index 8388e1c7..87eb1b84 100644 --- a/src/misc.c +++ b/src/misc.c @@ -372,7 +372,7 @@ replace_prefix (char **pname, const char *samp, size_t slen, /* Handling numbers. */ /* Convert VALUE, which is converted from a system integer type whose - minimum value is MINVAL and maximum MINVAL, to an decimal + minimum value is MINVAL and maximum MINVAL, to a decimal integer string. Use the storage in BUF and return a pointer to the converted string. If VALUE is converted from a negative integer in the range MINVAL .. -1, represent it with a string representation @@ -392,6 +392,14 @@ sysinttostr (uintmax_t value, intmax_t minval, uintmax_t maxval, } } +/* Convert T to a decimal integer string. Use the storage in BUF and + return a pointer to the converted string. */ +char * +timetostr (time_t t, char buf[SYSINT_BUFSIZE]) +{ + return sysinttostr (t, TYPE_MINIMUM (time_t), TYPE_MAXIMUM (time_t), buf); +} + /* Convert a prefix of the string ARG to a system integer type whose minimum value is MINVAL and maximum MAXVAL. If MINVAL is negative, negative integers MINVAL .. -1 are assumed to be represented using @@ -472,11 +480,10 @@ code_ns_fraction (int ns, char *p) } char const * -code_timespec (struct timespec t, char sbuf[TIMESPEC_STRSIZE_BOUND]) +code_timespec (struct timespec t, char tsbuf[TIMESPEC_STRSIZE_BOUND]) { time_t s = t.tv_sec; int ns = t.tv_nsec; - char *np; bool negative = s < 0; /* ignore invalid values of ns */ @@ -489,11 +496,12 @@ code_timespec (struct timespec t, char sbuf[TIMESPEC_STRSIZE_BOUND]) ns = BILLION - ns; } - np = umaxtostr (negative ? - (uintmax_t) s : (uintmax_t) s, sbuf + 1); - if (negative) - *--np = '-'; - code_ns_fraction (ns, sbuf + UINTMAX_STRSIZE_BOUND); - return np; + bool minus_zero = negative & !s; + char *sstr = timetostr (s, tsbuf + 1); + sstr[-1] = '-'; + sstr -= minus_zero; + code_ns_fraction (ns, sstr + strlen (sstr)); + return sstr; } struct timespec diff --git a/src/sparse.c b/src/sparse.c index 0a12e3ed..4ac4a40c 100644 --- a/src/sparse.c +++ b/src/sparse.c @@ -439,9 +439,8 @@ sparse_dump_region (struct tar_sparse_file *file, size_t i) } else { - char buf[UINTMAX_STRSIZE_BOUND]; struct stat st; - size_t n; + off_t n; if (fstat (file->fd, &st) == 0) n = file->stat_info->stat.st_size - st.st_size; else @@ -452,11 +451,11 @@ sparse_dump_region (struct tar_sparse_file *file, size_t i) WARNOPT (WARN_FILE_SHRANK, (0, 0, - ngettext ("%s: File shrank by %s byte; padding with zeros", - "%s: File shrank by %s bytes; padding with zeros", + ngettext ("%s: File shrank by %jd byte; padding with zeros", + "%s: File shrank by %jd bytes; padding with zeros", n), quotearg_colon (file->stat_info->orig_file_name), - STRINGIFY_BIGINT (n, buf))); + intmax (n))); if (! ignore_failed_read_option) set_exit_status (TAREXIT_DIFFERS); return false; diff --git a/src/system.c b/src/system.c index c07e2083..29aab4ea 100644 --- a/src/system.c +++ b/src/system.c @@ -662,10 +662,8 @@ sys_child_open_for_uncompress (void) static void dec_to_env (char const *envar, uintmax_t num) { - char buf[UINTMAX_STRSIZE_BOUND]; - char *numstr; - - numstr = STRINGIFY_BIGINT (num, buf); + char numstr[UINTMAX_STRSIZE_BOUND]; + sprintf (numstr, "%ju", num); if (setenv (envar, numstr, 1) != 0) xalloc_die (); } @@ -823,15 +821,13 @@ sys_wait_command (void) int sys_exec_info_script (const char **archive_name, int volume_number) { - pid_t pid; - char uintbuf[UINTMAX_STRSIZE_BOUND]; int p[2]; static void (*saved_handler) (int sig); xpipe (p); saved_handler = signal (SIGPIPE, SIG_IGN); - pid = xfork (); + pid_t pid = xfork (); if (pid != 0) { @@ -877,14 +873,17 @@ sys_exec_info_script (const char **archive_name, int volume_number) /* Child */ setenv ("TAR_VERSION", PACKAGE_VERSION, 1); setenv ("TAR_ARCHIVE", *archive_name, 1); - setenv ("TAR_VOLUME", STRINGIFY_BIGINT (volume_number, uintbuf), 1); - setenv ("TAR_BLOCKING_FACTOR", - STRINGIFY_BIGINT (blocking_factor, uintbuf), 1); + char intbuf[INT_BUFSIZE_BOUND (int)]; + sprintf (intbuf, "%d", volume_number); + setenv ("TAR_VOLUME", intbuf, 1); + sprintf (intbuf, "%d", blocking_factor); + setenv ("TAR_BLOCKING_FACTOR", intbuf, 1); setenv ("TAR_SUBCOMMAND", subcommand_string (subcommand_option), 1); setenv ("TAR_FORMAT", archive_format_string (current_format == DEFAULT_FORMAT ? archive_format : current_format), 1); - setenv ("TAR_FD", STRINGIFY_BIGINT (p[PWRITE], uintbuf), 1); + sprintf (intbuf, "%d", p[PWRITE]); + setenv ("TAR_FD", intbuf, 1); xclose (p[PREAD]); @@ -897,10 +896,7 @@ sys_exec_checkpoint_script (const char *script_name, const char *archive_name, int checkpoint_number) { - pid_t pid; - char uintbuf[UINTMAX_STRSIZE_BOUND]; - - pid = xfork (); + pid_t pid = xfork (); if (pid != 0) { @@ -921,9 +917,11 @@ sys_exec_checkpoint_script (const char *script_name, /* Child */ setenv ("TAR_VERSION", PACKAGE_VERSION, 1); setenv ("TAR_ARCHIVE", archive_name, 1); - setenv ("TAR_CHECKPOINT", STRINGIFY_BIGINT (checkpoint_number, uintbuf), 1); - setenv ("TAR_BLOCKING_FACTOR", - STRINGIFY_BIGINT (blocking_factor, uintbuf), 1); + char intbuf[INT_BUFSIZE_BOUND (int)]; + sprintf (intbuf, "%d", checkpoint_number); + setenv ("TAR_CHECKPOINT", intbuf, 1); + sprintf (intbuf, "%d", blocking_factor); + setenv ("TAR_BLOCKING_FACTOR", intbuf, 1); setenv ("TAR_SUBCOMMAND", subcommand_string (subcommand_option), 1); setenv ("TAR_FORMAT", archive_format_string (current_format == DEFAULT_FORMAT ? diff --git a/src/tar.c b/src/tar.c index d47cdac3..95ba25fc 100644 --- a/src/tar.c +++ b/src/tar.c @@ -130,7 +130,6 @@ bool delay_directory_restore_option; #include #include #include -#include #include #include #include diff --git a/src/xheader.c b/src/xheader.c index 96762c34..cf37e2d9 100644 --- a/src/xheader.c +++ b/src/xheader.c @@ -999,15 +999,10 @@ static void out_of_range_header (char const *keyword, char const *value, intmax_t minval, uintmax_t maxval) { - char minval_buf[INT_BUFSIZE_BOUND (intmax_t)]; - char maxval_buf[UINTMAX_STRSIZE_BOUND]; - char *minval_string = imaxtostr (minval, minval_buf); - char *maxval_string = umaxtostr (maxval, maxval_buf); - /* TRANSLATORS: The first %s is the pax extended header keyword (atime, gid, etc.). */ - ERROR ((0, 0, _("Extended header %s=%s is out of range %s..%s"), - keyword, value, minval_string, maxval_string)); + ERROR ((0, 0, _("Extended header %s=%s is out of range %jd..%ju"), + keyword, value, minval, maxval)); } static void -- 2.47.2