4#include "Stroika/Foundation/StroikaPreComp.h"
10#if qStroika_Foundation_Common_Platform_Windows
13#elif qStroika_Foundation_Common_Platform_POSIX
19#include "Stroika/Foundation/Execution/Common.h"
20#include "Stroika/Foundation/Execution/Exceptions.h"
21#include "Stroika/Foundation/Execution/Module.h"
22#include "Stroika/Foundation/Execution/Process.h"
32using namespace Stroika::Foundation::IO;
34using namespace Stroika::Foundation::Memory;
42 filesystem::path GetSysTmpRelativePath_ (
const AppTmpFileManager::Options& o)
44 return o.fRelativePathInsideTmpDir.value_or (
GetEXEPath ().stem ());
53 filesystem::path exeFileName = cleanedExePath.stem ();
58 auto u = exeFileName.u32string ();
59 for (
auto i = u.begin (); i != u.end (); ++i) {
74 tmpDir /= GetSysTmpRelativePath_ (options);
75 DbgTrace (
"tmpDir={} (assuring created now...)"_f, tmpDir);
77 create_directories (tmpDir);
80 DbgTrace (L
"Error creating tmpdirs, so adjusting and retrying : {}"_f, current_exception ());
82 tmpDir.replace_filename (
GetEXEPath ().stem ().generic_string () +
"-tmpdir");
83 create_directories (tmpDir);
85 for (
int i = 0; i < INT_MAX; ++i) {
86 filesystem::path trialD =
87 tmpDir / Format (
"{}-{}-{}"_f, exeFileName, Execution::GetCurrentProcessID (), i + rand ()).As<filesystem::path> ();
89 if (create_directory (trialD) ==
false) {
99AppTmpFileManager::~AppTmpFileManager ()
101 if (not fTmpDir_.empty ()) {
102 DbgTrace (L
"AppTmpFileManager::DTOR: clearing {}"_f, fTmpDir_);
104 remove_all (fTmpDir_);
107 DbgTrace (
"Ignoring exception clearly AppTmpFileManager files: {}"_f, current_exception ());
114 DbgTrace (
"AppTmpFileManager::DTOR: clearing {}"_f, fTmpDir_);
115 remove_all (fTmpDir_);
116 fTmpDir_ = move (rhs.fTmpDir_);
117 Assert (rhs.fTmpDir_.empty ());
123 filesystem::path fn = GetRootTmpDir ();
124 create_directories (fn);
128filesystem::path AppTmpFileManager::GetTmpDir (
const String& dirNameBase)
130 filesystem::path fn = GetRootTmpDir ();
131 create_directories (fn);
132 for (
int attempts = 0; attempts < 5; ++attempts) {
134 (void)snprintf (buf, NEltsOf (buf),
"-%d", ::rand ());
135 filesystem::path trialName = fn / (dirNameBase + buf).As<filesystem::path> ();
136 if (not is_directory (trialName)) {
137 if (create_directories (trialName)) {
138 DbgTrace (
"AppTmpFileManager::GetTempDir (): returning '{}'"_f, trialName);
143 DbgTrace (
"Attempt to create directory collided, so retrying ({})"_f, trialName, attempts);
146 "AppTmpFileManager::GetTmpDir (): failed to create tmpdir");
154ScopedTmpDir::ScopedTmpDir (
const String& fileNameBase)
159ScopedTmpDir::~ScopedTmpDir ()
163 remove_all (fTmpDir_);
166 DbgTrace (
"Ignoring exception DTOR: {}"_f, current_exception ());
175ScopedTmpFile::ScopedTmpFile (
const String& fileBaseName)
180ScopedTmpFile::~ScopedTmpFile ()
186 DbgTrace (
"Ignoring exception clearing file in ScopedTmpFile::~ScopedTmpFile: {}"_f, current_exception ());
202 filesystem::path baseNamePath = baseName.
As<filesystem::path> ();
203 Require (not baseNamePath.has_root_path ());
204 String basename{baseNamePath.stem ()};
205 String ext{baseNamePath.extension ()};
209 constexpr int kMaxAttempts_{100};
210 for (
int attempts = 0; attempts < kMaxAttempts_; ++attempts) {
212 (void)snprintf (buf, NEltsOf (buf),
"-%d", ::rand ());
213 filesystem::path trialName = inFolder / (basename + buf + ext).As<filesystem::path> ();
214 if (not exists (trialName)) {
215#if qStroika_Foundation_Common_Platform_Windows
216 if (HANDLE fd = ::CreateFile (trialName.native ().c_str (), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
217 nullptr, CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
nullptr);
218 fd != INVALID_HANDLE_VALUE) {
220 DbgTrace (
"AppTmpFileManager::GetTmpFile (): returning {}"_f, trialName);
225 if (
int fd = ::open (trialName.generic_string ().c_str (), O_RDWR | O_CREAT, filesystem::perms::all); fd >= 0) {
227 DbgTrace (
"AppTmpFileManager::GetTmpFile (): returning {}"_f, trialName);
233 DbgTrace (
"Attempt to create file ({}) collided, so retrying ({} attempts)"_f, trialName, attempts);
#define WeakAssert(c)
A WeakAssert() is for things that aren't guaranteed to be true, but are overwhelmingly likely to be t...
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Exception<> is a replacement (subclass) for any std c++ exception class (e.g. the default 'std::excep...
AppTmpFileManager & operator=(AppTmpFileManager &&rhs) noexcept
nonvirtual filesystem::path GetTmpFile(const String &fileBaseName)
AppTmpFileManager(const AppTmpFileManager &)=delete
void Throw(T &&e2Throw)
identical to builtin C++ 'throw' except that it does helpful, type dependent DbgTrace() messages firs...
filesystem::path GetEXEPath()
filesystem::path GetTemporary()
filesystem::path CreateTmpFile(const String &baseName)