aboutsummaryrefslogtreecommitdiff
path: root/libbutl/filesystem.cxx
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2018-04-28 22:25:21 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2018-04-28 22:25:21 +0300
commitc3f0489235f6d0e9cf9d6c302d7b086b4f9968dc (patch)
tree79cd4c5122b1290fcddf3980b027ae21e456863c /libbutl/filesystem.cxx
parenteddbd4b42e28179143d5b551cd909945edfd6f1a (diff)
Fix try_rmfile() to remove symlinks on Windows
Diffstat (limited to 'libbutl/filesystem.cxx')
-rw-r--r--libbutl/filesystem.cxx33
1 files changed, 24 insertions, 9 deletions
diff --git a/libbutl/filesystem.cxx b/libbutl/filesystem.cxx
index bff251a..2650c25 100644
--- a/libbutl/filesystem.cxx
+++ b/libbutl/filesystem.cxx
@@ -322,19 +322,34 @@ namespace butl
// error code. In such a case we just reset the attribute and repeat the
// attempt. If the attempt fails, then we try to restore the attribute.
//
+ // Yet another reason for the 'permission denied' failure can be a
+ // directory symlink.
+ //
if (ur != 0 && errno == EACCES)
{
DWORD a (GetFileAttributes (f));
- if (a != INVALID_FILE_ATTRIBUTES && (a & FILE_ATTRIBUTE_READONLY) != 0 &&
- SetFileAttributes (f, a & ~FILE_ATTRIBUTE_READONLY))
+ if (a != INVALID_FILE_ATTRIBUTES)
{
- ur = _unlink (f);
+ bool readonly ((a & FILE_ATTRIBUTE_READONLY) != 0);
- // Restoring the attribute is unlikely to fail as we managed to reset
- // it earlier.
+ // Note that we support only directory symlinks on Windows.
//
- if (ur != 0)
- SetFileAttributes (f, a);
+ bool symlink ((a & FILE_ATTRIBUTE_REPARSE_POINT) != 0 &&
+ (a & FILE_ATTRIBUTE_DIRECTORY) != 0);
+
+ if (readonly || symlink)
+ {
+ bool restore (readonly &&
+ SetFileAttributes (f, a & ~FILE_ATTRIBUTE_READONLY));
+
+ ur = symlink ? _rmdir (f) : _unlink (f);
+
+ // Restoring the attribute is unlikely to fail as we managed to reset
+ // it earlier.
+ //
+ if (ur != 0 && restore)
+ SetFileAttributes (f, a);
+ }
}
}
#endif
@@ -492,8 +507,8 @@ namespace butl
FSCTL_SET_REPARSE_POINT,
&rb,
sizeof (DWORD) + 2 * sizeof (WORD) + // Size of the header.
- rb.reparse_data_length, // Size of mount point reparse.
- NULL, // buffer.
+ rb.reparse_data_length, // Size of the mount point
+ NULL, // reparse buffer.
0,
&r,
NULL))