aboutsummaryrefslogtreecommitdiff
path: root/butl/filesystem.cxx
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2017-02-10 16:10:33 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2017-02-13 12:55:34 +0300
commit31e91691e815074ebdb49d258967e2b2a0bfc965 (patch)
tree1739e815c312b40fa9a8c64b7b144cf60d4c28bb /butl/filesystem.cxx
parent66ca47f856cc04774cbe07dc67e2e099e5d527f3 (diff)
Add path_entry(), fixes for path
Diffstat (limited to 'butl/filesystem.cxx')
-rw-r--r--butl/filesystem.cxx115
1 files changed, 69 insertions, 46 deletions
diff --git a/butl/filesystem.cxx b/butl/filesystem.cxx
index d4bb487..e7e54a8 100644
--- a/butl/filesystem.cxx
+++ b/butl/filesystem.cxx
@@ -34,78 +34,101 @@ using namespace std;
namespace butl
{
-#ifndef _WIN32
bool
file_exists (const char* p, bool fl)
{
- struct stat s;
- if ((fl ? stat (p, &s) : lstat (p, &s)) != 0)
- {
- if (errno == ENOENT || errno == ENOTDIR)
- return false;
- else
- throw system_error (errno, system_category ());
- }
+ auto pe (path_entry (p, fl));
+ return pe.first && (pe.second == entry_type::regular ||
+ (!fl && pe.second == entry_type::symlink));
+ }
- return S_ISREG (s.st_mode) || (!fl && S_ISLNK (s.st_mode));
+ bool
+ entry_exists (const char* p, bool fl)
+ {
+ return path_entry (p, fl).first;
}
-#else
+
bool
- file_exists (const char* p, bool)
+ dir_exists (const char* p)
{
- struct _stat s;
- if (_stat (p, &s) != 0)
+ auto pe (path_entry (p, true));
+ return pe.first && pe.second == entry_type::directory;
+ }
+
+#ifndef _WIN32
+ pair<bool, entry_type>
+ path_entry (const char* p, bool fl)
+ {
+ struct stat s;
+ if ((fl ? stat (p, &s) : lstat (p, &s)) != 0)
{
if (errno == ENOENT || errno == ENOTDIR)
- return false;
+ return make_pair (false, entry_type::unknown);
else
throw system_error (errno, system_category ());
}
- return S_ISREG (s.st_mode);
- }
-#endif
+ auto m (s.st_mode);
+ entry_type t (entry_type::unknown);
-#ifndef _WIN32
- bool
- entry_exists (const char* p, bool fl)
- {
- struct stat s;
- if ((fl ? stat (p, &s) : lstat (p, &s)) == 0)
+ if (S_ISREG (m))
+ t = entry_type::regular;
+ else if (S_ISDIR (m))
+ t = entry_type::directory;
+ else if (S_ISLNK (m))
+ t = entry_type::symlink;
+ else if (S_ISBLK (m) || S_ISCHR (m) || S_ISFIFO (m) || S_ISSOCK (m))
+ t = entry_type::other;
+
+ return make_pair (true, t);
+ }
#else
- bool
- entry_exists (const char* p, bool)
+ pair<bool, entry_type>
+ path_entry (const char* p, bool)
{
+ int r;
struct _stat s;
- if (_stat (p, &s) == 0)
-#endif
- return true;
-
- if (errno == ENOENT || errno == ENOTDIR)
- return false;
- throw system_error (errno, system_category ());
- }
+ // A path like 'C:', while being a root path in our terminology, is not as
+ // such for Windows, that maintains current directory for each drive, and
+ // so C: means the current directory on the drive C. This is not what we
+ // mean here, so need to append the trailing directory separator in such a
+ // case.
+ //
+ if (!path::traits::root (p, string::traits_type::length (p)))
+ r = _stat (p, &s);
+ else
+ {
+ string d (p);
+ d += path::traits::directory_separator;
+ r = _stat (d.c_str (), &s);
+ }
- bool
- dir_exists (const char* p)
- {
-#ifndef _WIN32
- struct stat s;
- if (stat (p, &s) != 0)
-#else
- struct _stat s;
- if (_stat (p, &s) != 0)
-#endif
+ if (r != 0)
{
if (errno == ENOENT || errno == ENOTDIR)
- return false;
+ return make_pair (false, entry_type::unknown);
else
throw system_error (errno, system_category ());
}
- return S_ISDIR (s.st_mode);
+ auto m (s.st_mode);
+ entry_type t (entry_type::unknown);
+
+ if (S_ISREG (m))
+ t = entry_type::regular;
+ else if (S_ISDIR (m))
+ t = entry_type::directory;
+ //
+ // S_ISLNK/S_IFDIR are not defined for Win32 but it does have
+ // symlinks.
+ //
+ //else if (S_ISLNK (m))
+ // t = entry_type::symlink;
+
+ return make_pair (true, t);
}
+#endif
mkdir_status
#ifndef _WIN32