aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/Support/Path.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/Support/Path.cpp')
-rw-r--r--contrib/llvm/lib/Support/Path.cpp328
1 files changed, 189 insertions, 139 deletions
diff --git a/contrib/llvm/lib/Support/Path.cpp b/contrib/llvm/lib/Support/Path.cpp
index c869b30a8e2d..d5a0ec55c682 100644
--- a/contrib/llvm/lib/Support/Path.cpp
+++ b/contrib/llvm/lib/Support/Path.cpp
@@ -11,10 +11,12 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/Support/Errc.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Process.h"
#include <cctype>
#include <cstdio>
#include <cstring>
@@ -26,16 +28,18 @@
#include <io.h>
#endif
+using namespace llvm;
+
namespace {
using llvm::StringRef;
using llvm::sys::path::is_separator;
#ifdef LLVM_ON_WIN32
const char *separators = "\\/";
- const char prefered_separator = '\\';
+ const char preferred_separator = '\\';
#else
const char separators = '/';
- const char prefered_separator = '/';
+ const char preferred_separator = '/';
#endif
StringRef find_first_component(StringRef path) {
@@ -161,10 +165,76 @@ enum FSEntity {
};
// Implemented in Unix/Path.inc and Windows/Path.inc.
-static llvm::error_code
-createUniqueEntity(const llvm::Twine &Model, int &ResultFD,
- llvm::SmallVectorImpl<char> &ResultPath,
- bool MakeAbsolute, unsigned Mode, FSEntity Type);
+static std::error_code TempDir(SmallVectorImpl<char> &result);
+
+static std::error_code createUniqueEntity(const Twine &Model, int &ResultFD,
+ SmallVectorImpl<char> &ResultPath,
+ bool MakeAbsolute, unsigned Mode,
+ FSEntity Type) {
+ SmallString<128> ModelStorage;
+ Model.toVector(ModelStorage);
+
+ if (MakeAbsolute) {
+ // Make model absolute by prepending a temp directory if it's not already.
+ if (!sys::path::is_absolute(Twine(ModelStorage))) {
+ SmallString<128> TDir;
+ if (std::error_code EC = TempDir(TDir))
+ return EC;
+ sys::path::append(TDir, Twine(ModelStorage));
+ ModelStorage.swap(TDir);
+ }
+ }
+
+ // From here on, DO NOT modify model. It may be needed if the randomly chosen
+ // path already exists.
+ ResultPath = ModelStorage;
+ // Null terminate.
+ ResultPath.push_back(0);
+ ResultPath.pop_back();
+
+retry_random_path:
+ // Replace '%' with random chars.
+ for (unsigned i = 0, e = ModelStorage.size(); i != e; ++i) {
+ if (ModelStorage[i] == '%')
+ ResultPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15];
+ }
+
+ // Try to open + create the file.
+ switch (Type) {
+ case FS_File: {
+ if (std::error_code EC =
+ sys::fs::openFileForWrite(Twine(ResultPath.begin()), ResultFD,
+ sys::fs::F_RW | sys::fs::F_Excl, Mode)) {
+ if (EC == errc::file_exists)
+ goto retry_random_path;
+ return EC;
+ }
+
+ return std::error_code();
+ }
+
+ case FS_Name: {
+ bool Exists;
+ std::error_code EC = sys::fs::exists(ResultPath.begin(), Exists);
+ if (EC)
+ return EC;
+ if (Exists)
+ goto retry_random_path;
+ return std::error_code();
+ }
+
+ case FS_Dir: {
+ if (std::error_code EC =
+ sys::fs::create_directory(ResultPath.begin(), false)) {
+ if (EC == errc::file_exists)
+ goto retry_random_path;
+ return EC;
+ }
+ return std::error_code();
+ }
+ }
+ llvm_unreachable("Invalid Type");
+}
namespace llvm {
namespace sys {
@@ -239,21 +309,18 @@ const_iterator &const_iterator::operator++() {
}
const_iterator &const_iterator::operator--() {
- // If we're at the end and the previous char was a '/', return '.'.
+ // If we're at the end and the previous char was a '/', return '.' unless
+ // we are the root path.
+ size_t root_dir_pos = root_dir_start(Path);
if (Position == Path.size() &&
- Path.size() > 1 &&
- is_separator(Path[Position - 1])
-#ifdef LLVM_ON_WIN32
- && Path[Position - 2] != ':'
-#endif
- ) {
+ Path.size() > root_dir_pos + 1 &&
+ is_separator(Path[Position - 1])) {
--Position;
Component = ".";
return *this;
}
// Skip separators unless it's the root directory.
- size_t root_dir_pos = root_dir_start(Path);
size_t end_pos = Position;
while(end_pos > 0 &&
@@ -403,7 +470,7 @@ void append(SmallVectorImpl<char> &path, const Twine &a,
if (!component_has_sep && !(path.empty() || is_root_name)) {
// Add a separator.
- path.push_back(prefered_separator);
+ path.push_back(preferred_separator);
}
path.append(i->begin(), i->end());
@@ -504,14 +571,21 @@ bool is_separator(char value) {
}
}
+static const char preferred_separator_string[] = { preferred_separator, '\0' };
+
+const StringRef get_separator() {
+ return preferred_separator_string;
+}
+
void system_temp_directory(bool erasedOnReboot, SmallVectorImpl<char> &result) {
result.clear();
-#ifdef __APPLE__
+#if defined(_CS_DARWIN_USER_TEMP_DIR) && defined(_CS_DARWIN_USER_CACHE_DIR)
// On Darwin, use DARWIN_USER_TEMP_DIR or DARWIN_USER_CACHE_DIR.
+ // macros defined in <unistd.h> on darwin >= 9
int ConfName = erasedOnReboot? _CS_DARWIN_USER_TEMP_DIR
: _CS_DARWIN_USER_CACHE_DIR;
- size_t ConfLen = confstr(ConfName, 0, 0);
+ size_t ConfLen = confstr(ConfName, nullptr, 0);
if (ConfLen > 0) {
do {
result.resize(ConfLen);
@@ -633,29 +707,30 @@ bool is_relative(const Twine &path) {
namespace fs {
-error_code getUniqueID(const Twine Path, UniqueID &Result) {
+std::error_code getUniqueID(const Twine Path, UniqueID &Result) {
file_status Status;
- error_code EC = status(Path, Status);
+ std::error_code EC = status(Path, Status);
if (EC)
return EC;
Result = Status.getUniqueID();
- return error_code::success();
+ return std::error_code();
}
-error_code createUniqueFile(const Twine &Model, int &ResultFd,
- SmallVectorImpl<char> &ResultPath, unsigned Mode) {
+std::error_code createUniqueFile(const Twine &Model, int &ResultFd,
+ SmallVectorImpl<char> &ResultPath,
+ unsigned Mode) {
return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File);
}
-error_code createUniqueFile(const Twine &Model,
- SmallVectorImpl<char> &ResultPath) {
+std::error_code createUniqueFile(const Twine &Model,
+ SmallVectorImpl<char> &ResultPath) {
int Dummy;
return createUniqueEntity(Model, Dummy, ResultPath, false, 0, FS_Name);
}
-static error_code createTemporaryFile(const Twine &Model, int &ResultFD,
- llvm::SmallVectorImpl<char> &ResultPath,
- FSEntity Type) {
+static std::error_code
+createTemporaryFile(const Twine &Model, int &ResultFD,
+ llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) {
SmallString<128> Storage;
StringRef P = Model.toNullTerminatedStringRef(Storage);
assert(P.find_first_of(separators) == StringRef::npos &&
@@ -665,24 +740,22 @@ static error_code createTemporaryFile(const Twine &Model, int &ResultFD,
true, owner_read | owner_write, Type);
}
-static error_code
+static std::error_code
createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD,
- llvm::SmallVectorImpl<char> &ResultPath,
- FSEntity Type) {
+ llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) {
const char *Middle = Suffix.empty() ? "-%%%%%%" : "-%%%%%%.";
return createTemporaryFile(Prefix + Middle + Suffix, ResultFD, ResultPath,
Type);
}
-
-error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
- int &ResultFD,
- SmallVectorImpl<char> &ResultPath) {
+std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
+ int &ResultFD,
+ SmallVectorImpl<char> &ResultPath) {
return createTemporaryFile(Prefix, Suffix, ResultFD, ResultPath, FS_File);
}
-error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
- SmallVectorImpl<char> &ResultPath) {
+std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
+ SmallVectorImpl<char> &ResultPath) {
int Dummy;
return createTemporaryFile(Prefix, Suffix, Dummy, ResultPath, FS_Name);
}
@@ -690,14 +763,14 @@ error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
// This is a mkdtemp with a different pattern. We use createUniqueEntity mostly
// for consistency. We should try using mkdtemp.
-error_code createUniqueDirectory(const Twine &Prefix,
- SmallVectorImpl<char> &ResultPath) {
+std::error_code createUniqueDirectory(const Twine &Prefix,
+ SmallVectorImpl<char> &ResultPath) {
int Dummy;
return createUniqueEntity(Prefix + "-%%%%%%", Dummy, ResultPath,
true, 0, FS_Dir);
}
-error_code make_absolute(SmallVectorImpl<char> &path) {
+std::error_code make_absolute(SmallVectorImpl<char> &path) {
StringRef p(path.data(), path.size());
bool rootDirectory = path::has_root_directory(p),
@@ -709,11 +782,12 @@ error_code make_absolute(SmallVectorImpl<char> &path) {
// Already absolute.
if (rootName && rootDirectory)
- return error_code::success();
+ return std::error_code();
// All of the following conditions will need the current directory.
SmallString<128> current_dir;
- if (error_code ec = current_path(current_dir)) return ec;
+ if (std::error_code ec = current_path(current_dir))
+ return ec;
// Relative path. Prepend the current directory.
if (!rootName && !rootDirectory) {
@@ -721,7 +795,7 @@ error_code make_absolute(SmallVectorImpl<char> &path) {
path::append(current_dir, p);
// Set path to the result.
path.swap(current_dir);
- return error_code::success();
+ return std::error_code();
}
if (!rootName && rootDirectory) {
@@ -730,7 +804,7 @@ error_code make_absolute(SmallVectorImpl<char> &path) {
path::append(curDirRootName, p);
// Set path to the result.
path.swap(curDirRootName);
- return error_code::success();
+ return std::error_code();
}
if (rootName && !rootDirectory) {
@@ -742,27 +816,68 @@ error_code make_absolute(SmallVectorImpl<char> &path) {
SmallString<128> res;
path::append(res, pRootName, bRootDirectory, bRelativePath, pRelativePath);
path.swap(res);
- return error_code::success();
+ return std::error_code();
}
llvm_unreachable("All rootName and rootDirectory combinations should have "
"occurred above!");
}
-error_code create_directories(const Twine &path, bool &existed) {
- SmallString<128> path_storage;
- StringRef p = path.toStringRef(path_storage);
+std::error_code create_directories(const Twine &Path, bool IgnoreExisting) {
+ SmallString<128> PathStorage;
+ StringRef P = Path.toStringRef(PathStorage);
+
+ // Be optimistic and try to create the directory
+ std::error_code EC = create_directory(P, IgnoreExisting);
+ // If we succeeded, or had any error other than the parent not existing, just
+ // return it.
+ if (EC != errc::no_such_file_or_directory)
+ return EC;
- StringRef parent = path::parent_path(p);
- if (!parent.empty()) {
- bool parent_exists;
- if (error_code ec = fs::exists(parent, parent_exists)) return ec;
+ // We failed because of a no_such_file_or_directory, try to create the
+ // parent.
+ StringRef Parent = path::parent_path(P);
+ if (Parent.empty())
+ return EC;
+
+ if ((EC = create_directories(Parent)))
+ return EC;
+
+ return create_directory(P, IgnoreExisting);
+}
- if (!parent_exists)
- if (error_code ec = create_directories(parent, existed)) return ec;
+std::error_code copy_file(const Twine &From, const Twine &To) {
+ int ReadFD, WriteFD;
+ if (std::error_code EC = openFileForRead(From, ReadFD))
+ return EC;
+ if (std::error_code EC = openFileForWrite(To, WriteFD, F_None)) {
+ close(ReadFD);
+ return EC;
}
- return create_directory(p, existed);
+ const size_t BufSize = 4096;
+ char *Buf = new char[BufSize];
+ int BytesRead = 0, BytesWritten = 0;
+ for (;;) {
+ BytesRead = read(ReadFD, Buf, BufSize);
+ if (BytesRead <= 0)
+ break;
+ while (BytesRead) {
+ BytesWritten = write(WriteFD, Buf, BytesRead);
+ if (BytesWritten < 0)
+ break;
+ BytesRead -= BytesWritten;
+ }
+ if (BytesWritten < 0)
+ break;
+ }
+ close(ReadFD);
+ close(WriteFD);
+ delete[] Buf;
+
+ if (BytesRead < 0 || BytesWritten < 0)
+ return std::error_code(errno, std::generic_category());
+ return std::error_code();
}
bool exists(file_status status) {
@@ -777,43 +892,30 @@ bool is_directory(file_status status) {
return status.type() == file_type::directory_file;
}
-error_code is_directory(const Twine &path, bool &result) {
+std::error_code is_directory(const Twine &path, bool &result) {
file_status st;
- if (error_code ec = status(path, st))
+ if (std::error_code ec = status(path, st))
return ec;
result = is_directory(st);
- return error_code::success();
+ return std::error_code();
}
bool is_regular_file(file_status status) {
return status.type() == file_type::regular_file;
}
-error_code is_regular_file(const Twine &path, bool &result) {
+std::error_code is_regular_file(const Twine &path, bool &result) {
file_status st;
- if (error_code ec = status(path, st))
+ if (std::error_code ec = status(path, st))
return ec;
result = is_regular_file(st);
- return error_code::success();
-}
-
-bool is_symlink(file_status status) {
- return status.type() == file_type::symlink_file;
-}
-
-error_code is_symlink(const Twine &path, bool &result) {
- file_status st;
- if (error_code ec = status(path, st))
- return ec;
- result = is_symlink(st);
- return error_code::success();
+ return std::error_code();
}
bool is_other(file_status status) {
return exists(status) &&
!is_regular_file(status) &&
- !is_directory(status) &&
- !is_symlink(status);
+ !is_directory(status);
}
void directory_entry::replace_filename(const Twine &filename, file_status st) {
@@ -824,26 +926,8 @@ void directory_entry::replace_filename(const Twine &filename, file_status st) {
Status = st;
}
-error_code has_magic(const Twine &path, const Twine &magic, bool &result) {
- SmallString<32> MagicStorage;
- StringRef Magic = magic.toStringRef(MagicStorage);
- SmallString<32> Buffer;
-
- if (error_code ec = get_magic(path, Magic.size(), Buffer)) {
- if (ec == errc::value_too_large) {
- // Magic.size() > file_size(Path).
- result = false;
- return error_code::success();
- }
- return ec;
- }
-
- result = Magic == Buffer;
- return error_code::success();
-}
-
/// @brief Identify the magic in magic.
- file_magic identify_magic(StringRef Magic) {
+file_magic identify_magic(StringRef Magic) {
if (Magic.size() < 4)
return file_magic::unknown;
switch ((unsigned char)Magic[0]) {
@@ -943,6 +1027,7 @@ error_code has_magic(const Twine &path, const Twine &magic, bool &result) {
case 0x66: // MPS R4000 Windows
case 0x50: // mc68K
case 0x4c: // 80386 Windows
+ case 0xc4: // ARMNT Windows
if (Magic[1] == 0x01)
return file_magic::coff_object;
@@ -973,56 +1058,21 @@ error_code has_magic(const Twine &path, const Twine &magic, bool &result) {
return file_magic::unknown;
}
-error_code identify_magic(const Twine &path, file_magic &result) {
- SmallString<32> Magic;
- error_code ec = get_magic(path, Magic.capacity(), Magic);
- if (ec && ec != errc::value_too_large)
- return ec;
-
- result = identify_magic(Magic);
- return error_code::success();
-}
-
-namespace {
-error_code remove_all_r(StringRef path, file_type ft, uint32_t &count) {
- if (ft == file_type::directory_file) {
- // This code would be a lot better with exceptions ;/.
- error_code ec;
- directory_iterator i(path, ec);
- if (ec) return ec;
- for (directory_iterator e; i != e; i.increment(ec)) {
- if (ec) return ec;
- file_status st;
- if (error_code ec = i->status(st)) return ec;
- if (error_code ec = remove_all_r(i->path(), st.type(), count)) return ec;
- }
- bool obviously_this_exists;
- if (error_code ec = remove(path, obviously_this_exists)) return ec;
- assert(obviously_this_exists);
- ++count; // Include the directory itself in the items removed.
- } else {
- bool obviously_this_exists;
- if (error_code ec = remove(path, obviously_this_exists)) return ec;
- assert(obviously_this_exists);
- ++count;
- }
-
- return error_code::success();
-}
-} // end unnamed namespace
+std::error_code identify_magic(const Twine &Path, file_magic &Result) {
+ int FD;
+ if (std::error_code EC = openFileForRead(Path, FD))
+ return EC;
-error_code remove_all(const Twine &path, uint32_t &num_removed) {
- SmallString<128> path_storage;
- StringRef p = path.toStringRef(path_storage);
+ char Buffer[32];
+ int Length = read(FD, Buffer, sizeof(Buffer));
+ if (close(FD) != 0 || Length < 0)
+ return std::error_code(errno, std::generic_category());
- file_status fs;
- if (error_code ec = status(path, fs))
- return ec;
- num_removed = 0;
- return remove_all_r(p, fs.type(), num_removed);
+ Result = identify_magic(StringRef(Buffer, Length));
+ return std::error_code();
}
-error_code directory_entry::status(file_status &result) const {
+std::error_code directory_entry::status(file_status &result) const {
return fs::status(Path, result);
}