]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Guard against out-of-range nanosecond time values and make it easy for
authorTim Kientzle <kientzle@gmail.com>
Sat, 6 Feb 2010 05:10:13 +0000 (00:10 -0500)
committerTim Kientzle <kientzle@gmail.com>
Sat, 6 Feb 2010 05:10:13 +0000 (00:10 -0500)
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

libarchive/archive_entry.c
libarchive/test/test_entry.c

index 550fdf16a62791611f940c1171dcce4fbede60dc..a45939283eb9fe814a2f7a60134597203a1b7e07 100644 (file)
@@ -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;
 }
 
index b6a2da177acb114831b8bfe8d0fb5c31ec42d255..cedc88a15c0ad3b36950d6b8d2b4d9318ac98fbb 100644 (file)
@@ -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);