From 807bb530ecf6cde6c13956a20f64db32e86b892e Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 29 Aug 2016 18:51:07 +0200 Subject: Add flag to file_exists() not to follow symlinks --- butl/filesystem | 13 +++++++------ butl/filesystem.cxx | 23 +++++++++++++++++++---- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/butl/filesystem b/butl/filesystem index 4b4af6a..6f199c9 100644 --- a/butl/filesystem +++ b/butl/filesystem @@ -32,17 +32,18 @@ namespace butl { - // Return true if the path is to an existing regular file. Note that - // this function resolves symlinks. + // Return true if the path is to an existing regular file. Note that by + // default this function follows symlinks. // LIBBUTL_EXPORT bool - file_exists (const char*); + file_exists (const char*, bool follow_symlinks = true); inline bool - file_exists (const path& p) {return file_exists (p.string ().c_str ());} + file_exists (const path& p, bool fs = true) { + return file_exists (p.string ().c_str (), fs);} - // Return true if the path is to an existing directory. Note that - // this function resolves symlinks. + // Return true if the path is to an existing directory. Note that this + // function follows symlinks. // LIBBUTL_EXPORT bool dir_exists (const char*); diff --git a/butl/filesystem.cxx b/butl/filesystem.cxx index 5584e00..a47140d 100644 --- a/butl/filesystem.cxx +++ b/butl/filesystem.cxx @@ -34,16 +34,27 @@ using namespace std; namespace butl { +#ifndef _WIN32 bool - file_exists (const char* p) + file_exists (const char* p, bool fl) { -#ifndef _WIN32 struct stat s; - if (stat (p, &s) != 0) + if ((fl ? stat (p, &s) : lstat (p, &s)) != 0) + { + if (errno == ENOENT || errno == ENOTDIR) + return false; + else + throw system_error (errno, system_category ()); + } + + return S_ISREG (s.st_mode) || (!fl && S_ISLNK (s.st_mode)); + } #else + bool + file_exists (const char* p, bool) + { struct _stat s; if (_stat (p, &s) != 0) -#endif { if (errno == ENOENT || errno == ENOTDIR) return false; @@ -53,6 +64,7 @@ namespace butl return S_ISREG (s.st_mode); } +#endif bool dir_exists (const char* p) @@ -172,6 +184,9 @@ namespace butl if (_unlink (p.string ().c_str ()) != 0) #endif { + // Strangely on Linux unlink() removes a dangling symlink but returns + // ENOENT. + // if (errno == ENOENT || errno == ENOTDIR) r = rmfile_status::not_exist; else if (!ignore_error) -- cgit v1.1