From: Tim Kientzle Date: Sat, 6 Feb 2010 05:10:13 +0000 (-0500) Subject: Guard against out-of-range nanosecond time values and make it easy for X-Git-Tag: v3.0.0a~1276 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=551e5e8550a4f171d9af70ee28c925145f0614b4;p=thirdparty%2Flibarchive.git Guard against out-of-range nanosecond time values and make it easy for people to make small time adjustments using code such as: archive_entry_set_ctime(entry, archive_entry_ctime(entry), archive_entry_ctime_nsec(entry) + 123456); SVN-Revision: 1882 --- diff --git a/libarchive/archive_entry.c b/libarchive/archive_entry.c index 550fdf16a..a45939283 100644 --- a/libarchive/archive_entry.c +++ b/libarchive/archive_entry.c @@ -98,6 +98,21 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_entry.c 201096 2009-12-28 02:41: #define ae_makedev(maj, min) makedev((maj), (min)) #endif +/* + * This adjustment is needed to support the following idiom for adding + * 1000ns to the stored time: + * archive_entry_set_atime(archive_entry_atime(), + * archive_entry_atime_nsec() + 1000) + * The additional if() here compensates for ambiguity in the C standard, + * which permits two possible interpretations of a % b when a is negative. + */ +#define FIX_NS(t,ns) \ + do { \ + t += ns / 1000000000; \ + ns %= 1000000000; \ + if (ns < 0) { --t; ns += 1000000000; } \ + } while (0) + static void aes_clean(struct aes *); static void aes_copy(struct aes *dest, struct aes *src); static const char * aes_get_mbs(struct aes *); @@ -891,6 +906,7 @@ archive_entry_update_hardlink_utf8(struct archive_entry *entry, const char *targ void archive_entry_set_atime(struct archive_entry *entry, time_t t, long ns) { + FIX_NS(t, ns); entry->stat_valid = 0; entry->ae_set |= AE_SET_ATIME; entry->ae_stat.aest_atime = t; @@ -905,11 +921,12 @@ archive_entry_unset_atime(struct archive_entry *entry) } void -archive_entry_set_birthtime(struct archive_entry *entry, time_t m, long ns) +archive_entry_set_birthtime(struct archive_entry *entry, time_t t, long ns) { + FIX_NS(t, ns); entry->stat_valid = 0; entry->ae_set |= AE_SET_BIRTHTIME; - entry->ae_stat.aest_birthtime = m; + entry->ae_stat.aest_birthtime = t; entry->ae_stat.aest_birthtime_nsec = ns; } @@ -923,6 +940,7 @@ archive_entry_unset_birthtime(struct archive_entry *entry) void archive_entry_set_ctime(struct archive_entry *entry, time_t t, long ns) { + FIX_NS(t, ns); entry->stat_valid = 0; entry->ae_set |= AE_SET_CTIME; entry->ae_stat.aest_ctime = t; @@ -1007,11 +1025,12 @@ archive_entry_set_mode(struct archive_entry *entry, mode_t m) } void -archive_entry_set_mtime(struct archive_entry *entry, time_t m, long ns) +archive_entry_set_mtime(struct archive_entry *entry, time_t t, long ns) { + FIX_NS(t, ns); entry->stat_valid = 0; entry->ae_set |= AE_SET_MTIME; - entry->ae_stat.aest_mtime = m; + entry->ae_stat.aest_mtime = t; entry->ae_stat.aest_mtime_nsec = ns; } diff --git a/libarchive/test/test_entry.c b/libarchive/test/test_entry.c index b6a2da177..cedc88a15 100644 --- a/libarchive/test/test_entry.c +++ b/libarchive/test/test_entry.c @@ -101,6 +101,12 @@ DEFINE_TEST(test_entry) archive_entry_set_atime(e, 13579, 24680); assertEqualInt(archive_entry_atime(e), 13579); assertEqualInt(archive_entry_atime_nsec(e), 24680); + archive_entry_set_atime(e, 13580, 1000000001L); + assertEqualInt(archive_entry_atime(e), 13581); + assertEqualInt(archive_entry_atime_nsec(e), 1); + archive_entry_set_atime(e, 13580, -7); + assertEqualInt(archive_entry_atime(e), 13579); + assertEqualInt(archive_entry_atime_nsec(e), 999999993); archive_entry_unset_atime(e); assertEqualInt(archive_entry_atime(e), 0); assertEqualInt(archive_entry_atime_nsec(e), 0); @@ -110,6 +116,12 @@ DEFINE_TEST(test_entry) archive_entry_set_birthtime(e, 17579, 24990); assertEqualInt(archive_entry_birthtime(e), 17579); assertEqualInt(archive_entry_birthtime_nsec(e), 24990); + archive_entry_set_birthtime(e, 17580, 1234567890L); + assertEqualInt(archive_entry_birthtime(e), 17581); + assertEqualInt(archive_entry_birthtime_nsec(e), 234567890); + archive_entry_set_birthtime(e, 17581, -24990); + assertEqualInt(archive_entry_birthtime(e), 17580); + assertEqualInt(archive_entry_birthtime_nsec(e), 999975010); archive_entry_unset_birthtime(e); assertEqualInt(archive_entry_birthtime(e), 0); assertEqualInt(archive_entry_birthtime_nsec(e), 0); @@ -119,6 +131,12 @@ DEFINE_TEST(test_entry) archive_entry_set_ctime(e, 13580, 24681); assertEqualInt(archive_entry_ctime(e), 13580); assertEqualInt(archive_entry_ctime_nsec(e), 24681); + archive_entry_set_ctime(e, 13581, 2008182348L); + assertEqualInt(archive_entry_ctime(e), 13583); + assertEqualInt(archive_entry_ctime_nsec(e), 8182348); + archive_entry_set_ctime(e, 13582, -24681); + assertEqualInt(archive_entry_ctime(e), 13581); + assertEqualInt(archive_entry_ctime_nsec(e), 999975319); archive_entry_unset_ctime(e); assertEqualInt(archive_entry_ctime(e), 0); assertEqualInt(archive_entry_ctime_nsec(e), 0); @@ -221,6 +239,12 @@ DEFINE_TEST(test_entry) archive_entry_set_mtime(e, 13581, 24682); assertEqualInt(archive_entry_mtime(e), 13581); assertEqualInt(archive_entry_mtime_nsec(e), 24682); + archive_entry_set_mtime(e, 13582, 1358297468); + assertEqualInt(archive_entry_mtime(e), 13583); + assertEqualInt(archive_entry_mtime_nsec(e), 358297468); + archive_entry_set_mtime(e, 13583, -24682); + assertEqualInt(archive_entry_mtime(e), 13582); + assertEqualInt(archive_entry_mtime_nsec(e), 999975318); archive_entry_unset_mtime(e); assertEqualInt(archive_entry_mtime(e), 0); assertEqualInt(archive_entry_mtime_nsec(e), 0);