1e0f8f574SDaniel Malea //===-- PlatformPOSIX.cpp ---------------------------------------*- C++ -*-===// 2e0f8f574SDaniel Malea // 3e0f8f574SDaniel Malea // The LLVM Compiler Infrastructure 4e0f8f574SDaniel Malea // 5e0f8f574SDaniel Malea // This file is distributed under the University of Illinois Open Source 6e0f8f574SDaniel Malea // License. See LICENSE.TXT for details. 7e0f8f574SDaniel Malea // 8e0f8f574SDaniel Malea //===----------------------------------------------------------------------===// 9e0f8f574SDaniel Malea 10e0f8f574SDaniel Malea #include "PlatformPOSIX.h" 11e0f8f574SDaniel Malea 12e0f8f574SDaniel Malea // C Includes 13e0f8f574SDaniel Malea // C++ Includes 14e0f8f574SDaniel Malea // Other libraries and framework includes 15e0f8f574SDaniel Malea // Project includes 16e0f8f574SDaniel Malea 17e0f8f574SDaniel Malea #include "lldb/Core/DataBufferHeap.h" 18e0f8f574SDaniel Malea #include "lldb/Core/Log.h" 19e0f8f574SDaniel Malea #include "lldb/Core/StreamString.h" 20e0f8f574SDaniel Malea #include "lldb/Host/File.h" 21e0f8f574SDaniel Malea #include "lldb/Host/FileSpec.h" 22e0f8f574SDaniel Malea #include "lldb/Host/Host.h" 23e0f8f574SDaniel Malea 24e0f8f574SDaniel Malea using namespace lldb; 25e0f8f574SDaniel Malea using namespace lldb_private; 26e0f8f574SDaniel Malea 27e0f8f574SDaniel Malea 28e0f8f574SDaniel Malea //------------------------------------------------------------------ 29e0f8f574SDaniel Malea /// Default Constructor 30e0f8f574SDaniel Malea //------------------------------------------------------------------ 31e0f8f574SDaniel Malea PlatformPOSIX::PlatformPOSIX (bool is_host) : 32e0f8f574SDaniel Malea Platform(is_host), // This is the local host platform 33e0f8f574SDaniel Malea m_remote_platform_sp () 34e0f8f574SDaniel Malea { 35e0f8f574SDaniel Malea } 36e0f8f574SDaniel Malea 37e0f8f574SDaniel Malea //------------------------------------------------------------------ 38e0f8f574SDaniel Malea /// Destructor. 39e0f8f574SDaniel Malea /// 40e0f8f574SDaniel Malea /// The destructor is virtual since this class is designed to be 41e0f8f574SDaniel Malea /// inherited from by the plug-in instance. 42e0f8f574SDaniel Malea //------------------------------------------------------------------ 43e0f8f574SDaniel Malea PlatformPOSIX::~PlatformPOSIX() 44e0f8f574SDaniel Malea { 45e0f8f574SDaniel Malea } 46e0f8f574SDaniel Malea 47e0f8f574SDaniel Malea lldb_private::OptionGroupOptions* 48e0f8f574SDaniel Malea PlatformPOSIX::GetConnectionOptions (lldb_private::CommandInterpreter& interpreter) 49e0f8f574SDaniel Malea { 50e0f8f574SDaniel Malea if (m_options.get() == NULL) 51e0f8f574SDaniel Malea { 52e0f8f574SDaniel Malea m_options.reset(new OptionGroupOptions(interpreter)); 53e0f8f574SDaniel Malea m_options->Append(new OptionGroupPlatformRSync()); 54e0f8f574SDaniel Malea m_options->Append(new OptionGroupPlatformSSH()); 55e0f8f574SDaniel Malea m_options->Append(new OptionGroupPlatformCaching()); 56e0f8f574SDaniel Malea } 57e0f8f574SDaniel Malea return m_options.get(); 58e0f8f574SDaniel Malea } 59e0f8f574SDaniel Malea 60e0f8f574SDaniel Malea lldb_private::Error 61e0f8f574SDaniel Malea PlatformPOSIX::RunShellCommand (const char *command, // Shouldn't be NULL 62e0f8f574SDaniel Malea const char *working_dir, // Pass NULL to use the current working directory 63e0f8f574SDaniel Malea int *status_ptr, // Pass NULL if you don't want the process exit status 64e0f8f574SDaniel Malea int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit 65e0f8f574SDaniel Malea std::string *command_output, // Pass NULL if you don't want the command output 66e0f8f574SDaniel Malea uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish 67e0f8f574SDaniel Malea { 68e0f8f574SDaniel Malea if (IsHost()) 69e0f8f574SDaniel Malea return Host::RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec); 70e0f8f574SDaniel Malea else 71e0f8f574SDaniel Malea { 72e0f8f574SDaniel Malea if (m_remote_platform_sp) 73e0f8f574SDaniel Malea return m_remote_platform_sp->RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec); 74e0f8f574SDaniel Malea else 75e0f8f574SDaniel Malea return Error("unable to run a remote command without a platform"); 76e0f8f574SDaniel Malea } 77e0f8f574SDaniel Malea } 78e0f8f574SDaniel Malea 79*fbb76349SGreg Clayton Error 80*fbb76349SGreg Clayton PlatformPOSIX::MakeDirectory (const char *path, uint32_t file_permissions) 81e0f8f574SDaniel Malea { 82*fbb76349SGreg Clayton if (m_remote_platform_sp) 83*fbb76349SGreg Clayton return m_remote_platform_sp->MakeDirectory(path, file_permissions); 84*fbb76349SGreg Clayton else 85*fbb76349SGreg Clayton return Platform::MakeDirectory(path ,file_permissions); 86e0f8f574SDaniel Malea } 87*fbb76349SGreg Clayton 88*fbb76349SGreg Clayton Error 89*fbb76349SGreg Clayton PlatformPOSIX::GetFilePermissions (const char *path, uint32_t &file_permissions) 90*fbb76349SGreg Clayton { 91*fbb76349SGreg Clayton if (m_remote_platform_sp) 92*fbb76349SGreg Clayton return m_remote_platform_sp->GetFilePermissions(path, file_permissions); 93*fbb76349SGreg Clayton else 94*fbb76349SGreg Clayton return Platform::GetFilePermissions(path ,file_permissions); 95*fbb76349SGreg Clayton } 96*fbb76349SGreg Clayton 97*fbb76349SGreg Clayton Error 98*fbb76349SGreg Clayton PlatformPOSIX::SetFilePermissions (const char *path, uint32_t file_permissions) 99*fbb76349SGreg Clayton { 100*fbb76349SGreg Clayton if (m_remote_platform_sp) 101*fbb76349SGreg Clayton return m_remote_platform_sp->MakeDirectory(path, file_permissions); 102*fbb76349SGreg Clayton else 103*fbb76349SGreg Clayton return Platform::SetFilePermissions(path ,file_permissions); 104e0f8f574SDaniel Malea } 105e0f8f574SDaniel Malea 106e0f8f574SDaniel Malea lldb::user_id_t 107e0f8f574SDaniel Malea PlatformPOSIX::OpenFile (const FileSpec& file_spec, 108e0f8f574SDaniel Malea uint32_t flags, 109*fbb76349SGreg Clayton uint32_t mode, 110e0f8f574SDaniel Malea Error &error) 111e0f8f574SDaniel Malea { 112e0f8f574SDaniel Malea if (IsHost()) 113e0f8f574SDaniel Malea return Host::OpenFile(file_spec, flags, mode, error); 114*fbb76349SGreg Clayton else if (m_remote_platform_sp) 115e0f8f574SDaniel Malea return m_remote_platform_sp->OpenFile(file_spec, flags, mode, error); 116*fbb76349SGreg Clayton else 117e0f8f574SDaniel Malea return Platform::OpenFile(file_spec, flags, mode, error); 118e0f8f574SDaniel Malea } 119e0f8f574SDaniel Malea 120e0f8f574SDaniel Malea bool 121e0f8f574SDaniel Malea PlatformPOSIX::CloseFile (lldb::user_id_t fd, Error &error) 122e0f8f574SDaniel Malea { 123e0f8f574SDaniel Malea if (IsHost()) 124e0f8f574SDaniel Malea return Host::CloseFile(fd, error); 125*fbb76349SGreg Clayton else if (m_remote_platform_sp) 126e0f8f574SDaniel Malea return m_remote_platform_sp->CloseFile(fd, error); 127*fbb76349SGreg Clayton else 128e0f8f574SDaniel Malea return Platform::CloseFile(fd, error); 129e0f8f574SDaniel Malea } 130e0f8f574SDaniel Malea 131e0f8f574SDaniel Malea uint64_t 132e0f8f574SDaniel Malea PlatformPOSIX::ReadFile (lldb::user_id_t fd, 133e0f8f574SDaniel Malea uint64_t offset, 134e0f8f574SDaniel Malea void *dst, 135e0f8f574SDaniel Malea uint64_t dst_len, 136e0f8f574SDaniel Malea Error &error) 137e0f8f574SDaniel Malea { 138e0f8f574SDaniel Malea if (IsHost()) 139e0f8f574SDaniel Malea return Host::ReadFile(fd, offset, dst, dst_len, error); 140*fbb76349SGreg Clayton else if (m_remote_platform_sp) 141e0f8f574SDaniel Malea return m_remote_platform_sp->ReadFile(fd, offset, dst, dst_len, error); 142*fbb76349SGreg Clayton else 143e0f8f574SDaniel Malea return Platform::ReadFile(fd, offset, dst, dst_len, error); 144e0f8f574SDaniel Malea } 145e0f8f574SDaniel Malea 146e0f8f574SDaniel Malea uint64_t 147e0f8f574SDaniel Malea PlatformPOSIX::WriteFile (lldb::user_id_t fd, 148e0f8f574SDaniel Malea uint64_t offset, 149e0f8f574SDaniel Malea const void* src, 150e0f8f574SDaniel Malea uint64_t src_len, 151e0f8f574SDaniel Malea Error &error) 152e0f8f574SDaniel Malea { 153e0f8f574SDaniel Malea if (IsHost()) 154e0f8f574SDaniel Malea return Host::WriteFile(fd, offset, src, src_len, error); 155*fbb76349SGreg Clayton else if (m_remote_platform_sp) 156e0f8f574SDaniel Malea return m_remote_platform_sp->WriteFile(fd, offset, src, src_len, error); 157*fbb76349SGreg Clayton else 158e0f8f574SDaniel Malea return Platform::WriteFile(fd, offset, src, src_len, error); 159e0f8f574SDaniel Malea } 160e0f8f574SDaniel Malea 161e0f8f574SDaniel Malea static uint32_t 162e0f8f574SDaniel Malea chown_file(Platform *platform, 163e0f8f574SDaniel Malea const char* path, 164e0f8f574SDaniel Malea uint32_t uid = UINT32_MAX, 165e0f8f574SDaniel Malea uint32_t gid = UINT32_MAX) 166e0f8f574SDaniel Malea { 167e0f8f574SDaniel Malea if (!platform || !path || *path == 0) 168e0f8f574SDaniel Malea return UINT32_MAX; 169e0f8f574SDaniel Malea 170e0f8f574SDaniel Malea if (uid == UINT32_MAX && gid == UINT32_MAX) 171e0f8f574SDaniel Malea return 0; // pretend I did chown correctly - actually I just didn't care 172e0f8f574SDaniel Malea 173e0f8f574SDaniel Malea StreamString command; 174e0f8f574SDaniel Malea command.PutCString("chown "); 175e0f8f574SDaniel Malea if (uid != UINT32_MAX) 176e0f8f574SDaniel Malea command.Printf("%d",uid); 177e0f8f574SDaniel Malea if (gid != UINT32_MAX) 178e0f8f574SDaniel Malea command.Printf(":%d",gid); 179e0f8f574SDaniel Malea command.Printf("%s",path); 180e0f8f574SDaniel Malea int status; 181e0f8f574SDaniel Malea platform->RunShellCommand(command.GetData(), 182e0f8f574SDaniel Malea NULL, 183e0f8f574SDaniel Malea &status, 184e0f8f574SDaniel Malea NULL, 185e0f8f574SDaniel Malea NULL, 186e0f8f574SDaniel Malea 10); 187e0f8f574SDaniel Malea return status; 188e0f8f574SDaniel Malea } 189e0f8f574SDaniel Malea 190e0f8f574SDaniel Malea lldb_private::Error 191e0f8f574SDaniel Malea PlatformPOSIX::PutFile (const lldb_private::FileSpec& source, 192e0f8f574SDaniel Malea const lldb_private::FileSpec& destination, 193e0f8f574SDaniel Malea uint32_t uid, 194e0f8f574SDaniel Malea uint32_t gid) 195e0f8f574SDaniel Malea { 196*fbb76349SGreg Clayton Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); 197*fbb76349SGreg Clayton 198e0f8f574SDaniel Malea if (IsHost()) 199e0f8f574SDaniel Malea { 200e0f8f574SDaniel Malea if (FileSpec::Equal(source, destination, true)) 201e0f8f574SDaniel Malea return Error(); 202e0f8f574SDaniel Malea // cp src dst 203e0f8f574SDaniel Malea // chown uid:gid dst 204e0f8f574SDaniel Malea std::string src_path (source.GetPath()); 205e0f8f574SDaniel Malea if (src_path.empty()) 206e0f8f574SDaniel Malea return Error("unable to get file path for source"); 207e0f8f574SDaniel Malea std::string dst_path (destination.GetPath()); 208e0f8f574SDaniel Malea if (dst_path.empty()) 209e0f8f574SDaniel Malea return Error("unable to get file path for destination"); 210e0f8f574SDaniel Malea StreamString command; 211e0f8f574SDaniel Malea command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str()); 212e0f8f574SDaniel Malea int status; 213e0f8f574SDaniel Malea RunShellCommand(command.GetData(), 214e0f8f574SDaniel Malea NULL, 215e0f8f574SDaniel Malea &status, 216e0f8f574SDaniel Malea NULL, 217e0f8f574SDaniel Malea NULL, 218e0f8f574SDaniel Malea 10); 219e0f8f574SDaniel Malea if (status != 0) 220e0f8f574SDaniel Malea return Error("unable to perform copy"); 221e0f8f574SDaniel Malea if (uid == UINT32_MAX && gid == UINT32_MAX) 222e0f8f574SDaniel Malea return Error(); 223e0f8f574SDaniel Malea if (chown_file(this,dst_path.c_str(),uid,gid) != 0) 224e0f8f574SDaniel Malea return Error("unable to perform chown"); 225e0f8f574SDaniel Malea return Error(); 226e0f8f574SDaniel Malea } 227*fbb76349SGreg Clayton else if (m_remote_platform_sp) 228e0f8f574SDaniel Malea { 229e0f8f574SDaniel Malea if (GetSupportsRSync()) 230e0f8f574SDaniel Malea { 231e0f8f574SDaniel Malea std::string src_path (source.GetPath()); 232e0f8f574SDaniel Malea if (src_path.empty()) 233e0f8f574SDaniel Malea return Error("unable to get file path for source"); 234e0f8f574SDaniel Malea std::string dst_path (destination.GetPath()); 235e0f8f574SDaniel Malea if (dst_path.empty()) 236e0f8f574SDaniel Malea return Error("unable to get file path for destination"); 237e0f8f574SDaniel Malea StreamString command; 238e0f8f574SDaniel Malea if (GetIgnoresRemoteHostname()) 239e0f8f574SDaniel Malea { 240e0f8f574SDaniel Malea if (!GetRSyncPrefix()) 241e0f8f574SDaniel Malea command.Printf("rsync %s %s %s", 242e0f8f574SDaniel Malea GetRSyncOpts(), 243e0f8f574SDaniel Malea src_path.c_str(), 244e0f8f574SDaniel Malea dst_path.c_str()); 245e0f8f574SDaniel Malea else 246e0f8f574SDaniel Malea command.Printf("rsync %s %s %s%s", 247e0f8f574SDaniel Malea GetRSyncOpts(), 248e0f8f574SDaniel Malea src_path.c_str(), 249e0f8f574SDaniel Malea GetRSyncPrefix(), 250e0f8f574SDaniel Malea dst_path.c_str()); 251e0f8f574SDaniel Malea } 252e0f8f574SDaniel Malea else 253e0f8f574SDaniel Malea command.Printf("rsync %s %s %s:%s", 254e0f8f574SDaniel Malea GetRSyncOpts(), 255e0f8f574SDaniel Malea src_path.c_str(), 256e0f8f574SDaniel Malea GetHostname(), 257e0f8f574SDaniel Malea dst_path.c_str()); 258e0f8f574SDaniel Malea if (log) 259e0f8f574SDaniel Malea log->Printf("[PutFile] Running command: %s\n", command.GetData()); 260e0f8f574SDaniel Malea int retcode; 261e0f8f574SDaniel Malea Host::RunShellCommand(command.GetData(), 262e0f8f574SDaniel Malea NULL, 263e0f8f574SDaniel Malea &retcode, 264e0f8f574SDaniel Malea NULL, 265e0f8f574SDaniel Malea NULL, 266e0f8f574SDaniel Malea 60); 267e0f8f574SDaniel Malea if (retcode == 0) 268e0f8f574SDaniel Malea { 269e0f8f574SDaniel Malea // Don't chown a local file for a remote system 270e0f8f574SDaniel Malea // if (chown_file(this,dst_path.c_str(),uid,gid) != 0) 271e0f8f574SDaniel Malea // return Error("unable to perform chown"); 272e0f8f574SDaniel Malea return Error(); 273e0f8f574SDaniel Malea } 274e0f8f574SDaniel Malea // if we are still here rsync has failed - let's try the slow way before giving up 275e0f8f574SDaniel Malea } 276*fbb76349SGreg Clayton 277*fbb76349SGreg Clayton if (log) 278*fbb76349SGreg Clayton log->Printf ("PlatformPOSIX::PutFile(src='%s', dst='%s', uid=%u, gid=%u)", 279*fbb76349SGreg Clayton source.GetPath().c_str(), 280*fbb76349SGreg Clayton destination.GetPath().c_str(), 281*fbb76349SGreg Clayton uid, 282*fbb76349SGreg Clayton gid); // REMOVE THIS PRINTF PRIOR TO CHECKIN 283e0f8f574SDaniel Malea // open 284e0f8f574SDaniel Malea // read, write, read, write, ... 285e0f8f574SDaniel Malea // close 286e0f8f574SDaniel Malea // chown uid:gid dst 287e0f8f574SDaniel Malea if (log) 288e0f8f574SDaniel Malea log->Printf("[PutFile] Using block by block transfer....\n"); 289*fbb76349SGreg Clayton 290*fbb76349SGreg Clayton uint32_t source_open_options = File::eOpenOptionRead; 291*fbb76349SGreg Clayton if (source.GetFileType() == FileSpec::eFileTypeSymbolicLink) 292*fbb76349SGreg Clayton source_open_options |= File::eOpenoptionDontFollowSymlinks; 293*fbb76349SGreg Clayton 294*fbb76349SGreg Clayton File source_file(source, source_open_options, lldb::eFilePermissionsUserRW); 295*fbb76349SGreg Clayton Error error; 296*fbb76349SGreg Clayton uint32_t permissions = source_file.GetPermissions(error); 297*fbb76349SGreg Clayton if (permissions == 0) 298*fbb76349SGreg Clayton permissions = lldb::eFilePermissionsFileDefault; 299*fbb76349SGreg Clayton 300e0f8f574SDaniel Malea if (!source_file.IsValid()) 301e0f8f574SDaniel Malea return Error("unable to open source file"); 302e0f8f574SDaniel Malea lldb::user_id_t dest_file = OpenFile (destination, 303e0f8f574SDaniel Malea File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate, 304*fbb76349SGreg Clayton permissions, 305e0f8f574SDaniel Malea error); 306e0f8f574SDaniel Malea if (log) 307e0f8f574SDaniel Malea log->Printf ("dest_file = %" PRIu64 "\n", dest_file); 308e0f8f574SDaniel Malea if (error.Fail()) 309e0f8f574SDaniel Malea return error; 310e0f8f574SDaniel Malea if (dest_file == UINT64_MAX) 311e0f8f574SDaniel Malea return Error("unable to open target file"); 312e0f8f574SDaniel Malea lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0)); 313e0f8f574SDaniel Malea uint64_t offset = 0; 314e0f8f574SDaniel Malea while (error.Success()) 315e0f8f574SDaniel Malea { 316e0f8f574SDaniel Malea size_t bytes_read = buffer_sp->GetByteSize(); 317e0f8f574SDaniel Malea error = source_file.Read(buffer_sp->GetBytes(), bytes_read); 318e0f8f574SDaniel Malea if (bytes_read) 319e0f8f574SDaniel Malea { 320e0f8f574SDaniel Malea WriteFile(dest_file, offset, buffer_sp->GetBytes(), bytes_read, error); 321e0f8f574SDaniel Malea offset += bytes_read; 322e0f8f574SDaniel Malea } 323e0f8f574SDaniel Malea else 324e0f8f574SDaniel Malea break; 325e0f8f574SDaniel Malea } 326e0f8f574SDaniel Malea CloseFile(dest_file, error); 327e0f8f574SDaniel Malea if (uid == UINT32_MAX && gid == UINT32_MAX) 328e0f8f574SDaniel Malea return error; 329e0f8f574SDaniel Malea // This is remopve, don't chown a local file... 330e0f8f574SDaniel Malea // std::string dst_path (destination.GetPath()); 331e0f8f574SDaniel Malea // if (chown_file(this,dst_path.c_str(),uid,gid) != 0) 332e0f8f574SDaniel Malea // return Error("unable to perform chown"); 333e0f8f574SDaniel Malea return error; 334e0f8f574SDaniel Malea } 335e0f8f574SDaniel Malea return Platform::PutFile(source,destination,uid,gid); 336e0f8f574SDaniel Malea } 337e0f8f574SDaniel Malea 338e0f8f574SDaniel Malea lldb::user_id_t 339e0f8f574SDaniel Malea PlatformPOSIX::GetFileSize (const FileSpec& file_spec) 340e0f8f574SDaniel Malea { 341e0f8f574SDaniel Malea if (IsHost()) 342e0f8f574SDaniel Malea return Host::GetFileSize(file_spec); 343*fbb76349SGreg Clayton else if (m_remote_platform_sp) 344e0f8f574SDaniel Malea return m_remote_platform_sp->GetFileSize(file_spec); 345*fbb76349SGreg Clayton else 346e0f8f574SDaniel Malea return Platform::GetFileSize(file_spec); 347e0f8f574SDaniel Malea } 348e0f8f574SDaniel Malea 349*fbb76349SGreg Clayton Error 350*fbb76349SGreg Clayton PlatformPOSIX::CreateSymlink(const char *src, const char *dst) 351*fbb76349SGreg Clayton { 352*fbb76349SGreg Clayton if (IsHost()) 353*fbb76349SGreg Clayton return Host::Symlink(src, dst); 354*fbb76349SGreg Clayton else if (m_remote_platform_sp) 355*fbb76349SGreg Clayton return m_remote_platform_sp->CreateSymlink(src, dst); 356*fbb76349SGreg Clayton else 357*fbb76349SGreg Clayton return Platform::CreateSymlink(src, dst); 358*fbb76349SGreg Clayton } 359*fbb76349SGreg Clayton 360e0f8f574SDaniel Malea bool 361e0f8f574SDaniel Malea PlatformPOSIX::GetFileExists (const FileSpec& file_spec) 362e0f8f574SDaniel Malea { 363e0f8f574SDaniel Malea if (IsHost()) 364e0f8f574SDaniel Malea return file_spec.Exists(); 365*fbb76349SGreg Clayton else if (m_remote_platform_sp) 366e0f8f574SDaniel Malea return m_remote_platform_sp->GetFileExists(file_spec); 367*fbb76349SGreg Clayton else 368e0f8f574SDaniel Malea return Platform::GetFileExists(file_spec); 369e0f8f574SDaniel Malea } 370e0f8f574SDaniel Malea 371*fbb76349SGreg Clayton Error 372*fbb76349SGreg Clayton PlatformPOSIX::Unlink (const char *path) 373e0f8f574SDaniel Malea { 374e0f8f574SDaniel Malea if (IsHost()) 375*fbb76349SGreg Clayton return Host::Unlink (path); 376*fbb76349SGreg Clayton else if (m_remote_platform_sp) 377*fbb76349SGreg Clayton return m_remote_platform_sp->Unlink(path); 378*fbb76349SGreg Clayton else 379*fbb76349SGreg Clayton return Platform::Unlink(path); 380e0f8f574SDaniel Malea } 381e0f8f574SDaniel Malea 382e0f8f574SDaniel Malea lldb_private::Error 383e0f8f574SDaniel Malea PlatformPOSIX::GetFile (const lldb_private::FileSpec& source /* remote file path */, 384e0f8f574SDaniel Malea const lldb_private::FileSpec& destination /* local file path */) 385e0f8f574SDaniel Malea { 386*fbb76349SGreg Clayton Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); 387*fbb76349SGreg Clayton 388e0f8f574SDaniel Malea // Check the args, first. 389e0f8f574SDaniel Malea std::string src_path (source.GetPath()); 390e0f8f574SDaniel Malea if (src_path.empty()) 391e0f8f574SDaniel Malea return Error("unable to get file path for source"); 392e0f8f574SDaniel Malea std::string dst_path (destination.GetPath()); 393e0f8f574SDaniel Malea if (dst_path.empty()) 394e0f8f574SDaniel Malea return Error("unable to get file path for destination"); 395e0f8f574SDaniel Malea if (IsHost()) 396e0f8f574SDaniel Malea { 397e0f8f574SDaniel Malea if (FileSpec::Equal(source, destination, true)) 398e0f8f574SDaniel Malea return Error("local scenario->source and destination are the same file path: no operation performed"); 399e0f8f574SDaniel Malea // cp src dst 400e0f8f574SDaniel Malea StreamString cp_command; 401e0f8f574SDaniel Malea cp_command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str()); 402e0f8f574SDaniel Malea int status; 403e0f8f574SDaniel Malea RunShellCommand(cp_command.GetData(), 404e0f8f574SDaniel Malea NULL, 405e0f8f574SDaniel Malea &status, 406e0f8f574SDaniel Malea NULL, 407e0f8f574SDaniel Malea NULL, 408e0f8f574SDaniel Malea 10); 409e0f8f574SDaniel Malea if (status != 0) 410e0f8f574SDaniel Malea return Error("unable to perform copy"); 411e0f8f574SDaniel Malea return Error(); 412e0f8f574SDaniel Malea } 413*fbb76349SGreg Clayton else if (m_remote_platform_sp) 414e0f8f574SDaniel Malea { 415e0f8f574SDaniel Malea if (GetSupportsRSync()) 416e0f8f574SDaniel Malea { 417e0f8f574SDaniel Malea StreamString command; 418e0f8f574SDaniel Malea if (GetIgnoresRemoteHostname()) 419e0f8f574SDaniel Malea { 420e0f8f574SDaniel Malea if (!GetRSyncPrefix()) 421e0f8f574SDaniel Malea command.Printf("rsync %s %s %s", 422e0f8f574SDaniel Malea GetRSyncOpts(), 423e0f8f574SDaniel Malea src_path.c_str(), 424e0f8f574SDaniel Malea dst_path.c_str()); 425e0f8f574SDaniel Malea else 426e0f8f574SDaniel Malea command.Printf("rsync %s %s%s %s", 427e0f8f574SDaniel Malea GetRSyncOpts(), 428e0f8f574SDaniel Malea GetRSyncPrefix(), 429e0f8f574SDaniel Malea src_path.c_str(), 430e0f8f574SDaniel Malea dst_path.c_str()); 431e0f8f574SDaniel Malea } 432e0f8f574SDaniel Malea else 433e0f8f574SDaniel Malea command.Printf("rsync %s %s:%s %s", 434e0f8f574SDaniel Malea GetRSyncOpts(), 435e0f8f574SDaniel Malea m_remote_platform_sp->GetHostname(), 436e0f8f574SDaniel Malea src_path.c_str(), 437e0f8f574SDaniel Malea dst_path.c_str()); 438e0f8f574SDaniel Malea if (log) 439e0f8f574SDaniel Malea log->Printf("[GetFile] Running command: %s\n", command.GetData()); 440e0f8f574SDaniel Malea int retcode; 441e0f8f574SDaniel Malea Host::RunShellCommand(command.GetData(), 442e0f8f574SDaniel Malea NULL, 443e0f8f574SDaniel Malea &retcode, 444e0f8f574SDaniel Malea NULL, 445e0f8f574SDaniel Malea NULL, 446e0f8f574SDaniel Malea 60); 447e0f8f574SDaniel Malea if (retcode == 0) 448e0f8f574SDaniel Malea return Error(); 449e0f8f574SDaniel Malea // If we are here, rsync has failed - let's try the slow way before giving up 450e0f8f574SDaniel Malea } 451e0f8f574SDaniel Malea // open src and dst 452e0f8f574SDaniel Malea // read/write, read/write, read/write, ... 453e0f8f574SDaniel Malea // close src 454e0f8f574SDaniel Malea // close dst 455e0f8f574SDaniel Malea if (log) 456e0f8f574SDaniel Malea log->Printf("[GetFile] Using block by block transfer....\n"); 457e0f8f574SDaniel Malea Error error; 458e0f8f574SDaniel Malea user_id_t fd_src = OpenFile (source, 459e0f8f574SDaniel Malea File::eOpenOptionRead, 460*fbb76349SGreg Clayton lldb::eFilePermissionsFileDefault, 461e0f8f574SDaniel Malea error); 462e0f8f574SDaniel Malea 463e0f8f574SDaniel Malea if (fd_src == UINT64_MAX) 464e0f8f574SDaniel Malea return Error("unable to open source file"); 465e0f8f574SDaniel Malea 466*fbb76349SGreg Clayton uint32_t permissions = 0; 467*fbb76349SGreg Clayton error = GetFilePermissions(source.GetPath().c_str(), permissions); 468e0f8f574SDaniel Malea 469e0f8f574SDaniel Malea if (permissions == 0) 470*fbb76349SGreg Clayton permissions = lldb::eFilePermissionsFileDefault; 471e0f8f574SDaniel Malea 472e0f8f574SDaniel Malea user_id_t fd_dst = Host::OpenFile(destination, 473e0f8f574SDaniel Malea File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate, 474e0f8f574SDaniel Malea permissions, 475e0f8f574SDaniel Malea error); 476e0f8f574SDaniel Malea 477e0f8f574SDaniel Malea if (fd_dst == UINT64_MAX) 478e0f8f574SDaniel Malea { 479e0f8f574SDaniel Malea if (error.Success()) 480e0f8f574SDaniel Malea error.SetErrorString("unable to open destination file"); 481e0f8f574SDaniel Malea } 482e0f8f574SDaniel Malea 483e0f8f574SDaniel Malea if (error.Success()) 484e0f8f574SDaniel Malea { 485e0f8f574SDaniel Malea lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0)); 486e0f8f574SDaniel Malea uint64_t offset = 0; 487e0f8f574SDaniel Malea error.Clear(); 488e0f8f574SDaniel Malea while (error.Success()) 489e0f8f574SDaniel Malea { 490e0f8f574SDaniel Malea const uint64_t n_read = ReadFile (fd_src, 491e0f8f574SDaniel Malea offset, 492e0f8f574SDaniel Malea buffer_sp->GetBytes(), 493e0f8f574SDaniel Malea buffer_sp->GetByteSize(), 494e0f8f574SDaniel Malea error); 495e0f8f574SDaniel Malea if (error.Fail()) 496e0f8f574SDaniel Malea break; 497e0f8f574SDaniel Malea if (n_read == 0) 498e0f8f574SDaniel Malea break; 499e0f8f574SDaniel Malea if (Host::WriteFile(fd_dst, 500e0f8f574SDaniel Malea offset, 501e0f8f574SDaniel Malea buffer_sp->GetBytes(), 502e0f8f574SDaniel Malea n_read, 503e0f8f574SDaniel Malea error) != n_read) 504e0f8f574SDaniel Malea { 505e0f8f574SDaniel Malea if (!error.Fail()) 506e0f8f574SDaniel Malea error.SetErrorString("unable to write to destination file"); 507e0f8f574SDaniel Malea break; 508e0f8f574SDaniel Malea } 509e0f8f574SDaniel Malea offset += n_read; 510e0f8f574SDaniel Malea } 511e0f8f574SDaniel Malea } 512e0f8f574SDaniel Malea // Ignore the close error of src. 513e0f8f574SDaniel Malea if (fd_src != UINT64_MAX) 514e0f8f574SDaniel Malea CloseFile(fd_src, error); 515e0f8f574SDaniel Malea // And close the dst file descriptot. 516e0f8f574SDaniel Malea if (fd_dst != UINT64_MAX && !Host::CloseFile(fd_dst, error)) 517e0f8f574SDaniel Malea { 518e0f8f574SDaniel Malea if (!error.Fail()) 519e0f8f574SDaniel Malea error.SetErrorString("unable to close destination file"); 520e0f8f574SDaniel Malea 521e0f8f574SDaniel Malea } 522e0f8f574SDaniel Malea return error; 523e0f8f574SDaniel Malea } 524e0f8f574SDaniel Malea return Platform::GetFile(source,destination); 525e0f8f574SDaniel Malea } 526e0f8f574SDaniel Malea 527e0f8f574SDaniel Malea std::string 528e0f8f574SDaniel Malea PlatformPOSIX::GetPlatformSpecificConnectionInformation() 529e0f8f574SDaniel Malea { 530e0f8f574SDaniel Malea StreamString stream; 531e0f8f574SDaniel Malea if (GetSupportsRSync()) 532e0f8f574SDaniel Malea { 533e0f8f574SDaniel Malea stream.PutCString("rsync"); 534e0f8f574SDaniel Malea if ( (GetRSyncOpts() && *GetRSyncOpts()) || 535e0f8f574SDaniel Malea (GetRSyncPrefix() && *GetRSyncPrefix()) || 536e0f8f574SDaniel Malea GetIgnoresRemoteHostname()) 537e0f8f574SDaniel Malea { 538e0f8f574SDaniel Malea stream.Printf(", options: "); 539e0f8f574SDaniel Malea if (GetRSyncOpts() && *GetRSyncOpts()) 540e0f8f574SDaniel Malea stream.Printf("'%s' ",GetRSyncOpts()); 541e0f8f574SDaniel Malea stream.Printf(", prefix: "); 542e0f8f574SDaniel Malea if (GetRSyncPrefix() && *GetRSyncPrefix()) 543e0f8f574SDaniel Malea stream.Printf("'%s' ",GetRSyncPrefix()); 544e0f8f574SDaniel Malea if (GetIgnoresRemoteHostname()) 545e0f8f574SDaniel Malea stream.Printf("ignore remote-hostname "); 546e0f8f574SDaniel Malea } 547e0f8f574SDaniel Malea } 548e0f8f574SDaniel Malea if (GetSupportsSSH()) 549e0f8f574SDaniel Malea { 550e0f8f574SDaniel Malea stream.PutCString("ssh"); 551e0f8f574SDaniel Malea if (GetSSHOpts() && *GetSSHOpts()) 552e0f8f574SDaniel Malea stream.Printf(", options: '%s' ",GetSSHOpts()); 553e0f8f574SDaniel Malea } 554e0f8f574SDaniel Malea if (GetLocalCacheDirectory() && *GetLocalCacheDirectory()) 555e0f8f574SDaniel Malea stream.Printf("cache dir: %s",GetLocalCacheDirectory()); 556e0f8f574SDaniel Malea if (stream.GetSize()) 557e0f8f574SDaniel Malea return stream.GetData(); 558e0f8f574SDaniel Malea else 559e0f8f574SDaniel Malea return ""; 560e0f8f574SDaniel Malea } 561e0f8f574SDaniel Malea 562e0f8f574SDaniel Malea bool 563e0f8f574SDaniel Malea PlatformPOSIX::CalculateMD5 (const FileSpec& file_spec, 564e0f8f574SDaniel Malea uint64_t &low, 565e0f8f574SDaniel Malea uint64_t &high) 566e0f8f574SDaniel Malea { 567e0f8f574SDaniel Malea if (IsHost()) 568e0f8f574SDaniel Malea return Platform::CalculateMD5 (file_spec, low, high); 569e0f8f574SDaniel Malea if (m_remote_platform_sp) 570e0f8f574SDaniel Malea return m_remote_platform_sp->CalculateMD5(file_spec, low, high); 571e0f8f574SDaniel Malea return false; 572e0f8f574SDaniel Malea } 573*fbb76349SGreg Clayton 574*fbb76349SGreg Clayton lldb_private::ConstString 575*fbb76349SGreg Clayton PlatformPOSIX::GetRemoteWorkingDirectory() 576*fbb76349SGreg Clayton { 577*fbb76349SGreg Clayton if (IsRemote() && m_remote_platform_sp) 578*fbb76349SGreg Clayton return m_remote_platform_sp->GetRemoteWorkingDirectory(); 579*fbb76349SGreg Clayton else 580*fbb76349SGreg Clayton return Platform::GetRemoteWorkingDirectory(); 581*fbb76349SGreg Clayton } 582*fbb76349SGreg Clayton 583*fbb76349SGreg Clayton bool 584*fbb76349SGreg Clayton PlatformPOSIX::SetRemoteWorkingDirectory(const lldb_private::ConstString &path) 585*fbb76349SGreg Clayton { 586*fbb76349SGreg Clayton if (IsRemote() && m_remote_platform_sp) 587*fbb76349SGreg Clayton return m_remote_platform_sp->SetRemoteWorkingDirectory(path); 588*fbb76349SGreg Clayton else 589*fbb76349SGreg Clayton return Platform::SetRemoteWorkingDirectory(path); 590*fbb76349SGreg Clayton } 591*fbb76349SGreg Clayton 592