aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-08-29 18:51:07 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-08-29 18:51:07 +0200
commit807bb530ecf6cde6c13956a20f64db32e86b892e (patch)
treea8e3b942717b17b8b4bbb6c39c8def9c1f5406fa
parent135a0bcb957dc836c425f51eeeeae4148092fdf8 (diff)
Add flag to file_exists() not to follow symlinks
-rw-r--r--butl/filesystem13
-rw-r--r--butl/filesystem.cxx23
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)