Coverage Report

Created: 2026-02-09 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmFileTimes.cxx
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file LICENSE.rst or https://cmake.org/licensing for details.  */
3
#include "cmFileTimes.h"
4
5
#include <utility>
6
7
#include <cm/memory>
8
9
#include "cmsys/Status.hxx"
10
11
#include "cm_sys_stat.h"
12
13
#if defined(_WIN32)
14
#  include <windows.h>
15
16
#  include "cmSystemTools.h"
17
#else
18
#  include <cerrno>
19
20
#  include <utime.h>
21
#endif
22
23
#if defined(_WIN32) &&                                                        \
24
  (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__MINGW32__))
25
#  include <io.h>
26
#endif
27
28
#ifdef _WIN32
29
class cmFileTimes::WindowsHandle
30
{
31
public:
32
  WindowsHandle(HANDLE h)
33
    : handle_(h)
34
  {
35
  }
36
  ~WindowsHandle()
37
  {
38
    if (this->handle_ != INVALID_HANDLE_VALUE) {
39
      CloseHandle(this->handle_);
40
    }
41
  }
42
  explicit operator bool() const
43
  {
44
    return this->handle_ != INVALID_HANDLE_VALUE;
45
  }
46
  bool operator!() const { return this->handle_ == INVALID_HANDLE_VALUE; }
47
  operator HANDLE() const { return this->handle_; }
48
49
private:
50
  HANDLE handle_;
51
};
52
#endif
53
54
class cmFileTimes::Times
55
{
56
public:
57
#if defined(_WIN32) && !defined(__CYGWIN__)
58
  FILETIME timeCreation;
59
  FILETIME timeLastAccess;
60
  FILETIME timeLastWrite;
61
#else
62
  struct utimbuf timeBuf;
63
#endif
64
};
65
66
0
cmFileTimes::cmFileTimes() = default;
67
cmFileTimes::cmFileTimes(std::string const& fileName)
68
0
{
69
0
  this->Load(fileName);
70
0
}
71
0
cmFileTimes::~cmFileTimes() = default;
72
73
cmsys::Status cmFileTimes::Load(std::string const& fileName)
74
0
{
75
0
  std::unique_ptr<Times> ptr;
76
0
  if (this->IsValid()) {
77
    // Invalidate this and reuse times
78
0
    ptr.swap(this->times);
79
0
  } else {
80
0
    ptr = cm::make_unique<Times>();
81
0
  }
82
83
#if defined(_WIN32) && !defined(__CYGWIN__)
84
  cmFileTimes::WindowsHandle handle =
85
    CreateFileW(cmSystemTools::ConvertToWindowsExtendedPath(fileName).c_str(),
86
                GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING,
87
                FILE_FLAG_BACKUP_SEMANTICS, 0);
88
  if (!handle) {
89
    return cmsys::Status::Windows_GetLastError();
90
  }
91
  if (!GetFileTime(handle, &ptr->timeCreation, &ptr->timeLastAccess,
92
                   &ptr->timeLastWrite)) {
93
    return cmsys::Status::Windows_GetLastError();
94
  }
95
#else
96
0
  struct stat st;
97
0
  if (stat(fileName.c_str(), &st) < 0) {
98
0
    return cmsys::Status::POSIX_errno();
99
0
  }
100
0
  ptr->timeBuf.actime = st.st_atime;
101
0
  ptr->timeBuf.modtime = st.st_mtime;
102
0
#endif
103
  // Accept times
104
0
  this->times = std::move(ptr);
105
0
  return cmsys::Status::Success();
106
0
}
107
108
cmsys::Status cmFileTimes::Store(std::string const& fileName) const
109
0
{
110
0
  if (!this->IsValid()) {
111
0
    return cmsys::Status::POSIX(EINVAL);
112
0
  }
113
114
#if defined(_WIN32) && !defined(__CYGWIN__)
115
  cmFileTimes::WindowsHandle handle = CreateFileW(
116
    cmSystemTools::ConvertToWindowsExtendedPath(fileName).c_str(),
117
    FILE_WRITE_ATTRIBUTES, 0, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
118
  if (!handle) {
119
    return cmsys::Status::Windows_GetLastError();
120
  }
121
  if (SetFileTime(handle, &this->times->timeCreation,
122
                  &this->times->timeLastAccess,
123
                  &this->times->timeLastWrite) == 0) {
124
    return cmsys::Status::Windows_GetLastError();
125
  }
126
#else
127
0
  if (utime(fileName.c_str(), &this->times->timeBuf) < 0) {
128
0
    return cmsys::Status::POSIX_errno();
129
0
  }
130
0
#endif
131
0
  return cmsys::Status::Success();
132
0
}
133
134
cmsys::Status cmFileTimes::Copy(std::string const& fromFile,
135
                                std::string const& toFile)
136
0
{
137
0
  cmFileTimes fileTimes;
138
0
  cmsys::Status load_status = fileTimes.Load(fromFile);
139
0
  if (!load_status) {
140
0
    return load_status;
141
0
  }
142
0
  return fileTimes.Store(toFile);
143
0
}