1 /* 2 * Copyright 2011-2013, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Oliver Tappe <zooey@hirschkaefer.de> 7 * Rene Gollent <rene@gollent.com> 8 */ 9 10 11 #include <package/FetchFileJob.h> 12 13 #include <stdio.h> 14 #include <curl/curl.h> 15 #include <sys/wait.h> 16 17 #include <Path.h> 18 19 20 namespace BPackageKit { 21 22 namespace BPrivate { 23 24 25 FetchFileJob::FetchFileJob(const BContext& context, const BString& title, 26 const BString& fileURL, const BEntry& targetEntry) 27 : 28 inherited(context, title), 29 fFileURL(fileURL), 30 fTargetEntry(targetEntry), 31 fTargetFile(&targetEntry, B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY), 32 fDownloadProgress(0.0) 33 { 34 } 35 36 37 FetchFileJob::~FetchFileJob() 38 { 39 } 40 41 42 float 43 FetchFileJob::DownloadProgress() const 44 { 45 return fDownloadProgress; 46 } 47 48 49 const char* 50 FetchFileJob::DownloadURL() const 51 { 52 return fFileURL.String(); 53 } 54 55 56 const char* 57 FetchFileJob::DownloadFileName() const 58 { 59 return fTargetEntry.Name(); 60 } 61 62 63 status_t 64 FetchFileJob::Execute() 65 { 66 status_t result = fTargetFile.InitCheck(); 67 if (result != B_OK) 68 return result; 69 70 CURL* handle = curl_easy_init(); 71 72 if (handle == NULL) 73 return B_NO_MEMORY; 74 75 result = curl_easy_setopt(handle, CURLOPT_NOPROGRESS, 0); 76 77 result = curl_easy_setopt(handle, CURLOPT_PROGRESSFUNCTION, 78 &_ProgressCallback); 79 if (result != CURLE_OK) 80 return B_BAD_VALUE; 81 82 result = curl_easy_setopt(handle, CURLOPT_PROGRESSDATA, this); 83 if (result != CURLE_OK) 84 return B_ERROR; 85 86 result = curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, 87 &_WriteCallback); 88 if (result != CURLE_OK) 89 return B_ERROR; 90 91 result = curl_easy_setopt(handle, CURLOPT_WRITEDATA, this); 92 if (result != CURLE_OK) 93 return B_ERROR; 94 95 result = curl_easy_setopt(handle, CURLOPT_PROGRESSFUNCTION, 96 &_ProgressCallback); 97 if (result != CURLE_OK) 98 return B_ERROR; 99 100 result = curl_easy_setopt(handle, CURLOPT_URL, fFileURL.String()); 101 if (result != CURLE_OK) 102 return B_ERROR; 103 104 result = curl_easy_perform(handle); 105 curl_easy_cleanup(handle); 106 if (result != CURLE_OK) { 107 // TODO: map more curl error codes to ours for more 108 // precise error reporting 109 return B_ERROR; 110 } 111 112 return B_OK; 113 } 114 115 116 int 117 FetchFileJob::_ProgressCallback(void *userp, double dltotal, double dlnow, 118 double ultotal, double ulnow) 119 { 120 FetchFileJob* job = reinterpret_cast<FetchFileJob*>(userp); 121 if (dltotal != 0) { 122 job->fDownloadProgress = dlnow / dltotal; 123 job->NotifyStateListeners(); 124 } 125 return 0; 126 } 127 128 129 size_t 130 FetchFileJob::_WriteCallback(void *buffer, size_t size, size_t nmemb, 131 void *userp) 132 { 133 FetchFileJob* job = reinterpret_cast<FetchFileJob*>(userp); 134 ssize_t dataWritten = job->fTargetFile.Write(buffer, size * nmemb); 135 return size_t(dataWritten); 136 } 137 138 139 void 140 FetchFileJob::Cleanup(status_t jobResult) 141 { 142 if (jobResult != B_OK) 143 fTargetEntry.Remove(); 144 } 145 146 147 } // namespace BPrivate 148 149 } // namespace BPackageKit 150