Error Platform::Install (const FileSpec& src, const FileSpec& dst) { Error error; Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); if (log) log->Printf ("Platform::Install (src='%s', dst='%s')", src.GetPath().c_str(), dst.GetPath().c_str()); FileSpec fixed_dst(dst); if (!fixed_dst.GetFilename()) fixed_dst.GetFilename() = src.GetFilename(); ConstString working_dir = GetWorkingDirectory(); if (dst) { if (dst.GetDirectory()) { const char first_dst_dir_char = dst.GetDirectory().GetCString()[0]; if (first_dst_dir_char == '/' || first_dst_dir_char == '\\') { fixed_dst.GetDirectory() = dst.GetDirectory(); } // If the fixed destination file doesn't have a directory yet, // then we must have a relative path. We will resolve this relative // path against the platform's working directory if (!fixed_dst.GetDirectory()) { FileSpec relative_spec; std::string path; if (working_dir) { relative_spec.SetFile(working_dir.GetCString(), false); relative_spec.AppendPathComponent(dst.GetPath().c_str()); fixed_dst.GetDirectory() = relative_spec.GetDirectory(); } else { error.SetErrorStringWithFormat("platform working directory must be valid for relative path '%s'", dst.GetPath().c_str()); return error; } } } else { if (working_dir) { fixed_dst.GetDirectory() = working_dir; } else { error.SetErrorStringWithFormat("platform working directory must be valid for relative path '%s'", dst.GetPath().c_str()); return error; } } } else { if (working_dir) { fixed_dst.GetDirectory() = working_dir; } else { error.SetErrorStringWithFormat("platform working directory must be valid when destination directory is empty"); return error; } } if (log) log->Printf ("Platform::Install (src='%s', dst='%s') fixed_dst='%s'", src.GetPath().c_str(), dst.GetPath().c_str(), fixed_dst.GetPath().c_str()); if (GetSupportsRSync()) { error = PutFile(src, dst); } else { switch (src.GetFileType()) { case FileSpec::eFileTypeDirectory: { if (GetFileExists (fixed_dst)) Unlink (fixed_dst.GetPath().c_str()); uint32_t permissions = src.GetPermissions(); if (permissions == 0) permissions = eFilePermissionsDirectoryDefault; std::string dst_dir_path(fixed_dst.GetPath()); error = MakeDirectory(dst_dir_path.c_str(), permissions); if (error.Success()) { // Make a filespec that only fills in the directory of a FileSpec so // when we enumerate we can quickly fill in the filename for dst copies FileSpec recurse_dst; recurse_dst.GetDirectory().SetCString(dst_dir_path.c_str()); std::string src_dir_path (src.GetPath()); RecurseCopyBaton baton = { recurse_dst, this, Error() }; FileSpec::EnumerateDirectory(src_dir_path.c_str(), true, true, true, RecurseCopy_Callback, &baton); return baton.error; } } break; case FileSpec::eFileTypeRegular: if (GetFileExists (fixed_dst)) Unlink (fixed_dst.GetPath().c_str()); error = PutFile(src, fixed_dst); break; case FileSpec::eFileTypeSymbolicLink: { if (GetFileExists (fixed_dst)) Unlink (fixed_dst.GetPath().c_str()); char buf[PATH_MAX]; error = Host::Readlink(src.GetPath().c_str(), buf, sizeof(buf)); if (error.Success()) error = CreateSymlink(dst.GetPath().c_str(), buf); } break; case FileSpec::eFileTypePipe: error.SetErrorString("platform install doesn't handle pipes"); break; case FileSpec::eFileTypeSocket: error.SetErrorString("platform install doesn't handle sockets"); break; case FileSpec::eFileTypeInvalid: case FileSpec::eFileTypeUnknown: case FileSpec::eFileTypeOther: error.SetErrorString("platform install doesn't handle non file or directory items"); break; } } return error; }