Electroneum
tools::private_file Class Reference

A file restricted to process owner AND process. Deletes file on destruction. More...

#include <util.h>

Public Member Functions

 private_file () noexcept
 handle() == nullptr && filename.empty(). More...
 
 private_file (private_file &&)=default
 
private_fileoperator= (private_file &&)=default
 
 ~private_file () noexcept
 Deletes filename() and closes handle(). More...
 
std::FILE * handle () const noexcept
 
const std::string & filename () const noexcept
 

Static Public Member Functions

static private_file create (std::string filename)
 

Detailed Description

A file restricted to process owner AND process. Deletes file on destruction.

Definition at line 71 of file util.h.

Constructor & Destructor Documentation

◆ private_file() [1/2]

tools::private_file::private_file ( )
noexcept

handle() == nullptr && filename.empty().

Definition at line 120 of file util.cpp.

120 : m_handle(), m_filename() {}

◆ private_file() [2/2]

tools::private_file::private_file ( private_file &&  )
default

◆ ~private_file()

tools::private_file::~private_file ( )
noexcept

Deletes filename() and closes handle().

Definition at line 228 of file util.cpp.

229  {
230  try
231  {
232  boost::system::error_code ec{};
233  boost::filesystem::remove(filename(), ec);
234  }
235  catch (...) {}
236  }
const std::string & filename() const noexcept
Definition: util.h:92

Member Function Documentation

◆ create()

private_file tools::private_file::create ( std::string  filename)
static
Returns
File only readable by owner and only used by this process OR private_file{} on error.

Definition at line 125 of file util.cpp.

126  {
127 #ifdef WIN32
128  struct close_handle
129  {
130  void operator()(HANDLE handle) const noexcept
131  {
132  CloseHandle(handle);
133  }
134  };
135 
136  std::unique_ptr<void, close_handle> process = nullptr;
137  {
138  HANDLE temp{};
139  const bool fail = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, std::addressof(temp)) == 0;
140  process.reset(temp);
141  if (fail)
142  return {};
143  }
144 
145  DWORD sid_size = 0;
146  GetTokenInformation(process.get(), TokenOwner, nullptr, 0, std::addressof(sid_size));
147  if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
148  return {};
149 
150  std::unique_ptr<char[]> sid{new char[sid_size]};
151  if (!GetTokenInformation(process.get(), TokenOwner, sid.get(), sid_size, std::addressof(sid_size)))
152  return {};
153 
154  const PSID psid = reinterpret_cast<const PTOKEN_OWNER>(sid.get())->Owner;
155  const DWORD daclSize =
156  sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD);
157 
158  const std::unique_ptr<char[]> dacl{new char[daclSize]};
159  if (!InitializeAcl(reinterpret_cast<PACL>(dacl.get()), daclSize, ACL_REVISION))
160  return {};
161 
162  if (!AddAccessAllowedAce(reinterpret_cast<PACL>(dacl.get()), ACL_REVISION, (READ_CONTROL | FILE_GENERIC_READ | DELETE), psid))
163  return {};
164 
165  SECURITY_DESCRIPTOR descriptor{};
166  if (!InitializeSecurityDescriptor(std::addressof(descriptor), SECURITY_DESCRIPTOR_REVISION))
167  return {};
168 
169  if (!SetSecurityDescriptorDacl(std::addressof(descriptor), true, reinterpret_cast<PACL>(dacl.get()), false))
170  return {};
171 
172  SECURITY_ATTRIBUTES attributes{sizeof(SECURITY_ATTRIBUTES), std::addressof(descriptor), false};
173  std::unique_ptr<void, close_handle> file{
174  CreateFile(
175  name.c_str(),
176  GENERIC_WRITE, FILE_SHARE_READ,
177  std::addressof(attributes),
178  CREATE_NEW, (FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE),
179  nullptr
180  )
181  };
182  if (file)
183  {
184  const int fd = _open_osfhandle(reinterpret_cast<intptr_t>(file.get()), 0);
185  if (0 <= fd)
186  {
187  file.release();
188  std::FILE* real_file = _fdopen(fd, "w");
189  if (!real_file)
190  {
191  _close(fd);
192  }
193  return {real_file, std::move(name)};
194  }
195  }
196 #else
197  const int fdr = open(name.c_str(), (O_RDONLY | O_CREAT), S_IRUSR);
198  if (0 <= fdr)
199  {
200  struct stat rstats = {};
201  if (fstat(fdr, std::addressof(rstats)) != 0)
202  {
203  close(fdr);
204  return {};
205  }
206  fchmod(fdr, (S_IRUSR | S_IWUSR));
207  const int fdw = open(name.c_str(), O_RDWR);
208  fchmod(fdr, rstats.st_mode);
209  close(fdr);
210 
211  if (0 <= fdw)
212  {
213  struct stat wstats = {};
214  if (fstat(fdw, std::addressof(wstats)) == 0 &&
215  rstats.st_dev == wstats.st_dev && rstats.st_ino == wstats.st_ino &&
216  flock_exnb(fdw) == 0 && ftruncate(fdw, 0) == 0)
217  {
218  std::FILE* file = fdopen(fdw, "w");
219  if (file) return {file, std::move(name)};
220  }
221  close(fdw);
222  }
223  }
224 #endif
225  return {};
226  }
std::FILE * handle() const noexcept
Definition: util.h:91
const char * name
const T & move(const T &t)
Definition: gtest-port.h:1317
Here is the call graph for this function:
Here is the caller graph for this function:

◆ filename()

const std::string& tools::private_file::filename ( void  ) const
inlinenoexcept

Definition at line 92 of file util.h.

92 { return m_filename; }

◆ handle()

std::FILE* tools::private_file::handle ( ) const
inlinenoexcept

Definition at line 91 of file util.h.

91 { return m_handle.get(); }
Here is the caller graph for this function:

◆ operator=()

private_file& tools::private_file::operator= ( private_file &&  )
default

The documentation for this class was generated from the following files: