Skip to content

Commit 6a332e1

Browse files
committed
Fix temp file handling
IB-8938 Signed-off-by: Raul Metsma <raul@metsma.ee>
1 parent 7825391 commit 6a332e1

5 files changed

Lines changed: 47 additions & 38 deletions

File tree

src/Container.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,6 @@ void digidoc::terminate()
163163
{
164164
try {
165165
Conf::init(nullptr);
166-
util::File::deleteTempFiles();
167166
} catch (...) {
168167
// Don't throw on terminate
169168
}

src/DataFile.cpp

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "util/ZipSerialize.h"
2626

2727
#include <array>
28+
#include <filesystem>
2829
#include <fstream>
2930
#include <sstream>
3031

@@ -106,25 +107,48 @@ DataFilePrivate::DataFilePrivate(const ZipSerialize &z, string filename, string
106107
d->size.emplace((unsigned long)r.size);
107108
if(r.size > MAX_MEM_FILE)
108109
{
109-
auto fs = make_unique<fstream>(util::File::tempFileName(), fstream::in|fstream::out|fstream::binary|fstream::trunc);
110-
if(!fs->is_open())
111-
THROW("Failed to open destination file");
112-
array<char,10240> buf{};
113-
for(size_t size = 0, currentStreamSize = 0;
114-
(size = r(buf.data(), buf.size())) > 0; currentStreamSize += size)
115-
{
116-
if(currentStreamSize + size > r.size)
117-
THROW("ZIP entry actual size exceeds uncompressed_size %zu", r.size);
118-
if(!fs->write(buf.data(), size))
119-
THROW("Failed to write '%s' data to stream. Stream size: %d", m_filename.c_str(), currentStreamSize);
110+
try {
111+
m_tempFile = util::File::tempFileName();
112+
auto fs = make_unique<fstream>(m_tempFile, fstream::in|fstream::out|fstream::binary|fstream::trunc);
113+
if(!fs->is_open())
114+
THROW("Failed to open destination file");
115+
array<char,10240> buf{};
116+
for(size_t size = 0, currentStreamSize = 0;
117+
(size = r(buf.data(), buf.size())) > 0; currentStreamSize += size)
118+
{
119+
if(currentStreamSize + size > r.size)
120+
THROW("ZIP entry actual size exceeds uncompressed_size %zu", r.size);
121+
if(!fs->write(buf.data(), size))
122+
THROW("Failed to write '%s' data to stream. Stream size: %d", m_filename.c_str(), currentStreamSize);
123+
}
124+
if(!fs->flush())
125+
THROW("Failed to flush '%s' data to temporary file.", m_filename.c_str());
126+
fs->clear();
127+
if(!fs->seekg(0, istream::beg))
128+
THROW("Failed to rewind '%s' temporary file.", m_filename.c_str());
129+
m_is = std::move(fs);
130+
} catch(...) {
131+
if(!m_tempFile.empty())
132+
{
133+
error_code ec;
134+
filesystem::remove(m_tempFile, ec);
135+
}
136+
throw;
120137
}
121-
m_is = std::move(fs);
122138
}
123139
else
124140
m_is = make_unique<stringstream>(r(MAX_MEM_FILE));
125141
}
126142

127-
DataFilePrivate::~DataFilePrivate() noexcept = default;
143+
DataFilePrivate::~DataFilePrivate() noexcept
144+
{
145+
m_is.reset();
146+
if(!m_tempFile.empty())
147+
{
148+
error_code ec;
149+
filesystem::remove(m_tempFile, ec);
150+
}
151+
}
128152

129153
void DataFilePrivate::digest(const Digest &digest) const
130154
{

src/DataFile_p.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "DataFile.h"
2323

24+
#include <filesystem>
2425
#include <istream>
2526
#include <memory>
2627
#include <optional>
@@ -52,6 +53,7 @@ class DataFilePrivate final: public DataFile
5253

5354
struct Private;
5455
std::unique_ptr<Private> d;
56+
std::filesystem::path m_tempFile;
5557
std::unique_ptr<std::istream> m_is;
5658
std::string m_id, m_filename, m_mediatype;
5759
};

src/util/File.cpp

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ using f_statbuf = struct stat;
6262
using f_utimbuf = struct utimbuf;
6363
#endif
6464

65-
stack<fs::path> File::tempFiles;
6665

6766
static string decodeName(fs::path path)
6867
{
@@ -224,20 +223,23 @@ string File::path(string dir, string_view relativePath)
224223
*/
225224
fs::path File::tempFileName()
226225
{
226+
fs::path result;
227227
#ifdef _WIN32
228228
// requires TMP environment variable to be set
229229
wchar_t *fileName = _wtempnam(nullptr, nullptr); // TODO: static buffer, not thread-safe
230230
if(!fileName)
231231
THROW("Failed to create a temporary file name.");
232-
tempFiles.emplace(fileName);
232+
result = fileName;
233233
free(fileName);
234234
#else
235-
string tmp = "XXXXXX";
236-
if(mkstemp(tmp.data()) == -1)
235+
auto result_str = (fs::temp_directory_path() / "XXXXXX").string();
236+
int fd = mkstemp(result_str.data());
237+
if(fd == -1)
237238
THROW("Failed to create a temporary file name.");
238-
tempFiles.push(fs::temp_directory_path() / tmp);
239+
::close(fd);
240+
result = result_str;
239241
#endif
240-
return tempFiles.top();
242+
return result;
241243
}
242244

243245
/**
@@ -292,21 +294,6 @@ string File::digidocppPath()
292294
#endif
293295
}
294296

295-
/**
296-
* Tries to delete all temporary files and directories whose names were handled out with tempFileName, tempDirectory and createTempDirectory.
297-
* The deletion of directories is recursive.
298-
*/
299-
void File::deleteTempFiles()
300-
{
301-
error_code ec;
302-
while(!tempFiles.empty())
303-
{
304-
if(!fs::remove(tempFiles.top(), ec) || ec)
305-
WARN("Tried to remove the temporary file or directory '%s', but failed.", decodeName(tempFiles.top()).c_str());
306-
tempFiles.pop();
307-
}
308-
}
309-
310297
/**
311298
* Helper method for converting strings with non-ascii characters to the URI format (%HH for each non-ascii character).
312299
*

src/util/File.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#include "../Exception.h"
2323

2424
#include <filesystem>
25-
#include <stack>
2625

2726
namespace digidoc
2827
{
@@ -47,7 +46,6 @@ namespace digidoc
4746
static std::string path(std::string dir, std::string_view relativePath);
4847
static std::filesystem::path tempFileName();
4948
static void createDirectory(std::string path);
50-
static void deleteTempFiles();
5149
static std::string toUriPath(const std::string &path);
5250
static std::string fromUriPath(std::string_view path);
5351
static std::vector<unsigned char> hexToBin(std::string_view in);
@@ -59,7 +57,6 @@ namespace digidoc
5957
#ifdef __APPLE__
6058
static std::string frameworkResourcesPath(std::string_view name);
6159
#endif
62-
static std::stack<std::filesystem::path> tempFiles;
6360
};
6461

6562
}

0 commit comments

Comments
 (0)