diff --git a/src/incremen.c b/src/incremen.c index 7130bc2..e4ceb98 100644 --- a/src/incremen.c +++ b/src/incremen.c @@ -1084,37 +1084,78 @@ read_obstack (FILE *fp, struct obstack *stk, size_t *pcount) already been read. Throw a fatal error if the string cannot be converted or if the - converted value is less than MIN_VAL. */ + converted value is less than MIN_VAL. (FIELDNAME is used only as part + of these error messages.) */ static void -read_negative_num (FILE *fp, intmax_t min_val, intmax_t *pval) +read_negative_num (FILE *fp, const char *fieldname, intmax_t min_val, intmax_t *pval) { int c; size_t i; char buf[INT_BUFSIZE_BOUND (intmax_t)]; + char offbuf[INT_BUFSIZE_BOUND (off_t)]; char *ep; buf[0] = '-'; for (i = 1; ISDIGIT (c = getc (fp)); i++) { - if (i == sizeof buf - 1) - FATAL_ERROR ((0, 0, _("Field too long while reading snapshot file"))); + if (i == sizeof buf - 1) { + buf[i] = 0; + FATAL_ERROR ((0, 0, + _("%s: %s:\n after reading \"%s\" [field \"%s\" at byte %s]"), + quotearg_colon (listed_incremental_option), + _("Field too long while reading snapshot file"), + buf, + fieldname, offtostr(ftello(fp),offbuf) )); + } buf[i] = c; } + buf[i] = 0; if (c < 0) { if (ferror (fp)) - FATAL_ERROR ((0, errno, _("Read error in snapshot file"))); + FATAL_ERROR ((0, errno, + _("%s: %s:\n after reading \"%s\" [field \"%s\" at byte %s]"), + quotearg_colon (listed_incremental_option), + _("Read error in snapshot file"), + buf, + fieldname, offtostr(ftello(fp),offbuf) )); else - FATAL_ERROR ((0, 0, _("Unexpected EOF in snapshot file"))); + FATAL_ERROR ((0, 0, + _("%s: %s:\n after reading \"%s\" [field \"%s\" at byte %s]"), + quotearg_colon (listed_incremental_option), + _("Unexpected EOF in snapshot file"), + buf, + fieldname, offtostr(ftello(fp),offbuf) )); } + if (c) + FATAL_ERROR ((0, errno, + _("%s: %s:\n non-numeric character 0x%x found after reading \"%s\" [field \"%s\" at byte %s]"), + quotearg_colon (listed_incremental_option), + _("Unexpected field value in snapshot file"), + c, buf, + fieldname, offtostr(ftello(fp),offbuf) )); - buf[i] = 0; errno = 0; *pval = strtoimax (buf, &ep, 10); - if (c || errno || *pval < min_val) - FATAL_ERROR ((0, errno, _("Unexpected field value in snapshot file"))); + if (errno) + FATAL_ERROR ((0, errno, + _("%s: %s:\n strtoimax failed on value \"%s\" [field \"%s\" at byte %s]"), + quotearg_colon (listed_incremental_option), + _("Unexpected field value in snapshot file"), + buf, + fieldname, offtostr(ftello(fp),offbuf) )); + if (*pval < min_val) { + char minbuf[INT_BUFSIZE_BOUND (intmax_t)]; + + FATAL_ERROR ((0, errno, + _("%s: %s:\n value \"%s\" below min %s [field \"%s\" at byte %s]"), + quotearg_colon (listed_incremental_option), + _("Unexpected field value in snapshot file"), + buf, imaxtostr(min_val,minbuf), + fieldname, offtostr(ftello(fp),offbuf) )); + } } /* Read from file FP a nul-terminated string and convert it to @@ -1122,47 +1163,90 @@ read_negative_num (FILE *fp, intmax_t min_val, intmax_t *pval) value in PVAL. Assume C has already been read. Throw a fatal error if the string cannot be converted or if the - converted value exceeds MAX_VAL. + converted value exceeds MAX_VAL. (FIELDNAME is used only as part + of these error messages.) Return the last character read or EOF on end of file. */ static int -read_unsigned_num (int c, FILE *fp, uintmax_t max_val, intmax_t *pval) +read_unsigned_num (int c, FILE *fp, const char *fieldname, uintmax_t max_val, intmax_t *pval) { size_t i; uintmax_t u; char buf[UINTMAX_STRSIZE_BOUND], *ep; + char offbuf[INT_BUFSIZE_BOUND (off_t)]; for (i = 0; ISDIGIT (c); i++) { - if (i == sizeof buf - 1) - FATAL_ERROR ((0, 0, _("Field too long while reading snapshot file"))); + if (i == sizeof buf - 1) { + buf[i] = 0; + FATAL_ERROR ((0, 0, + _("%s: %s:\n after reading \"%s\" [field \"%s\" at byte %s]"), + quotearg_colon (listed_incremental_option), + _("Field too long while reading snapshot file"), + buf, + fieldname, offtostr(ftello(fp),offbuf) )); + } buf[i] = c; c = getc (fp); } + buf[i] = 0; if (c < 0) { if (ferror (fp)) - FATAL_ERROR ((0, errno, _("Read error in snapshot file"))); + FATAL_ERROR ((0, errno, + _("%s: %s:\n after reading \"%s\" [field \"%s\" at byte %s]"), + quotearg_colon (listed_incremental_option), + _("Read error in snapshot file"), + buf, + fieldname, offtostr(ftello(fp),offbuf) )); else if (i == 0) return c; else - FATAL_ERROR ((0, 0, _("Unexpected EOF in snapshot file"))); + FATAL_ERROR ((0, 0, + _("%s: %s:\n after reading \"%s\" [field \"%s\" at byte %s]"), + quotearg_colon (listed_incremental_option), + _("Unexpected EOF in snapshot file"), + buf, + fieldname, offtostr(ftello(fp),offbuf) )); } + if (c) + FATAL_ERROR ((0, errno, + _("%s: %s:\n non-numeric character 0x%x found after reading \"%s\" [field \"%s\" at byte %s]"), + quotearg_colon (listed_incremental_option), + _("Unexpected field value in snapshot file"), + c, buf, + fieldname, offtostr(ftello(fp),offbuf) )); - buf[i] = 0; errno = 0; u = strtoumax (buf, &ep, 10); - if (c || errno || max_val < u) - FATAL_ERROR ((0, errno, _("Unexpected field value in snapshot file"))); + if (errno) + FATAL_ERROR ((0, errno, + _("%s: %s:\n strtoumax failed on value \"%s\" [field \"%s\" at byte %s]"), + quotearg_colon (listed_incremental_option), + _("Unexpected field value in snapshot file"), + buf, + fieldname, offtostr(ftello(fp),offbuf) )); + if (max_val < u) { + char maxbuf[INT_BUFSIZE_BOUND (uintmax_t)]; + + FATAL_ERROR ((0, errno, + _("%s: %s:\n value \"%s\" exceeds max %s [field \"%s\" at byte %s]"), + quotearg_colon (listed_incremental_option), + _("Unexpected field value in snapshot file"), + buf, uinttostr(max_val,maxbuf), + fieldname, offtostr(ftello(fp),offbuf) )); + } *pval = represent_uintmax (u); return c; } /* Read from file FP a nul-terminated string and convert it to - an integer in the range MIN_VAL..MAXVAL. Return the resulting - value, converted to intmax_t, in PVAL. MINVAL must be nonpositive. + an integer in the range MIN_VAL..MAX_VAL. Return the resulting + value, converted to intmax_t, in PVAL. MIN_VAL must be nonpositive + and MAX_VAL positive. FIELDNAME simply a label for the snapshot-file + field currently being read, used only for generating error messages. Throw a fatal error if the string cannot be converted or if the converted value is out of range. @@ -1170,15 +1254,15 @@ read_unsigned_num (int c, FILE *fp, uintmax_t max_val, intmax_t *pval) Return the last character read or EOF on end of file. */ static int -read_num (FILE *fp, intmax_t min_val, uintmax_t max_val, intmax_t *pval) +read_num (FILE *fp, const char *fieldname, intmax_t min_val, uintmax_t max_val, intmax_t *pval) { int c = getc (fp); if (c == '-') { - read_negative_num (fp, min_val, pval); + read_negative_num (fp, fieldname, min_val, pval); return 0; } - return read_unsigned_num (c, fp, max_val, pval); + return read_unsigned_num (c, fp, fieldname, max_val, pval); } /* Read from FP two NUL-terminated strings representing a struct @@ -1189,14 +1273,24 @@ read_num (FILE *fp, intmax_t min_val, uintmax_t max_val, intmax_t *pval) static void read_timespec (FILE *fp, struct timespec *pval) { + char offbuf[INT_BUFSIZE_BOUND (off_t)]; intmax_t i; - int c = read_num (fp, TYPE_MINIMUM (time_t), TYPE_MAXIMUM (time_t), &i); + int c = read_num (fp, "tv_sec", TYPE_MINIMUM (time_t), TYPE_MAXIMUM (time_t), &i); pval->tv_sec = i; - if (c || read_num (fp, 0, BILLION - 1, &i)) - FATAL_ERROR ((0, 0, "%s: %s", + if (c) + FATAL_ERROR ((0, 0, + _("%s: %s:\n at start of field [field \"%s\" at byte %s]"), quotearg_colon (listed_incremental_option), - _("Unexpected EOF in snapshot file"))); + _("Unexpected EOF in snapshot file"), + "tv_sec", offtostr(ftello(fp),offbuf) )); + + if (read_num (fp, "tv_nsec", 0, BILLION - 1, &i)) + FATAL_ERROR ((0, 0, + _("%s: %s:\n at start of field [field \"%s\" at byte %s]"), + quotearg_colon (listed_incremental_option), + _("Unexpected EOF in snapshot file"), + "tv_nsec", offtostr(ftello(fp),offbuf) )); pval->tv_nsec = i; } @@ -1205,6 +1299,7 @@ static void read_incr_db_2 (void) { struct obstack stk; + char offbuf[INT_BUFSIZE_BOUND (off_t)]; obstack_init (&stk); @@ -1221,19 +1316,19 @@ read_incr_db_2 (void) char *content; size_t s; - if (read_num (listed_incremental_stream, 0, 1, &i)) + if (read_num (listed_incremental_stream, "nfs", 0, 1, &i)) return; /* Normal return */ nfs = i; read_timespec (listed_incremental_stream, &mtime); - if (read_num (listed_incremental_stream, + if (read_num (listed_incremental_stream, "dev", TYPE_MINIMUM (dev_t), TYPE_MAXIMUM (dev_t), &i)) break; dev = i; - if (read_num (listed_incremental_stream, + if (read_num (listed_incremental_stream, "ino", TYPE_MINIMUM (ino_t), TYPE_MAXIMUM (ino_t), &i)) break; ino = i; @@ -1246,17 +1341,22 @@ read_incr_db_2 (void) while (read_obstack (listed_incremental_stream, &stk, &s) == 0 && s > 1) ; if (getc (listed_incremental_stream) != 0) - FATAL_ERROR ((0, 0, "%s: %s", + FATAL_ERROR ((0, 0, + _("%s: %s:\n at end of dumpdir data [field \"%s\" at byte %s]"), quotearg_colon (listed_incremental_option), - _("Missing record terminator"))); + _("Missing record terminator"), + "dircontents", offtostr(ftello(listed_incremental_stream),offbuf) )); content = obstack_finish (&stk); note_directory (name, mtime, dev, ino, nfs, false, content); obstack_free (&stk, content); } - FATAL_ERROR ((0, 0, "%s: %s", + FATAL_ERROR ((0, 0, + _("%s: %s:\n at start of new field [field \"%s\" at byte %s]"), quotearg_colon (listed_incremental_option), - _("Unexpected EOF in snapshot file"))); + _("Unexpected EOF in snapshot file"), + "?", offtostr(ftello(listed_incremental_stream),offbuf) )); + } /* Read incremental snapshot file (directory file).