aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Support/FileUtilities.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Support/FileUtilities.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Support/FileUtilities.cpp66
1 files changed, 66 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/Support/FileUtilities.cpp b/contrib/llvm-project/llvm/lib/Support/FileUtilities.cpp
index 489b8d119e6f..eda3eb044901 100644
--- a/contrib/llvm-project/llvm/lib/Support/FileUtilities.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/FileUtilities.cpp
@@ -17,6 +17,7 @@
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Process.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdint>
#include <cstdlib>
@@ -323,4 +324,69 @@ llvm::Error llvm::writeFileAtomically(
return Error::success();
}
+Expected<FilePermissionsApplier>
+FilePermissionsApplier::create(StringRef InputFilename) {
+ sys::fs::file_status Status;
+
+ if (InputFilename != "-") {
+ if (auto EC = sys::fs::status(InputFilename, Status))
+ return createFileError(InputFilename, EC);
+ } else {
+ Status.permissions(static_cast<sys::fs::perms>(0777));
+ }
+
+ return FilePermissionsApplier(InputFilename, Status);
+}
+
+Error FilePermissionsApplier::apply(
+ StringRef OutputFilename, bool CopyDates,
+ Optional<sys::fs::perms> OverwritePermissions) {
+ sys::fs::file_status Status = InputStatus;
+
+ if (OverwritePermissions)
+ Status.permissions(*OverwritePermissions);
+
+ int FD = 0;
+
+ // Writing to stdout should not be treated as an error here, just
+ // do not set access/modification times or permissions.
+ if (OutputFilename == "-")
+ return Error::success();
+
+ if (std::error_code EC = sys::fs::openFileForWrite(OutputFilename, FD,
+ sys::fs::CD_OpenExisting))
+ return createFileError(OutputFilename, EC);
+
+ if (CopyDates)
+ if (std::error_code EC = sys::fs::setLastAccessAndModificationTime(
+ FD, Status.getLastAccessedTime(), Status.getLastModificationTime()))
+ return createFileError(OutputFilename, EC);
+
+ sys::fs::file_status OStat;
+ if (std::error_code EC = sys::fs::status(FD, OStat))
+ return createFileError(OutputFilename, EC);
+ if (OStat.type() == sys::fs::file_type::regular_file) {
+#ifndef _WIN32
+ // Keep ownership if llvm-objcopy is called under root.
+ if (OutputFilename == InputFilename && OStat.getUser() == 0)
+ sys::fs::changeFileOwnership(FD, Status.getUser(), Status.getGroup());
+#endif
+
+ sys::fs::perms Perm = Status.permissions();
+ if (OutputFilename != InputFilename)
+ Perm = static_cast<sys::fs::perms>(Perm & ~sys::fs::getUmask() & ~06000);
+#ifdef _WIN32
+ if (std::error_code EC = sys::fs::setPermissions(OutputFilename, Perm))
+#else
+ if (std::error_code EC = sys::fs::setPermissions(FD, Perm))
+#endif
+ return createFileError(OutputFilename, EC);
+ }
+
+ if (std::error_code EC = sys::Process::SafelyCloseFileDescriptor(FD))
+ return createFileError(OutputFilename, EC);
+
+ return Error::success();
+}
+
char llvm::AtomicFileWriteError::ID;