Perms(Perms) {}
#elif defined(LLVM_ON_WIN32)
file_status() = default;
-
- file_status(file_type Type) : Type(Type) {}
-
- file_status(file_type Type, uint32_t LastAccessTimeHigh,
- uint32_t LastAccessTimeLow, uint32_t LastWriteTimeHigh,
- uint32_t LastWriteTimeLow, uint32_t VolumeSerialNumber,
- uint32_t FileSizeHigh, uint32_t FileSizeLow,
+\r
+ file_status(file_type Type) : Type(Type) {}\r
+\r
+ file_status(file_type Type, perms Perms, uint32_t LastAccessTimeHigh,\r
+ uint32_t LastAccessTimeLow, uint32_t LastWriteTimeHigh,\r
+ uint32_t LastWriteTimeLow, uint32_t VolumeSerialNumber,\r
+ uint32_t FileSizeHigh, uint32_t FileSizeLow,\r
uint32_t FileIndexHigh, uint32_t FileIndexLow)
: LastAccessedTimeHigh(LastAccessTimeHigh), LastAccessedTimeLow(LastAccessTimeLow),
LastWriteTimeHigh(LastWriteTimeHigh),
- LastWriteTimeLow(LastWriteTimeLow),
- VolumeSerialNumber(VolumeSerialNumber), FileSizeHigh(FileSizeHigh),
- FileSizeLow(FileSizeLow), FileIndexHigh(FileIndexHigh),
- FileIndexLow(FileIndexLow), Type(Type) {}
- #endif
-
- // getters
+ LastWriteTimeLow(LastWriteTimeLow),\r
+ VolumeSerialNumber(VolumeSerialNumber), FileSizeHigh(FileSizeHigh),\r
+ FileSizeLow(FileSizeLow), FileIndexHigh(FileIndexHigh),\r
+ FileIndexLow(FileIndexLow), Type(Type), Perms(Perms) {}\r
+ #endif\r
+\r
+ // getters\r
file_type type() const { return Type; }
perms permissions() const { return Perms; }
TimePoint<> getLastAccessedTime() const;
std::error_code status(const Twine &path, file_status &result,
bool follow = true);
-/// @brief A version for when a file descriptor is already available.
-std::error_code status(int FD, file_status &Result);
-
-/// @brief Get file size.
-///
-/// @param Path Input path.
+/// @brief A version for when a file descriptor is already available.\r
+std::error_code status(int FD, file_status &Result);\r
+\r
+/// @brief Set file permissions.\r
+///\r
+/// @param Path File to set permissions on.\r
+/// @param Permissions New file permissions.\r
+/// @returns errc::success if the permissions were successfully set, otherwise\r
+/// a platform-specific error_code.\r
+/// @note On Windows, all permissions except *_write are ignored. Using any of\r
+/// owner_write, group_write, or all_write will make the file writable.\r
+/// Otherwise, the file will be marked as read-only.\r
+std::error_code setPermissions(const Twine &Path, perms Permissions);\r
+\r
+/// @brief Get file permissions.\r
+///\r
+/// @param Path File to get permissions from.\r
+/// @returns the permissions if they were successfully retrieved, otherwise a\r
+/// platform-specific error_code.\r
+/// @note On Windows, if the file does not have the FILE_ATTRIBUTE_READONLY\r
+/// attribute, all_all will be returned. Otherwise, all_read | all_exe\r
+/// will be returned.\r
+ErrorOr<perms> getPermissions(const Twine &Path);\r
+\r
+/// @brief Get file size.\r
+///\r
+/// @param Path Input path.\r
/// @param Result Set to the size of the file in \a Path.
/// @returns errc::success if result has been successfully set, otherwise a
/// platform-specific error_code.
}
std::error_code directory_entry::status(file_status &result) const {
- return fs::status(Path, result, FollowSymlinks);
-}
-
-} // end namespace fs
-} // end namespace sys
-} // end namespace llvm
+ return fs::status(Path, result, FollowSymlinks);\r
+}\r
+\r
+ErrorOr<perms> getPermissions(const Twine &Path) {\r
+ file_status Status;\r
+ if (std::error_code EC = status(Path, Status))\r
+ return EC;\r
+\r
+ return Status.permissions();\r
+}\r
+\r
+} // end namespace fs\r
+} // end namespace sys\r
+} // end namespace llvm\r
// Include the truly platform-specific parts.
#if defined(LLVM_ON_UNIX)
std::error_code status(int FD, file_status &Result) {
struct stat Status;
int StatRet = ::fstat(FD, &Status);
- return fillStatus(StatRet, Status, Result);
-}
-
-std::error_code setLastModificationAndAccessTime(int FD, TimePoint<> Time) {
-#if defined(HAVE_FUTIMENS)
- timespec Times[2];
+ return fillStatus(StatRet, Status, Result);\r
+}\r
+\r
+std::error_code setPermissions(const Twine &Path, perms Permissions) {\r
+ SmallString<128> PathStorage;\r
+ StringRef P = Path.toNullTerminatedStringRef(PathStorage);\r
+\r
+ if (::chmod(P.begin(), Permissions))\r
+ return std::error_code(errno, std::generic_category());\r
+ return std::error_code();\r
+}\r
+\r
+std::error_code setLastModificationAndAccessTime(int FD, TimePoint<> Time) {\r
+#if defined(HAVE_FUTIMENS)\r
+ timespec Times[2];\r
Times[0] = Times[1] = sys::toTimeSpec(Time);
if (::futimens(FD, Times))
return std::error_code(errno, std::generic_category());
goto handle_status_error;
{
- file_type Type = (Info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- ? file_type::directory_file
- : file_type::regular_file;
- Result =
- file_status(Type, Info.ftLastAccessTime.dwHighDateTime,
- Info.ftLastAccessTime.dwLowDateTime,
- Info.ftLastWriteTime.dwHighDateTime,
- Info.ftLastWriteTime.dwLowDateTime,
- Info.dwVolumeSerialNumber, Info.nFileSizeHigh,
- Info.nFileSizeLow, Info.nFileIndexHigh, Info.nFileIndexLow);
- return std::error_code();
- }
-
+ file_type Type = (Info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)\r
+ ? file_type::directory_file\r
+ : file_type::regular_file;\r
+ perms Permissions = (Info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)\r
+ ? (all_read | all_exe)\r
+ : all_all;\r
+ Result = file_status(\r
+ Type, Permissions, Info.ftLastAccessTime.dwHighDateTime,\r
+ Info.ftLastAccessTime.dwLowDateTime,\r
+ Info.ftLastWriteTime.dwHighDateTime, Info.ftLastWriteTime.dwLowDateTime,\r
+ Info.dwVolumeSerialNumber, Info.nFileSizeHigh, Info.nFileSizeLow,\r
+ Info.nFileIndexHigh, Info.nFileIndexLow);\r
+ return std::error_code();\r
+ }\r
+\r
handle_status_error:
DWORD LastError = ::GetLastError();
if (LastError == ERROR_FILE_NOT_FOUND ||
std::error_code status(int FD, file_status &Result) {
HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
- return getStatus(FileHandle, Result);
-}
-
-std::error_code setLastModificationAndAccessTime(int FD, TimePoint<> Time) {
- FILETIME FT = toFILETIME(Time);
- HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
+ return getStatus(FileHandle, Result);\r
+}\r
+\r
+std::error_code setPermissions(const Twine &Path, perms Permissions) {\r
+ SmallVector<wchar_t, 128> PathUTF16;\r
+ if (std::error_code EC = widenPath(Path, PathUTF16))\r
+ return EC;\r
+\r
+ DWORD Attributes = ::GetFileAttributesW(PathUTF16.begin());\r
+ if (Attributes == INVALID_FILE_ATTRIBUTES)\r
+ return mapWindowsError(GetLastError());\r
+\r
+ // There are many Windows file attributes that are not to do with the file\r
+ // permissions (e.g. FILE_ATTRIBUTE_HIDDEN). We need to be careful to preserve\r
+ // them.\r
+ if (Permissions & all_write) {\r
+ Attributes &= ~FILE_ATTRIBUTE_READONLY;\r
+ if (Attributes == 0)\r
+ // FILE_ATTRIBUTE_NORMAL indicates no other attributes are set.\r
+ Attributes |= FILE_ATTRIBUTE_NORMAL;\r
+ }\r
+ else {\r
+ Attributes |= FILE_ATTRIBUTE_READONLY;\r
+ // FILE_ATTRIBUTE_NORMAL is not compatible with any other attributes, so\r
+ // remove it, if it is present.\r
+ Attributes &= ~FILE_ATTRIBUTE_NORMAL;\r
+ }\r
+\r
+ if (!::SetFileAttributesW(PathUTF16.begin(), Attributes))\r
+ return mapWindowsError(GetLastError());\r
+\r
+ return std::error_code();\r
+}\r
+\r
+std::error_code setLastModificationAndAccessTime(int FD, TimePoint<> Time) {\r
+ FILETIME FT = toFILETIME(Time);\r
+ HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(FD));\r
if (!SetFileTime(FileHandle, NULL, &FT, &FT))
return mapWindowsError(::GetLastError());
return std::error_code();
fs::UniqueID D1, D2;
ASSERT_NO_ERROR(fs::getUniqueID(TestDirectory, D1));
ASSERT_NO_ERROR(fs::getUniqueID(path, D2));
- ASSERT_EQ(D1, D2) << "D1: " << TestDirectory << "\nD2: " << path;
-}
-
-} // anonymous namespace
+ ASSERT_EQ(D1, D2) << "D1: " << TestDirectory << "\nD2: " << path;\r
+}\r
+\r
+TEST_F(FileSystemTest, permissions) {\r
+ int FD;\r
+ SmallString<64> TempPath;\r
+ ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "temp", FD, TempPath));\r
+ FileRemover Cleanup(TempPath);\r
+\r
+ // Make sure it exists.\r
+ ASSERT_TRUE(fs::exists(Twine(TempPath)));\r
+\r
+ auto CheckPermissions = [&](fs::perms Expected) {\r
+ ErrorOr<fs::perms> Actual = fs::getPermissions(TempPath);\r
+ return Actual && *Actual == Expected;\r
+ };\r
+\r
+ std::error_code NoError;\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::all_all), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::all_all));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::all_read | fs::all_exe), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::all_read | fs::all_exe));\r
+\r
+#if defined(LLVM_ON_WIN32)\r
+ fs::perms ReadOnly = fs::all_read | fs::all_exe;\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::no_perms), NoError);\r
+ EXPECT_TRUE(CheckPermissions(ReadOnly));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::owner_read), NoError);\r
+ EXPECT_TRUE(CheckPermissions(ReadOnly));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::owner_write), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::all_all));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::owner_exe), NoError);\r
+ EXPECT_TRUE(CheckPermissions(ReadOnly));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::owner_all), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::all_all));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::group_read), NoError);\r
+ EXPECT_TRUE(CheckPermissions(ReadOnly));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::group_write), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::all_all));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::group_exe), NoError);\r
+ EXPECT_TRUE(CheckPermissions(ReadOnly));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::group_all), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::all_all));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::others_read), NoError);\r
+ EXPECT_TRUE(CheckPermissions(ReadOnly));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::others_write), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::all_all));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::others_exe), NoError);\r
+ EXPECT_TRUE(CheckPermissions(ReadOnly));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::others_all), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::all_all));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::all_read), NoError);\r
+ EXPECT_TRUE(CheckPermissions(ReadOnly));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::all_write), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::all_all));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::all_exe), NoError);\r
+ EXPECT_TRUE(CheckPermissions(ReadOnly));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::set_uid_on_exe), NoError);\r
+ EXPECT_TRUE(CheckPermissions(ReadOnly));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::set_gid_on_exe), NoError);\r
+ EXPECT_TRUE(CheckPermissions(ReadOnly));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::sticky_bit), NoError);\r
+ EXPECT_TRUE(CheckPermissions(ReadOnly));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::set_uid_on_exe |\r
+ fs::set_gid_on_exe |\r
+ fs::sticky_bit),\r
+ NoError);\r
+ EXPECT_TRUE(CheckPermissions(ReadOnly));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, ReadOnly | fs::set_uid_on_exe |\r
+ fs::set_gid_on_exe |\r
+ fs::sticky_bit),\r
+ NoError);\r
+ EXPECT_TRUE(CheckPermissions(ReadOnly));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::all_all | fs::set_uid_on_exe |\r
+ fs::set_gid_on_exe |\r
+ fs::sticky_bit),\r
+ NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::all_all));\r
+#else\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::no_perms), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::no_perms));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::owner_read), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::owner_read));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::owner_write), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::owner_write));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::owner_exe), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::owner_exe));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::owner_all), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::owner_all));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::group_read), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::group_read));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::group_write), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::group_write));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::group_exe), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::group_exe));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::group_all), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::group_all));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::others_read), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::others_read));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::others_write), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::others_write));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::others_exe), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::others_exe));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::others_all), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::others_all));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::all_read), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::all_read));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::all_write), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::all_write));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::all_exe), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::all_exe));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::set_uid_on_exe), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::set_uid_on_exe));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::set_gid_on_exe), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::set_gid_on_exe));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::sticky_bit), NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::sticky_bit));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::set_uid_on_exe |\r
+ fs::set_gid_on_exe |\r
+ fs::sticky_bit),\r
+ NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::set_uid_on_exe | fs::set_gid_on_exe |\r
+ fs::sticky_bit));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::all_read | fs::set_uid_on_exe |\r
+ fs::set_gid_on_exe |\r
+ fs::sticky_bit),\r
+ NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::all_read | fs::set_uid_on_exe |\r
+ fs::set_gid_on_exe | fs::sticky_bit));\r
+\r
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::all_all | fs::set_uid_on_exe |\r
+ fs::set_gid_on_exe |\r
+ fs::sticky_bit),\r
+ NoError);\r
+ EXPECT_TRUE(CheckPermissions(fs::all_all | fs::set_uid_on_exe |\r
+ fs::set_gid_on_exe | fs::sticky_bit));\r
+#endif\r
+}\r
+\r
+} // anonymous namespace\r