llvm::Error
writeFileAtomically(StringRef TempPathModel, StringRef FinalPath,
std::function<llvm::Error(llvm::raw_ostream &)> Writer);
+
+ /// FilePermssionsApplier helps to copy permissions from an input file to
+ /// an output one. It memorizes the status of the input file and can apply
+ /// permissions and dates to the output file.
+ class FilePermissionsApplier {
+ public:
+ static Expected<FilePermissionsApplier> create(StringRef InputFilename);
+
+ /// Apply stored permissions to the \p OutputFilename.
+ /// Copy LastAccess and ModificationTime if \p CopyDates is true.
+ /// Overwrite stored permissions if \p OverwritePermissions is specified.
+ Error apply(StringRef OutputFilename, bool CopyDates = false,
+ Optional<sys::fs::perms> OverwritePermissions = None);
+
+ private:
+ FilePermissionsApplier(StringRef InputFilename, sys::fs::file_status Status)
+ : InputFilename(InputFilename), InputStatus(Status) {}
+
+ StringRef InputFilename;
+ sys::fs::file_status InputStatus;
+ };
} // End llvm namespace
#endif
#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>
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;
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/Memory.h"
llvm_unreachable("unsupported output format");
}
-static Error restoreStatOnFile(StringRef Filename,
- const sys::fs::file_status &Stat,
- const ConfigManager &ConfigMgr) {
- int FD;
- const CommonConfig &Config = ConfigMgr.getCommonConfig();
-
- // Writing to stdout should not be treated as an error here, just
- // do not set access/modification times or permissions.
- if (Filename == "-")
- return Error::success();
-
- if (auto EC =
- sys::fs::openFileForWrite(Filename, FD, sys::fs::CD_OpenExisting))
- return createFileError(Filename, EC);
-
- if (Config.PreserveDates)
- if (auto EC = sys::fs::setLastAccessAndModificationTime(
- FD, Stat.getLastAccessedTime(), Stat.getLastModificationTime()))
- return createFileError(Filename, EC);
-
- sys::fs::file_status OStat;
- if (std::error_code EC = sys::fs::status(FD, OStat))
- return createFileError(Filename, EC);
- if (OStat.type() == sys::fs::file_type::regular_file) {
-#ifndef _WIN32
- // Keep ownership if llvm-objcopy is called under root.
- if (Config.InputFilename == Config.OutputFilename && OStat.getUser() == 0)
- sys::fs::changeFileOwnership(FD, Stat.getUser(), Stat.getGroup());
-#endif
-
- sys::fs::perms Perm = Stat.permissions();
- if (Config.InputFilename != Config.OutputFilename)
- Perm = static_cast<sys::fs::perms>(Perm & ~sys::fs::getUmask() & ~06000);
-#ifdef _WIN32
- if (auto EC = sys::fs::setPermissions(Filename, Perm))
-#else
- if (auto EC = sys::fs::setPermissions(FD, Perm))
-#endif
- return createFileError(Filename, EC);
- }
-
- if (auto EC = sys::Process::SafelyCloseFileDescriptor(FD))
- return createFileError(Filename, EC);
-
- return Error::success();
-}
-
/// The function executeObjcopy does the higher level dispatch based on the type
/// of input (raw binary, archive or single object file) and takes care of the
/// format-agnostic modifications, i.e. preserving dates.
static Error executeObjcopy(ConfigManager &ConfigMgr) {
CommonConfig &Config = ConfigMgr.Common;
- sys::fs::file_status Stat;
- if (Config.InputFilename != "-") {
- if (auto EC = sys::fs::status(Config.InputFilename, Stat))
- return createFileError(Config.InputFilename, EC);
- } else {
- Stat.permissions(static_cast<sys::fs::perms>(0777));
- }
+ Expected<FilePermissionsApplier> PermsCarrier =
+ FilePermissionsApplier::create(Config.InputFilename);
+ if (!PermsCarrier)
+ return PermsCarrier.takeError();
std::function<Error(raw_ostream & OutFile)> ObjcopyFunc;
}
}
- if (Error E = restoreStatOnFile(Config.OutputFilename, Stat, ConfigMgr))
+ if (Error E =
+ PermsCarrier->apply(Config.OutputFilename, Config.PreserveDates))
return E;
- if (!Config.SplitDWO.empty()) {
- Stat.permissions(static_cast<sys::fs::perms>(0666));
- if (Error E = restoreStatOnFile(Config.SplitDWO, Stat, ConfigMgr))
+ if (!Config.SplitDWO.empty())
+ if (Error E = PermsCarrier->apply(Config.SplitDWO, Config.PreserveDates,
+ static_cast<sys::fs::perms>(0666)))
return E;
- }
return Error::success();
}