summaryrefslogtreecommitdiff
path: root/lib/Support/Path.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-12-18 20:10:56 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-12-18 20:10:56 +0000
commit044eb2f6afba375a914ac9d8024f8f5142bb912e (patch)
tree1475247dc9f9fe5be155ebd4c9069c75aadf8c20 /lib/Support/Path.cpp
parenteb70dddbd77e120e5d490bd8fbe7ff3f8fa81c6b (diff)
Notes
Diffstat (limited to 'lib/Support/Path.cpp')
-rw-r--r--lib/Support/Path.cpp173
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,