fs.cpp raw

   1  // Copyright (c) 2017-present The Bitcoin Core developers
   2  // Distributed under the MIT software license, see the accompanying
   3  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
   4  
   5  #include <util/fs.h>
   6  
   7  #include <util/check.h>
   8  #include <util/syserror.h>
   9  
  10  #include <cerrno>
  11  #include <string>
  12  
  13  #ifndef WIN32
  14  #include <fcntl.h>
  15  #include <unistd.h>
  16  #else
  17  #include <limits>
  18  #include <windows.h>
  19  #endif
  20  
  21  namespace fsbridge {
  22  
  23  FILE *fopen(const fs::path& p, const char *mode)
  24  {
  25  #ifndef WIN32
  26      return ::fopen(p.c_str(), mode);
  27  #else
  28      return ::fopen(p.utf8string().c_str(), mode);
  29  #endif
  30  }
  31  
  32  fs::path AbsPathJoin(const fs::path& base, const fs::path& path)
  33  {
  34      assert(base.is_absolute());
  35      return path.empty() ? base : fs::path(base / path);
  36  }
  37  
  38  #ifndef WIN32
  39  
  40  static std::string GetErrorReason()
  41  {
  42      return SysErrorString(errno);
  43  }
  44  
  45  FileLock::FileLock(const fs::path& file)
  46  {
  47      fd = open(file.c_str(), O_RDWR);
  48      if (fd == -1) {
  49          reason = GetErrorReason();
  50      }
  51  }
  52  
  53  FileLock::~FileLock()
  54  {
  55      if (fd != -1) {
  56          close(fd);
  57      }
  58  }
  59  
  60  bool FileLock::TryLock()
  61  {
  62      if (fd == -1) {
  63          return false;
  64      }
  65  
  66      struct flock lock;
  67      lock.l_type = F_WRLCK;
  68      lock.l_whence = SEEK_SET;
  69      lock.l_start = 0;
  70      lock.l_len = 0;
  71      if (fcntl(fd, F_SETLK, &lock) == -1) {
  72          reason = GetErrorReason();
  73          return false;
  74      }
  75  
  76      return true;
  77  }
  78  #else
  79  
  80  static std::string GetErrorReason() {
  81      return Win32ErrorString(GetLastError());
  82  }
  83  
  84  FileLock::FileLock(const fs::path& file)
  85  {
  86      hFile = CreateFileW(file.wstring().c_str(),  GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  87          nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
  88      if (hFile == INVALID_HANDLE_VALUE) {
  89          reason = GetErrorReason();
  90      }
  91  }
  92  
  93  FileLock::~FileLock()
  94  {
  95      if (hFile != INVALID_HANDLE_VALUE) {
  96          CloseHandle(hFile);
  97      }
  98  }
  99  
 100  bool FileLock::TryLock()
 101  {
 102      if (hFile == INVALID_HANDLE_VALUE) {
 103          return false;
 104      }
 105      _OVERLAPPED overlapped = {};
 106      if (!LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, 0, std::numeric_limits<DWORD>::max(), std::numeric_limits<DWORD>::max(), &overlapped)) {
 107          reason = GetErrorReason();
 108          return false;
 109      }
 110      return true;
 111  }
 112  #endif
 113  
 114  } // namespace fsbridge
 115