cmFileTimes.cxx 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include "cmFileTimes.h"
  4. #include <utility>
  5. #include <cm/memory>
  6. #include "cm_sys_stat.h"
  7. #if defined(_WIN32)
  8. # include <windows.h>
  9. # include "cmSystemTools.h"
  10. #else
  11. # include <utime.h>
  12. #endif
  13. #if defined(_WIN32) && \
  14. (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__MINGW32__))
  15. # include <io.h>
  16. #endif
  17. #ifdef _WIN32
  18. class cmFileTimes::WindowsHandle
  19. {
  20. public:
  21. WindowsHandle(HANDLE h)
  22. : handle_(h)
  23. {
  24. }
  25. ~WindowsHandle()
  26. {
  27. if (this->handle_ != INVALID_HANDLE_VALUE) {
  28. CloseHandle(this->handle_);
  29. }
  30. }
  31. explicit operator bool() const
  32. {
  33. return this->handle_ != INVALID_HANDLE_VALUE;
  34. }
  35. bool operator!() const { return this->handle_ == INVALID_HANDLE_VALUE; }
  36. operator HANDLE() const { return this->handle_; }
  37. private:
  38. HANDLE handle_;
  39. };
  40. #endif
  41. class cmFileTimes::Times
  42. {
  43. public:
  44. #if defined(_WIN32) && !defined(__CYGWIN__)
  45. FILETIME timeCreation;
  46. FILETIME timeLastAccess;
  47. FILETIME timeLastWrite;
  48. #else
  49. struct utimbuf timeBuf;
  50. #endif
  51. };
  52. cmFileTimes::cmFileTimes() = default;
  53. cmFileTimes::cmFileTimes(std::string const& fileName)
  54. {
  55. this->Load(fileName);
  56. }
  57. cmFileTimes::~cmFileTimes() = default;
  58. bool cmFileTimes::Load(std::string const& fileName)
  59. {
  60. std::unique_ptr<Times> ptr;
  61. if (this->IsValid()) {
  62. // Invalidate this and re-use times
  63. ptr.swap(this->times);
  64. } else {
  65. ptr = cm::make_unique<Times>();
  66. }
  67. #if defined(_WIN32) && !defined(__CYGWIN__)
  68. cmFileTimes::WindowsHandle handle =
  69. CreateFileW(cmSystemTools::ConvertToWindowsExtendedPath(fileName).c_str(),
  70. GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING,
  71. FILE_FLAG_BACKUP_SEMANTICS, 0);
  72. if (!handle) {
  73. return false;
  74. }
  75. if (!GetFileTime(handle, &ptr->timeCreation, &ptr->timeLastAccess,
  76. &ptr->timeLastWrite)) {
  77. return false;
  78. }
  79. #else
  80. struct stat st;
  81. if (stat(fileName.c_str(), &st) < 0) {
  82. return false;
  83. }
  84. ptr->timeBuf.actime = st.st_atime;
  85. ptr->timeBuf.modtime = st.st_mtime;
  86. #endif
  87. // Accept times
  88. this->times = std::move(ptr);
  89. return true;
  90. }
  91. bool cmFileTimes::Store(std::string const& fileName) const
  92. {
  93. if (!this->IsValid()) {
  94. return false;
  95. }
  96. #if defined(_WIN32) && !defined(__CYGWIN__)
  97. cmFileTimes::WindowsHandle handle = CreateFileW(
  98. cmSystemTools::ConvertToWindowsExtendedPath(fileName).c_str(),
  99. FILE_WRITE_ATTRIBUTES, 0, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
  100. if (!handle) {
  101. return false;
  102. }
  103. return SetFileTime(handle, &this->times->timeCreation,
  104. &this->times->timeLastAccess,
  105. &this->times->timeLastWrite) != 0;
  106. #else
  107. return utime(fileName.c_str(), &this->times->timeBuf) >= 0;
  108. #endif
  109. }
  110. bool cmFileTimes::Copy(std::string const& fromFile, std::string const& toFile)
  111. {
  112. cmFileTimes fileTimes;
  113. return (fileTimes.Load(fromFile) && fileTimes.Store(toFile));
  114. }