This fixes linking against a DLL of libc++ while using the common headers (generated from the static version of the library, but which work for both shared and static versions) when calling e.g. std::filesystem::u8path.
134 lines
4.7 KiB
Diff
134 lines
4.7 KiB
Diff
From 96748da73f57e6b080643d03e41e8a690ee571a9 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <martin@martin.st>
|
|
Date: Wed, 4 Nov 2020 23:55:10 +0200
|
|
Subject: [PATCH 08/25] [libcxx] Implement the permissions function for windows
|
|
|
|
Differential Revision: https://reviews.llvm.org/D91171
|
|
|
|
(cherry picked from commit 40117b700f723a27b90989a429ceb66c0873b161)
|
|
---
|
|
libcxx/src/filesystem/operations.cpp | 10 ++----
|
|
libcxx/src/filesystem/posix_compat.h | 54 ++++++++++++++++++++++++++++
|
|
2 files changed, 57 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/libcxx/src/filesystem/operations.cpp b/libcxx/src/filesystem/operations.cpp
|
|
index fc18de9e5d80..47cd5e23c092 100644
|
|
--- a/libcxx/src/filesystem/operations.cpp
|
|
+++ b/libcxx/src/filesystem/operations.cpp
|
|
@@ -455,10 +455,6 @@ perms posix_get_perms(const StatT& st) noexcept {
|
|
return static_cast<perms>(st.st_mode) & perms::mask;
|
|
}
|
|
|
|
-::mode_t posix_convert_perms(perms prms) {
|
|
- return static_cast< ::mode_t>(prms & perms::mask);
|
|
-}
|
|
-
|
|
file_status create_file_status(error_code& m_ec, path const& p,
|
|
const StatT& path_stat, error_code* ec) {
|
|
if (ec)
|
|
@@ -530,7 +526,7 @@ bool posix_ftruncate(const FileDescriptor& fd, off_t to_size, error_code& ec) {
|
|
}
|
|
|
|
bool posix_fchmod(const FileDescriptor& fd, const StatT& st, error_code& ec) {
|
|
- if (::fchmod(fd.fd, st.st_mode) == -1) {
|
|
+ if (detail::fchmod(fd.fd, st.st_mode) == -1) {
|
|
ec = capture_errno();
|
|
return true;
|
|
}
|
|
@@ -1212,11 +1208,11 @@ void __permissions(const path& p, perms prms, perm_options opts,
|
|
else if (remove_perms)
|
|
prms = st.permissions() & ~prms;
|
|
}
|
|
- const auto real_perms = detail::posix_convert_perms(prms);
|
|
+ const auto real_perms = static_cast<detail::ModeT>(prms & perms::mask);
|
|
|
|
#if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD)
|
|
const int flags = set_sym_perms ? AT_SYMLINK_NOFOLLOW : 0;
|
|
- if (::fchmodat(AT_FDCWD, p.c_str(), real_perms, flags) == -1) {
|
|
+ if (detail::fchmodat(AT_FDCWD, p.c_str(), real_perms, flags) == -1) {
|
|
return err.report(capture_errno());
|
|
}
|
|
#else
|
|
diff --git a/libcxx/src/filesystem/posix_compat.h b/libcxx/src/filesystem/posix_compat.h
|
|
index 1adce3a779c2..af4a3691db33 100644
|
|
--- a/libcxx/src/filesystem/posix_compat.h
|
|
+++ b/libcxx/src/filesystem/posix_compat.h
|
|
@@ -349,6 +349,57 @@ wchar_t *realpath(const wchar_t *path, wchar_t *resolved_name) {
|
|
}
|
|
return buff.release();
|
|
}
|
|
+
|
|
+#define AT_FDCWD -1
|
|
+#define AT_SYMLINK_NOFOLLOW 1
|
|
+using ModeT = int;
|
|
+
|
|
+int fchmod_handle(HANDLE h, int perms) {
|
|
+ FILE_BASIC_INFO basic;
|
|
+ if (!GetFileInformationByHandleEx(h, FileBasicInfo, &basic, sizeof(basic)))
|
|
+ return set_errno();
|
|
+ DWORD orig_attributes = basic.FileAttributes;
|
|
+ basic.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
|
|
+ if ((perms & 0222) == 0)
|
|
+ basic.FileAttributes |= FILE_ATTRIBUTE_READONLY;
|
|
+ if (basic.FileAttributes != orig_attributes &&
|
|
+ !SetFileInformationByHandle(h, FileBasicInfo, &basic, sizeof(basic)))
|
|
+ return set_errno();
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int fchmodat(int fd, const wchar_t *path, int perms, int flag) {
|
|
+ DWORD attributes = GetFileAttributesW(path);
|
|
+ if (attributes == INVALID_FILE_ATTRIBUTES)
|
|
+ return set_errno();
|
|
+ if (attributes & FILE_ATTRIBUTE_REPARSE_POINT &&
|
|
+ !(flag & AT_SYMLINK_NOFOLLOW)) {
|
|
+ // If the file is a symlink, and we are supposed to operate on the target
|
|
+ // of the symlink, we need to open a handle to it, without the
|
|
+ // FILE_FLAG_OPEN_REPARSE_POINT flag, to open the destination of the
|
|
+ // symlink, and operate on it via the handle.
|
|
+ detail::WinHandle h(path, FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES, 0);
|
|
+ if (!h)
|
|
+ return set_errno();
|
|
+ return fchmod_handle(h, perms);
|
|
+ } else {
|
|
+ // For a non-symlink, or if operating on the symlink itself instead of
|
|
+ // its target, we can use SetFileAttributesW, saving a few calls.
|
|
+ DWORD orig_attributes = attributes;
|
|
+ attributes &= ~FILE_ATTRIBUTE_READONLY;
|
|
+ if ((perms & 0222) == 0)
|
|
+ attributes |= FILE_ATTRIBUTE_READONLY;
|
|
+ if (attributes != orig_attributes && !SetFileAttributesW(path, attributes))
|
|
+ return set_errno();
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int fchmod(int fd, int perms) {
|
|
+ HANDLE h = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
|
|
+ return fchmod_handle(h, perms);
|
|
+}
|
|
+
|
|
#else
|
|
int symlink_file(const char *oldname, const char *newname) {
|
|
return ::symlink(oldname, newname);
|
|
@@ -358,6 +409,8 @@ int symlink_dir(const char *oldname, const char *newname) {
|
|
}
|
|
using ::chdir;
|
|
using ::close;
|
|
+using ::fchmod;
|
|
+using ::fchmodat;
|
|
using ::fstat;
|
|
using ::ftruncate;
|
|
using ::getcwd;
|
|
@@ -375,6 +428,7 @@ using ::truncate;
|
|
#define O_BINARY 0
|
|
|
|
using StatVFS = struct statvfs;
|
|
+using ModeT = ::mode_t;
|
|
|
|
#endif
|
|
|
|
--
|
|
2.25.1
|
|
|