X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fincremen.c;h=7130bc22773b40dc7317036278c3407d533f0b0d;hb=cd7bdd4076ca154575bbef85eb2157e59befcfe2;hp=69cbd59a470687af78ba9623c8e5696853b9fa90;hpb=d88b2a613f4b1a5554e8c34c8f75b91abff5f0e9;p=chaz%2Ftar diff --git a/src/incremen.c b/src/incremen.c index 69cbd59..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 @@ -446,6 +447,7 @@ procdir (const char *name_buffer, struct tar_stat_info *st, struct directory *directory; struct stat *stat_data = &st->stat; bool nfs = NFS_FILE_STAT (*stat_data); + bool perhaps_renamed = false; if ((directory = find_directory (name_buffer)) != NULL) { @@ -500,9 +502,7 @@ procdir (const char *name_buffer, struct tar_stat_info *st, } else { - WARNOPT (WARN_RENAME_DIRECTORY, - (0, 0, _("%s: Directory has been renamed"), - quotearg_colon (name_buffer))); + perhaps_renamed = true; directory->children = ALL_CHILDREN; directory->device_number = stat_data->st_dev; directory->inode_number = stat_data->st_ino; @@ -521,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, @@ -560,13 +560,21 @@ procdir (const char *name_buffer, struct tar_stat_info *st, if (one_file_system_option && st->parent && stat_data->st_dev != st->parent->stat.st_dev) - /* FIXME: - WARNOPT (WARN_XDEV, - (0, 0, - _("%s: directory is on a different filesystem; not dumped"), - quotearg_colon (directory->name))); - */ - directory->children = NO_CHILDREN; + { + WARNOPT (WARN_XDEV, + (0, 0, + _("%s: directory is on a different filesystem; not dumped"), + quotearg_colon (directory->name))); + directory->children = NO_CHILDREN; + /* If there is any dumpdir info in that directory, remove it */ + if (directory->dump) + { + dumpdir_free (directory->dump); + directory->dump = NULL; + } + perhaps_renamed = false; + } + else if (flag & PD_FORCE_CHILDREN) { directory->children = PD_CHILDREN(flag); @@ -574,6 +582,11 @@ procdir (const char *name_buffer, struct tar_stat_info *st, *entry = 'N'; } + if (perhaps_renamed) + WARNOPT (WARN_RENAME_DIRECTORY, + (0, 0, _("%s: Directory has been renamed"), + quotearg_colon (name_buffer))); + DIR_SET_FLAG (directory, DIRF_INIT); if (directory->children != NO_CHILDREN) @@ -848,7 +861,7 @@ store_rename (struct directory *dir, struct obstack *stk) are ignored when hit by this function next time. If the chain forms a cycle, prev points to the entry DIR is renamed from. In this case it still retains DIRF_RENAMED flag, which will be - cleared in the `else' branch below */ + cleared in the 'else' branch below */ for (prev = dir; prev && prev->orig != dir; prev = prev->orig) DIR_CLEAR_FLAG (prev, DIRF_RENAMED); @@ -934,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; @@ -957,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; @@ -985,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))) { @@ -1015,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); @@ -1039,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); @@ -1144,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. @@ -1153,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++) @@ -1178,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 @@ -1206,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); @@ -1242,6 +1212,7 @@ read_incr_db_2 (void) for (;;) { + intmax_t i; struct timespec mtime; dev_t dev; ino_t ino; @@ -1250,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; @@ -1379,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);