[libcxx-commits] [libcxx] 40117b7 - [libcxx] Implement the permissions function for windows
Martin Storsjö via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Feb 2 23:28:17 PST 2021
Author: Martin Storsjö
Date: 2021-02-03T09:23:24+02:00
New Revision: 40117b700f723a27b90989a429ceb66c0873b161
URL: https://github.com/llvm/llvm-project/commit/40117b700f723a27b90989a429ceb66c0873b161
DIFF: https://github.com/llvm/llvm-project/commit/40117b700f723a27b90989a429ceb66c0873b161.diff
LOG: [libcxx] Implement the permissions function for windows
Differential Revision: https://reviews.llvm.org/D91171
Added:
Modified:
libcxx/src/filesystem/operations.cpp
libcxx/src/filesystem/posix_compat.h
Removed:
################################################################################
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
More information about the libcxx-commits
mailing list