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