Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
ThroughTmpFileWriter.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include "Stroika/Foundation/StroikaPreComp.h"
5
6#include <cstdio>
7
8#if qStroika_Foundation_Common_Platform_Windows
9#include <windows.h>
10#elif qStroika_Foundation_Common_Platform_POSIX
11#include <unistd.h>
12#endif
13
16#include "Stroika/Foundation/Containers/Common.h"
17#include "Stroika/Foundation/Execution/Activity.h"
18#include "Stroika/Foundation/Execution/Exceptions.h"
19#include "Stroika/Foundation/Execution/Throw.h"
20#if qStroika_Foundation_Common_Platform_Windows
21#include "Stroika/Foundation/Execution/Platform/Windows/Exception.h"
22#endif
24
25#include "Exception.h"
26
28
29using namespace Stroika::Foundation;
32using namespace Stroika::Foundation::Execution;
33using namespace Stroika::Foundation::IO;
35
36#if qStroika_Foundation_Common_Platform_Windows
38#endif
39
40/*
41 ********************************************************************************
42 ************************ FileSystem::ThroughTmpFileWriter **********************
43 ********************************************************************************
44 */
45ThroughTmpFileWriter::ThroughTmpFileWriter (const filesystem::path& realFileName, const String& tmpSuffix)
46 : fRealFilePath_{realFileName}
47 , fTmpFilePath_{filesystem::path{realFileName}.operator+= (tmpSuffix.As<wstring> ())}
48{
49 Require (not realFileName.empty ());
50 Require (not tmpSuffix.empty ());
51}
52
53ThroughTmpFileWriter::~ThroughTmpFileWriter ()
54{
55 if (not fTmpFilePath_.empty ()) {
56 DbgTrace ("ThroughTmpFileWriter::DTOR - tmpfile not successfully commited to {}"_f, fRealFilePath_);
57 // ignore errors on unlink, cuz nothing to be done in DTOR anyhow...(@todo perhaps should at least tracelog)
58#if qStroika_Foundation_Common_Platform_POSIX
59 (void)::unlink (fTmpFilePath_.c_str ());
60#elif qStroika_Foundation_Common_Platform_Windows
61 (void)::DeleteFileW (fTmpFilePath_.c_str ());
62#else
64#endif
65 }
66}
67
69{
70 Require (not fTmpFilePath_.empty ()); // cannot Commit more than once
71 // Also - NOTE - you MUST close fTmpFilePath (any file descriptors that have opened it) BEFORE the Commit!
72
73 auto activity = LazyEvalActivity ([&] () -> String { return "committing temporary file {} to {}"_f(fTmpFilePath_, fRealFilePath_); });
74 DeclareActivity currentActivity{&activity};
75#if qStroika_Foundation_Common_Platform_POSIX
76 FileSystem::Exception::ThrowPOSIXErrNoIfNegative (::rename (fTmpFilePath_.c_str (), fRealFilePath_.c_str ()), fTmpFilePath_, fRealFilePath_);
77#elif qStroika_Foundation_Common_Platform_Windows
78 try {
79 ThrowIfZeroGetLastError (::MoveFileExW (fTmpFilePath_.c_str (), fRealFilePath_.c_str (), MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH));
80 }
81 catch (const system_error& we) {
82 // On Win9x - this fails cuz OS not impl...
83 if (we.code () == error_code{ERROR_CALL_NOT_IMPLEMENTED, system_category ()}) {
84 ::DeleteFileW (fRealFilePath_.c_str ());
85 ThrowIfZeroGetLastError (::MoveFileW (fTmpFilePath_.c_str (), fRealFilePath_.c_str ()));
86 }
87 else {
88 ReThrow ();
89 }
90 }
91#else
93#endif
94 fTmpFilePath_.clear ();
95}
#define AssertNotImplemented()
Definition Assertions.h:401
#define DbgTrace
Definition Trace.h:309
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
static INT_TYPE ThrowPOSIXErrNoIfNegative(INT_TYPE returnCode, const path &p1={}, const path &p2={})