[libcxx-commits] [PATCH] D91171: [16/N] [libcxx] Implement the permissions function for windows

Martin Storsjö via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Mon Dec 7 04:08:43 PST 2020


mstorsjo updated this revision to Diff 309867.
mstorsjo set the repository for this revision to rG LLVM Github Monorepo.
mstorsjo added a comment.

Added comments about the two conditional branches, skipping the set operation if there's no change.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D91171/new/

https://reviews.llvm.org/D91171

Files:
  libcxx/src/filesystem/operations.cpp


Index: libcxx/src/filesystem/operations.cpp
===================================================================
--- libcxx/src/filesystem/operations.cpp
+++ libcxx/src/filesystem/operations.cpp
@@ -672,9 +672,11 @@
   return static_cast<perms>(st.st_mode) & perms::mask;
 }
 
+#if !defined(_LIBCPP_WIN32API)
 ::mode_t posix_convert_perms(perms prms) {
   return static_cast< ::mode_t>(prms & perms::mask);
 }
+#endif
 
 file_status create_file_status(error_code& m_ec, path const& p,
                                const StatT& path_stat, error_code* ec) {
@@ -746,6 +748,7 @@
   return false;
 }
 
+#if !defined(_LIBCPP_WIN32API)
 bool posix_fchmod(const FileDescriptor& fd, const StatT& st, error_code& ec) {
   if (::fchmod(fd.fd, st.st_mode) == -1) {
     ec = capture_errno();
@@ -754,6 +757,7 @@
   ec.clear();
   return false;
 }
+#endif
 
 bool stat_equivalent(const StatT& st1, const StatT& st2) {
   return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
@@ -1136,8 +1140,10 @@
       return err.report(errc::bad_file_descriptor);
 
     // Set the permissions and truncate the file we opened.
+#if !defined(_LIBCPP_WIN32API)
     if (detail::posix_fchmod(to_fd, from_stat, m_ec))
       return err.report(m_ec);
+#endif
     if (detail::posix_ftruncate(to_fd, 0, m_ec))
       return err.report(m_ec);
   }
@@ -1424,6 +1430,7 @@
     else if (remove_perms)
       prms = st.permissions() & ~prms;
   }
+#if !defined(_LIBCPP_WIN32API)
   const auto real_perms = detail::posix_convert_perms(prms);
 
 #if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD)
@@ -1438,6 +1445,41 @@
     return err.report(capture_errno());
   }
 #endif
+#else
+  DWORD attributes = GetFileAttributesW(p.c_str());
+  if (attributes == INVALID_FILE_ATTRIBUTES)
+    return err.report(detail::make_windows_error(GetLastError()));
+  if (attributes & FILE_ATTRIBUTE_REPARSE_POINT && resolve_symlinks) {
+    // 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(p.c_str(), FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
+                        0);
+    if (!h)
+      return err.report(detail::make_windows_error(GetLastError()));
+    FILE_BASIC_INFO basic;
+    if (!GetFileInformationByHandleEx(h, FileBasicInfo, &basic, sizeof(basic)))
+      return err.report(detail::make_windows_error(GetLastError()));
+    DWORD orig_attributes = basic.FileAttributes;
+    basic.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
+    if ((static_cast<int>(prms) & 0222) == 0)
+      basic.FileAttributes |= FILE_ATTRIBUTE_READONLY;
+    if (basic.FileAttributes != orig_attributes &&
+        !SetFileInformationByHandle(h, FileBasicInfo, &basic, sizeof(basic)))
+      return err.report(detail::make_windows_error(GetLastError()));
+  } 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 ((static_cast<int>(prms) & 0222) == 0)
+      attributes |= FILE_ATTRIBUTE_READONLY;
+    if (attributes != orig_attributes &&
+        !SetFileAttributesW(p.c_str(), attributes))
+      return err.report(detail::make_windows_error(GetLastError()));
+  }
+#endif
 }
 
 path __read_symlink(const path& p, error_code* ec) {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D91171.309867.patch
Type: text/x-patch
Size: 3526 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libcxx-commits/attachments/20201207/9fcdb4d4/attachment.bin>


More information about the libcxx-commits mailing list