diff options
Diffstat (limited to 'source/Host/posix')
-rw-r--r-- | source/Host/posix/ConnectionFileDescriptorPosix.cpp | 62 | ||||
-rw-r--r-- | source/Host/posix/FileSystem.cpp | 181 | ||||
-rw-r--r-- | source/Host/posix/HostInfoPosix.cpp | 32 | ||||
-rw-r--r-- | source/Host/posix/HostProcessPosix.cpp | 17 | ||||
-rw-r--r-- | source/Host/posix/LockFilePosix.cpp | 77 | ||||
-rw-r--r-- | source/Host/posix/PipePosix.cpp | 24 |
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 |