diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/mobile_image_mounter.c | 122 | 
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:  }  /** + * Uploads an image to the device. + * + * @param client The connected mobile_image_mounter client. + * @param image_type Type of image that is being uploaded. + * @param image_size Total size of the image. + * @param upload_cb Callback function that gets the data chunks for uploading + *    the image. + * @param userdata User defined data for the upload callback function. + * + * @return MOBILE_IMAGE_MOUNTER_E_SUCCESS on succes, or a + *    MOBILE_IMAGE_MOUNTER_E_* error code otherwise. + */ +mobile_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) +{ +	if (!client || !image_type || (image_size == 0) || !upload_cb) { +		return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG; +	} +	mobile_image_mounter_lock(client); +	plist_t result = NULL; + +	plist_t dict = plist_new_dict(); +	plist_dict_insert_item(dict, "Command", plist_new_string("ReceiveBytes")); +	plist_dict_insert_item(dict, "ImageSize", plist_new_uint(image_size)); +	plist_dict_insert_item(dict, "ImageType", plist_new_string(image_type)); + +	mobile_image_mounter_error_t res = mobile_image_mounter_error(property_list_service_send_xml_plist(client->parent, dict)); +	plist_free(dict); + +	if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) { +		debug_info("Error sending XML plist to device!"); +		goto leave_unlock; +	} + +	res = mobile_image_mounter_error(property_list_service_receive_plist(client->parent, &result)); +	if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) { +		debug_info("Error receiving response from device!"); +		goto leave_unlock; +	} +	res = MOBILE_IMAGE_MOUNTER_E_COMMAND_FAILED; + +	char* strval = NULL; +	plist_t node = plist_dict_get_item(result, "Status"); +	if (node && plist_get_node_type(node) == PLIST_STRING) { +		plist_get_string_val(node, &strval); +	} +	if (!strval) { +		debug_info("Error: Unexpected response received!"); +		goto leave_unlock; +	} +	if (strcmp(strval, "ReceiveBytesAck") != 0) { +		debug_info("Error: didn't get ReceiveBytesAck but %s", strval); +		free(strval); +		goto leave_unlock; +	} +	free(strval); + +	size_t tx = 0; +	size_t bufsize = 65536; +	unsigned char *buf = (unsigned char*)malloc(bufsize); +	if (!buf) { +		debug_info("Out of memory"); +		res = MOBILE_IMAGE_MOUNTER_E_UNKNOWN_ERROR; +		goto leave_unlock; +	} +	debug_info("uploading image (%d bytes)", (int)image_size); +	while (tx < image_size) { +		size_t remaining = image_size - tx; +		size_t amount = (remaining < bufsize) ? remaining : bufsize; +		ssize_t r = upload_cb(buf, amount, userdata); +		if (r < 0) { +			debug_info("upload_cb returned %d", (int)r); +			break; +		} +		uint32_t sent = 0; +		if (service_send(client->parent->parent, (const char*)buf, (uint32_t)r, &sent) != SERVICE_E_SUCCESS) { +			debug_info("service_send failed"); +			break; +		} +		tx += r; +	} +	free(buf); +	if (tx < image_size) { +		debug_info("Error: failed to upload image"); +		goto leave_unlock; +	} +	debug_info("image uploaded"); + +	res = mobile_image_mounter_error(property_list_service_receive_plist(client->parent, &result)); +	if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) { +		debug_info("Error receiving response from device!"); +		goto leave_unlock; +	} +	res = MOBILE_IMAGE_MOUNTER_E_COMMAND_FAILED; + +	strval = NULL; +	node = plist_dict_get_item(result, "Status"); +	if (node && plist_get_node_type(node) == PLIST_STRING) { +		plist_get_string_val(node, &strval); +	} +	if (!strval) { +		debug_info("Error: Unexpected response received!");	 +		goto leave_unlock; +	} +	if (strcmp(strval, "Complete") != 0) { +		debug_info("Error: didn't get Complete but %s", strval); +		free(strval); +		goto leave_unlock; +	} else { +		res = MOBILE_IMAGE_MOUNTER_E_SUCCESS; +	} +	free(strval); +	 + +leave_unlock: +	mobile_image_mounter_unlock(client); +	if (result) +		plist_free(result); +	return res; + +} + +/**   * Mounts an image on the device.   *   * @param client The connected mobile_image_mounter client.  | 
