aboutsummaryrefslogtreecommitdiff
path: root/butl/filesystem.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'butl/filesystem.cxx')
-rw-r--r--butl/filesystem.cxx126
1 files changed, 80 insertions, 46 deletions
diff --git a/butl/filesystem.cxx b/butl/filesystem.cxx
index 2a1fad9..90e8e81 100644
--- a/butl/filesystem.cxx
+++ b/butl/filesystem.cxx
@@ -15,48 +15,6 @@ using namespace std;
namespace butl
{
- // Figuring out whether we have the nanoseconds in some form.
- //
- template <typename S>
- inline 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>
- inline constexpr auto nsec (const S* s) -> decltype(s->st_mtimespec.tv_nsec)
- {
- return s->st_mtimespec.tv_nsec; // MacOS X.
- }
-
- template <typename S>
- inline constexpr auto nsec (const S* s) -> decltype(s->st_mtime_n)
- {
- return s->st_mtime_n; // AIX 5.2 and later.
- }
-
- template <typename S>
- inline constexpr int nsec (...) {return 0;}
-
- timestamp
- file_mtime (const path& p)
- {
- struct stat s;
- if (::stat (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)
{
@@ -88,7 +46,7 @@ namespace butl
}
mkdir_status
- try_mkdir (const path& p, mode_t m)
+ try_mkdir (const dir_path& p, mode_t m)
{
mkdir_status r (mkdir_status::success);
@@ -109,11 +67,11 @@ namespace butl
}
mkdir_status
- try_mkdir_p (const path& p, mode_t m)
+ try_mkdir_p (const dir_path& p, mode_t m)
{
if (!p.root ())
{
- path d (p.directory ());
+ dir_path d (p.directory ());
if (!dir_exists (d))
try_mkdir_p (d, m);
@@ -123,7 +81,7 @@ namespace butl
}
rmdir_status
- try_rmdir (const path& p)
+ try_rmdir (const dir_path& p)
{
rmdir_status r (rmdir_status::success);
@@ -140,6 +98,29 @@ namespace butl
return r;
}
+ void
+ rmdir_r (const dir_path& p)
+ {
+ // An nftw()-based implementation (for platforms that support it)
+ // might be a faster way.
+ //
+ for (const dir_entry& de: dir_iterator (p))
+ {
+ path ep (p / de.path ()); //@@ Would be good to reuse the buffer.
+
+ if (de.ltype () == entry_type::directory)
+ rmdir_r (path_cast<dir_path> (ep));
+ else
+ try_rmfile (ep);
+ }
+
+ rmdir_status r (try_rmdir (p));
+
+ if (r != rmdir_status::success)
+ throw system_error (r == rmdir_status::not_empty ? ENOTEMPTY : ENOENT,
+ system_category ());
+ }
+
rmfile_status
try_rmfile (const path& p)
{
@@ -156,6 +137,59 @@ namespace butl
return r;
}
+ // Figuring out whether we have the nanoseconds in some form.
+ //
+ template <typename S>
+ inline 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>
+ inline constexpr auto nsec (const S* s) -> decltype(s->st_mtimespec.tv_nsec)
+ {
+ return s->st_mtimespec.tv_nsec; // MacOS X.
+ }
+
+ template <typename S>
+ inline constexpr auto nsec (const S* s) -> decltype(s->st_mtime_n)
+ {
+ return s->st_mtime_n; // AIX 5.2 and later.
+ }
+
+ template <typename S>
+ inline constexpr int nsec (...) {return 0;}
+
+ timestamp
+ file_mtime (const path& p)
+ {
+ struct stat s;
+ if (::stat (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;
+ }
+
+ permissions
+ path_permissions (const path& p)
+ {
+ struct stat s;
+ if (::stat (p.string ().c_str (), &s) != 0)
+ throw system_error (errno, system_category ());
+
+ return static_cast<permissions> (
+ s.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO));
+ }
+
#ifndef _WIN32
// dir_entry