xref: /haiku/src/kits/package/FetchFileJob.cpp (revision 04a0e9c7b68cbe3a43d38e2bca8e860fd80936fb)
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