aboutsummaryrefslogtreecommitdiff
path: root/butl/filesystem.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'butl/filesystem.cxx')
-rw-r--r--butl/filesystem.cxx44
1 files changed, 43 insertions, 1 deletions
diff --git a/butl/filesystem.cxx b/butl/filesystem.cxx
index 230bc8e..7c8893e 100644
--- a/butl/filesystem.cxx
+++ b/butl/filesystem.cxx
@@ -4,7 +4,7 @@
#include <butl/filesystem>
-#include <unistd.h> // rmdir(), unlink()
+#include <unistd.h> // stat, rmdir(), unlink()
#include <sys/types.h> // stat
#include <sys/stat.h> // stat, lstat(), S_IS*, mkdir()
@@ -14,6 +14,48 @@ using namespace std;
namespace butl
{
+ // Figuring out whether we have the nanoseconds in some form.
+ //
+ template <typename S>
+ constexpr auto nsec (const S* s) -> decltype(s->st_mtim.tv_nsec)
+ {
+ return s->st_mtim.tv_nsec; // POSIX (GNU/Linux, Solaris).
+ }
+
+ template <typename S>
+ constexpr auto nsec (const S* s) -> decltype(s->st_mtimespec.tv_nsec)
+ {
+ return s->st_mtimespec.tv_nsec; // MacOS X.
+ }
+
+ template <typename S>
+ constexpr auto nsec (const S* s) -> decltype(s->st_mtime_n)
+ {
+ return s->st_mtime_n; // AIX 5.2 and later.
+ }
+
+ template <typename S>
+ constexpr int nsec (...) {return 0;}
+
+ timestamp
+ file_mtime (const path& p)
+ {
+ struct stat s;
+ if (::lstat (p.string ().c_str (), &s) != 0)
+ {
+ if (errno == ENOENT || errno == ENOTDIR)
+ return timestamp_nonexistent;
+ else
+ throw system_error (errno, system_category ());
+ }
+
+ return S_ISREG (s.st_mode)
+ ? system_clock::from_time_t (s.st_mtime) +
+ chrono::duration_cast<duration> (
+ chrono::nanoseconds (nsec<struct stat> (&s)))
+ : timestamp_nonexistent;
+ }
+
bool
dir_exists (const path& p)
{