mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-13 09:33:50 +00:00
Support/FileSystem: Implement bool equivalent(file_status A, file_status B);
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@146364 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
c3b00e8040
commit
d45fbe6227
@ -39,6 +39,10 @@
|
||||
#include <stack>
|
||||
#include <string>
|
||||
|
||||
#if HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
namespace llvm {
|
||||
namespace sys {
|
||||
namespace fs {
|
||||
@ -94,7 +98,20 @@ struct space_info {
|
||||
/// a platform specific member to store the result.
|
||||
class file_status
|
||||
{
|
||||
// implementation defined status field.
|
||||
#if defined(LLVM_ON_UNIX)
|
||||
dev_t st_dev;
|
||||
ino_t st_ino;
|
||||
#elif defined (LLVM_ON_WIN32)
|
||||
uint32_t LastWriteTimeHigh;
|
||||
uint32_t LastWriteTimeLow;
|
||||
uint32_t VolumeSerialNumber;
|
||||
uint32_t FileSizeHigh;
|
||||
uint32_t FileSizeLow;
|
||||
uint32_t FileIndexHigh;
|
||||
uint32_t FileIndexLow;
|
||||
#endif
|
||||
friend bool equivalent(file_status A, file_status B);
|
||||
friend error_code status(const Twine &path, file_status &result);
|
||||
file_type Type;
|
||||
public:
|
||||
explicit file_status(file_type v=file_type::status_error)
|
||||
@ -244,6 +261,8 @@ bool equivalent(file_status A, file_status B);
|
||||
|
||||
/// @brief Do paths represent the same thing?
|
||||
///
|
||||
/// assert(status_known(A) || status_known(B));
|
||||
///
|
||||
/// @param A Input path A.
|
||||
/// @param B Input path B.
|
||||
/// @param result Set to true if stat(A) and stat(B) have the same device and
|
||||
|
@ -273,28 +273,17 @@ error_code exists(const Twine &path, bool &result) {
|
||||
return success;
|
||||
}
|
||||
|
||||
bool equivalent(file_status A, file_status B) {
|
||||
assert(status_known(A) && status_known(B));
|
||||
return A.st_dev == B.st_dev &&
|
||||
A.st_ino == B.st_ino;
|
||||
}
|
||||
|
||||
error_code equivalent(const Twine &A, const Twine &B, bool &result) {
|
||||
// Get arguments.
|
||||
SmallString<128> a_storage;
|
||||
SmallString<128> b_storage;
|
||||
StringRef a = A.toNullTerminatedStringRef(a_storage);
|
||||
StringRef b = B.toNullTerminatedStringRef(b_storage);
|
||||
|
||||
struct stat stat_a, stat_b;
|
||||
int error_b = ::stat(b.begin(), &stat_b);
|
||||
int error_a = ::stat(a.begin(), &stat_a);
|
||||
|
||||
// If both are invalid, it's an error. If only one is, the result is false.
|
||||
if (error_a != 0 || error_b != 0) {
|
||||
if (error_a == error_b)
|
||||
return error_code(errno, system_category());
|
||||
result = false;
|
||||
} else {
|
||||
result =
|
||||
stat_a.st_dev == stat_b.st_dev &&
|
||||
stat_a.st_ino == stat_b.st_ino;
|
||||
}
|
||||
|
||||
file_status fsA, fsB;
|
||||
if (error_code ec = status(A, fsA)) return ec;
|
||||
if (error_code ec = status(B, fsB)) return ec;
|
||||
result = equivalent(fsA, fsB);
|
||||
return success;
|
||||
}
|
||||
|
||||
@ -341,6 +330,9 @@ error_code status(const Twine &path, file_status &result) {
|
||||
else
|
||||
result = file_status(file_type::type_unknown);
|
||||
|
||||
result.st_dev = status.st_dev;
|
||||
result.st_ino = status.st_ino;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -350,66 +350,22 @@ error_code exists(const Twine &path, bool &result) {
|
||||
return success;
|
||||
}
|
||||
|
||||
bool equivalent(file_status A, file_status B) {
|
||||
assert(status_known(A) && status_known(B));
|
||||
return A.FileIndexHigh == B.FileIndexHigh &&
|
||||
A.FileIndexLow == B.FileIndexLow &&
|
||||
A.FileSizeHigh == B.FileSizeHigh &&
|
||||
A.FileSizeLow == B.FileSizeLow &&
|
||||
A.LastWriteTimeHigh == B.LastWriteTimeHigh &&
|
||||
A.LastWriteTimeLow == B.LastWriteTimeLow &&
|
||||
A.VolumeSerialNumber == B.VolumeSerialNumber;
|
||||
}
|
||||
|
||||
error_code equivalent(const Twine &A, const Twine &B, bool &result) {
|
||||
// Get arguments.
|
||||
SmallString<128> a_storage;
|
||||
SmallString<128> b_storage;
|
||||
StringRef a = A.toStringRef(a_storage);
|
||||
StringRef b = B.toStringRef(b_storage);
|
||||
|
||||
// Convert to utf-16.
|
||||
SmallVector<wchar_t, 128> wide_a;
|
||||
SmallVector<wchar_t, 128> wide_b;
|
||||
if (error_code ec = UTF8ToUTF16(a, wide_a)) return ec;
|
||||
if (error_code ec = UTF8ToUTF16(b, wide_b)) return ec;
|
||||
|
||||
ScopedFileHandle HandleB(
|
||||
::CreateFileW(wide_b.begin(),
|
||||
0,
|
||||
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
0,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS,
|
||||
0));
|
||||
|
||||
ScopedFileHandle HandleA(
|
||||
::CreateFileW(wide_a.begin(),
|
||||
0,
|
||||
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
0,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS,
|
||||
0));
|
||||
|
||||
// If both handles are invalid, it's an error.
|
||||
if (!HandleA && !HandleB)
|
||||
return windows_error(::GetLastError());
|
||||
|
||||
// If only one is invalid, it's false.
|
||||
if (!HandleA || !HandleB) {
|
||||
result = false;
|
||||
return success;
|
||||
}
|
||||
|
||||
// Get file information.
|
||||
BY_HANDLE_FILE_INFORMATION InfoA, InfoB;
|
||||
if (!::GetFileInformationByHandle(HandleA, &InfoA))
|
||||
return windows_error(::GetLastError());
|
||||
if (!::GetFileInformationByHandle(HandleB, &InfoB))
|
||||
return windows_error(::GetLastError());
|
||||
|
||||
// See if it's all the same.
|
||||
result =
|
||||
InfoA.dwVolumeSerialNumber == InfoB.dwVolumeSerialNumber &&
|
||||
InfoA.nFileIndexHigh == InfoB.nFileIndexHigh &&
|
||||
InfoA.nFileIndexLow == InfoB.nFileIndexLow &&
|
||||
InfoA.nFileSizeHigh == InfoB.nFileSizeHigh &&
|
||||
InfoA.nFileSizeLow == InfoB.nFileSizeLow &&
|
||||
InfoA.ftLastWriteTime.dwLowDateTime ==
|
||||
InfoB.ftLastWriteTime.dwLowDateTime &&
|
||||
InfoA.ftLastWriteTime.dwHighDateTime ==
|
||||
InfoB.ftLastWriteTime.dwHighDateTime;
|
||||
|
||||
file_status fsA, fsB;
|
||||
if (error_code ec = status(A, fsA)) return ec;
|
||||
if (error_code ec = status(B, fsB)) return ec;
|
||||
result = equivalent(fsA, fsB);
|
||||
return success;
|
||||
}
|
||||
|
||||
@ -467,8 +423,7 @@ error_code status(const Twine &path, file_status &result) {
|
||||
return success;
|
||||
}
|
||||
|
||||
if (error_code ec = UTF8ToUTF16(path8,
|
||||
path_utf16))
|
||||
if (error_code ec = UTF8ToUTF16(path8, path_utf16))
|
||||
return ec;
|
||||
|
||||
DWORD attr = ::GetFileAttributesW(path_utf16.begin());
|
||||
@ -491,8 +446,29 @@ error_code status(const Twine &path, file_status &result) {
|
||||
|
||||
if (attr & FILE_ATTRIBUTE_DIRECTORY)
|
||||
result = file_status(file_type::directory_file);
|
||||
else
|
||||
else {
|
||||
result = file_status(file_type::regular_file);
|
||||
ScopedFileHandle h(
|
||||
::CreateFileW(path_utf16.begin(),
|
||||
0, // Attributes only.
|
||||
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS,
|
||||
0));
|
||||
if (!h)
|
||||
goto handle_status_error;
|
||||
BY_HANDLE_FILE_INFORMATION Info;
|
||||
if (!::GetFileInformationByHandle(h, &Info))
|
||||
goto handle_status_error;
|
||||
result.FileIndexHigh = Info.nFileIndexHigh;
|
||||
result.FileIndexLow = Info.nFileIndexLow;
|
||||
result.FileSizeHigh = Info.nFileSizeHigh;
|
||||
result.FileSizeLow = Info.nFileSizeLow;
|
||||
result.LastWriteTimeHigh = Info.ftLastWriteTime.dwHighDateTime;
|
||||
result.LastWriteTimeLow = Info.ftLastWriteTime.dwLowDateTime;
|
||||
result.VolumeSerialNumber = Info.dwVolumeSerialNumber;
|
||||
}
|
||||
|
||||
return success;
|
||||
|
||||
|
@ -183,6 +183,11 @@ TEST_F(FileSystemTest, TempFiles) {
|
||||
ASSERT_NO_ERROR(fs::unique_file("%%-%%-%%-%%.temp", FD2, TempPath2));
|
||||
ASSERT_NE(TempPath.str(), TempPath2.str());
|
||||
|
||||
fs::file_status A, B;
|
||||
ASSERT_NO_ERROR(fs::status(Twine(TempPath), A));
|
||||
ASSERT_NO_ERROR(fs::status(Twine(TempPath2), B));
|
||||
EXPECT_FALSE(fs::equivalent(A, B));
|
||||
|
||||
// Try to copy the first to the second.
|
||||
EXPECT_EQ(
|
||||
fs::copy_file(Twine(TempPath), Twine(TempPath2)), errc::file_exists);
|
||||
@ -204,6 +209,9 @@ TEST_F(FileSystemTest, TempFiles) {
|
||||
bool equal;
|
||||
ASSERT_NO_ERROR(fs::equivalent(Twine(TempPath), Twine(TempPath2), equal));
|
||||
EXPECT_TRUE(equal);
|
||||
ASSERT_NO_ERROR(fs::status(Twine(TempPath), A));
|
||||
ASSERT_NO_ERROR(fs::status(Twine(TempPath2), B));
|
||||
EXPECT_TRUE(fs::equivalent(A, B));
|
||||
|
||||
// Remove Temp1.
|
||||
::close(FileDescriptor);
|
||||
|
Loading…
x
Reference in New Issue
Block a user