X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fincremen.c;h=7130bc22773b40dc7317036278c3407d533f0b0d;hb=cd7bdd4076ca154575bbef85eb2157e59befcfe2;hp=d5bc1e41d88fa6c0d8067da6d27a62f6a60e3774;hpb=643a8844a578ff146cfe746fe6091d29502b6c40;p=chaz%2Ftar diff --git a/src/incremen.c b/src/incremen.c index d5bc1e4..7130bc2 100644 --- a/src/incremen.c +++ b/src/incremen.c @@ -1,21 +1,22 @@ /* GNU dump extensions to tar. - Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001, - 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. + Copyright 1988, 1992-1994, 1996-1997, 1999-2001, 2003-2009, 2013 + Free Software Foundation, Inc. - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 3, or (at your option) any later - version. + This file is part of GNU tar. - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - Public License for more details. + GNU tar is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + GNU tar is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ #include #include @@ -447,7 +448,7 @@ procdir (const char *name_buffer, struct tar_stat_info *st, struct stat *stat_data = &st->stat; bool nfs = NFS_FILE_STAT (*stat_data); bool perhaps_renamed = false; - + if ((directory = find_directory (name_buffer)) != NULL) { if (DIR_IS_INITED (directory)) @@ -520,7 +521,7 @@ procdir (const char *name_buffer, struct tar_stat_info *st, stat_data->st_ino); directory = note_directory (name_buffer, - get_stat_mtime(stat_data), + get_stat_mtime (stat_data), stat_data->st_dev, stat_data->st_ino, nfs, @@ -573,7 +574,7 @@ procdir (const char *name_buffer, struct tar_stat_info *st, } perhaps_renamed = false; } - + else if (flag & PD_FORCE_CHILDREN) { directory->children = PD_CHILDREN(flag); @@ -946,8 +947,6 @@ read_incr_db_01 (int version, const char *initbuf) { int n; uintmax_t u; - time_t sec; - long int nsec; char *buf = NULL; size_t bufsize = 0; char *ebuf; @@ -969,21 +968,15 @@ read_incr_db_01 (int version, const char *initbuf) bufsize = strlen (buf) + 1; } - sec = TYPE_MINIMUM (time_t); - nsec = -1; - errno = 0; - u = strtoumax (buf, &ebuf, 10); - if (!errno && TYPE_MAXIMUM (time_t) < u) - errno = ERANGE; - if (errno || buf == ebuf) + 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 { - sec = u; - if (version == 1 && *ebuf) { char const *buf_ns = ebuf + 1; @@ -997,20 +990,13 @@ read_incr_db_01 (int version, const char *initbuf) quotearg_colon (listed_incremental_option), lineno, _("Invalid time stamp"))); - sec = TYPE_MINIMUM (time_t); + newer_mtime_option.tv_sec = TYPE_MINIMUM (time_t); + newer_mtime_option.tv_nsec = -1; } else - nsec = u; - } - else - { - /* pre-1 incremental format does not contain nanoseconds */ - nsec = 0; + newer_mtime_option.tv_nsec = u; } } - newer_mtime_option.tv_sec = sec; - newer_mtime_option.tv_nsec = nsec; - while (0 < (n = getline (&buf, &bufsize, listed_incremental_stream))) { @@ -1027,20 +1013,12 @@ read_incr_db_01 (int version, const char *initbuf) if (version == 1) { - errno = 0; - u = strtoumax (strp, &ebuf, 10); - if (!errno && TYPE_MAXIMUM (time_t) < u) - errno = ERANGE; - if (errno || strp == ebuf || *ebuf != ' ') - { - ERROR ((0, errno, "%s:%ld: %s", - quotearg_colon (listed_incremental_option), lineno, - _("Invalid modification time (seconds)"))); - sec = (time_t) -1; - } - else - sec = u; + 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); @@ -1051,46 +1029,30 @@ read_incr_db_01 (int version, const char *initbuf) ERROR ((0, errno, "%s:%ld: %s", quotearg_colon (listed_incremental_option), lineno, _("Invalid modification time (nanoseconds)"))); - nsec = -1; + mtime.tv_nsec = -1; } else - nsec = u; - mtime.tv_sec = sec; - mtime.tv_nsec = nsec; + mtime.tv_nsec = u; strp = ebuf; } else - memset (&mtime, 0, sizeof mtime); + mtime.tv_sec = mtime.tv_nsec = 0; - errno = 0; - u = strtoumax (strp, &ebuf, 10); - if (!errno && TYPE_MAXIMUM (dev_t) < u) - errno = ERANGE; - if (errno || strp == ebuf || *ebuf != ' ') - { - ERROR ((0, errno, "%s:%ld: %s", - quotearg_colon (listed_incremental_option), lineno, - _("Invalid device number"))); - dev = (dev_t) -1; - } - else - dev = u; + 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"))); - errno = 0; - u = strtoumax (strp, &ebuf, 10); - if (!errno && TYPE_MAXIMUM (ino_t) < u) - errno = ERANGE; - if (errno || strp == ebuf || *ebuf != ' ') - { - ERROR ((0, errno, "%s:%ld: %s", - quotearg_colon (listed_incremental_option), lineno, - _("Invalid inode number"))); - ino = (ino_t) -1; - } - else - ino = u; + 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); @@ -1156,8 +1118,8 @@ read_negative_num (FILE *fp, intmax_t min_val, intmax_t *pval) } /* Read from file FP a nul-terminated string and convert it to - uintmax_t. Return the resulting value in PVAL. Assume C has - already been read. + uintmax_t. Return an intmax_t representation of the resulting + 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. @@ -1165,9 +1127,10 @@ read_negative_num (FILE *fp, intmax_t min_val, intmax_t *pval) Return the last character read or EOF on end of file. */ static int -read_unsigned_num (int c, FILE *fp, uintmax_t max_val, uintmax_t *pval) +read_unsigned_num (int c, FILE *fp, uintmax_t max_val, intmax_t *pval) { size_t i; + uintmax_t u; char buf[UINTMAX_STRSIZE_BOUND], *ep; for (i = 0; ISDIGIT (c); i++) @@ -1190,24 +1153,32 @@ read_unsigned_num (int c, FILE *fp, uintmax_t max_val, uintmax_t *pval) buf[i] = 0; errno = 0; - *pval = strtoumax (buf, &ep, 10); - if (c || errno || max_val < *pval) + u = strtoumax (buf, &ep, 10); + if (c || errno || max_val < u) FATAL_ERROR ((0, errno, _("Unexpected field value in snapshot file"))); + *pval = represent_uintmax (u); return c; } /* Read from file FP a nul-terminated string and convert it to - uintmax_t. Return the resulting value in PVAL. + an integer in the range MIN_VAL..MAXVAL. Return the resulting + value, converted to intmax_t, in PVAL. MINVAL must be nonpositive. Throw a fatal error if the string cannot be converted or if the - converted value exceeds MAX_VAL. + converted value is out of range. Return the last character read or EOF on end of file. */ static int -read_num (FILE *fp, uintmax_t max_val, uintmax_t *pval) +read_num (FILE *fp, intmax_t min_val, uintmax_t max_val, intmax_t *pval) { - return read_unsigned_num (getc (fp), fp, max_val, pval); + int c = getc (fp); + if (c == '-') + { + read_negative_num (fp, min_val, pval); + return 0; + } + return read_unsigned_num (c, fp, max_val, pval); } /* Read from FP two NUL-terminated strings representing a struct @@ -1218,34 +1189,21 @@ read_num (FILE *fp, uintmax_t max_val, uintmax_t *pval) static void read_timespec (FILE *fp, struct timespec *pval) { - int c = getc (fp); intmax_t i; - uintmax_t u; - - if (c == '-') - { - read_negative_num (fp, TYPE_MINIMUM (time_t), &i); - c = 0; - pval->tv_sec = i; - } - else - { - c = read_unsigned_num (c, fp, TYPE_MAXIMUM (time_t), &u); - pval->tv_sec = u; - } + int c = read_num (fp, TYPE_MINIMUM (time_t), TYPE_MAXIMUM (time_t), &i); + pval->tv_sec = i; - if (c || read_num (fp, BILLION - 1, &u)) + if (c || read_num (fp, 0, BILLION - 1, &i)) FATAL_ERROR ((0, 0, "%s: %s", quotearg_colon (listed_incremental_option), _("Unexpected EOF in snapshot file"))); - pval->tv_nsec = u; + pval->tv_nsec = i; } /* Read incremental snapshot format 2 */ static void read_incr_db_2 (void) { - uintmax_t u; struct obstack stk; obstack_init (&stk); @@ -1254,6 +1212,7 @@ read_incr_db_2 (void) for (;;) { + intmax_t i; struct timespec mtime; dev_t dev; ino_t ino; @@ -1262,20 +1221,22 @@ read_incr_db_2 (void) char *content; size_t s; - if (read_num (listed_incremental_stream, 1, &u)) + if (read_num (listed_incremental_stream, 0, 1, &i)) return; /* Normal return */ - nfs = u; + nfs = i; read_timespec (listed_incremental_stream, &mtime); - if (read_num (listed_incremental_stream, TYPE_MAXIMUM (dev_t), &u)) + if (read_num (listed_incremental_stream, + TYPE_MINIMUM (dev_t), TYPE_MAXIMUM (dev_t), &i)) break; - dev = u; + dev = i; - if (read_num (listed_incremental_stream, TYPE_MAXIMUM (ino_t), &u)) + if (read_num (listed_incremental_stream, + TYPE_MINIMUM (ino_t), TYPE_MAXIMUM (ino_t), &i)) break; - ino = u; + ino = i; if (read_obstack (listed_incremental_stream, &stk, &s)) break; @@ -1391,20 +1352,21 @@ write_directory_file_entry (void *entry, void *data) if (DIR_IS_FOUND (directory)) { - char buf[UINTMAX_STRSIZE_BOUND]; + char buf[max (SYSINT_BUFSIZE, INT_BUFSIZE_BOUND (intmax_t))]; char const *s; s = DIR_IS_NFS (directory) ? "1" : "0"; fwrite (s, 2, 1, fp); - s = (TYPE_SIGNED (time_t) - ? imaxtostr (directory->mtime.tv_sec, buf) - : umaxtostr (directory->mtime.tv_sec, buf)); + s = sysinttostr (directory->mtime.tv_sec, TYPE_MINIMUM (time_t), + TYPE_MAXIMUM (time_t), buf); fwrite (s, strlen (s) + 1, 1, fp); - s = umaxtostr (directory->mtime.tv_nsec, buf); + s = imaxtostr (directory->mtime.tv_nsec, buf); fwrite (s, strlen (s) + 1, 1, fp); - s = umaxtostr (directory->device_number, buf); + s = sysinttostr (directory->device_number, + TYPE_MINIMUM (dev_t), TYPE_MAXIMUM (dev_t), buf); fwrite (s, strlen (s) + 1, 1, fp); - s = umaxtostr (directory->inode_number, buf); + s = sysinttostr (directory->inode_number, + TYPE_MINIMUM (ino_t), TYPE_MAXIMUM (ino_t), buf); fwrite (s, strlen (s) + 1, 1, fp); fwrite (directory->name, strlen (directory->name) + 1, 1, fp);