<p>Hi Nick,</p>
<div>The tests</div>
<div>LLVM-Unit :: Support/Release+Asserts/SupportTests.exe/FileSystemTest.FileMapping<br>LLVM-Unit :: Support/Release+Asserts/SupportTests.exe/FileSystemTest.Permissions</div>
<div>fail on one of builders:<br><a href="http://lab.llvm.org:8011/builders/clang-native-mingw32-win7/builds/2206/steps/test-llvm/logs/fail">http://lab.llvm.org:8011/builders/clang-native-mingw32-win7/builds/2206/steps/test-llvm/logs/fail</a></div>

<div>Please have a look at them?</div>
<p>Thanks</p>
<p>Galina<br><br></p>
<div class="gmail_quote">On Tue, Jun 19, 2012 at 5:28 PM, Nick Kledzik <span dir="ltr"><<a href="mailto:kledzik@apple.com" target="_blank">kledzik@apple.com</a>></span> wrote:<br>
<blockquote style="BORDER-LEFT:#ccc 1px solid;MARGIN:0px 0px 0px 0.8ex;PADDING-LEFT:1ex" class="gmail_quote">Author: kledzik<br>Date: Tue Jun 19 19:28:54 2012<br>New Revision: 158770<br><br>URL: <a href="http://llvm.org/viewvc/llvm-project?rev=158770&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=158770&view=rev</a><br>
Log:<br>Add permissions(), map_file_pages(), and unmap_file_pages() to llvm::sys::fs and add unit test. Unix is implemented.  Windows side needs to be implemented.<br><br>Modified:<br>   llvm/trunk/include/llvm/Support/FileSystem.h<br>
   llvm/trunk/lib/Support/Unix/PathV2.inc<br>   llvm/trunk/lib/Support/Windows/PathV2.inc<br>   llvm/trunk/unittests/Support/Path.cpp<br><br>Modified: llvm/trunk/include/llvm/Support/FileSystem.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/FileSystem.h?rev=158770&r1=158769&r2=158770&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/FileSystem.h?rev=158770&r1=158769&r2=158770&view=diff</a><br>
==============================================================================<br>--- llvm/trunk/include/llvm/Support/FileSystem.h (original)<br>+++ llvm/trunk/include/llvm/Support/FileSystem.h Tue Jun 19 19:28:54 2012<br>
@@ -94,6 +94,55 @@<br>  uint64_t available;<br> };<br><br>+<br>+enum perms {<br>+  no_perms     = 0,<br>+  owner_read   = 0400,<br>+  owner_write  = 0200,<br>+  owner_exe    = 0100,<br>+  owner_all    = owner_read | owner_write | owner_exe,<br>
+  group_read   =  040,<br>+  group_write  =  020,<br>+  group_exe    =  010,<br>+  group_all    = group_read | group_write | group_exe,<br>+  others_read  =   04,<br>+  others_write =   02,<br>+  others_exe   =   01,<br>
+  others_all   = others_read | others_write | others_exe,<br>+  all_all      = owner_all | group_all | others_all,<br>+  set_uid_on_exe  = 04000,<br>+  set_gid_on_exe  = 02000,<br>+  sticky_bit      = 01000,<br>+  perms_mask      = all_all | set_uid_on_exe | set_gid_on_exe | sticky_bit,<br>
+  perms_not_known = 0xFFFF,<br>+  add_perms       = 0x1000,<br>+  remove_perms    = 0x2000,<br>+  symlink_perms   = 0x4000<br>+};<br>+<br>+// Helper functions so that you can use & and | to manipulate perms bits:<br>
+inline perms operator|(perms l , perms r) {<br>+  return static_cast<perms>(<br>+             static_cast<unsigned short>(l) | static_cast<unsigned short>(r));<br>+}<br>+inline perms operator&(perms l , perms r) {<br>
+  return static_cast<perms>(<br>+             static_cast<unsigned short>(l) & static_cast<unsigned short>(r));<br>+}<br>+inline perms &operator|=(perms &l, perms r) {<br>+  l = l | r;<br>+  return l;<br>
+}<br>+inline perms &operator&=(perms &l, perms r) {<br>+  l = l & r;<br>+  return l;<br>+}<br>+inline perms operator~(perms x) {<br>+  return static_cast<perms>(~static_cast<unsigned short>(x));<br>
+}<br>+<br>+<br>+<br> /// file_status - Represents the result of a call to stat and friends. It has<br> ///               a platform specific member to store the result.<br> class file_status<br>@@ -113,12 +162,19 @@<br>  friend bool equivalent(file_status A, file_status B);<br>
  friend error_code status(const Twine &path, file_status &result);<br>  file_type Type;<br>+  perms Perms;<br> public:<br>-  explicit file_status(file_type v=file_type::status_error)<br>-    : Type(v) {}<br>+  explicit file_status(file_type v=file_type::status_error,<br>
+                      perms prms=perms_not_known)<br>+    : Type(v), Perms(prms) {}<br><br>+  // getters<br>  file_type type() const { return Type; }<br>+  perms permissions() const { return Perms; }<br>+<br>+  // setters<br>
  void type(file_type v) { Type = v; }<br>+  void permissions(perms p) { Perms = p; }<br> };<br><br> /// file_magic - An "enum class" enumeration of file types based on magic (the first<br>@@ -395,6 +451,13 @@<br>
 ///          platform specific error_code.<br> error_code status(const Twine &path, file_status &result);<br><br>+/// @brief Modifies permission bits on a file<br>+///<br>+/// @param path Input path.<br>+/// @results errc::success if permissions have been changed, otherwise a<br>
+///          platform specific error_code.<br>+error_code permissions(const Twine &path, perms prms);<br>+<br> /// @brief Is status available?<br> ///<br> /// @param path Input path.<br>@@ -513,6 +576,33 @@<br> error_code GetMainExecutable(const char *argv0, void *MainAddr,<br>
                             SmallVectorImpl<char> &result);<br><br>+<br>+/// @brief Memory maps the contents of a file<br>+///<br>+/// @param path Path to file to map.<br>+/// @param file_offset Byte offset in file where mapping should begin.<br>
+/// @param size_t Byte length of range of the file to map.<br>+/// @param map_writable If true, the file will be mapped in r/w such<br>+///        that changes to the the mapped buffer will be flushed back<br>+///        to the file.  If false, the file will be mapped read-only<br>
+///        and the buffer will be read-only.<br>+/// @param result Set to the start address of the mapped buffer.<br>+/// @results errc::success if result has been successfully set, otherwise a<br>+///          platform specific error_code.<br>
+error_code map_file_pages(const Twine &path, off_t file_offset, size_t size,<br>+                          bool map_writable, void *&result);<br>+<br>+<br>+/// @brief Memory unmaps the contents of a file<br>+///<br>
+/// @param base Pointer to the start of the buffer.<br>+/// @param size Byte length of the range to unmmap.<br>+/// @results errc::success if result has been successfully set, otherwise a<br>+///          platform specific error_code.<br>
+error_code unmap_file_pages(void *base, size_t size);<br>+<br>+<br>+<br> /// @}<br> /// @name Iterators<br> /// @{<br><br>Modified: llvm/trunk/lib/Support/Unix/PathV2.inc<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Unix/PathV2.inc?rev=158770&r1=158769&r2=158770&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Unix/PathV2.inc?rev=158770&r1=158769&r2=158770&view=diff</a><br>
==============================================================================<br>--- llvm/trunk/lib/Support/Unix/PathV2.inc (original)<br>+++ llvm/trunk/lib/Support/Unix/PathV2.inc Tue Jun 19 19:28:54 2012<br>@@ -24,6 +24,9 @@<br>
 #if HAVE_FCNTL_H<br> #include <fcntl.h><br> #endif<br>+#ifdef HAVE_SYS_MMAN_H<br>+#include <sys/mman.h><br>+#endif<br> #if HAVE_DIRENT_H<br> # include <dirent.h><br> # define NAMLEN(dirent) strlen((dirent)->d_name)<br>
@@ -325,20 +328,22 @@<br>    return ec;<br>  }<br><br>+  perms prms = static_cast<perms>(status.st_mode & perms_mask);<br>+<br>  if (S_ISDIR(status.st_mode))<br>-    result = file_status(file_type::directory_file);<br>
+    result = file_status(file_type::directory_file, prms);<br>  else if (S_ISREG(status.st_mode))<br>-    result = file_status(file_type::regular_file);<br>+    result = file_status(file_type::regular_file, prms);<br>  else if (S_ISBLK(status.st_mode))<br>
-    result = file_status(file_type::block_file);<br>+    result = file_status(file_type::block_file, prms);<br>  else if (S_ISCHR(status.st_mode))<br>-    result = file_status(file_type::character_file);<br>+    result = file_status(file_type::character_file, prms);<br>
  else if (S_ISFIFO(status.st_mode))<br>-    result = file_status(file_type::fifo_file);<br>+    result = file_status(file_type::fifo_file, prms);<br>  else if (S_ISSOCK(status.st_mode))<br>-    result = file_status(file_type::socket_file);<br>
+    result = file_status(file_type::socket_file, prms);<br>  else<br>-    result = file_status(file_type::type_unknown);<br>+    result = file_status(file_type::type_unknown, prms);<br><br>  result.fs_st_dev = status.st_dev;<br>
  result.fs_st_ino = status.st_ino;<br>@@ -346,6 +351,35 @@<br>  return error_code::success();<br> }<br><br>+// Modifies permissions on a file.<br>+error_code permissions(const Twine &path, perms prms) {<br>+  if ((prms & add_perms) && (prms & remove_perms))<br>
+    llvm_unreachable("add_perms and remove_perms are mutually exclusive");<br>+<br>+  // Get current permissions<br>+  file_status info;<br>+  if (error_code ec = status(path, info)) {<br>+    return ec;<br>+  }<br>
+<br>+  // Set updated permissions.<br>+  SmallString<128> path_storage;<br>+  StringRef p = path.toNullTerminatedStringRef(path_storage);<br>+  perms permsToSet;<br>+  if (prms & add_perms) {<br>+    permsToSet = (info.permissions() | prms) & perms_mask;<br>
+  } else if (prms & remove_perms) {<br>+    permsToSet = (info.permissions() & ~prms) & perms_mask;<br>+  } else {<br>+    permsToSet = prms & perms_mask;<br>+  }<br>+  if (::chmod(p.begin(), static_cast<mode_t>(permsToSet))) {<br>
+    return error_code(errno, system_category());<br>+  }<br>+<br>+  return error_code::success();<br>+}<br>+<br> // Since this is most often used for temporary files, mode defaults to 0600.<br> error_code unique_file(const Twine &model, int &result_fd,<br>
                       SmallVectorImpl<char> &result_path,<br>@@ -495,6 +529,36 @@<br>  return error_code::success();<br> }<br><br>+error_code map_file_pages(const Twine &path, off_t file_offset, size_t size,<br>
+                                            bool map_writable, void *&result) {<br>+  SmallString<128> path_storage;<br>+  StringRef name = path.toNullTerminatedStringRef(path_storage);<br>+  int oflags = map_writable ? O_RDWR : O_RDONLY;<br>
+  int ofd = ::open(name.begin(), oflags);<br>+  if ( ofd == -1 )<br>+    return error_code(errno, system_category());<br>+  AutoFD fd(ofd);<br>+  int flags = map_writable ? MAP_SHARED : MAP_PRIVATE;<br>+  int prot = map_writable ? (PROT_READ|PROT_WRITE) : PROT_READ;<br>
+#ifdef MAP_FILE<br>+  flags |= MAP_FILE;<br>+#endif<br>+  result = ::mmap(0, size, prot, flags, fd, file_offset);<br>+  if (result == MAP_FAILED) {<br>+    return error_code(errno, system_category());<br>+  }<br>+<br>+  return error_code::success();<br>
+}<br>+<br>+error_code unmap_file_pages(void *base, size_t size) {<br>+  if ( ::munmap(base, size) == -1 )<br>+    return error_code(errno, system_category());<br>+<br>+  return error_code::success();<br>+}<br>+<br>+<br> } // end namespace fs<br>
 } // end namespace sys<br> } // end namespace llvm<br><br>Modified: llvm/trunk/lib/Support/Windows/PathV2.inc<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Windows/PathV2.inc?rev=158770&r1=158769&r2=158770&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Windows/PathV2.inc?rev=158770&r1=158769&r2=158770&view=diff</a><br>
==============================================================================<br>--- llvm/trunk/lib/Support/Windows/PathV2.inc (original)<br>+++ llvm/trunk/lib/Support/Windows/PathV2.inc Tue Jun 19 19:28:54 2012<br>@@ -497,6 +497,41 @@<br>
  return error_code::success();<br> }<br><br>+<br>+// Modifies permissions on a file.<br>+error_code permissions(const Twine &path, perms prms) {<br>+#if 0 // verify code below before enabling:<br>+  // If the permissions bits are not trying to modify<br>
+  // "write" permissions, there is nothing to do.<br>+  if (!(prms & (owner_write|group_write|others_write)))<br>+    return error_code::success();<br>+<br>+  SmallString<128> path_storage;<br>+  SmallVector<wchar_t, 128> path_utf16;<br>
+<br>+  if (error_code ec = UTF8ToUTF16(path.toStringRef(path_storage),<br>+                                  path_utf16))<br>+    return ec;<br>+<br>+  DWORD attributes = ::GetFileAttributesW(path_utf16.begin());<br>+<br>
+  if (prms & add_perms) {<br>+    attributes &= ~FILE_ATTRIBUTE_READONLY;<br>+  }<br>+  else if (prms & remove_perms) {<br>+    attributes |= FILE_ATTRIBUTE_READONLY;<br>+  }<br>+  else {<br>+    assert(0 && "neither add_perms or remove_perms is set");<br>
+  }<br>+<br>+  if ( ! ::SetFileAttributesW(path_utf16.begin(), attributes))<br>+    return windows_error(::GetLastError());<br>+#endif<br>+  return error_code::success();<br>+}<br>+<br>+<br> // FIXME: mode should be used here and default to user r/w only,<br>
 // it currently comes in as a UNIX mode.<br> error_code unique_file(const Twine &model, int &result_fd,<br>@@ -755,6 +790,17 @@<br>  return error_code::success();<br> }<br><br>+error_code map_file_pages(const Twine &path, off_t file_offset, size_t size,<br>
+                                            bool map_writable, void *&result) {<br>+  assert(0 && "NOT IMPLEMENTED");<br>+}<br>+<br>+error_code unmap_file_pages(void *base, size_t size) {<br>+  assert(0 && "NOT IMPLEMENTED");<br>
+}<br>+<br>+<br>+<br> } // end namespace fs<br> } // end namespace sys<br> } // end namespace llvm<br><br>Modified: llvm/trunk/unittests/Support/Path.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/Path.cpp?rev=158770&r1=158769&r2=158770&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/Path.cpp?rev=158770&r1=158769&r2=158770&view=diff</a><br>
==============================================================================<br>--- llvm/trunk/unittests/Support/Path.cpp (original)<br>+++ llvm/trunk/unittests/Support/Path.cpp Tue Jun 19 19:28:54 2012<br>@@ -312,4 +312,69 @@<br>
  }<br> }<br><br>+<br>+TEST_F(FileSystemTest, Permissions) {<br>+  // Create a temp file.<br>+  int FileDescriptor;<br>+  SmallString<64> TempPath;<br>+  ASSERT_NO_ERROR(<br>+    fs::unique_file("%%-%%-%%-%%.temp", FileDescriptor, TempPath));<br>
+<br>+  // Mark file as read-only<br>+  const fs::perms AllWrite = fs::owner_write|fs::group_write|fs::others_write;<br>+  ASSERT_NO_ERROR(fs::permissions(Twine(TempPath), fs::remove_perms|AllWrite));<br>+<br>+  // Verify file is read-only<br>
+  fs::file_status Status;<br>+  ASSERT_NO_ERROR(fs::status(Twine(TempPath), Status));<br>+  bool AnyWriteBits = (Status.permissions() & AllWrite);<br>+  EXPECT_FALSE(AnyWriteBits);<br>+<br>+  // Mark file as read-write<br>
+  ASSERT_NO_ERROR(fs::permissions(Twine(TempPath), fs::add_perms|AllWrite));<br>+<br>+  // Verify file is read-write<br>+  ASSERT_NO_ERROR(fs::status(Twine(TempPath), Status));<br>+  AnyWriteBits = (Status.permissions() & AllWrite);<br>
+  EXPECT_TRUE(AnyWriteBits);<br>+}<br>+<br>+TEST_F(FileSystemTest, FileMapping) {<br>+  // Create a temp file.<br>+  int FileDescriptor;<br>+  SmallString<64> TempPath;<br>+  ASSERT_NO_ERROR(<br>+    fs::unique_file("%%-%%-%%-%%.temp", FileDescriptor, TempPath));<br>
+<br>+  // Grow temp file to be 4096 bytes<br>+  ASSERT_NO_ERROR(sys::fs::resize_file(Twine(TempPath), 4096));<br>+<br>+  // Map in temp file and add some content<br>+  void* MappedMemory;<br>+  ASSERT_NO_ERROR(fs::map_file_pages(Twine(TempPath), 0, 4096,<br>
+                                true /*writable*/, MappedMemory));<br>+  char* Memory = reinterpret_cast<char*>(MappedMemory);<br>+  strcpy(Memory, "hello there");<br>+<br>+  // Unmap temp file<br>+  ASSERT_NO_ERROR(fs::unmap_file_pages(MappedMemory, 4096));<br>
+  MappedMemory = NULL;<br>+  Memory = NULL;<br>+<br>+  // Map it back in read-only<br>+  ASSERT_NO_ERROR(fs::map_file_pages(Twine(TempPath), 0, 4096,<br>+                                false /*read-only*/, MappedMemory));<br>
+<br>+  // Verify content<br>+  Memory = reinterpret_cast<char*>(MappedMemory);<br>+  bool SAME = (strcmp(Memory, "hello there") == 0);<br>+  EXPECT_TRUE(SAME);<br>+<br>+  // Unmap temp file<br>+  ASSERT_NO_ERROR(fs::unmap_file_pages(MappedMemory, 4096));<br>
+  MappedMemory = NULL;<br>+  Memory = NULL;<br>+}<br>+<br>+<br> } // anonymous namespace<br><br><br>_______________________________________________<br>llvm-commits mailing list<br><a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br></blockquote></div><br>