summaryrefslogtreecommitdiffstats
path: root/lldb/source/Host/common
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Host/common')
-rw-r--r--lldb/source/Host/common/File.cpp109
-rw-r--r--lldb/source/Host/common/FileSpec.cpp135
-rw-r--r--lldb/source/Host/common/Host.cpp172
3 files changed, 410 insertions, 6 deletions
diff --git a/lldb/source/Host/common/File.cpp b/lldb/source/Host/common/File.cpp
index 343312fb484..ec33bca4905 100644
--- a/lldb/source/Host/common/File.cpp
+++ b/lldb/source/Host/common/File.cpp
@@ -83,6 +83,20 @@ File::File(const char *path, uint32_t options, uint32_t permissions) :
Open (path, options, permissions);
}
+File::File (const FileSpec& filespec,
+ uint32_t options,
+ uint32_t permissions) :
+ m_descriptor (kInvalidDescriptor),
+ m_stream (kInvalidStream),
+ m_options (0),
+ m_owned (false)
+{
+ if (filespec)
+ {
+ Open (filespec.GetPath().c_str(), options, permissions);
+ }
+}
+
File::File (const File &rhs) :
m_descriptor (kInvalidDescriptor),
m_stream (kInvalidStream),
@@ -261,6 +275,53 @@ File::Open (const char *path, uint32_t options, uint32_t permissions)
return error;
}
+uint32_t
+File::GetPermissions (const char *path, Error &error)
+{
+ if (path && path[0])
+ {
+ struct stat file_stats;
+ if (::stat (path, &file_stats) == -1)
+ error.SetErrorToErrno();
+ else
+ {
+ error.Clear();
+ return file_stats.st_mode; // All bits from lldb_private::File::Permissions match those in POSIX mode bits
+ }
+ }
+ else
+ {
+ if (path)
+ error.SetErrorString ("invalid path");
+ else
+ error.SetErrorString ("empty path");
+ }
+ return 0;
+}
+
+uint32_t
+File::GetPermissions(Error &error) const
+{
+ int fd = GetDescriptor();
+ if (fd != kInvalidDescriptor)
+ {
+ struct stat file_stats;
+ if (::fstat (fd, &file_stats) == -1)
+ error.SetErrorToErrno();
+ else
+ {
+ error.Clear();
+ return file_stats.st_mode; // All bits from lldb_private::File::Permissions match those in POSIX mode bits
+ }
+ }
+ else
+ {
+ error.SetErrorString ("invalid file descriptor");
+ }
+ return 0;
+}
+
+
Error
File::Close ()
{
@@ -755,3 +816,51 @@ File::PrintfVarArg (const char *format, va_list args)
}
return result;
}
+
+mode_t
+File::ConvertOpenOptionsForPOSIXOpen (uint32_t open_options)
+{
+ mode_t mode = 0;
+ if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite)
+ mode |= O_RDWR;
+ else if (open_options & eOpenOptionWrite)
+ mode |= O_WRONLY;
+
+ if (open_options & eOpenOptionAppend)
+ mode |= O_APPEND;
+
+ if (open_options & eOpenOptionTruncate)
+ mode |= O_TRUNC;
+
+ if (open_options & eOpenOptionNonBlocking)
+ mode |= O_NONBLOCK;
+
+ if (open_options & eOpenOptionCanCreateNewOnly)
+ mode |= O_CREAT | O_EXCL;
+ else if (open_options & eOpenOptionCanCreate)
+ mode |= O_CREAT;
+
+ return mode;
+}
+
+#define O_RDONLY 0x0000 /* open for reading only */
+#define O_WRONLY 0x0001 /* open for writing only */
+#define O_RDWR 0x0002 /* open for reading and writing */
+#define O_ACCMODE 0x0003 /* mask for above modes */
+#define O_NONBLOCK 0x0004 /* no delay */
+#define O_APPEND 0x0008 /* set append mode */
+#define O_SYNC 0x0080 /* synch I/O file integrity */
+#define O_SHLOCK 0x0010 /* open with shared file lock */
+#define O_EXLOCK 0x0020 /* open with exclusive file lock */
+#define O_ASYNC 0x0040 /* signal pgrp when data ready */
+#define O_FSYNC O_SYNC /* source compatibility: do not use */
+#define O_NOFOLLOW 0x0100 /* don't follow symlinks */
+#define O_CREAT 0x0200 /* create if nonexistant */
+#define O_TRUNC 0x0400 /* truncate to zero length */
+#define O_EXCL 0x0800 /* error if already exists */
+#define O_EVTONLY 0x8000 /* descriptor requested for event notifications only */
+#define O_NOCTTY 0x20000 /* don't assign controlling terminal */
+#define O_DIRECTORY 0x100000
+#define O_SYMLINK 0x200000 /* allow open of a symlink */
+#define O_DSYNC 0x400000 /* synch I/O data integrity */
+#define O_CLOEXEC 0x1000000 /* implicitly set FD_CLOEXEC */
diff --git a/lldb/source/Host/common/FileSpec.cpp b/lldb/source/Host/common/FileSpec.cpp
index 0bf7681aa48..66818453bc0 100644
--- a/lldb/source/Host/common/FileSpec.cpp
+++ b/lldb/source/Host/common/FileSpec.cpp
@@ -29,6 +29,7 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
+#include "lldb/Core/StreamString.h"
#include "lldb/Host/File.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Core/DataBufferHeap.h"
@@ -1106,6 +1107,140 @@ FileSpec::EnumerateDirectory
return eEnumerateDirectoryResultNext;
}
+FileSpec
+FileSpec::CopyByAppendingPathComponent (const char *new_path) const
+{
+ const bool resolve = false;
+ if (m_filename.IsEmpty() && m_directory.IsEmpty())
+ return FileSpec(new_path,resolve);
+ StreamString stream;
+ if (m_filename.IsEmpty())
+ stream.Printf("%s/%s",m_directory.GetCString(),new_path);
+ else if (m_directory.IsEmpty())
+ stream.Printf("%s/%s",m_filename.GetCString(),new_path);
+ else
+ stream.Printf("%s/%s/%s",m_directory.GetCString(), m_filename.GetCString(),new_path);
+ return FileSpec(stream.GetData(),resolve);
+}
+
+FileSpec
+FileSpec::CopyByRemovingLastPathComponent () const
+{
+ const bool resolve = false;
+ if (m_filename.IsEmpty() && m_directory.IsEmpty())
+ return FileSpec("",resolve);
+ if (m_directory.IsEmpty())
+ return FileSpec("",resolve);
+ if (m_filename.IsEmpty())
+ {
+ const char* dir_cstr = m_directory.GetCString();
+ const char* last_slash_ptr = ::strrchr(dir_cstr, '/');
+
+ // check for obvious cases before doing the full thing
+ if (!last_slash_ptr)
+ return FileSpec("",resolve);
+ if (last_slash_ptr == dir_cstr)
+ return FileSpec("/",resolve);
+
+ size_t last_slash_pos = last_slash_ptr - dir_cstr+1;
+ ConstString new_path(dir_cstr,last_slash_pos);
+ return FileSpec(new_path.GetCString(),resolve);
+ }
+ else
+ return FileSpec(m_directory.GetCString(),resolve);
+}
+
+const char*
+FileSpec::GetLastPathComponent () const
+{
+ if (m_filename.IsEmpty() && m_directory.IsEmpty())
+ return NULL;
+ if (m_filename.IsEmpty())
+ {
+ const char* dir_cstr = m_directory.GetCString();
+ const char* last_slash_ptr = ::strrchr(dir_cstr, '/');
+ if (last_slash_ptr == NULL)
+ return m_directory.GetCString();
+ if (last_slash_ptr == dir_cstr)
+ {
+ if (last_slash_ptr[1] == 0)
+ return last_slash_ptr;
+ else
+ return last_slash_ptr+1;
+ }
+ if (last_slash_ptr[1] != 0)
+ return last_slash_ptr+1;
+ const char* penultimate_slash_ptr = last_slash_ptr;
+ while (*penultimate_slash_ptr)
+ {
+ --penultimate_slash_ptr;
+ if (penultimate_slash_ptr == dir_cstr)
+ break;
+ if (*penultimate_slash_ptr == '/')
+ break;
+ }
+ ConstString new_path(penultimate_slash_ptr+1,last_slash_ptr-penultimate_slash_ptr);
+ return new_path.AsCString();
+ }
+ return m_filename.GetCString();
+}
+
+void
+FileSpec::AppendPathComponent (const char *new_path)
+{
+ const bool resolve = false;
+ if (m_filename.IsEmpty() && m_directory.IsEmpty())
+ {
+ SetFile(new_path,resolve);
+ return;
+ }
+ StreamString stream;
+ if (m_filename.IsEmpty())
+ stream.Printf("%s/%s",m_directory.GetCString(),new_path);
+ else if (m_directory.IsEmpty())
+ stream.Printf("%s/%s",m_filename.GetCString(),new_path);
+ else
+ stream.Printf("%s/%s/%s",m_directory.GetCString(), m_filename.GetCString(),new_path);
+ SetFile(stream.GetData(), resolve);
+}
+
+void
+FileSpec::RemoveLastPathComponent ()
+{
+ const bool resolve = false;
+ if (m_filename.IsEmpty() && m_directory.IsEmpty())
+ {
+ SetFile("",resolve);
+ return;
+ }
+ if (m_directory.IsEmpty())
+ {
+ SetFile("",resolve);
+ return;
+ }
+ if (m_filename.IsEmpty())
+ {
+ const char* dir_cstr = m_directory.GetCString();
+ const char* last_slash_ptr = ::strrchr(dir_cstr, '/');
+
+ // check for obvious cases before doing the full thing
+ if (!last_slash_ptr)
+ {
+ SetFile("",resolve);
+ return;
+ }
+ if (last_slash_ptr == dir_cstr)
+ {
+ SetFile("/",resolve);
+ return;
+ }
+ size_t last_slash_pos = last_slash_ptr - dir_cstr+1;
+ ConstString new_path(dir_cstr,last_slash_pos);
+ SetFile(new_path.GetCString(),resolve);
+ }
+ else
+ SetFile(m_directory.GetCString(),resolve);
+}
//------------------------------------------------------------------
/// Returns true if the filespec represents an implementation source
/// file (files with a ".c", ".cpp", ".m", ".mm" (many more)
diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp
index 826069b358c..efe97237d42 100644
--- a/lldb/source/Host/common/Host.cpp
+++ b/lldb/source/Host/common/Host.cpp
@@ -1472,7 +1472,11 @@ Host::RunShellCommand (const char *command,
error = LaunchProcess (launch_info);
const lldb::pid_t pid = launch_info.GetProcessID();
- if (pid != LLDB_INVALID_PROCESS_ID)
+
+ if (error.Success() && pid == LLDB_INVALID_PROCESS_ID)
+ error.SetErrorString("failed to get process ID");
+
+ if (error.Success())
{
// The process successfully launched, so we can defer ownership of
// "shell_info" to the MonitorShellCommand callback function that will
@@ -1524,10 +1528,6 @@ Host::RunShellCommand (const char *command,
}
shell_info->can_delete.SetValue(true, eBroadcastAlways);
}
- else
- {
- error.SetErrorString("failed to get process ID");
- }
if (output_file_path)
::unlink (output_file_path);
@@ -1613,9 +1613,169 @@ Host::SetCrashDescription (const char *description)
}
lldb::pid_t
-LaunchApplication (const FileSpec &app_file_spec)
+Host::LaunchApplication (const FileSpec &app_file_spec)
{
return LLDB_INVALID_PROCESS_ID;
}
+uint32_t
+Host::MakeDirectory (const char* path, mode_t mode)
+{
+ return UINT32_MAX;
+}
+#endif
+
+typedef std::map<lldb::user_id_t, lldb::FileSP> FDToFileMap;
+FDToFileMap& GetFDToFileMap()
+{
+ static FDToFileMap g_fd2filemap;
+ return g_fd2filemap;
+}
+
+lldb::user_id_t
+Host::OpenFile (const FileSpec& file_spec,
+ uint32_t flags,
+ mode_t mode,
+ Error &error)
+{
+ std::string path (file_spec.GetPath());
+ if (path.empty())
+ {
+ error.SetErrorString("empty path");
+ return UINT64_MAX;
+ }
+ FileSP file_sp(new File());
+ error = file_sp->Open(path.c_str(),flags,mode);
+ if (file_sp->IsValid() == false)
+ return UINT64_MAX;
+ lldb::user_id_t fd = file_sp->GetDescriptor();
+ GetFDToFileMap()[fd] = file_sp;
+ return fd;
+}
+
+bool
+Host::CloseFile (lldb::user_id_t fd, Error &error)
+{
+ if (fd == UINT64_MAX)
+ {
+ error.SetErrorString ("invalid file descriptor");
+ return false;
+ }
+ FDToFileMap& file_map = GetFDToFileMap();
+ FDToFileMap::iterator pos = file_map.find(fd);
+ if (pos == file_map.end())
+ {
+ error.SetErrorStringWithFormat ("invalid host file descriptor %" PRIu64, fd);
+ return false;
+ }
+ FileSP file_sp = pos->second;
+ if (!file_sp)
+ {
+ error.SetErrorString ("invalid host backing file");
+ return false;
+ }
+ error = file_sp->Close();
+ file_map.erase(pos);
+ return error.Success();
+}
+
+uint64_t
+Host::WriteFile (lldb::user_id_t fd, uint64_t offset, const void* src, uint64_t src_len, Error &error)
+{
+ if (fd == UINT64_MAX)
+ {
+ error.SetErrorString ("invalid file descriptor");
+ return UINT64_MAX;
+ }
+ FDToFileMap& file_map = GetFDToFileMap();
+ FDToFileMap::iterator pos = file_map.find(fd);
+ if (pos == file_map.end())
+ {
+ error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64 , fd);
+ return false;
+ }
+ FileSP file_sp = pos->second;
+ if (!file_sp)
+ {
+ error.SetErrorString ("invalid host backing file");
+ return UINT64_MAX;
+ }
+ if (file_sp->SeekFromStart(offset, &error) != offset || error.Fail())
+ return UINT64_MAX;
+ size_t bytes_written = src_len;
+ error = file_sp->Write(src, bytes_written);
+ if (error.Fail())
+ return UINT64_MAX;
+ return bytes_written;
+}
+
+uint64_t
+Host::ReadFile (lldb::user_id_t fd, uint64_t offset, void* dst, uint64_t dst_len, Error &error)
+{
+ if (fd == UINT64_MAX)
+ {
+ error.SetErrorString ("invalid file descriptor");
+ return UINT64_MAX;
+ }
+ FDToFileMap& file_map = GetFDToFileMap();
+ FDToFileMap::iterator pos = file_map.find(fd);
+ if (pos == file_map.end())
+ {
+ error.SetErrorStringWithFormat ("invalid host file descriptor %" PRIu64, fd);
+ return false;
+ }
+ FileSP file_sp = pos->second;
+ if (!file_sp)
+ {
+ error.SetErrorString ("invalid host backing file");
+ return UINT64_MAX;
+ }
+ if (file_sp->SeekFromStart(offset, &error) != offset || error.Fail())
+ return UINT64_MAX;
+ size_t bytes_read = dst_len;
+ error = file_sp->Read(dst ,bytes_read);
+ if (error.Fail())
+ return UINT64_MAX;
+ return bytes_read;
+}
+
+lldb::user_id_t
+Host::GetFileSize (const FileSpec& file_spec)
+{
+ return file_spec.GetByteSize();
+}
+
+bool
+Host::GetFileExists (const FileSpec& file_spec)
+{
+ return file_spec.Exists();
+}
+
+bool
+Host::CalculateMD5 (const FileSpec& file_spec,
+ uint64_t &low,
+ uint64_t &high)
+{
+#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)
+ 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;
+#else
+ // your own MD5 implementation here
+ return false;
#endif
+}
OpenPOWER on IntegriCloud