summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2014-02-09 22:31:00 +0100
committerGravatar Nikias Bassen2014-02-09 22:31:00 +0100
commit31602444c0bd71cbea320d02a12c2a8e66ef4e32 (patch)
treedd4924d52041ad846806ce4407e4e96053618844 /src
parentd3aaca14c8926c8b4e315d912266b093ff8a6de4 (diff)
downloadlibimobiledevice-31602444c0bd71cbea320d02a12c2a8e66ef4e32.tar.gz
libimobiledevice-31602444c0bd71cbea320d02a12c2a8e66ef4e32.tar.bz2
mobile_image_mounter: implemented new image file uploading method
Diffstat (limited to 'src')
-rw-r--r--src/mobile_image_mounter.c122
1 files changed, 122 insertions, 0 deletions
diff --git a/src/mobile_image_mounter.c b/src/mobile_image_mounter.c
index bc439f9..9e6d8e9 100644
--- a/src/mobile_image_mounter.c
+++ b/src/mobile_image_mounter.c
@@ -190,6 +190,128 @@ leave_unlock:
190} 190}
191 191
192/** 192/**
193 * Uploads an image to the device.
194 *
195 * @param client The connected mobile_image_mounter client.
196 * @param image_type Type of image that is being uploaded.
197 * @param image_size Total size of the image.
198 * @param upload_cb Callback function that gets the data chunks for uploading
199 * the image.
200 * @param userdata User defined data for the upload callback function.
201 *
202 * @return MOBILE_IMAGE_MOUNTER_E_SUCCESS on succes, or a
203 * MOBILE_IMAGE_MOUNTER_E_* error code otherwise.
204 */
205mobile_image_mounter_error_t mobile_image_mounter_upload_image(mobile_image_mounter_client_t client, const char *image_type, size_t image_size, mobile_image_mounter_upload_cb_t upload_cb, void* userdata)
206{
207 if (!client || !image_type || (image_size == 0) || !upload_cb) {
208 return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG;
209 }
210 mobile_image_mounter_lock(client);
211 plist_t result = NULL;
212
213 plist_t dict = plist_new_dict();
214 plist_dict_insert_item(dict, "Command", plist_new_string("ReceiveBytes"));
215 plist_dict_insert_item(dict, "ImageSize", plist_new_uint(image_size));
216 plist_dict_insert_item(dict, "ImageType", plist_new_string(image_type));
217
218 mobile_image_mounter_error_t res = mobile_image_mounter_error(property_list_service_send_xml_plist(client->parent, dict));
219 plist_free(dict);
220
221 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
222 debug_info("Error sending XML plist to device!");
223 goto leave_unlock;
224 }
225
226 res = mobile_image_mounter_error(property_list_service_receive_plist(client->parent, &result));
227 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
228 debug_info("Error receiving response from device!");
229 goto leave_unlock;
230 }
231 res = MOBILE_IMAGE_MOUNTER_E_COMMAND_FAILED;
232
233 char* strval = NULL;
234 plist_t node = plist_dict_get_item(result, "Status");
235 if (node && plist_get_node_type(node) == PLIST_STRING) {
236 plist_get_string_val(node, &strval);
237 }
238 if (!strval) {
239 debug_info("Error: Unexpected response received!");
240 goto leave_unlock;
241 }
242 if (strcmp(strval, "ReceiveBytesAck") != 0) {
243 debug_info("Error: didn't get ReceiveBytesAck but %s", strval);
244 free(strval);
245 goto leave_unlock;
246 }
247 free(strval);
248
249 size_t tx = 0;
250 size_t bufsize = 65536;
251 unsigned char *buf = (unsigned char*)malloc(bufsize);
252 if (!buf) {
253 debug_info("Out of memory");
254 res = MOBILE_IMAGE_MOUNTER_E_UNKNOWN_ERROR;
255 goto leave_unlock;
256 }
257 debug_info("uploading image (%d bytes)", (int)image_size);
258 while (tx < image_size) {
259 size_t remaining = image_size - tx;
260 size_t amount = (remaining < bufsize) ? remaining : bufsize;
261 ssize_t r = upload_cb(buf, amount, userdata);
262 if (r < 0) {
263 debug_info("upload_cb returned %d", (int)r);
264 break;
265 }
266 uint32_t sent = 0;
267 if (service_send(client->parent->parent, (const char*)buf, (uint32_t)r, &sent) != SERVICE_E_SUCCESS) {
268 debug_info("service_send failed");
269 break;
270 }
271 tx += r;
272 }
273 free(buf);
274 if (tx < image_size) {
275 debug_info("Error: failed to upload image");
276 goto leave_unlock;
277 }
278 debug_info("image uploaded");
279
280 res = mobile_image_mounter_error(property_list_service_receive_plist(client->parent, &result));
281 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
282 debug_info("Error receiving response from device!");
283 goto leave_unlock;
284 }
285 res = MOBILE_IMAGE_MOUNTER_E_COMMAND_FAILED;
286
287 strval = NULL;
288 node = plist_dict_get_item(result, "Status");
289 if (node && plist_get_node_type(node) == PLIST_STRING) {
290 plist_get_string_val(node, &strval);
291 }
292 if (!strval) {
293 debug_info("Error: Unexpected response received!");
294 goto leave_unlock;
295 }
296 if (strcmp(strval, "Complete") != 0) {
297 debug_info("Error: didn't get Complete but %s", strval);
298 free(strval);
299 goto leave_unlock;
300 } else {
301 res = MOBILE_IMAGE_MOUNTER_E_SUCCESS;
302 }
303 free(strval);
304
305
306leave_unlock:
307 mobile_image_mounter_unlock(client);
308 if (result)
309 plist_free(result);
310 return res;
311
312}
313
314/**
193 * Mounts an image on the device. 315 * Mounts an image on the device.
194 * 316 *
195 * @param client The connected mobile_image_mounter client. 317 * @param client The connected mobile_image_mounter client.