summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Support
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2017-02-21 20:55:47 +0000
committerZachary Turner <zturner@google.com>2017-02-21 20:55:47 +0000
commit392ed9d342229b95d77a5ec6310e10093f73e75c (patch)
tree2b223846e02b9c38cebf8b5b61092040cc73bf3a /llvm/lib/Support
parentccee0e0c055327d202e48b5dfeb06cb3716e49d0 (diff)
downloadbcm5719-llvm-392ed9d342229b95d77a5ec6310e10093f73e75c.tar.gz
bcm5719-llvm-392ed9d342229b95d77a5ec6310e10093f73e75c.zip
[Support] Add a function to check if a file resides locally.
Differential Revision: https://reviews.llvm.org/D30010 llvm-svn: 295768
Diffstat (limited to 'llvm/lib/Support')
-rw-r--r--llvm/lib/Support/MemoryBuffer.cpp34
-rw-r--r--llvm/lib/Support/Unix/Path.inc66
-rw-r--r--llvm/lib/Support/Windows/Path.inc74
3 files changed, 153 insertions, 21 deletions
diff --git a/llvm/lib/Support/MemoryBuffer.cpp b/llvm/lib/Support/MemoryBuffer.cpp
index a3a18c9283c..227e792d83d 100644
--- a/llvm/lib/Support/MemoryBuffer.cpp
+++ b/llvm/lib/Support/MemoryBuffer.cpp
@@ -103,7 +103,7 @@ public:
static ErrorOr<std::unique_ptr<MemoryBuffer>>
getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize,
- uint64_t Offset, bool RequiresNullTerminator, bool IsVolatileSize);
+ uint64_t Offset, bool RequiresNullTerminator, bool IsVolatile);
std::unique_ptr<MemoryBuffer>
MemoryBuffer::getMemBuffer(StringRef InputData, StringRef BufferName,
@@ -178,8 +178,8 @@ MemoryBuffer::getFileOrSTDIN(const Twine &Filename, int64_t FileSize,
ErrorOr<std::unique_ptr<MemoryBuffer>>
MemoryBuffer::getFileSlice(const Twine &FilePath, uint64_t MapSize,
- uint64_t Offset) {
- return getFileAux(FilePath, -1, MapSize, Offset, false, false);
+ uint64_t Offset, bool IsVolatile) {
+ return getFileAux(FilePath, -1, MapSize, Offset, false, IsVolatile);
}
@@ -254,19 +254,19 @@ getMemoryBufferForStream(int FD, const Twine &BufferName) {
ErrorOr<std::unique_ptr<MemoryBuffer>>
MemoryBuffer::getFile(const Twine &Filename, int64_t FileSize,
- bool RequiresNullTerminator, bool IsVolatileSize) {
+ bool RequiresNullTerminator, bool IsVolatile) {
return getFileAux(Filename, FileSize, FileSize, 0,
- RequiresNullTerminator, IsVolatileSize);
+ RequiresNullTerminator, IsVolatile);
}
static ErrorOr<std::unique_ptr<MemoryBuffer>>
getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize,
uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator,
- bool IsVolatileSize);
+ bool IsVolatile);
static ErrorOr<std::unique_ptr<MemoryBuffer>>
getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize,
- uint64_t Offset, bool RequiresNullTerminator, bool IsVolatileSize) {
+ uint64_t Offset, bool RequiresNullTerminator, bool IsVolatile) {
int FD;
std::error_code EC = sys::fs::openFileForRead(Filename, FD);
if (EC)
@@ -274,7 +274,7 @@ getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize,
ErrorOr<std::unique_ptr<MemoryBuffer>> Ret =
getOpenFileImpl(FD, Filename, FileSize, MapSize, Offset,
- RequiresNullTerminator, IsVolatileSize);
+ RequiresNullTerminator, IsVolatile);
close(FD);
return Ret;
}
@@ -285,11 +285,11 @@ static bool shouldUseMmap(int FD,
off_t Offset,
bool RequiresNullTerminator,
int PageSize,
- bool IsVolatileSize) {
+ bool IsVolatile) {
// mmap may leave the buffer without null terminator if the file size changed
// by the time the last page is mapped in, so avoid it if the file size is
// likely to change.
- if (IsVolatileSize)
+ if (IsVolatile)
return false;
// We don't use mmap for small files because this can severely fragment our
@@ -300,7 +300,6 @@ static bool shouldUseMmap(int FD,
if (!RequiresNullTerminator)
return true;
-
// If we don't know the file size, use fstat to find out. fstat on an open
// file descriptor is cheaper than stat on a random path.
// FIXME: this chunk of code is duplicated, but it avoids a fstat when
@@ -338,7 +337,7 @@ static bool shouldUseMmap(int FD,
static ErrorOr<std::unique_ptr<MemoryBuffer>>
getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize,
uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator,
- bool IsVolatileSize) {
+ bool IsVolatile) {
static int PageSize = sys::Process::getPageSize();
// Default is to map the full file.
@@ -365,7 +364,7 @@ getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize,
}
if (shouldUseMmap(FD, FileSize, MapSize, Offset, RequiresNullTerminator,
- PageSize, IsVolatileSize)) {
+ PageSize, IsVolatile)) {
std::error_code EC;
std::unique_ptr<MemoryBuffer> Result(
new (NamedBufferAlloc(Filename))
@@ -415,17 +414,16 @@ getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize,
ErrorOr<std::unique_ptr<MemoryBuffer>>
MemoryBuffer::getOpenFile(int FD, const Twine &Filename, uint64_t FileSize,
- bool RequiresNullTerminator, bool IsVolatileSize) {
+ bool RequiresNullTerminator, bool IsVolatile) {
return getOpenFileImpl(FD, Filename, FileSize, FileSize, 0,
- RequiresNullTerminator, IsVolatileSize);
+ RequiresNullTerminator, IsVolatile);
}
ErrorOr<std::unique_ptr<MemoryBuffer>>
MemoryBuffer::getOpenFileSlice(int FD, const Twine &Filename, uint64_t MapSize,
- int64_t Offset) {
+ int64_t Offset, bool IsVolatile) {
assert(MapSize != uint64_t(-1));
- return getOpenFileImpl(FD, Filename, -1, MapSize, Offset, false,
- /*IsVolatileSize*/ false);
+ return getOpenFileImpl(FD, Filename, -1, MapSize, Offset, false, IsVolatile);
}
ErrorOr<std::unique_ptr<MemoryBuffer>> MemoryBuffer::getSTDIN() {
diff --git a/llvm/lib/Support/Unix/Path.inc b/llvm/lib/Support/Unix/Path.inc
index 10e21af5371..94cb6817e40 100644
--- a/llvm/lib/Support/Unix/Path.inc
+++ b/llvm/lib/Support/Unix/Path.inc
@@ -65,23 +65,32 @@
#endif
#include <sys/types.h>
-#if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__)
+#if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && \
+ !defined(__linux__)
#include <sys/statvfs.h>
#define STATVFS statvfs
+#define FSTATVFS fstatvfs
#define STATVFS_F_FRSIZE(vfs) vfs.f_frsize
#else
-#ifdef __OpenBSD__
+#if defined(__OpenBSD__) || defined(__FreeBSD__)
#include <sys/param.h>
#include <sys/mount.h>
-#elif defined(__ANDROID__)
+#elif defined(__linux__)
+#include <linux/magic.h>
#include <sys/vfs.h>
#else
#include <sys/mount.h>
#endif
#define STATVFS statfs
+#define FSTATVFS fstatfs
#define STATVFS_F_FRSIZE(vfs) static_cast<uint64_t>(vfs.f_bsize)
#endif
+#if defined(__NetBSD__)
+#define STATVFS_F_FLAG(vfs) (vfs).f_flag
+#else
+#define STATVFS_F_FLAG(vfs) (vfs).f_flags
+#endif
using namespace llvm;
@@ -335,6 +344,40 @@ std::error_code remove(const Twine &path, bool IgnoreNonExisting) {
return std::error_code();
}
+static bool is_local_impl(struct STATVFS &Vfs) {
+#if defined(__linux__)
+ constexpr uint32_t CIFS_MAGIC_NUMBER = 0xFF534D42;
+ switch ((uint32_t)Vfs.f_type) {
+ case NFS_SUPER_MAGIC:
+ case SMB_SUPER_MAGIC:
+ case CIFS_MAGIC_NUMBER:
+ return false;
+ default:
+ return true;
+ }
+#else
+ return !!(STATVFS_F_FLAG(Vfs) & MNT_LOCAL);
+#endif
+}
+
+std::error_code is_local(const Twine &Path, bool &Result) {
+ struct STATVFS Vfs;
+ if (::STATVFS(Path.str().c_str(), &Vfs))
+ return std::error_code(errno, std::generic_category());
+
+ Result = is_local_impl(Vfs);
+ return std::error_code();
+}
+
+std::error_code is_local(int FD, bool &Result) {
+ struct STATVFS Vfs;
+ if (::FSTATVFS(FD, &Vfs))
+ return std::error_code(errno, std::generic_category());
+
+ Result = is_local_impl(Vfs);
+ return std::error_code();
+}
+
std::error_code rename(const Twine &from, const Twine &to) {
// Get arguments.
SmallString<128> from_storage;
@@ -491,6 +534,23 @@ std::error_code mapped_file_region::init(int FD, uint64_t Offset,
int flags = (Mode == readwrite) ? MAP_SHARED : MAP_PRIVATE;
int prot = (Mode == readonly) ? PROT_READ : (PROT_READ | PROT_WRITE);
+#if defined(__APPLE__)
+//----------------------------------------------------------------------
+// Newer versions of MacOSX have a flag that will allow us to read from
+// binaries whose code signature is invalid without crashing by using
+// the MAP_RESILIENT_CODESIGN flag. Also if a file from removable media
+// is mapped we can avoid crashing and return zeroes to any pages we try
+// to read if the media becomes unavailable by using the
+// MAP_RESILIENT_MEDIA flag.
+//----------------------------------------------------------------------
+#if defined(MAP_RESILIENT_CODESIGN)
+ flags |= MAP_RESILIENT_CODESIGN;
+#endif
+#if defined(MAP_RESILIENT_MEDIA)
+ flags |= MAP_RESILIENT_MEDIA;
+#endif
+#endif // #if defined (__APPLE__)
+
Mapping = ::mmap(nullptr, Size, prot, flags, FD, Offset);
if (Mapping == MAP_FAILED)
return std::error_code(errno, std::generic_category());
diff --git a/llvm/lib/Support/Windows/Path.inc b/llvm/lib/Support/Windows/Path.inc
index 3597b551098..d9e1ff4ffe4 100644
--- a/llvm/lib/Support/Windows/Path.inc
+++ b/llvm/lib/Support/Windows/Path.inc
@@ -277,6 +277,80 @@ std::error_code remove(const Twine &path, bool IgnoreNonExisting) {
return std::error_code();
}
+static std::error_code is_local_internal(SmallVectorImpl<wchar_t> &Path,
+ bool &Result) {
+ SmallVector<wchar_t, 128> VolumePath;
+ size_t Len = 128;
+ while (true) {
+ VolumePath.resize(Len);
+ BOOL Success =
+ ::GetVolumePathNameW(Path.data(), VolumePath.data(), VolumePath.size());
+
+ if (Success)
+ break;
+
+ DWORD Err = ::GetLastError();
+ if (Err != ERROR_INSUFFICIENT_BUFFER)
+ return mapWindowsError(Err);
+
+ Len *= 2;
+ }
+ // If the output buffer has exactly enough space for the path name, but not
+ // the null terminator, it will leave the output unterminated. Push a null
+ // terminator onto the end to ensure that this never happens.
+ VolumePath.push_back(L'\0');
+ VolumePath.set_size(wcslen(VolumePath.data()));
+ const wchar_t *P = VolumePath.data();
+
+ UINT Type = ::GetDriveTypeW(P);
+ switch (Type) {
+ case DRIVE_FIXED:
+ Result = true;
+ return std::error_code();
+ case DRIVE_REMOTE:
+ case DRIVE_CDROM:
+ case DRIVE_RAMDISK:
+ case DRIVE_REMOVABLE:
+ Result = false;
+ return std::error_code();
+ default:
+ return make_error_code(errc::no_such_file_or_directory);
+ }
+ llvm_unreachable("Unreachable!");
+}
+
+std::error_code is_local(const Twine &path, bool &result) {
+ if (!llvm::sys::fs::exists(path) || !llvm::sys::path::has_root_path(path))
+ return make_error_code(errc::no_such_file_or_directory);
+
+ SmallString<128> Storage;
+ StringRef P = path.toStringRef(Storage);
+
+ // Convert to utf-16.
+ SmallVector<wchar_t, 128> WidePath;
+ if (std::error_code ec = widenPath(P, WidePath))
+ return ec;
+ return is_local_internal(WidePath, result);
+}
+
+std::error_code is_local(int FD, bool &Result) {
+ SmallVector<wchar_t, 128> FinalPath;
+ HANDLE Handle = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
+
+ size_t Len = 128;
+ do {
+ FinalPath.reserve(Len);
+ Len = ::GetFinalPathNameByHandleW(Handle, FinalPath.data(),
+ FinalPath.capacity() - 1, VOLUME_NAME_NT);
+ if (Len == 0)
+ return mapWindowsError(::GetLastError());
+ } while (Len > FinalPath.capacity());
+
+ FinalPath.set_size(Len);
+
+ return is_local_internal(FinalPath, Result);
+}
+
std::error_code rename(const Twine &from, const Twine &to) {
// Convert to utf-16.
SmallVector<wchar_t, 128> wide_from;
OpenPOWER on IntegriCloud