aboutsummaryrefslogtreecommitdiff
path: root/source/Host/posix
diff options
context:
space:
mode:
Diffstat (limited to 'source/Host/posix')
-rw-r--r--source/Host/posix/ConnectionFileDescriptorPosix.cpp62
-rw-r--r--source/Host/posix/FileSystem.cpp181
-rw-r--r--source/Host/posix/HostInfoPosix.cpp32
-rw-r--r--source/Host/posix/HostProcessPosix.cpp17
-rw-r--r--source/Host/posix/LockFilePosix.cpp77
-rw-r--r--source/Host/posix/PipePosix.cpp24
6 files changed, 288 insertions, 105 deletions
diff --git a/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/source/Host/posix/ConnectionFileDescriptorPosix.cpp
index fe70c33bf5ae..f12f98c30b44 100644
--- a/source/Host/posix/ConnectionFileDescriptorPosix.cpp
+++ b/source/Host/posix/ConnectionFileDescriptorPosix.cpp
@@ -39,7 +39,6 @@
#include "llvm/ADT/SmallVector.h"
#endif
// Project includes
-#include "lldb/lldb-private-log.h"
#include "lldb/Core/Communication.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/StreamString.h"
@@ -82,6 +81,17 @@ ConnectionFileDescriptor::ConnectionFileDescriptor(int fd, bool owns_fd)
OpenCommandPipe();
}
+ConnectionFileDescriptor::ConnectionFileDescriptor(Socket* socket)
+ : Connection()
+ , m_pipe()
+ , m_mutex(Mutex::eMutexTypeRecursive)
+ , m_shutting_down(false)
+ , m_waiting_for_accept(false)
+ , m_child_processes_inherit(false)
+{
+ InitializeSocket(socket);
+}
+
ConnectionFileDescriptor::~ConnectionFileDescriptor()
{
Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT));
@@ -156,6 +166,14 @@ ConnectionFileDescriptor::Connect(const char *s, Error *error_ptr)
// unix://SOCKNAME
return NamedSocketAccept(s + strlen("unix-accept://"), error_ptr);
}
+ else if (strstr(s, "adb://") == s)
+ {
+ int port = -1;
+ sscanf(s, "adb://%*[^:]:%d", &port);
+ char host_and_port[sizeof("localhost:65535")];
+ snprintf(host_and_port, sizeof(host_and_port), "localhost:%d", port);
+ return ConnectTCP(host_and_port, error_ptr);
+ }
else if (strstr(s, "connect://") == s)
{
return ConnectTCP(s + strlen("connect://"), error_ptr);
@@ -354,6 +372,9 @@ ConnectionFileDescriptor::Disconnect(Error *error_ptr)
if (error_ptr)
*error_ptr = error.Fail() ? error : error2;
+ // Close any pipes we were using for async interrupts
+ m_pipe.Close();
+
m_uri.clear();
m_shutting_down = false;
return status;
@@ -376,8 +397,12 @@ ConnectionFileDescriptor::Read(void *dst, size_t dst_len, uint32_t timeout_usec,
status = eConnectionStatusTimedOut;
return 0;
}
- else if (m_shutting_down)
- return eConnectionStatusError;
+
+ if (m_shutting_down)
+ {
+ status = eConnectionStatusError;
+ return 0;
+ }
status = BytesAvailable(timeout_usec, error_ptr);
if (status != eConnectionStatusSuccess)
@@ -671,8 +696,10 @@ ConnectionFileDescriptor::BytesAvailable(uint32_t timeout_usec, Error *error_ptr
return eConnectionStatusSuccess;
if (have_pipe_fd && FD_ISSET(pipe_fd, FD_SET_DATA(read_fds)))
{
- // We got a command to exit. Read the data from that pipe:
- char buffer[16];
+ // There is an interrupt or exit command in the command pipe
+ // Read the data from that pipe:
+ char buffer[1];
+
ssize_t bytes_read;
do
@@ -684,8 +711,9 @@ ConnectionFileDescriptor::BytesAvailable(uint32_t timeout_usec, Error *error_ptr
{
case 'q':
if (log)
- log->Printf("%p ConnectionFileDescriptor::BytesAvailable() got data: %*s from the command channel.",
- static_cast<void *>(this), static_cast<int>(bytes_read), buffer);
+ log->Printf("%p ConnectionFileDescriptor::BytesAvailable() "
+ "got data: %c from the command channel.",
+ static_cast<void *>(this), buffer[0]);
return eConnectionStatusEndOfFile;
case 'i':
// Interrupt the current read
@@ -759,15 +787,7 @@ ConnectionFileDescriptor::SocketListenAndAccept(const char *s, Error *error_ptr)
if (error.Fail())
return eConnectionStatusError;
- m_write_sp.reset(socket);
- m_read_sp = m_write_sp;
- if (error.Fail())
- {
- return eConnectionStatusError;
- }
- StreamString strm;
- strm.Printf("connect://%s:%u",socket->GetRemoteIPAddress().c_str(), socket->GetRemotePortNumber());
- m_uri.swap(strm.GetString());
+ InitializeSocket(socket);
return eConnectionStatusSuccess;
}
@@ -832,3 +852,13 @@ ConnectionFileDescriptor::SetChildProcessesInherit(bool child_processes_inherit)
{
m_child_processes_inherit = child_processes_inherit;
}
+
+void
+ConnectionFileDescriptor::InitializeSocket(Socket* socket)
+{
+ m_write_sp.reset(socket);
+ m_read_sp = m_write_sp;
+ StreamString strm;
+ strm.Printf("connect://%s:%u",socket->GetRemoteIPAddress().c_str(), socket->GetRemotePortNumber());
+ m_uri.swap(strm.GetString());
+}
diff --git a/source/Host/posix/FileSystem.cpp b/source/Host/posix/FileSystem.cpp
index 571316811142..52698039b46e 100644
--- a/source/Host/posix/FileSystem.cpp
+++ b/source/Host/posix/FileSystem.cpp
@@ -10,8 +10,16 @@
#include "lldb/Host/FileSystem.h"
// C includes
+#include <dirent.h>
+#include <sys/mount.h>
+#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
+#ifdef __linux__
+#include <sys/statfs.h>
+#include <sys/mount.h>
+#include <linux/magic.h>
+#endif
// lldb Includes
#include "lldb/Core/Error.h"
@@ -28,70 +36,91 @@ FileSystem::GetNativePathSyntax()
}
Error
-FileSystem::MakeDirectory(const char *path, uint32_t file_permissions)
+FileSystem::MakeDirectory(const FileSpec &file_spec, uint32_t file_permissions)
{
- Error error;
- if (path && path[0])
+ if (file_spec)
{
- if (::mkdir(path, file_permissions) != 0)
+ Error error;
+ if (::mkdir(file_spec.GetCString(), file_permissions) == -1)
{
error.SetErrorToErrno();
+ errno = 0;
switch (error.GetError())
{
case ENOENT:
{
// Parent directory doesn't exist, so lets make it if we can
- FileSpec spec(path, false);
- if (spec.GetDirectory() && spec.GetFilename())
+ // Make the parent directory and try again
+ FileSpec parent_file_spec{file_spec.GetDirectory().GetCString(), false};
+ error = MakeDirectory(parent_file_spec, file_permissions);
+ if (error.Fail())
+ return error;
+ // Try and make the directory again now that the parent directory was made successfully
+ if (::mkdir(file_spec.GetCString(), file_permissions) == -1)
{
- // Make the parent directory and try again
- Error error2 = MakeDirectory(spec.GetDirectory().GetCString(), file_permissions);
- if (error2.Success())
- {
- // Try and make the directory again now that the parent directory was made successfully
- if (::mkdir(path, file_permissions) == 0)
- error.Clear();
- else
- error.SetErrorToErrno();
- }
+ error.SetErrorToErrno();
+ return error;
}
}
- break;
-
case EEXIST:
{
- FileSpec path_spec(path, false);
- if (path_spec.IsDirectory())
- error.Clear(); // It is a directory and it already exists
+ if (file_spec.IsDirectory())
+ return Error{}; // It is a directory and it already exists
}
- break;
}
}
+ return error;
}
- else
- {
- error.SetErrorString("empty path");
- }
- return error;
+ return Error{"empty path"};
}
Error
-FileSystem::DeleteDirectory(const char *path, bool recurse)
+FileSystem::DeleteDirectory(const FileSpec &file_spec, bool recurse)
{
Error error;
- if (path && path[0])
+ if (file_spec)
{
if (recurse)
{
- StreamString command;
- command.Printf("rm -rf \"%s\"", path);
- int status = ::system(command.GetString().c_str());
- if (status != 0)
- error.SetError(status, eErrorTypeGeneric);
+ // Save all sub directories in a list so we don't recursively call this function
+ // and possibly run out of file descriptors if the directory is too deep.
+ std::vector<FileSpec> sub_directories;
+
+ FileSpec::ForEachItemInDirectory (file_spec.GetCString(), [&error, &sub_directories](FileSpec::FileType file_type, const FileSpec &spec) -> FileSpec::EnumerateDirectoryResult {
+ if (file_type == FileSpec::eFileTypeDirectory)
+ {
+ // Save all directorires and process them after iterating through this directory
+ sub_directories.push_back(spec);
+ }
+ else
+ {
+ // Update sub_spec to point to the current file and delete it
+ error = FileSystem::Unlink(spec);
+ }
+ // If anything went wrong, stop iterating, else process the next file
+ if (error.Fail())
+ return FileSpec::eEnumerateDirectoryResultQuit;
+ else
+ return FileSpec::eEnumerateDirectoryResultNext;
+ });
+
+ if (error.Success())
+ {
+ // Now delete all sub directories with separate calls that aren't
+ // recursively calling into this function _while_ this function is
+ // iterating through the current directory.
+ for (const auto &sub_directory : sub_directories)
+ {
+ error = DeleteDirectory(sub_directory, recurse);
+ if (error.Fail())
+ break;
+ }
+ }
}
- else
+
+ if (error.Success())
{
- if (::rmdir(path) != 0)
+ if (::rmdir(file_spec.GetCString()) != 0)
error.SetErrorToErrno();
}
}
@@ -103,11 +132,11 @@ FileSystem::DeleteDirectory(const char *path, bool recurse)
}
Error
-FileSystem::GetFilePermissions(const char *path, uint32_t &file_permissions)
+FileSystem::GetFilePermissions(const FileSpec &file_spec, uint32_t &file_permissions)
{
Error error;
struct stat file_stats;
- if (::stat(path, &file_stats) == 0)
+ if (::stat(file_spec.GetCString(), &file_stats) == 0)
{
// The bits in "st_mode" currently match the definitions
// for the file mode bits in unix.
@@ -121,10 +150,10 @@ FileSystem::GetFilePermissions(const char *path, uint32_t &file_permissions)
}
Error
-FileSystem::SetFilePermissions(const char *path, uint32_t file_permissions)
+FileSystem::SetFilePermissions(const FileSpec &file_spec, uint32_t file_permissions)
{
Error error;
- if (::chmod(path, file_permissions) != 0)
+ if (::chmod(file_spec.GetCString(), file_permissions) != 0)
error.SetErrorToErrno();
return error;
}
@@ -142,60 +171,72 @@ FileSystem::GetFileExists(const FileSpec &file_spec)
}
Error
-FileSystem::Symlink(const char *src, const char *dst)
+FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst)
{
Error error;
- if (::symlink(dst, src) == -1)
+ if (::link(dst.GetCString(), src.GetCString()) == -1)
error.SetErrorToErrno();
return error;
}
Error
-FileSystem::Unlink(const char *path)
+FileSystem::Symlink(const FileSpec &src, const FileSpec &dst)
{
Error error;
- if (::unlink(path) == -1)
+ if (::symlink(dst.GetCString(), src.GetCString()) == -1)
error.SetErrorToErrno();
return error;
}
Error
-FileSystem::Readlink(const char *path, char *buf, size_t buf_len)
+FileSystem::Unlink(const FileSpec &file_spec)
{
Error error;
- ssize_t count = ::readlink(path, buf, buf_len);
+ if (::unlink(file_spec.GetCString()) == -1)
+ error.SetErrorToErrno();
+ return error;
+}
+
+Error
+FileSystem::Readlink(const FileSpec &src, FileSpec &dst)
+{
+ Error error;
+ char buf[PATH_MAX];
+ ssize_t count = ::readlink(src.GetCString(), buf, sizeof(buf) - 1);
if (count < 0)
error.SetErrorToErrno();
- else if (static_cast<size_t>(count) < (buf_len - 1))
- buf[count] = '\0'; // Success
else
- error.SetErrorString("'buf' buffer is too small to contain link contents");
+ {
+ buf[count] = '\0'; // Success
+ dst.SetFile(buf, false);
+ }
return error;
}
-bool
-FileSystem::CalculateMD5(const FileSpec &file_spec, uint64_t &low, uint64_t &high)
+static bool IsLocal(const struct statfs& info)
{
-#if defined(__APPLE__)
- StreamString md5_cmd_line;
- md5_cmd_line.Printf("md5 -q '%s'", file_spec.GetPath().c_str());
- std::string hash_string;
- Error err = Host::RunShellCommand(md5_cmd_line.GetData(), NULL, NULL, NULL, &hash_string, 60);
- if (err.Fail())
- return false;
- // a correctly formed MD5 is 16-bytes, that is 32 hex digits
- // if the output is any other length it is probably wrong
- if (hash_string.size() != 32)
+#ifdef __linux__
+ #define CIFS_MAGIC_NUMBER 0xFF534D42
+ switch ((uint32_t)info.f_type)
+ {
+ case NFS_SUPER_MAGIC:
+ case SMB_SUPER_MAGIC:
+ case CIFS_MAGIC_NUMBER:
return false;
- std::string part1(hash_string, 0, 16);
- std::string part2(hash_string, 16);
- const char *part1_cstr = part1.c_str();
- const char *part2_cstr = part2.c_str();
- high = ::strtoull(part1_cstr, NULL, 16);
- low = ::strtoull(part2_cstr, NULL, 16);
- return true;
+ default:
+ return true;
+ }
#else
- // your own MD5 implementation here
- return false;
+ return (info.f_flags & MNT_LOCAL) != 0;
#endif
}
+
+bool
+FileSystem::IsLocal(const FileSpec &spec)
+{
+ struct statfs statfs_info;
+ std::string path (spec.GetPath());
+ if (statfs(path.c_str(), &statfs_info) == 0)
+ return ::IsLocal(statfs_info);
+ return false;
+}
diff --git a/source/Host/posix/HostInfoPosix.cpp b/source/Host/posix/HostInfoPosix.cpp
index 018d423ee9d3..c04db71e1b81 100644
--- a/source/Host/posix/HostInfoPosix.cpp
+++ b/source/Host/posix/HostInfoPosix.cpp
@@ -8,7 +8,6 @@
//===----------------------------------------------------------------------===//
#include "lldb/lldb-python.h"
-
#include "lldb/Core/Log.h"
#include "lldb/Host/posix/HostInfoPosix.h"
@@ -17,6 +16,7 @@
#include <grp.h>
#include <limits.h>
+#include <mutex>
#include <netdb.h>
#include <pwd.h>
#include <sys/types.h>
@@ -47,9 +47,31 @@ HostInfoPosix::GetHostname(std::string &s)
return false;
}
+#ifdef __ANDROID_NDK__
+#include <android/api-level.h>
+#endif
+#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
+#define USE_GETPWUID
+#endif
+
+#ifdef USE_GETPWUID
+static std::mutex s_getpwuid_lock;
+#endif
+
const char *
HostInfoPosix::LookupUserName(uint32_t uid, std::string &user_name)
{
+#ifdef USE_GETPWUID
+ // getpwuid_r is missing from android-9
+ // make getpwuid thread safe with a mutex
+ std::lock_guard<std::mutex> lock(s_getpwuid_lock);
+ struct passwd *user_info_ptr = ::getpwuid(uid);
+ if (user_info_ptr)
+ {
+ user_name.assign(user_info_ptr->pw_name);
+ return user_name.c_str();
+ }
+#else
struct passwd user_info;
struct passwd *user_info_ptr = &user_info;
char user_buffer[PATH_MAX];
@@ -62,8 +84,9 @@ HostInfoPosix::LookupUserName(uint32_t uid, std::string &user_name)
return user_name.c_str();
}
}
+#endif
user_name.clear();
- return NULL;
+ return nullptr;
}
const char *
@@ -153,11 +176,8 @@ HostInfoPosix::ComputeSupportExeDirectory(FileSpec &file_spec)
char *lib_pos = ::strstr(raw_path, "/lib");
if (lib_pos != nullptr)
{
- // First terminate the raw path at the start of lib.
- *lib_pos = '\0';
-
// Now write in bin in place of lib.
- ::strncpy(lib_pos, "/bin", PATH_MAX - (lib_pos - raw_path));
+ ::snprintf(lib_pos, PATH_MAX - (lib_pos - raw_path), "/bin");
if (log)
log->Printf("Host::%s() derived the bin path as: %s", __FUNCTION__, raw_path);
diff --git a/source/Host/posix/HostProcessPosix.cpp b/source/Host/posix/HostProcessPosix.cpp
index 8e19add048ee..5761a79da27f 100644
--- a/source/Host/posix/HostProcessPosix.cpp
+++ b/source/Host/posix/HostProcessPosix.cpp
@@ -69,28 +69,25 @@ Error HostProcessPosix::GetMainModule(FileSpec &file_spec) const
// Use special code here because proc/[pid]/exe is a symbolic link.
char link_path[PATH_MAX];
- char exe_path[PATH_MAX] = "";
- if (snprintf (link_path, PATH_MAX, "/proc/%" PRIu64 "/exe", m_process) <= 0)
+ if (snprintf(link_path, PATH_MAX, "/proc/%" PRIu64 "/exe", m_process) != 1)
{
error.SetErrorString("Unable to build /proc/<pid>/exe string");
return error;
}
- error = FileSystem::Readlink(link_path, exe_path, llvm::array_lengthof(exe_path));
+ error = FileSystem::Readlink(FileSpec{link_path, false}, file_spec);
if (!error.Success())
return error;
- const ssize_t len = strlen(exe_path);
// If the binary has been deleted, the link name has " (deleted)" appended.
// Remove if there.
- static const ssize_t deleted_len = strlen(" (deleted)");
- if (len > deleted_len &&
- !strcmp(exe_path + len - deleted_len, " (deleted)"))
+ if (file_spec.GetFilename().GetStringRef().endswith(" (deleted)"))
{
- exe_path[len - deleted_len] = 0;
+ const char *filename = file_spec.GetFilename().GetCString();
+ static const size_t deleted_len = strlen(" (deleted)");
+ const size_t len = file_spec.GetFilename().GetLength();
+ file_spec.GetFilename().SetCStringWithLength(filename, len - deleted_len);
}
-
- file_spec.SetFile(exe_path, false);
return error;
}
diff --git a/source/Host/posix/LockFilePosix.cpp b/source/Host/posix/LockFilePosix.cpp
new file mode 100644
index 000000000000..e52b648799b7
--- /dev/null
+++ b/source/Host/posix/LockFilePosix.cpp
@@ -0,0 +1,77 @@
+//===-- LockFilePosix.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Host/posix/LockFilePosix.h"
+
+#include <fcntl.h>
+
+using namespace lldb;
+using namespace lldb_private;
+
+namespace
+{
+
+Error fileLock (int fd, int cmd, int lock_type, const uint64_t start, const uint64_t len)
+{
+ struct flock fl;
+
+ fl.l_type = lock_type;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = start;
+ fl.l_len = len;
+ fl.l_pid = ::getpid ();
+
+ Error error;
+ if (::fcntl (fd, cmd, &fl) == -1)
+ error.SetErrorToErrno ();
+
+ return error;
+}
+
+} // namespace
+
+LockFilePosix::LockFilePosix (int fd)
+ : LockFileBase (fd)
+{
+}
+
+LockFilePosix::~LockFilePosix ()
+{
+ Unlock ();
+}
+
+Error
+LockFilePosix::DoWriteLock (const uint64_t start, const uint64_t len)
+{
+ return fileLock (m_fd, F_SETLKW, F_WRLCK, start, len);
+}
+
+Error
+LockFilePosix::DoTryWriteLock (const uint64_t start, const uint64_t len)
+{
+ return fileLock (m_fd, F_SETLK, F_WRLCK, start, len);
+}
+
+Error
+LockFilePosix::DoReadLock (const uint64_t start, const uint64_t len)
+{
+ return fileLock (m_fd, F_SETLKW, F_RDLCK, start, len);
+}
+
+Error
+LockFilePosix::DoTryReadLock (const uint64_t start, const uint64_t len)
+{
+ return fileLock (m_fd, F_SETLK, F_RDLCK, start, len);
+}
+
+Error
+LockFilePosix::DoUnlock ()
+{
+ return fileLock (m_fd, F_SETLK, F_UNLCK, m_start, m_len);
+}
diff --git a/source/Host/posix/PipePosix.cpp b/source/Host/posix/PipePosix.cpp
index 1650f1e7979b..0ed319facf93 100644
--- a/source/Host/posix/PipePosix.cpp
+++ b/source/Host/posix/PipePosix.cpp
@@ -129,9 +129,27 @@ SelectIO(int handle, bool is_read, const std::function<Error(bool&)> &io_handler
}
PipePosix::PipePosix()
+ : m_fds{
+ PipePosix::kInvalidDescriptor,
+ PipePosix::kInvalidDescriptor
+ } {}
+
+PipePosix::PipePosix(int read_fd, int write_fd)
+ : m_fds{read_fd, write_fd} {}
+
+PipePosix::PipePosix(PipePosix &&pipe_posix)
+ : PipeBase{std::move(pipe_posix)},
+ m_fds{
+ pipe_posix.ReleaseReadFileDescriptor(),
+ pipe_posix.ReleaseWriteFileDescriptor()
+ } {}
+
+PipePosix &PipePosix::operator=(PipePosix &&pipe_posix)
{
- m_fds[READ] = PipePosix::kInvalidDescriptor;
- m_fds[WRITE] = PipePosix::kInvalidDescriptor;
+ PipeBase::operator=(std::move(pipe_posix));
+ m_fds[READ] = pipe_posix.ReleaseReadFileDescriptor();
+ m_fds[WRITE] = pipe_posix.ReleaseWriteFileDescriptor();
+ return *this;
}
PipePosix::~PipePosix()
@@ -317,7 +335,7 @@ PipePosix::Close()
Error
PipePosix::Delete(llvm::StringRef name)
{
- return FileSystem::Unlink(name.data());
+ return FileSystem::Unlink(FileSpec{name.data(), true});
}
bool