From: Tim Kientzle Date: Wed, 17 Sep 2008 22:04:52 +0000 (-0400) Subject: archive_entry support for storing and managing birthtime data X-Git-Tag: v2.6.0~84 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8ac32d2763a3f55084a6932f1e776b0cf505782e;p=thirdparty%2Flibarchive.git archive_entry support for storing and managing birthtime data Submitted by: Pedro Giffuni SVN-Revision: 209 --- diff --git a/configure.ac b/configure.ac index 75cb4d143..b49b00bc3 100644 --- a/configure.ac +++ b/configure.ac @@ -191,7 +191,12 @@ AC_CHECK_TYPE(off_t, [long long]) AC_TYPE_SIZE_T AC_CHECK_TYPE(id_t, [unsigned long]) AC_CHECK_TYPE(uintptr_t, [unsigned int]) + +# Check for birthtime in struct stat +AC_CHECK_MEMBERS([struct stat.st_birthtime]) + # Check for high-resolution timestamps in struct stat +AC_CHECK_MEMBERS([struct stat.st_birthtimespec.tv_nsec]) AC_CHECK_MEMBERS([struct stat.st_mtimespec.tv_nsec]) AC_CHECK_MEMBERS([struct stat.st_mtim.tv_nsec]) # Check for block size support in struct stat diff --git a/libarchive/archive_entry.c b/libarchive/archive_entry.c index 9c870f28f..1ea0b9469 100644 --- a/libarchive/archive_entry.c +++ b/libarchive/archive_entry.c @@ -460,6 +460,24 @@ archive_entry_atime_is_set(struct archive_entry *entry) return (entry->ae_set & AE_SET_ATIME); } +time_t +archive_entry_birthtime(struct archive_entry *entry) +{ + return (entry->ae_stat.aest_birthtime); +} + +long +archive_entry_birthtime_nsec(struct archive_entry *entry) +{ + return (entry->ae_stat.aest_birthtime_nsec); +} + +int +archive_entry_birthtime_is_set(struct archive_entry *entry) +{ + return (entry->ae_set & AE_SET_BIRTHTIME); +} + time_t archive_entry_ctime(struct archive_entry *entry) { @@ -837,6 +855,22 @@ archive_entry_unset_atime(struct archive_entry *entry) entry->ae_set &= ~AE_SET_ATIME; } +void +archive_entry_set_birthtime(struct archive_entry *entry, time_t m, long ns) +{ + entry->stat_valid = 0; + entry->ae_set |= AE_SET_BIRTHTIME; + entry->ae_stat.aest_birthtime = m; + entry->ae_stat.aest_birthtime_nsec = ns; +} + +void +archive_entry_unset_birthtime(struct archive_entry *entry) +{ + archive_entry_set_birthtime(entry, 0, 0); + entry->ae_set &= ~AE_SET_BIRTHTIME; +} + void archive_entry_set_ctime(struct archive_entry *entry, time_t t, long ns) { diff --git a/libarchive/archive_entry.h b/libarchive/archive_entry.h index 88f4ad857..25a136ac6 100644 --- a/libarchive/archive_entry.h +++ b/libarchive/archive_entry.h @@ -174,6 +174,9 @@ __LA_DECL struct archive_entry *archive_entry_new(void); __LA_DECL time_t archive_entry_atime(struct archive_entry *); __LA_DECL long archive_entry_atime_nsec(struct archive_entry *); __LA_DECL int archive_entry_atime_is_set(struct archive_entry *); +__LA_DECL time_t archive_entry_birthtime(struct archive_entry *); +__LA_DECL long archive_entry_birthtime_nsec(struct archive_entry *); +__LA_DECL int archive_entry_birthtime_is_set(struct archive_entry *); __LA_DECL time_t archive_entry_ctime(struct archive_entry *); __LA_DECL long archive_entry_ctime_nsec(struct archive_entry *); __LA_DECL int archive_entry_ctime_is_set(struct archive_entry *); @@ -224,6 +227,8 @@ __LA_DECL const wchar_t *archive_entry_uname_w(struct archive_entry *); __LA_DECL void archive_entry_set_atime(struct archive_entry *, time_t, long); __LA_DECL void archive_entry_unset_atime(struct archive_entry *); +__LA_DECL void archive_entry_set_birthtime(struct archive_entry *, time_t, long); +__LA_DECL void archive_entry_unset_birthtime(struct archive_entry *); __LA_DECL void archive_entry_set_ctime(struct archive_entry *, time_t, long); __LA_DECL void archive_entry_unset_ctime(struct archive_entry *); __LA_DECL void archive_entry_set_dev(struct archive_entry *, dev_t); diff --git a/libarchive/archive_entry_copy_stat.c b/libarchive/archive_entry_copy_stat.c index 514db0274..ba8812a9f 100644 --- a/libarchive/archive_entry_copy_stat.c +++ b/libarchive/archive_entry_copy_stat.c @@ -47,6 +47,12 @@ archive_entry_copy_stat(struct archive_entry *entry, const struct stat *st) archive_entry_set_atime(entry, st->st_atime, 0); archive_entry_set_ctime(entry, st->st_ctime, 0); archive_entry_set_mtime(entry, st->st_mtime, 0); +#if HAVE_STRUCT_STAT_ST_BIRTHTIME + archive_entry_set_birthtime(entry, st->st_birthtime, 0); +#endif +#endif +#if HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC + archive_entry_set_birthtime(entry, st->st_birthtime, st->st_birthtimespec.tv_nsec); #endif archive_entry_set_dev(entry, st->st_dev); archive_entry_set_gid(entry, st->st_gid); diff --git a/libarchive/archive_entry_private.h b/libarchive/archive_entry_private.h index 9b3e7f578..622fd2365 100644 --- a/libarchive/archive_entry_private.h +++ b/libarchive/archive_entry_private.h @@ -112,6 +112,8 @@ struct archive_entry { uint32_t aest_ctime_nsec; int64_t aest_mtime; uint32_t aest_mtime_nsec; + int64_t aest_birthtime; + uint32_t aest_birthtime_nsec; gid_t aest_gid; ino_t aest_ino; mode_t aest_mode; diff --git a/libarchive/archive_entry_stat.c b/libarchive/archive_entry_stat.c index 6ef5b3728..5a627d7d8 100644 --- a/libarchive/archive_entry_stat.c +++ b/libarchive/archive_entry_stat.c @@ -64,6 +64,9 @@ archive_entry_stat(struct archive_entry *entry) * the appropriate conversions get invoked. */ st->st_atime = archive_entry_atime(entry); +#if HAVE_STRUCT_STAT_ST_BIRTHTIME + st->st_birthtime = archive_entry_birthtime(entry); +#endif st->st_ctime = archive_entry_ctime(entry); st->st_mtime = archive_entry_mtime(entry); st->st_dev = archive_entry_dev(entry); @@ -88,6 +91,9 @@ archive_entry_stat(struct archive_entry *entry) st->st_ctim.tv_nsec = archive_entry_ctime_nsec(entry); st->st_mtim.tv_nsec = archive_entry_mtime_nsec(entry); #endif +#if HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC + st->st_birthtimespec.tv_nsec = archive_entry_birthtime_nsec(entry); +#endif /* * TODO: On Linux, store 32 or 64 here depending on whether diff --git a/libarchive/test/test_entry.c b/libarchive/test/test_entry.c index 9891b0669..8b9cb8b3c 100644 --- a/libarchive/test/test_entry.c +++ b/libarchive/test/test_entry.c @@ -79,6 +79,15 @@ DEFINE_TEST(test_entry) assertEqualInt(archive_entry_atime_nsec(e), 0); assert(!archive_entry_atime_is_set(e)); + /* birthtime */ + archive_entry_set_birthtime(e, 17579, 24990); + assertEqualInt(archive_entry_birthtime(e), 17579); + assertEqualInt(archive_entry_birthtime_nsec(e), 24990); + archive_entry_unset_birthtime(e); + assertEqualInt(archive_entry_birthtime(e), 0); + assertEqualInt(archive_entry_birthtime_nsec(e), 0); + assert(!archive_entry_birthtime_is_set(e)); + /* ctime */ archive_entry_set_ctime(e, 13580, 24681); assertEqualInt(archive_entry_ctime(e), 13580); @@ -312,6 +321,7 @@ DEFINE_TEST(test_entry) /* Set values in 'e' */ archive_entry_clear(e); archive_entry_set_atime(e, 13579, 24680); + archive_entry_set_birthtime(e, 13779, 24990); archive_entry_set_ctime(e, 13580, 24681); #if ARCHIVE_VERSION_NUMBER >= 1009000 archive_entry_set_dev(e, 235); @@ -348,6 +358,8 @@ DEFINE_TEST(test_entry) /* Clone should have same contents. */ assertEqualInt(archive_entry_atime(e2), 13579); assertEqualInt(archive_entry_atime_nsec(e2), 24680); + assertEqualInt(archive_entry_birthtime(e2), 13779); + assertEqualInt(archive_entry_birthtime_nsec(e2), 24990); assertEqualInt(archive_entry_ctime(e2), 13580); assertEqualInt(archive_entry_ctime_nsec(e2), 24681); #if ARCHIVE_VERSION_NUMBER >= 1009000 @@ -435,6 +447,7 @@ DEFINE_TEST(test_entry) /* Change the original */ archive_entry_set_atime(e, 13580, 24690); + archive_entry_set_birthtime(e, 13980, 24999); archive_entry_set_ctime(e, 13590, 24691); #if ARCHIVE_VERSION_NUMBER >= 1009000 archive_entry_set_dev(e, 245); @@ -468,6 +481,8 @@ DEFINE_TEST(test_entry) /* Clone should still have same contents. */ assertEqualInt(archive_entry_atime(e2), 13579); assertEqualInt(archive_entry_atime_nsec(e2), 24680); + assertEqualInt(archive_entry_birthtime(e2), 13779); + assertEqualInt(archive_entry_birthtime_nsec(e2), 24990); assertEqualInt(archive_entry_ctime(e2), 13580); assertEqualInt(archive_entry_ctime_nsec(e2), 24681); #if ARCHIVE_VERSION_NUMBER >= 1009000 @@ -561,6 +576,8 @@ DEFINE_TEST(test_entry) archive_entry_clear(e); assertEqualInt(archive_entry_atime(e), 0); assertEqualInt(archive_entry_atime_nsec(e), 0); + assertEqualInt(archive_entry_birthtime(e), 0); + assertEqualInt(archive_entry_birthtime_nsec(e), 0); assertEqualInt(archive_entry_ctime(e), 0); assertEqualInt(archive_entry_ctime_nsec(e), 0); assertEqualInt(archive_entry_dev(e), 0);