diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Support/FileUtilities.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Support/FileUtilities.cpp | 66 |
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; |