summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorOliver Reiche <oliver.reiche@huawei.com>2022-03-07 13:23:13 +0100
committerOliver Reiche <oliver.reiche@huawei.com>2022-03-08 13:47:21 +0100
commitde9fc75a961eea20aba6eeb3fc56d2e9f8d8f494 (patch)
tree9c551602e417876958867ca9707a334d07513db0 /src
parentd1f1da9ce54efa058681f2d78e427e08c1cb171b (diff)
downloadjustbuild-de9fc75a961eea20aba6eeb3fc56d2e9f8d8f494.tar.gz
FileSystemManager: Implement fd-less file copy
Diffstat (limited to 'src')
-rw-r--r--src/buildtool/file_system/TARGETS1
-rw-r--r--src/buildtool/file_system/file_system_manager.hpp72
2 files changed, 61 insertions, 12 deletions
diff --git a/src/buildtool/file_system/TARGETS b/src/buildtool/file_system/TARGETS
index ef817912..d780c47a 100644
--- a/src/buildtool/file_system/TARGETS
+++ b/src/buildtool/file_system/TARGETS
@@ -11,6 +11,7 @@
, "deps":
[ "object_type"
, ["src/buildtool/logging", "logging"]
+ , ["src/buildtool/system", "system"]
, ["@", "gsl-lite", "", "gsl-lite"]
]
, "stage": ["src", "buildtool", "file_system"]
diff --git a/src/buildtool/file_system/file_system_manager.hpp b/src/buildtool/file_system/file_system_manager.hpp
index 75902890..df04bcec 100644
--- a/src/buildtool/file_system/file_system_manager.hpp
+++ b/src/buildtool/file_system/file_system_manager.hpp
@@ -8,12 +8,14 @@
#include <optional>
#ifdef __unix__
+#include <sys/wait.h>
#include <unistd.h>
#endif
#include "gsl-lite/gsl-lite.hpp"
#include "src/buildtool/file_system/object_type.hpp"
#include "src/buildtool/logging/logger.hpp"
+#include "src/buildtool/system/system.hpp"
/// \brief Implements primitive file system functionality.
/// Catches all exceptions for use with exception-free callers.
@@ -139,29 +141,52 @@ class FileSystemManager {
[[nodiscard]] static auto CopyFile(
std::filesystem::path const& src,
std::filesystem::path const& dst,
+ bool fd_less = false,
std::filesystem::copy_options opt =
std::filesystem::copy_options::overwrite_existing) noexcept
-> bool {
- try {
- return std::filesystem::copy_file(src, dst, opt);
- } catch (std::exception const& e) {
- Logger::Log(LogLevel::Error,
- "copying file from {} to {}:\n{}",
- src.string(),
- dst.string(),
- e.what());
- return false;
+ if (fd_less) {
+ pid_t pid = ::fork();
+ if (pid == -1) {
+ Logger::Log(
+ LogLevel::Error,
+ "Failed to copy file: cannot fork a child process.");
+ return false;
+ }
+
+ if (pid == 0) {
+ // Disable logging errors in child to avoid the use of mutexes.
+ System::ExitWithoutCleanup(
+ CopyFileImpl</*kLogError=*/false>(src, dst, opt)
+ ? EXIT_SUCCESS
+ : EXIT_FAILURE);
+ }
+
+ int status{};
+ ::waitpid(pid, &status, 0);
+
+ // NOLINTNEXTLINE(hicpp-signed-bitwise)
+ if (WEXITSTATUS(status) != EXIT_SUCCESS) {
+ Logger::Log(LogLevel::Error,
+ "Failed copying file {} to {}",
+ src.string(),
+ dst.string());
+ return false;
+ }
+ return true;
}
+ return CopyFileImpl(src, dst, opt);
}
template <ObjectType kType>
requires(IsFileObject(kType)) [[nodiscard]] static auto CopyFileAs(
std::filesystem::path const& src,
std::filesystem::path const& dst,
+ bool fd_less = false,
std::filesystem::copy_options opt =
std::filesystem::copy_options::overwrite_existing) noexcept
-> bool {
- return CopyFile(src, dst, opt) and
+ return CopyFile(src, dst, fd_less, opt) and
SetFilePermissions(dst, IsExecutableObject(kType));
}
@@ -169,14 +194,16 @@ class FileSystemManager {
std::filesystem::path const& src,
std::filesystem::path const& dst,
ObjectType type,
+ bool fd_less = false,
std::filesystem::copy_options opt =
std::filesystem::copy_options::overwrite_existing) noexcept
-> bool {
switch (type) {
case ObjectType::File:
- return CopyFileAs<ObjectType::File>(src, dst, opt);
+ return CopyFileAs<ObjectType::File>(src, dst, fd_less, opt);
case ObjectType::Executable:
- return CopyFileAs<ObjectType::Executable>(src, dst, opt);
+ return CopyFileAs<ObjectType::Executable>(
+ src, dst, fd_less, opt);
case ObjectType::Tree:
break;
}
@@ -543,6 +570,27 @@ class FileSystemManager {
}
}
+ template <bool kLogError = true>
+ [[nodiscard]] static auto CopyFileImpl(
+ std::filesystem::path const& src,
+ std::filesystem::path const& dst,
+ std::filesystem::copy_options opt =
+ std::filesystem::copy_options::overwrite_existing) noexcept
+ -> bool {
+ try {
+ return std::filesystem::copy_file(src, dst, opt);
+ } catch (std::exception const& e) {
+ if constexpr (kLogError) {
+ Logger::Log(LogLevel::Error,
+ "copying file from {} to {}:\n{}",
+ src.string(),
+ dst.string(),
+ e.what());
+ }
+ return false;
+ }
+ }
+
/// \brief Set special permissions for files.
/// Set to 0444 for non-executables and set to 0555 for executables.
static auto SetFilePermissions(std::filesystem::path const& path,