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