Browse Source

cmFileTimes: New RAII based cmFileTimes class

This adds a new RAII based cmFileTimes class.
It is supposed to replace the C style cmSystemToolsFileTime interface.
Sebastian Holtermann 6 years ago
parent
commit
4b45a5d5c7
4 changed files with 170 additions and 0 deletions
  1. 2 0
      Source/CMakeLists.txt
  2. 127 0
      Source/cmFileTimes.cxx
  3. 40 0
      Source/cmFileTimes.h
  4. 1 0
      bootstrap

+ 2 - 0
Source/CMakeLists.txt

@@ -242,6 +242,8 @@ set(SRCS
   cmFileTime.h
   cmFileTimeCache.cxx
   cmFileTimeCache.h
+  cmFileTimes.cxx
+  cmFileTimes.h
   cmFortranParserImpl.cxx
   cmFSPermissions.cxx
   cmFSPermissions.h

+ 127 - 0
Source/cmFileTimes.cxx

@@ -0,0 +1,127 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmFileTimes.h"
+
+#include "cmAlgorithms.h"
+#include "cm_sys_stat.h"
+
+#include <utility>
+
+#if defined(_WIN32)
+#  include "cmSystemTools.h"
+#  include <windows.h>
+#else
+#  include <utime.h>
+#endif
+
+#if defined(_WIN32) &&                                                        \
+  (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__MINGW32__))
+#  include <io.h>
+#endif
+
+#ifdef _WIN32
+class cmFileTimes::WindowsHandle
+{
+public:
+  WindowsHandle(HANDLE h)
+    : handle_(h)
+  {
+  }
+  ~WindowsHandle()
+  {
+    if (this->handle_ != INVALID_HANDLE_VALUE) {
+      CloseHandle(this->handle_);
+    }
+  }
+  explicit operator bool() const
+  {
+    return this->handle_ != INVALID_HANDLE_VALUE;
+  }
+  bool operator!() const { return this->handle_ == INVALID_HANDLE_VALUE; }
+  operator HANDLE() const { return this->handle_; }
+
+private:
+  HANDLE handle_;
+};
+#endif
+
+class cmFileTimes::Times
+{
+public:
+#if defined(_WIN32) && !defined(__CYGWIN__)
+  FILETIME timeCreation;
+  FILETIME timeLastAccess;
+  FILETIME timeLastWrite;
+#else
+  struct utimbuf timeBuf;
+#endif
+};
+
+cmFileTimes::cmFileTimes() = default;
+cmFileTimes::cmFileTimes(std::string const& fileName)
+{
+  Load(fileName);
+}
+cmFileTimes::~cmFileTimes() = default;
+
+bool cmFileTimes::Load(std::string const& fileName)
+{
+  std::unique_ptr<Times> ptr;
+  if (IsValid()) {
+    // Invalidate this and re-use times
+    ptr.swap(this->times);
+  } else {
+    ptr = cm::make_unique<Times>();
+  }
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+  cmFileTimes::WindowsHandle handle =
+    CreateFileW(cmSystemTools::ConvertToWindowsExtendedPath(fileName).c_str(),
+                GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING,
+                FILE_FLAG_BACKUP_SEMANTICS, 0);
+  if (!handle) {
+    return false;
+  }
+  if (!GetFileTime(handle, &ptr->timeCreation, &ptr->timeLastAccess,
+                   &ptr->timeLastWrite)) {
+    return false;
+  }
+#else
+  struct stat st;
+  if (stat(fileName.c_str(), &st) < 0) {
+    return false;
+  }
+  ptr->timeBuf.actime = st.st_atime;
+  ptr->timeBuf.modtime = st.st_mtime;
+#endif
+  // Accept times
+  this->times = std::move(ptr);
+  return true;
+}
+
+bool cmFileTimes::Store(std::string const& fileName) const
+{
+  if (!IsValid()) {
+    return false;
+  }
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+  cmFileTimes::WindowsHandle handle = CreateFileW(
+    cmSystemTools::ConvertToWindowsExtendedPath(fileName).c_str(),
+    FILE_WRITE_ATTRIBUTES, 0, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
+  if (!handle) {
+    return false;
+  }
+  return SetFileTime(handle, &this->times->timeCreation,
+                     &this->times->timeLastAccess,
+                     &this->times->timeLastWrite) != 0;
+#else
+  return utime(fileName.c_str(), &this->times->timeBuf) >= 0;
+#endif
+}
+
+bool cmFileTimes::Copy(std::string const& fromFile, std::string const& toFile)
+{
+  cmFileTimes fileTimes;
+  return (fileTimes.Load(fromFile) && fileTimes.Store(toFile));
+}

+ 40 - 0
Source/cmFileTimes.h

@@ -0,0 +1,40 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cmFileTimes_h
+#define cmFileTimes_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <memory> // IWYU pragma: keep
+#include <string>
+
+/** \class cmFileTimes
+ * \brief Loads and stores file times.
+ */
+class cmFileTimes
+{
+public:
+  cmFileTimes();
+  //! Calls Load()
+  cmFileTimes(std::string const& fileName);
+  ~cmFileTimes();
+
+  //! @return true, if file times were loaded successfully
+  bool IsValid() const { return (times != nullptr); }
+  //! Try to load the file times from @a fileName and @return IsValid()
+  bool Load(std::string const& fileName);
+  //! Stores the file times at @a fileName (if IsValid())
+  bool Store(std::string const& fileName) const;
+
+  //! Copies the file times of @a fromFile to @a toFile
+  static bool Copy(std::string const& fromFile, std::string const& toFile);
+
+private:
+#ifdef _WIN32
+  class WindowsHandle;
+#endif
+  class Times;
+  std::unique_ptr<Times> times;
+};
+
+#endif

+ 1 - 0
bootstrap

@@ -306,6 +306,7 @@ CMAKE_CXX_SOURCES="\
   cmFileInstaller \
   cmFileTime \
   cmFileTimeCache \
+  cmFileTimes \
   cmFindBase \
   cmFindCommon \
   cmFindFileCommand \