static bool decode_signed_num (intmax_t *num, char const *arg, intmax_t minval, uintmax_t maxval, char const *keyword) { char *arg_lim; intmax_t u = strtosysint (arg, &arg_lim, minval, maxval); if (errno == EINVAL || *arg_lim) { ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"), keyword, arg)); return false; } if (errno == ERANGE) { out_of_range_header (keyword, arg, minval, maxval); return false; } *num = u; return true; }
/* Read incremental snapshot formats 0 and 1 */ static void read_incr_db_01 (int version, const char *initbuf) { int n; uintmax_t u; char *buf = NULL; size_t bufsize = 0; char *ebuf; long lineno = 1; if (version == 1) { if (getline (&buf, &bufsize, listed_incremental_stream) <= 0) { read_error (listed_incremental_option); free (buf); return; } ++lineno; } else { buf = strdup (initbuf); bufsize = strlen (buf) + 1; } newer_mtime_option = decode_timespec (buf, &ebuf, false); if (! valid_timespec (newer_mtime_option)) ERROR ((0, errno, "%s:%ld: %s", quotearg_colon (listed_incremental_option), lineno, _("Invalid time stamp"))); else { if (version == 1 && *ebuf) { char const *buf_ns = ebuf + 1; errno = 0; u = strtoumax (buf_ns, &ebuf, 10); if (!errno && BILLION <= u) errno = ERANGE; if (errno || buf_ns == ebuf) { ERROR ((0, errno, "%s:%ld: %s", quotearg_colon (listed_incremental_option), lineno, _("Invalid time stamp"))); newer_mtime_option.tv_sec = TYPE_MINIMUM (time_t); newer_mtime_option.tv_nsec = -1; } else newer_mtime_option.tv_nsec = u; } } while (0 < (n = getline (&buf, &bufsize, listed_incremental_stream))) { dev_t dev; ino_t ino; bool nfs = buf[0] == '+'; char *strp = buf + nfs; struct timespec mtime; lineno++; if (buf[n - 1] == '\n') buf[n - 1] = '\0'; if (version == 1) { mtime = decode_timespec (strp, &ebuf, false); strp = ebuf; if (!valid_timespec (mtime) || *strp != ' ') ERROR ((0, errno, "%s:%ld: %s", quotearg_colon (listed_incremental_option), lineno, _("Invalid modification time"))); errno = 0; u = strtoumax (strp, &ebuf, 10); if (!errno && BILLION <= u) errno = ERANGE; if (errno || strp == ebuf || *ebuf != ' ') { ERROR ((0, errno, "%s:%ld: %s", quotearg_colon (listed_incremental_option), lineno, _("Invalid modification time (nanoseconds)"))); mtime.tv_nsec = -1; } else mtime.tv_nsec = u; strp = ebuf; } else mtime.tv_sec = mtime.tv_nsec = 0; dev = strtosysint (strp, &ebuf, TYPE_MINIMUM (dev_t), TYPE_MAXIMUM (dev_t)); strp = ebuf; if (errno || *strp != ' ') ERROR ((0, errno, "%s:%ld: %s", quotearg_colon (listed_incremental_option), lineno, _("Invalid device number"))); ino = strtosysint (strp, &ebuf, TYPE_MINIMUM (ino_t), TYPE_MAXIMUM (ino_t)); strp = ebuf; if (errno || *strp != ' ') ERROR ((0, errno, "%s:%ld: %s", quotearg_colon (listed_incremental_option), lineno, _("Invalid inode number"))); strp++; unquote_string (strp); note_directory (strp, mtime, dev, ino, nfs, false, NULL); } free (buf); }
static bool read_num (FILE *fp, char const *fieldname, intmax_t min_val, uintmax_t max_val, intmax_t *pval) { 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 == '-'; for (i = 0; (i == 0 && negative) || ISDIGIT (c); i++) { buf[i] = c; if (i == sizeof buf - 1) FATAL_ERROR ((0, 0, _("%s: byte %s: %s %.*s... too long"), quotearg_colon (listed_incremental_option), offtostr (ftello (fp), offbuf), fieldname, i + 1, buf)); c = getc (fp); } buf[i] = 0; if (c < 0) { if (ferror (fp)) read_fatal (listed_incremental_option); if (i != 0) FATAL_ERROR ((0, 0, "%s: %s", quotearg_colon (listed_incremental_option), _("Unexpected EOF in snapshot file"))); return false; } if (c) { unsigned uc = c; FATAL_ERROR ((0, 0, _("%s: byte %s: %s %s followed by invalid byte 0x%02x"), quotearg_colon (listed_incremental_option), offtostr (ftello (fp), offbuf), fieldname, buf, uc)); } *pval = strtosysint (buf, NULL, min_val, max_val); conversion_errno = errno; switch (conversion_errno) { case ERANGE: FATAL_ERROR ((0, conversion_errno, _("%s: byte %s: (valid range %s..%s)\n\t%s %s"), quotearg_colon (listed_incremental_option), offtostr (ftello (fp), offbuf), imaxtostr (min_val, minbuf), umaxtostr (max_val, maxbuf), fieldname, buf)); default: FATAL_ERROR ((0, conversion_errno, _("%s: byte %s: %s %s"), quotearg_colon (listed_incremental_option), offtostr (ftello (fp), offbuf), fieldname, buf)); case 0: break; } return true; }