diff options
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,  | 
