196 const std::vector<unsigned char>&
data,
199 namespace fs = std::filesystem;
201 if (mode == WriteMode::Plain)
203 std::ofstream dataofs;
207 throw armarx::LocalException(
"Could not write data to filesystem file '" +
208 p.string() +
"'. Skipping this file.");
210 dataofs.write(
reinterpret_cast<const char*
>(
data.data()),
data.size());
215 const fs::path dir = p.parent_path().empty() ? fs::current_path() : p.parent_path();
216 const std::string filename = p.filename().string();
219 fs::path tmpl = dir / (filename +
".tmpXXXXXX");
220 std::string tmpl_str = tmpl.string();
223 int fd = ::mkstemp(tmpl_str.data());
226 throw std::system_error(errno, std::generic_category(),
"mkstemp failed");
230 const unsigned char* buf =
data.data();
231 size_t left =
data.size();
234 ssize_t n = ::write(fd, buf, left);
239 ::unlink(tmpl_str.c_str());
240 throw std::system_error(e, std::generic_category(),
"write failed");
243 left -=
static_cast<size_t>(n);
249 if (mode == WriteMode::AtomicDurable and ::fdatasync(fd) != 0)
253 ::unlink(tmpl_str.c_str());
254 throw std::system_error(e, std::generic_category(),
"fdatasync failed");
257 if (::close(fd) != 0)
260 ::unlink(tmpl_str.c_str());
261 throw std::system_error(e, std::generic_category(),
"close failed");
265 if (::rename(tmpl_str.c_str(), p.c_str()) != 0)
268 ::unlink(tmpl_str.c_str());
269 throw std::system_error(e, std::generic_category(),
"rename failed");
274 if (mode == WriteMode::AtomicDurable)
276 int dfd = ::open(dir.c_str(), O_DIRECTORY | O_RDONLY);
289 if (!std::filesystem::exists(p))
291 throw std::runtime_error(
"File not found: " + p.string());
294 std::ifstream dataifs(p, std::ios::binary);
298 throw std::runtime_error(
"Could not open file: " + p.string());
301 std::vector<unsigned char> datafilecontent((std::istreambuf_iterator<char>(dataifs)),
302 (std::istreambuf_iterator<char>()));
307 throw std::runtime_error(
"Error reading file: " + p.string());
311 return datafilecontent;
332 int ret = ::deflateInit2(
333 &zs, level, Z_DEFLATED, GZIP_WINDOW_BITS, GZIP_MEM_LEVEL, Z_DEFAULT_STRATEGY);
336 throw std::runtime_error(
"gzipCompress: deflateInit2 failed with code " +
337 std::to_string(ret));
340 std::vector<unsigned char> out;
342 out.resize(::deflateBound(&zs,
static_cast<uLong
>(
data.size())));
344 zs.next_in =
const_cast<Bytef*
>(
data.data());
345 zs.avail_in =
static_cast<uInt
>(
data.size());
346 zs.next_out = out.data();
347 zs.avail_out =
static_cast<uInt
>(out.size());
349 ret = ::deflate(&zs, Z_FINISH);
350 const std::size_t written = zs.total_out;
353 if (ret != Z_STREAM_END)
355 throw std::runtime_error(
"gzipCompress: deflate did not finish, code " +
356 std::to_string(ret));
367 int ret = ::inflateInit2(&zs, GZIP_WINDOW_BITS);
370 throw std::runtime_error(
"gzipDecompress: inflateInit2 failed with code " +
371 std::to_string(ret));
374 zs.next_in =
const_cast<Bytef*
>(
data.data());
375 zs.avail_in =
static_cast<uInt
>(
data.size());
377 std::vector<unsigned char> out;
378 std::vector<unsigned char> chunk(GZIP_CHUNK);
382 zs.next_out = chunk.data();
383 zs.avail_out =
static_cast<uInt
>(chunk.size());
385 ret = ::inflate(&zs, Z_NO_FLUSH);
387 if (ret != Z_OK and ret != Z_STREAM_END and ret != Z_BUF_ERROR)
390 throw std::runtime_error(
"gzipDecompress: inflate failed with code " +
391 std::to_string(ret));
394 out.insert(out.end(), chunk.begin(), chunk.end() - zs.avail_out);
397 }
while (ret != Z_STREAM_END and zs.avail_out == 0);
401 if (ret != Z_STREAM_END)
403 throw std::runtime_error(
"gzipDecompress: truncated gzip stream");
412 std::vector<std::filesystem::path> ret;
413 for (
const auto& subdir : std::filesystem::directory_iterator(p))
415 std::filesystem::path subdirPath = subdir.path();
416 if (std::filesystem::is_directory(subdirPath))
418 ret.push_back(subdirPath);
421 std::sort(ret.begin(),
423 [](
const std::filesystem::path& a,
const std::filesystem::path& b) ->
bool
424 { return a.string() < b.string(); });
431 std::vector<std::filesystem::path> ret;
432 for (
const auto& subdir : std::filesystem::directory_iterator(p))
434 std::filesystem::path subdirPath = subdir.path();
435 if (std::filesystem::is_regular_file(subdirPath))
437 ret.push_back(subdirPath);
440 std::sort(ret.begin(),
442 [](
const std::filesystem::path& a,
const std::filesystem::path& b) ->
bool
443 { return a.string() > b.string(); });
480 namespace fs = std::filesystem;
482 if (!fs::exists(dir) || !fs::is_directory(dir))
488 fs::path testFile = dir /
".ltm_write_test_XXXXXX";
489 std::string testPath = testFile.string();
491 int fd = ::mkstemp(testPath.data());
498 ::unlink(testPath.c_str());