summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/Support/Unix/Path.inc
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/Support/Unix/Path.inc')
-rw-r--r--contrib/llvm/lib/Support/Unix/Path.inc137
1 files changed, 130 insertions, 7 deletions
diff --git a/contrib/llvm/lib/Support/Unix/Path.inc b/contrib/llvm/lib/Support/Unix/Path.inc
index d85c37a..84aafcb 100644
--- a/contrib/llvm/lib/Support/Unix/Path.inc
+++ b/contrib/llvm/lib/Support/Unix/Path.inc
@@ -25,6 +25,9 @@
#if HAVE_FCNTL_H
#include <fcntl.h>
#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
@@ -47,6 +50,7 @@
#ifdef __APPLE__
#include <mach-o/dyld.h>
+#include <sys/attr.h>
#endif
// Both stdio.h and cstdio are included via different pathes and
@@ -60,6 +64,25 @@
# define PATH_MAX 4096
#endif
+#include <sys/types.h>
+#if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__)
+#include <sys/statvfs.h>
+#define STATVFS statvfs
+#define STATVFS_F_FRSIZE(vfs) vfs.f_frsize
+#else
+#ifdef __OpenBSD__
+#include <sys/param.h>
+#include <sys/mount.h>
+#elif defined(__ANDROID__)
+#include <sys/vfs.h>
+#else
+#include <sys/mount.h>
+#endif
+#define STATVFS statfs
+#define STATVFS_F_FRSIZE(vfs) static_cast<uint64_t>(vfs.f_bsize)
+#endif
+
+
using namespace llvm;
namespace llvm {
@@ -70,7 +93,7 @@ namespace fs {
defined(__linux__) || defined(__CYGWIN__) || defined(__DragonFly__)
static int
test_dir(char ret[PATH_MAX], const char *dir, const char *bin)
-{
+{
struct stat sb;
char fullpath[PATH_MAX];
@@ -174,6 +197,12 @@ std::string getMainExecutable(const char *argv0, void *MainAddr) {
return "";
}
+TimeValue file_status::getLastAccessedTime() const {
+ TimeValue Ret;
+ Ret.fromEpochTime(fs_st_atime);
+ return Ret;
+}
+
TimeValue file_status::getLastModificationTime() const {
TimeValue Ret;
Ret.fromEpochTime(fs_st_mtime);
@@ -184,6 +213,18 @@ UniqueID file_status::getUniqueID() const {
return UniqueID(fs_st_dev, fs_st_ino);
}
+ErrorOr<space_info> disk_space(const Twine &Path) {
+ struct STATVFS Vfs;
+ if (::STATVFS(Path.str().c_str(), &Vfs))
+ return std::error_code(errno, std::generic_category());
+ auto FrSize = STATVFS_F_FRSIZE(Vfs);
+ space_info SpaceInfo;
+ SpaceInfo.capacity = static_cast<uint64_t>(Vfs.f_blocks) * FrSize;
+ SpaceInfo.free = static_cast<uint64_t>(Vfs.f_bfree) * FrSize;
+ SpaceInfo.available = static_cast<uint64_t>(Vfs.f_bavail) * FrSize;
+ return SpaceInfo;
+}
+
std::error_code current_path(SmallVectorImpl<char> &result) {
result.clear();
@@ -373,8 +414,9 @@ static std::error_code fillStatus(int StatRet, const struct stat &Status,
perms Perms = static_cast<perms>(Status.st_mode);
Result =
- file_status(Type, Perms, Status.st_dev, Status.st_ino, Status.st_mtime,
- Status.st_uid, Status.st_gid, Status.st_size);
+ file_status(Type, Perms, Status.st_dev, Status.st_ino, Status.st_atime,
+ Status.st_mtime, Status.st_uid, Status.st_gid,
+ Status.st_size);
return std::error_code();
}
@@ -506,13 +548,47 @@ std::error_code detail::directory_iterator_increment(detail::DirIterState &it) {
return std::error_code();
}
-std::error_code openFileForRead(const Twine &Name, int &ResultFD) {
+#if !defined(F_GETPATH)
+static bool hasProcSelfFD() {
+ // If we have a /proc filesystem mounted, we can quickly establish the
+ // real name of the file with readlink
+ static const bool Result = (::access("/proc/self/fd", R_OK) == 0);
+ return Result;
+}
+#endif
+
+std::error_code openFileForRead(const Twine &Name, int &ResultFD,
+ SmallVectorImpl<char> *RealPath) {
SmallString<128> Storage;
StringRef P = Name.toNullTerminatedStringRef(Storage);
while ((ResultFD = open(P.begin(), O_RDONLY)) < 0) {
if (errno != EINTR)
return std::error_code(errno, std::generic_category());
}
+ // Attempt to get the real name of the file, if the user asked
+ if(!RealPath)
+ return std::error_code();
+ RealPath->clear();
+#if defined(F_GETPATH)
+ // When F_GETPATH is availble, it is the quickest way to get
+ // the real path name.
+ char Buffer[MAXPATHLEN];
+ if (::fcntl(ResultFD, F_GETPATH, Buffer) != -1)
+ RealPath->append(Buffer, Buffer + strlen(Buffer));
+#else
+ char Buffer[PATH_MAX];
+ if (hasProcSelfFD()) {
+ char ProcPath[64];
+ snprintf(ProcPath, sizeof(ProcPath), "/proc/self/fd/%d", ResultFD);
+ ssize_t CharCount = ::readlink(ProcPath, Buffer, sizeof(Buffer));
+ if (CharCount > 0)
+ RealPath->append(Buffer, Buffer + CharCount);
+ } else {
+ // Use ::realpath to get the real path name
+ if (::realpath(P.begin(), Buffer) != nullptr)
+ RealPath->append(Buffer, Buffer + strlen(Buffer));
+ }
+#endif
return std::error_code();
}
@@ -546,6 +622,53 @@ std::error_code openFileForWrite(const Twine &Name, int &ResultFD,
return std::error_code();
}
+std::error_code getPathFromOpenFD(int FD, SmallVectorImpl<char> &ResultPath) {
+ if (FD < 0)
+ return make_error_code(errc::bad_file_descriptor);
+
+#if defined(F_GETPATH)
+ // When F_GETPATH is availble, it is the quickest way to get
+ // the path from a file descriptor.
+ ResultPath.reserve(MAXPATHLEN);
+ if (::fcntl(FD, F_GETPATH, ResultPath.begin()) == -1)
+ return std::error_code(errno, std::generic_category());
+
+ ResultPath.set_size(strlen(ResultPath.begin()));
+#else
+ // If we have a /proc filesystem mounted, we can quickly establish the
+ // real name of the file with readlink. Otherwise, we don't know how to
+ // get the filename from a file descriptor. Give up.
+ if (!fs::hasProcSelfFD())
+ return make_error_code(errc::function_not_supported);
+
+ ResultPath.reserve(PATH_MAX);
+ char ProcPath[64];
+ snprintf(ProcPath, sizeof(ProcPath), "/proc/self/fd/%d", FD);
+ ssize_t CharCount = ::readlink(ProcPath, ResultPath.begin(), ResultPath.capacity());
+ if (CharCount < 0)
+ return std::error_code(errno, std::generic_category());
+
+ // Was the filename truncated?
+ if (static_cast<size_t>(CharCount) == ResultPath.capacity()) {
+ // Use lstat to get the size of the filename
+ struct stat sb;
+ if (::lstat(ProcPath, &sb) < 0)
+ return std::error_code(errno, std::generic_category());
+
+ ResultPath.reserve(sb.st_size + 1);
+ CharCount = ::readlink(ProcPath, ResultPath.begin(), ResultPath.capacity());
+ if (CharCount < 0)
+ return std::error_code(errno, std::generic_category());
+
+ // Test for race condition: did the link size change?
+ if (CharCount > sb.st_size)
+ return std::error_code(ENAMETOOLONG, std::generic_category());
+ }
+ ResultPath.set_size(static_cast<size_t>(CharCount));
+#endif
+ return std::error_code();
+}
+
} // end namespace fs
namespace path {
@@ -586,12 +709,12 @@ static bool getDarwinConfDir(bool TempDir, SmallVectorImpl<char> &Result) {
}
static bool getUserCacheDir(SmallVectorImpl<char> &Result) {
- // First try using XDS_CACHE_HOME env variable,
+ // First try using XDG_CACHE_HOME env variable,
// as specified in XDG Base Directory Specification at
// http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
- if (const char *XdsCacheDir = std::getenv("XDS_CACHE_HOME")) {
+ if (const char *XdgCacheDir = std::getenv("XDG_CACHE_HOME")) {
Result.clear();
- Result.append(XdsCacheDir, XdsCacheDir + strlen(XdsCacheDir));
+ Result.append(XdgCacheDir, XdgCacheDir + strlen(XdgCacheDir));
return true;
}
OpenPOWER on IntegriCloud