From 82c4576a9d226343973147ffa591ac282dedb29b Mon Sep 17 00:00:00 2001 From: KWSys Upstream Date: Thu, 30 May 2024 10:30:12 -0400 Subject: [PATCH] KWSys 2024-05-30 (cb379374) Code extracted from: https://gitlab.kitware.com/utils/kwsys.git at commit cb3793745292850727dfcdb32ac200132961041e (master). Upstream Shortlog ----------------- Jochem van Boxtel (1): 510b13b4 SystemTools: Add FileId class and GetFileId function --- SystemTools.cxx | 69 ++++++++++++++++++++++++++++++++++++++++++++++ SystemTools.hxx.in | 46 +++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) diff --git a/SystemTools.cxx b/SystemTools.cxx index 11018a6bef..63566160fa 100644 --- a/SystemTools.cxx +++ b/SystemTools.cxx @@ -1356,6 +1356,75 @@ bool SystemTools::DeleteRegistryValue(const std::string&, KeyWOW64) } #endif +#ifdef _WIN32 +SystemTools::WindowsFileId::WindowsFileId(unsigned long volumeSerialNumber, + unsigned long fileIndexHigh, + unsigned long fileIndexLow) + : m_volumeSerialNumber(volumeSerialNumber) + , m_fileIndexHigh(fileIndexHigh) + , m_fileIndexLow(fileIndexLow) +{ +} + +bool SystemTools::WindowsFileId::operator==(const WindowsFileId& o) const +{ + return (m_volumeSerialNumber == o.m_volumeSerialNumber && + m_fileIndexHigh == o.m_fileIndexHigh && + m_fileIndexLow == o.m_fileIndexLow); +} + +bool SystemTools::WindowsFileId::operator!=(const WindowsFileId& o) const +{ + return !(*this == o); +} +#else +SystemTools::UnixFileId::UnixFileId(dev_t volumeSerialNumber, + ino_t fileSerialNumber, off_t fileSize) + : m_volumeSerialNumber(volumeSerialNumber) + , m_fileSerialNumber(fileSerialNumber) + , m_fileSize(fileSize) +{ +} + +bool SystemTools::UnixFileId::operator==(const UnixFileId& o) const +{ + return (m_volumeSerialNumber == o.m_volumeSerialNumber && + m_fileSerialNumber == o.m_fileSerialNumber && + m_fileSize == o.m_fileSize); +} + +bool SystemTools::UnixFileId::operator!=(const UnixFileId& o) const +{ + return !(*this == o); +} +#endif + +bool SystemTools::GetFileId(const std::string& file, FileId& id) +{ +#ifdef _WIN32 + HANDLE hFile = + CreateFileW(Encoding::ToWide(file).c_str(), GENERIC_READ, FILE_SHARE_READ, + nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); + if (hFile != INVALID_HANDLE_VALUE) { + BY_HANDLE_FILE_INFORMATION fiBuf; + GetFileInformationByHandle(hFile, &fiBuf); + CloseHandle(hFile); + id = FileId(fiBuf.dwVolumeSerialNumber, fiBuf.nFileIndexHigh, + fiBuf.nFileIndexLow); + return true; + } else { + return false; + } +#else + struct stat fileStat; + if (stat(file.c_str(), &fileStat) == 0) { + id = FileId(fileStat.st_dev, fileStat.st_ino, fileStat.st_size); + return true; + } + return false; +#endif +} + bool SystemTools::SameFile(const std::string& file1, const std::string& file2) { #ifdef _WIN32 diff --git a/SystemTools.hxx.in b/SystemTools.hxx.in index 729928e6f3..294ffca326 100644 --- a/SystemTools.hxx.in +++ b/SystemTools.hxx.in @@ -616,6 +616,52 @@ public: static CopyStatus CloneFileContent(std::string const& source, std::string const& destination); + /** + * Object encapsulating a unique identifier for a file + * or directory + */ +#ifdef _WIN32 + class WindowsFileId + { + public: + WindowsFileId() = default; + WindowsFileId(unsigned long volumeSerialNumber, + unsigned long fileIndexHigh, unsigned long fileIndexLow); + + bool operator==(const WindowsFileId& o) const; + bool operator!=(const WindowsFileId& o) const; + + private: + unsigned long m_volumeSerialNumber; + unsigned long m_fileIndexHigh; + unsigned long m_fileIndexLow; + }; + using FileId = WindowsFileId; +#else + class UnixFileId + { + public: + UnixFileId() = default; + UnixFileId(dev_t volumeSerialNumber, ino_t fileSerialNumber, + off_t fileSize); + + bool operator==(const UnixFileId& o) const; + bool operator!=(const UnixFileId& o) const; + + private: + dev_t m_volumeSerialNumber; + ino_t m_fileSerialNumber; + off_t m_fileSize; + }; + using FileId = UnixFileId; +#endif + + /** + * Outputs a FileId for the given file or directory. + * Returns true on success, false on failure + */ + static bool GetFileId(const std::string& file, FileId& id); + /** * Return true if the two files are the same file */