diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:10:56 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:10:56 +0000 |
commit | 044eb2f6afba375a914ac9d8024f8f5142bb912e (patch) | |
tree | 1475247dc9f9fe5be155ebd4c9069c75aadf8c20 /lib/Support/Path.cpp | |
parent | eb70dddbd77e120e5d490bd8fbe7ff3f8fa81c6b (diff) |
Notes
Diffstat (limited to 'lib/Support/Path.cpp')
-rw-r--r-- | lib/Support/Path.cpp | 173 |
1 files changed, 143 insertions, 30 deletions
diff --git a/lib/Support/Path.cpp b/lib/Support/Path.cpp index ea59ba62d7bd..f229f23a4f84 100644 --- a/lib/Support/Path.cpp +++ b/lib/Support/Path.cpp @@ -18,6 +18,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Process.h" +#include "llvm/Support/Signals.h" #include <cctype> #include <cstring> @@ -159,10 +160,11 @@ enum FSEntity { FS_Name }; -static std::error_code createUniqueEntity(const Twine &Model, int &ResultFD, - SmallVectorImpl<char> &ResultPath, - bool MakeAbsolute, unsigned Mode, - FSEntity Type) { +static std::error_code +createUniqueEntity(const Twine &Model, int &ResultFD, + SmallVectorImpl<char> &ResultPath, bool MakeAbsolute, + unsigned Mode, FSEntity Type, + sys::fs::OpenFlags Flags = sys::fs::F_None) { SmallString<128> ModelStorage; Model.toVector(ModelStorage); @@ -195,7 +197,7 @@ retry_random_path: case FS_File: { if (std::error_code EC = sys::fs::openFileForWrite(Twine(ResultPath.begin()), ResultFD, - sys::fs::F_RW | sys::fs::F_Excl, Mode)) { + Flags | sys::fs::F_Excl, Mode)) { if (EC == errc::file_exists) goto retry_random_path; return EC; @@ -439,10 +441,6 @@ void append(SmallVectorImpl<char> &path, Style style, const Twine &a, for (auto &component : components) { bool path_has_sep = !path.empty() && is_separator(path[path.size() - 1], style); - bool component_has_sep = - !component.empty() && is_separator(component[0], style); - bool is_root_name = has_root_name(component, style); - if (path_has_sep) { // Strip separators from beginning of component. size_t loc = component.find_first_not_of(separators(style)); @@ -453,7 +451,10 @@ void append(SmallVectorImpl<char> &path, Style style, const Twine &a, continue; } - if (!component_has_sep && !(path.empty() || is_root_name)) { + bool component_has_sep = + !component.empty() && is_separator(component[0], style); + if (!component_has_sep && + !(path.empty() || has_root_name(component, style))) { // Add a separator. path.push_back(preferred_separator(style)); } @@ -750,8 +751,9 @@ std::error_code getUniqueID(const Twine Path, UniqueID &Result) { std::error_code createUniqueFile(const Twine &Model, int &ResultFd, SmallVectorImpl<char> &ResultPath, - unsigned Mode) { - return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File); + unsigned Mode, sys::fs::OpenFlags Flags) { + return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File, + Flags); } std::error_code createUniqueFile(const Twine &Model, @@ -762,28 +764,32 @@ std::error_code createUniqueFile(const Twine &Model, static std::error_code createTemporaryFile(const Twine &Model, int &ResultFD, - llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) { + llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type, + sys::fs::OpenFlags Flags) { SmallString<128> Storage; StringRef P = Model.toNullTerminatedStringRef(Storage); assert(P.find_first_of(separators(Style::native)) == StringRef::npos && "Model must be a simple filename."); // Use P.begin() so that createUniqueEntity doesn't need to recreate Storage. - return createUniqueEntity(P.begin(), ResultFD, ResultPath, - true, owner_read | owner_write, Type); + return createUniqueEntity(P.begin(), ResultFD, ResultPath, true, + owner_read | owner_write, Type, Flags); } static std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD, - llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) { + llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type, + sys::fs::OpenFlags Flags = sys::fs::F_None) { const char *Middle = Suffix.empty() ? "-%%%%%%" : "-%%%%%%."; return createTemporaryFile(Prefix + Middle + Suffix, ResultFD, ResultPath, - Type); + Type, Flags); } std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD, - SmallVectorImpl<char> &ResultPath) { - return createTemporaryFile(Prefix, Suffix, ResultFD, ResultPath, FS_File); + SmallVectorImpl<char> &ResultPath, + sys::fs::OpenFlags Flags) { + return createTemporaryFile(Prefix, Suffix, ResultFD, ResultPath, FS_File, + Flags); } std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, @@ -953,11 +959,11 @@ ErrorOr<MD5::MD5Result> md5_contents(const Twine &Path) { return Result; } -bool exists(file_status status) { +bool exists(const basic_file_status &status) { return status_known(status) && status.type() != file_type::file_not_found; } -bool status_known(file_status s) { +bool status_known(const basic_file_status &s) { return s.type() != file_type::status_error; } @@ -968,7 +974,7 @@ file_type get_file_type(const Twine &Path, bool Follow) { return st.type(); } -bool is_directory(file_status status) { +bool is_directory(const basic_file_status &status) { return status.type() == file_type::directory_file; } @@ -980,7 +986,7 @@ std::error_code is_directory(const Twine &path, bool &result) { return std::error_code(); } -bool is_regular_file(file_status status) { +bool is_regular_file(const basic_file_status &status) { return status.type() == file_type::regular_file; } @@ -992,7 +998,7 @@ std::error_code is_regular_file(const Twine &path, bool &result) { return std::error_code(); } -bool is_symlink_file(file_status status) { +bool is_symlink_file(const basic_file_status &status) { return status.type() == file_type::symlink_file; } @@ -1004,7 +1010,7 @@ std::error_code is_symlink_file(const Twine &path, bool &result) { return std::error_code(); } -bool is_other(file_status status) { +bool is_other(const basic_file_status &status) { return exists(status) && !is_regular_file(status) && !is_directory(status); @@ -1018,17 +1024,14 @@ std::error_code is_other(const Twine &Path, bool &Result) { return std::error_code(); } -void directory_entry::replace_filename(const Twine &filename, file_status st) { +void directory_entry::replace_filename(const Twine &filename, + basic_file_status st) { SmallString<128> path = path::parent_path(Path); path::append(path, filename); Path = path.str(); Status = st; } -std::error_code directory_entry::status(file_status &result) const { - return fs::status(Path, result, FollowSymlinks); -} - ErrorOr<perms> getPermissions(const Twine &Path) { file_status Status; if (std::error_code EC = status(Path, Status)) @@ -1051,6 +1054,116 @@ ErrorOr<perms> getPermissions(const Twine &Path) { namespace llvm { namespace sys { +namespace fs { +TempFile::TempFile(StringRef Name, int FD) : TmpName(Name), FD(FD) {} +TempFile::TempFile(TempFile &&Other) { *this = std::move(Other); } +TempFile &TempFile::operator=(TempFile &&Other) { + TmpName = std::move(Other.TmpName); + FD = Other.FD; + Other.Done = true; + return *this; +} + +TempFile::~TempFile() { assert(Done); } + +Error TempFile::discard() { + Done = true; + std::error_code RemoveEC; +// On windows closing will remove the file. +#ifndef LLVM_ON_WIN32 + // Always try to close and remove. + if (!TmpName.empty()) { + RemoveEC = fs::remove(TmpName); + sys::DontRemoveFileOnSignal(TmpName); + } +#endif + + if (!RemoveEC) + TmpName = ""; + + if (FD != -1 && close(FD) == -1) { + std::error_code EC = std::error_code(errno, std::generic_category()); + return errorCodeToError(EC); + } + FD = -1; + + return errorCodeToError(RemoveEC); +} + +Error TempFile::keep(const Twine &Name) { + assert(!Done); + Done = true; + // Always try to close and rename. +#ifdef LLVM_ON_WIN32 + // If we cant't cancel the delete don't rename. + std::error_code RenameEC = cancelDeleteOnClose(FD); + if (!RenameEC) + RenameEC = rename_fd(FD, Name); + // If we can't rename, discard the temporary file. + if (RenameEC) + removeFD(FD); +#else + std::error_code RenameEC = fs::rename(TmpName, Name); + // If we can't rename, discard the temporary file. + if (RenameEC) + remove(TmpName); + sys::DontRemoveFileOnSignal(TmpName); +#endif + + if (!RenameEC) + TmpName = ""; + + if (close(FD) == -1) { + std::error_code EC(errno, std::generic_category()); + return errorCodeToError(EC); + } + FD = -1; + + return errorCodeToError(RenameEC); +} + +Error TempFile::keep() { + assert(!Done); + Done = true; + +#ifdef LLVM_ON_WIN32 + if (std::error_code EC = cancelDeleteOnClose(FD)) + return errorCodeToError(EC); +#else + sys::DontRemoveFileOnSignal(TmpName); +#endif + + TmpName = ""; + + if (close(FD) == -1) { + std::error_code EC(errno, std::generic_category()); + return errorCodeToError(EC); + } + FD = -1; + + return Error::success(); +} + +Expected<TempFile> TempFile::create(const Twine &Model, unsigned Mode) { + int FD; + SmallString<128> ResultPath; + if (std::error_code EC = createUniqueFile(Model, FD, ResultPath, Mode, + sys::fs::F_RW | sys::fs::F_Delete)) + return errorCodeToError(EC); + + TempFile Ret(ResultPath, FD); +#ifndef LLVM_ON_WIN32 + if (sys::RemoveFileOnSignal(ResultPath)) { + // Make sure we delete the file when RemoveFileOnSignal fails. + consumeError(Ret.discard()); + std::error_code EC(errc::operation_not_permitted); + return errorCodeToError(EC); + } +#endif + return std::move(Ret); +} +} + namespace path { bool user_cache_directory(SmallVectorImpl<char> &Result, const Twine &Path1, |