mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-19 17:47:38 +00:00
Modified the implementation of fs::GetUniqueID on Windows such that it actually finds a unique identifier for a file. Also adds unit tests for GetUniqueID.
llvm-svn: 184351
This commit is contained in:
parent
c82a0b3e6d
commit
406fa22a89
@ -162,6 +162,7 @@ class file_status
|
||||
#endif
|
||||
friend bool equivalent(file_status A, file_status B);
|
||||
friend error_code status(const Twine &path, file_status &result);
|
||||
friend error_code GetUniqueID(const Twine Path, uint64_t &Result);
|
||||
file_type Type;
|
||||
perms Perms;
|
||||
public:
|
||||
|
@ -426,15 +426,20 @@ error_code file_size(const Twine &path, uint64_t &result) {
|
||||
}
|
||||
|
||||
error_code GetUniqueID(const Twine Path, uint64_t &Result) {
|
||||
// FIXME: this is only unique if the file is accessed by the same file path.
|
||||
// How do we do this for C:\dir\file and ..\dir\file ? Unix has inode
|
||||
// numbers, but the concept doesn't exist in Windows.
|
||||
SmallString<128> Storage;
|
||||
StringRef P = Path.toStringRef(Storage);
|
||||
uint64_t UniqueID = 0;
|
||||
for (StringRef::iterator I = P.begin(), E = P.end(); I != E; ++I)
|
||||
UniqueID += *I;
|
||||
Result = UniqueID;
|
||||
file_status Status;
|
||||
if (error_code E = status(Path, Status))
|
||||
return E;
|
||||
|
||||
// The file is uniquely identified by the volume serial number along
|
||||
// with the 64-bit file identifier.
|
||||
Result = (static_cast<uint64_t>(Status.FileIndexHigh) << 32ULL) |
|
||||
static_cast<uint64_t>(Status.FileIndexLow);
|
||||
|
||||
// Because the serial number is 32-bits, but we've already used up all 64
|
||||
// bits for the file index, XOR the serial number into the high 32 bits of
|
||||
// the resulting value. We could potentially get collisons from this, but
|
||||
// the likelihood is low.
|
||||
Result ^= (static_cast<uint64_t>(Status.VolumeSerialNumber) << 32ULL);
|
||||
|
||||
return error_code::success();
|
||||
}
|
||||
|
@ -164,6 +164,42 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(FileSystemTest, Unique) {
|
||||
// Create a temp file.
|
||||
int FileDescriptor;
|
||||
SmallString<64> TempPath;
|
||||
ASSERT_NO_ERROR(
|
||||
fs::unique_file("%%-%%-%%-%%.temp", FileDescriptor, TempPath));
|
||||
|
||||
// The same file should return an identical unique id.
|
||||
uint64_t F1, F2;
|
||||
ASSERT_NO_ERROR(fs::GetUniqueID(Twine(TempPath), F1));
|
||||
ASSERT_NO_ERROR(fs::GetUniqueID(Twine(TempPath), F2));
|
||||
ASSERT_EQ(F1, F2);
|
||||
|
||||
// Different files should return different unique ids.
|
||||
int FileDescriptor2;
|
||||
SmallString<64> TempPath2;
|
||||
ASSERT_NO_ERROR(
|
||||
fs::unique_file("%%-%%-%%-%%.temp", FileDescriptor2, TempPath2));
|
||||
|
||||
uint64_t D;
|
||||
ASSERT_NO_ERROR(fs::GetUniqueID(Twine(TempPath2), D));
|
||||
ASSERT_NE(D, F1);
|
||||
::close(FileDescriptor2);
|
||||
|
||||
ASSERT_NO_ERROR(fs::remove(Twine(TempPath2)));
|
||||
|
||||
// Two paths representing the same file on disk should still provide the
|
||||
// same unique id. We can test this by making a hard link.
|
||||
ASSERT_NO_ERROR(fs::create_hard_link(Twine(TempPath), Twine(TempPath2)));
|
||||
uint64_t D2;
|
||||
ASSERT_NO_ERROR(fs::GetUniqueID(Twine(TempPath2), D2));
|
||||
ASSERT_EQ(D2, F1);
|
||||
|
||||
::close(FileDescriptor);
|
||||
}
|
||||
|
||||
TEST_F(FileSystemTest, TempFiles) {
|
||||
// Create a temp file.
|
||||
int FileDescriptor;
|
||||
|
Loading…
Reference in New Issue
Block a user