diff options
Diffstat (limited to 'butl/filesystem.cxx')
-rw-r--r-- | butl/filesystem.cxx | 115 |
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 |