diff options
Diffstat (limited to 'lldb/source/Host/common')
-rw-r--r-- | lldb/source/Host/common/File.cpp | 109 | ||||
-rw-r--r-- | lldb/source/Host/common/FileSpec.cpp | 135 | ||||
-rw-r--r-- | lldb/source/Host/common/Host.cpp | 172 |
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 +} |