resolve cyclic dependency with zstd
[platform/upstream/cmake.git] / Source / cmFileTimes.cxx
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
5 #include <utility>
6
7 #include <cm/memory>
8
9 #include "cm_sys_stat.h"
10
11 #if defined(_WIN32)
12 #  include <windows.h>
13
14 #  include "cmSystemTools.h"
15 #else
16 #  include <utime.h>
17 #endif
18
19 #if defined(_WIN32) &&                                                        \
20   (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__MINGW32__))
21 #  include <io.h>
22 #endif
23
24 #ifdef _WIN32
25 class cmFileTimes::WindowsHandle
26 {
27 public:
28   WindowsHandle(HANDLE h)
29     : handle_(h)
30   {
31   }
32   ~WindowsHandle()
33   {
34     if (this->handle_ != INVALID_HANDLE_VALUE) {
35       CloseHandle(this->handle_);
36     }
37   }
38   explicit operator bool() const
39   {
40     return this->handle_ != INVALID_HANDLE_VALUE;
41   }
42   bool operator!() const { return this->handle_ == INVALID_HANDLE_VALUE; }
43   operator HANDLE() const { return this->handle_; }
44
45 private:
46   HANDLE handle_;
47 };
48 #endif
49
50 class cmFileTimes::Times
51 {
52 public:
53 #if defined(_WIN32) && !defined(__CYGWIN__)
54   FILETIME timeCreation;
55   FILETIME timeLastAccess;
56   FILETIME timeLastWrite;
57 #else
58   struct utimbuf timeBuf;
59 #endif
60 };
61
62 cmFileTimes::cmFileTimes() = default;
63 cmFileTimes::cmFileTimes(std::string const& fileName)
64 {
65   this->Load(fileName);
66 }
67 cmFileTimes::~cmFileTimes() = default;
68
69 bool cmFileTimes::Load(std::string const& fileName)
70 {
71   std::unique_ptr<Times> ptr;
72   if (this->IsValid()) {
73     // Invalidate this and re-use times
74     ptr.swap(this->times);
75   } else {
76     ptr = cm::make_unique<Times>();
77   }
78
79 #if defined(_WIN32) && !defined(__CYGWIN__)
80   cmFileTimes::WindowsHandle handle =
81     CreateFileW(cmSystemTools::ConvertToWindowsExtendedPath(fileName).c_str(),
82                 GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING,
83                 FILE_FLAG_BACKUP_SEMANTICS, 0);
84   if (!handle) {
85     return false;
86   }
87   if (!GetFileTime(handle, &ptr->timeCreation, &ptr->timeLastAccess,
88                    &ptr->timeLastWrite)) {
89     return false;
90   }
91 #else
92   struct stat st;
93   if (stat(fileName.c_str(), &st) < 0) {
94     return false;
95   }
96   ptr->timeBuf.actime = st.st_atime;
97   ptr->timeBuf.modtime = st.st_mtime;
98 #endif
99   // Accept times
100   this->times = std::move(ptr);
101   return true;
102 }
103
104 bool cmFileTimes::Store(std::string const& fileName) const
105 {
106   if (!this->IsValid()) {
107     return false;
108   }
109
110 #if defined(_WIN32) && !defined(__CYGWIN__)
111   cmFileTimes::WindowsHandle handle = CreateFileW(
112     cmSystemTools::ConvertToWindowsExtendedPath(fileName).c_str(),
113     FILE_WRITE_ATTRIBUTES, 0, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
114   if (!handle) {
115     return false;
116   }
117   return SetFileTime(handle, &this->times->timeCreation,
118                      &this->times->timeLastAccess,
119                      &this->times->timeLastWrite) != 0;
120 #else
121   return utime(fileName.c_str(), &this->times->timeBuf) >= 0;
122 #endif
123 }
124
125 bool cmFileTimes::Copy(std::string const& fromFile, std::string const& toFile)
126 {
127   cmFileTimes fileTimes;
128   return (fileTimes.Load(fromFile) && fileTimes.Store(toFile));
129 }