[llvm-commits] [llvm] r158770 - in /llvm/trunk: include/llvm/Support/FileSystem.h lib/Support/Unix/PathV2.inc lib/Support/Windows/PathV2.inc unittests/Support/Path.cpp

Nick Kledzik kledzik at apple.com
Thu Jun 21 15:37:13 PDT 2012


These new functions are not implemented for Windows.  Michael Spencer said he would do the Windows implementation.

In cases like this, is it better to check in the test cases known to not work on some platforms, so they can get tested on the others.  Or check  in the test cases disabled?

-Nick

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

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20120621/8bce34c2/attachment.html>


More information about the llvm-commits mailing list