aboutsummaryrefslogtreecommitdiff
path: root/libbutl/fdstream.cxx
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2020-03-07 14:07:28 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2020-03-09 14:18:20 +0300
commitdcccba655fe848564e961b3f285ce3a82d3ac73a (patch)
tree598ced3b406d80c23798672930e1a17cfe112b75 /libbutl/fdstream.cxx
parent63b2988e4f2630cc688ff43b7e5f0d4f977896cd (diff)
Add more support for symlinks on Windows
See mksymlink() for details of the symlinks support on Windows.
Diffstat (limited to 'libbutl/fdstream.cxx')
-rw-r--r--libbutl/fdstream.cxx33
1 files changed, 24 insertions, 9 deletions
diff --git a/libbutl/fdstream.cxx b/libbutl/fdstream.cxx
index b58240c..54f3e9e 100644
--- a/libbutl/fdstream.cxx
+++ b/libbutl/fdstream.cxx
@@ -1091,19 +1091,34 @@ namespace butl
// to take care of preserving the permissions ourselves. Note that Wine's
// implementation of _sopen() works properly.
//
+ // Also note that _sopen() creates a dangling symlink target if _O_EXCL is
+ // set. Thus, we need to prevent such a creation manually.
+ //
bool pass_perm (of & _O_CREAT);
- if (pass_perm && file_exists (path (f)))
+ if (pass_perm)
{
- // If the _O_CREAT flag is set then we need to clear it so that we can
- // omit the permissions. But if the _O_EXCL flag is set as well we can't
- // do that as fdopen() wouldn't fail as expected.
- //
- if (of & _O_EXCL)
- throw_generic_ios_failure (EEXIST);
+ if (file_exists (f)) // Follows symlink.
+ {
+ // If the _O_CREAT flag is set then we need to clear it so that we can
+ // omit the permissions. But if the _O_EXCL flag is set as well we can't
+ // do that as fdopen() wouldn't fail as expected.
+ //
+ if (of & _O_EXCL)
+ throw_generic_ios_failure (EEXIST);
- of &= ~_O_CREAT;
- pass_perm = false;
+ of &= ~_O_CREAT;
+ pass_perm = false;
+ }
+ else if (of & _O_EXCL)
+ {
+ pair<bool, entry_stat> pe (path_entry (f)); // Doesn't follow symlink.
+
+ // Fail for a dangling symlink.
+ //
+ if (pe.first && pe.second.type == entry_type::symlink)
+ throw_generic_ios_failure (EEXIST);
+ }
}
// Make sure the file descriptor is not inheritable by default.