diff options
Diffstat (limited to 'tools/idevicebackup4.c')
| -rw-r--r-- | tools/idevicebackup4.c | 1674 | 
1 files changed, 0 insertions, 1674 deletions
| diff --git a/tools/idevicebackup4.c b/tools/idevicebackup4.c deleted file mode 100644 index b34064e..0000000 --- a/tools/idevicebackup4.c +++ /dev/null @@ -1,1674 +0,0 @@ -/* - * idevicebackup4.c - * Command line interface to use the device's backup and restore service - * - * Copyright (c) 2009-2010 Martin Szulecki All Rights Reserved. - * Copyright (c) 2010      Nikias Bassen All Rights Reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA  - */ - -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <stdlib.h> -#include <signal.h> -#include <glib.h> -#include <glib/gstdio.h> -#include <gcrypt.h> -#include <unistd.h> - -#include <libimobiledevice/libimobiledevice.h> -#include <libimobiledevice/lockdown.h> -#include <libimobiledevice/mobilebackup2.h> -#include <libimobiledevice/notification_proxy.h> -#include <libimobiledevice/afc.h> - -#define MOBILEBACKUP2_SERVICE_NAME "com.apple.mobilebackup2" -#define NP_SERVICE_NAME "com.apple.mobile.notification_proxy" - -#define LOCK_ATTEMPTS 50 -#define LOCK_WAIT 200000 - -#define CODE_SUCCESS 0x00 -#define CODE_ERROR_LOCAL 0x06 -#define CODE_ERROR_REMOTE 0x0b -#define CODE_FILE_DATA 0x0c - -static mobilebackup2_client_t mobilebackup2 = NULL; -static lockdownd_client_t client = NULL; -static afc_client_t afc = NULL; -static idevice_t phone = NULL; - -static int verbose = 1; -static int quit_flag = 0; - -#define PRINT_VERBOSE(min_level, ...) if (verbose >= min_level) { printf(__VA_ARGS__); }; - -enum cmd_mode { -	CMD_BACKUP, -	CMD_RESTORE, -	CMD_INFO, -	CMD_LIST, -	CMD_LEAVE -}; - -enum plist_format_t { -	PLIST_FORMAT_XML, -	PLIST_FORMAT_BINARY -}; - -static void notify_cb(const char *notification, void *userdata) -{ -	if (!strcmp(notification, NP_SYNC_CANCEL_REQUEST)) { -		PRINT_VERBOSE(1, "User has cancelled the backup process on the device.\n"); -		quit_flag++; -	} else { -		PRINT_VERBOSE(1, "Unhandled notification '%s' (TODO: implement)\n", notification); -	} -} - -static void free_dictionary(char **dictionary) -{ -	int i = 0; - -	if (!dictionary) -		return; - -	for (i = 0; dictionary[i]; i++) { -		free(dictionary[i]); -	} -	free(dictionary); -} - -static void mobilebackup_afc_get_file_contents(const char *filename, char **data, uint64_t *size) -{ -	if (!afc || !data || !size) { -		return; -	} - -	char **fileinfo = NULL; -	uint32_t fsize = 0; -		 -	afc_get_file_info(afc, filename, &fileinfo); -	if (!fileinfo) { -		return; -	} -	int i; -	for (i = 0; fileinfo[i]; i+=2) { -		if (!strcmp(fileinfo[i], "st_size")) { -			fsize = atol(fileinfo[i+1]); -			break; -		} -	} -	free_dictionary(fileinfo); - -	if (fsize == 0) { -		return; -	} -		 -	uint64_t f = 0; -	afc_file_open(afc, filename, AFC_FOPEN_RDONLY, &f); -	if (!f) { -		return; -	} -	char *buf = (char*)malloc((uint32_t)fsize); -	uint32_t done = 0; -	while (done < fsize) { -		uint32_t bread = 0; -		afc_file_read(afc, f, buf+done, 65536, &bread); -		if (bread > 0) { -			 -		} else { -			break; -		} -		done += bread; -	} -	if (done == fsize) { -		*size = fsize; -		*data = buf; -	} else { -		free(buf); -	} -	afc_file_close(afc, f); -} - -static plist_t mobilebackup_factory_info_plist_new() -{ -	/* gather data from lockdown */ -	GTimeVal tv = {0, 0}; -	plist_t value_node = NULL; -	plist_t root_node = NULL; -	char *uuid = NULL; -	char *uuid_uppercase = NULL; - -	plist_t ret = plist_new_dict(); - -	/* get basic device information in one go */ -	lockdownd_get_value(client, NULL, NULL, &root_node); - -	/* set fields we understand */ -	value_node = plist_dict_get_item(root_node, "BuildVersion"); -	plist_dict_insert_item(ret, "Build Version", plist_copy(value_node)); - -	value_node = plist_dict_get_item(root_node, "DeviceName"); -	plist_dict_insert_item(ret, "Device Name", plist_copy(value_node)); -	plist_dict_insert_item(ret, "Display Name", plist_copy(value_node)); - -	/* FIXME: How is the GUID generated? */ -	plist_dict_insert_item(ret, "GUID", plist_new_string("---")); - -	value_node = plist_dict_get_item(root_node, "IntegratedCircuitCardIdentity"); -	if (value_node) -		plist_dict_insert_item(ret, "ICCID", plist_copy(value_node)); - -	value_node = plist_dict_get_item(root_node, "InternationalMobileEquipmentIdentity"); -	if (value_node) -		plist_dict_insert_item(ret, "IMEI", plist_copy(value_node)); - -	g_get_current_time(&tv); -	plist_dict_insert_item(ret, "Last Backup Date", plist_new_date(tv.tv_sec, 0)); - -	value_node = plist_dict_get_item(root_node, "PhoneNumber"); -	if (value_node && (plist_get_node_type(value_node) == PLIST_STRING)) { -		plist_dict_insert_item(ret, "Phone Number", plist_copy(value_node)); -	} - -	value_node = plist_dict_get_item(root_node, "ProductType"); -	plist_dict_insert_item(ret, "Product Type", plist_copy(value_node)); - -	value_node = plist_dict_get_item(root_node, "ProductVersion"); -	plist_dict_insert_item(ret, "Product Version", plist_copy(value_node)); - -	value_node = plist_dict_get_item(root_node, "SerialNumber"); -	plist_dict_insert_item(ret, "Serial Number", plist_copy(value_node)); - -	/* FIXME Sync Settings? */ - -	value_node = plist_dict_get_item(root_node, "UniqueDeviceID"); -	idevice_get_uuid(phone, &uuid); -	plist_dict_insert_item(ret, "Target Identifier", plist_new_string(uuid)); - -	plist_dict_insert_item(ret, "Target Type", plist_new_string("Device")); - -	/* uppercase */ -	uuid_uppercase = g_ascii_strup(uuid, -1); -	plist_dict_insert_item(ret, "Unique Identifier", plist_new_string(uuid_uppercase)); -	free(uuid_uppercase); -	free(uuid); - -	char *data_buf = NULL; -	uint64_t data_size = 0; -	mobilebackup_afc_get_file_contents("/Books/iBooksData2.plist", &data_buf, &data_size); -	if (data_buf) { -		plist_dict_insert_item(ret, "iBooks Data 2", plist_new_data(data_buf, data_size)); -		free(data_buf); -	} - -	plist_t files = plist_new_dict(); -	const char *itunesfiles[] = { -		"ApertureAlbumPrefs", -		"IC-Info.sidb", -		"IC-Info.sidv", -		"PhotosFolderAlbums", -		"PhotosFolderName", -		"PhotosFolderPrefs", -		"iPhotoAlbumPrefs", -		"iTunesApplicationIDs", -		"iTunesPrefs", -		"iTunesPrefs.plist", -		NULL -	}; -	int i = 0; -	for (i = 0; itunesfiles[i]; i++) { -		data_buf = NULL; -		data_size = 0; -		gchar *fname = g_strconcat("/iTunes_Control/iTunes/", itunesfiles[i], NULL); -		mobilebackup_afc_get_file_contents(fname, &data_buf, &data_size); -		g_free(fname); -		if (data_buf) { -			plist_dict_insert_item(files, itunesfiles[i], plist_new_data(data_buf, data_size)); -			free(data_buf); -		} -	} -	plist_dict_insert_item(ret, "iTunes Files", files); - -	plist_t itunes_settings = plist_new_dict(); -	lockdownd_get_value(client, "com.apple.iTunes", NULL, &itunes_settings); -	plist_dict_insert_item(ret, "iTunes Settings", itunes_settings); - -	plist_dict_insert_item(ret, "iTunes Version", plist_new_string("10.0.1")); - -	plist_free(root_node); - -	return ret; -} - -static void buffer_read_from_filename(const char *filename, char **buffer, uint64_t *length) -{ -	FILE *f; -	uint64_t size; - -	*length = 0; - -	f = fopen(filename, "rb"); -	if (!f) { -		return; -	} - -	fseek(f, 0, SEEK_END); -	size = ftell(f); -	rewind(f); - -	if (size == 0) { -		return; -	} - -	*buffer = (char*)malloc(sizeof(char)*size); -	fread(*buffer, sizeof(char), size, f); -	fclose(f); - -	*length = size; -} - -static void buffer_write_to_filename(const char *filename, const char *buffer, uint64_t length) -{ -	FILE *f; - -	f = fopen(filename, "ab"); -	if (!f) -		f = fopen(filename, "wb"); -	if (f) { -		fwrite(buffer, sizeof(char), length, f); -		fclose(f); -	} -} - -static int plist_read_from_filename(plist_t *plist, const char *filename) -{ -	char *buffer = NULL; -	uint64_t length; - -	if (!filename) -		return 0; - -	buffer_read_from_filename(filename, &buffer, &length); - -	if (!buffer) { -		return 0; -	} - -	if ((length > 8) && (memcmp(buffer, "bplist00", 8) == 0)) { -		plist_from_bin(buffer, length, plist); -	} else { -		plist_from_xml(buffer, length, plist); -	} - -	free(buffer); - -	return 1; -} - -static int plist_write_to_filename(plist_t plist, const char *filename, enum plist_format_t format) -{ -	char *buffer = NULL; -	uint32_t length; - -	if (!plist || !filename) -		return 0; - -	if (format == PLIST_FORMAT_XML) -		plist_to_xml(plist, &buffer, &length); -	else if (format == PLIST_FORMAT_BINARY) -		plist_to_bin(plist, &buffer, &length); -	else -		return 0; - -	buffer_write_to_filename(filename, buffer, length); - -	free(buffer); - -	return 1; -} - -static int mb2_status_check_snapshot_state(const char *path, const char *uuid, const char *matches) -{ -	int ret = -1; -	plist_t status_plist = NULL; -	gchar *file_path = g_build_path(G_DIR_SEPARATOR_S, path, uuid, "Status.plist", NULL); - -	plist_read_from_filename(&status_plist, file_path); -	g_free(file_path); -	if (!status_plist) { -		printf("Could not read Status.plist!\n"); -		return ret; -	} -	plist_t node = plist_dict_get_item(status_plist, "SnapshotState"); -	if (node && (plist_get_node_type(node) == PLIST_STRING)) { -		char* sval = NULL; -		plist_get_string_val(node, &sval); -		if (sval) { -			ret = (strcmp(sval, matches) == 0) ? 1 : 0; -		} -	} else { -		printf("%s: ERROR could not get SnapshotState key from Status.plist!\n", __func__); -	} -	plist_free(status_plist); -	return ret; -} - -static int mobilebackup_info_is_current_device(plist_t info) -{ -	plist_t value_node = NULL; -	plist_t node = NULL; -	plist_t root_node = NULL; -	int ret = 0; - -	if (!info) -		return ret; - -	if (plist_get_node_type(info) != PLIST_DICT) -		return ret; - -	/* get basic device information in one go */ -	lockdownd_get_value(client, NULL, NULL, &root_node); - -	/* verify UUID */ -	value_node = plist_dict_get_item(root_node, "UniqueDeviceID"); -	node = plist_dict_get_item(info, "Target Identifier"); - -	if(plist_compare_node_value(value_node, node)) -		ret = 1; -	else { -		printf("Info.plist: UniqueDeviceID does not match.\n"); -	} - -	/* verify SerialNumber */ -	if (ret == 1) { -		value_node = plist_dict_get_item(root_node, "SerialNumber"); -		node = plist_dict_get_item(info, "Serial Number"); - -		if(plist_compare_node_value(value_node, node)) -			ret = 1; -		else { -			printf("Info.plist: SerialNumber does not match.\n"); -			ret = 0; -		} -	} - -	/* verify ProductVersion to prevent using backup with different OS version */ -	if (ret == 1) { -		value_node = plist_dict_get_item(root_node, "ProductVersion"); -		node = plist_dict_get_item(info, "Product Version"); - -		if(plist_compare_node_value(value_node, node)) -			ret = 1; -		else { -			printf("Info.plist: ProductVersion does not match.\n"); -			ret = 0; -		} -	} - -	plist_free(root_node); -	root_node = NULL; - -	value_node = NULL; -	node = NULL; - -	return ret; -} - -static void do_post_notification(const char *notification) -{ -	uint16_t nport = 0; -	np_client_t np; - -	if (!client) { -		if (lockdownd_client_new_with_handshake(phone, &client, "idevicebackup") != LOCKDOWN_E_SUCCESS) { -			return; -		} -	} - -	lockdownd_start_service(client, NP_SERVICE_NAME, &nport); -	if (nport) { -		np_client_new(phone, nport, &np); -		if (np) { -			np_post_notification(np, notification); -			np_client_free(np); -		} -	} else { -		printf("Could not start %s\n", NP_SERVICE_NAME); -	} -} - -static void print_progress_real(double progress, int flush) -{ -	int i = 0; -	PRINT_VERBOSE(1, "\r["); -	for(i = 0; i < 50; i++) { -		if(i < progress / 2) { -			PRINT_VERBOSE(1, "="); -		} else { -			PRINT_VERBOSE(1, " "); -		} -	} -	PRINT_VERBOSE(1, "] %3.0f%%", progress); - -	if (flush > 0) { -		fflush(stdout); -		if (progress == 100) -			PRINT_VERBOSE(1, "\n"); -	} -} - -static void print_progress(uint64_t current, uint64_t total) -{ -	gchar *format_size = NULL; -	double progress = ((double)current/(double)total)*100; -	if (progress < 0) -		return; - -	if (progress > 100) -		progress = 100; - -	print_progress_real((double)progress, 0); - -	format_size = g_format_size_for_display(current); -	PRINT_VERBOSE(1, " (%s", format_size); -	g_free(format_size); -	format_size = g_format_size_for_display(total); -	PRINT_VERBOSE(1, "/%s)     ", format_size); -	g_free(format_size); - -	fflush(stdout); -	if (progress == 100) -		PRINT_VERBOSE(1, "\n"); -} - -static void mb2_multi_status_add_file_error(plist_t status_dict, const char *path, int error_code, const char *error_message) -{ -	if (!status_dict) return; -	plist_t filedict = plist_new_dict(); -	plist_dict_insert_item(filedict, "DLFileErrorString", plist_new_string(error_message)); -	plist_dict_insert_item(filedict, "DLFileErrorCode", plist_new_uint(error_code)); -	plist_dict_insert_item(status_dict, path, filedict); -} - -static int errno_to_device_error(int errno_value) -{ -	switch (errno_value) { -		case ENOENT: -			return -6; -		case EEXIST: -			return -7; -		default: -			return -errno_value; -	} -} - -static int mb2_handle_send_file(const char *backup_dir, const char *path, plist_t *errplist) -{ -	uint32_t nlen = 0; -	uint32_t pathlen = strlen(path); -	uint32_t bytes = 0; -	gchar *localfile = g_build_path(G_DIR_SEPARATOR_S, backup_dir, path, NULL); -	char buf[32768]; -	struct stat fst; - -	FILE *f = NULL; -	uint32_t slen = 0; -	int errcode = -1; -	int result = -1; -	uint32_t length; -	off_t total; -	off_t sent; - -	mobilebackup2_error_t err; - -	/* send path length */ -	nlen = GUINT32_TO_BE(pathlen); -	err = mobilebackup2_send_raw(mobilebackup2, (const char*)&nlen, sizeof(nlen), &bytes); -	if (err != MOBILEBACKUP2_E_SUCCESS) { -		goto leave_proto_err; -	} -	if (bytes != (uint32_t)sizeof(nlen)) { -		err = MOBILEBACKUP2_E_MUX_ERROR; -		goto leave_proto_err; -	} - -	/* send path */ -	err = mobilebackup2_send_raw(mobilebackup2, path, pathlen, &bytes); -	if (err != MOBILEBACKUP2_E_SUCCESS) { -		goto leave_proto_err; -	} -	if (bytes != pathlen) { -		err = MOBILEBACKUP2_E_MUX_ERROR; -		goto leave_proto_err; -	} - -	if (stat(localfile, &fst) < 0) { -		if (errno != ENOENT) -			printf("%s: stat failed on '%s': %d\n", __func__, localfile, errno); -		errcode = errno; -		goto leave; -	} - -	total = fst.st_size; - -	gchar *format_size = g_format_size_for_display(total); -	PRINT_VERBOSE(1, "Sending file '%s': (%s)\n", path, format_size); -	g_free(format_size); - -	if (total == 0) { -		errcode = 0; -		goto leave; -	} - -	f = fopen(localfile, "rb"); -	if (!f) { -		printf("%s: Error opening local file '%s': %d\n", __func__, localfile, errno); -		errcode = errno; -		goto leave; -	} - -	sent = 0; -	do { -		length = ((total-sent) < (off_t)sizeof(buf)) ? (uint32_t)total-sent : (uint32_t)sizeof(buf); -		/* send data size (file size + 1) */ -		nlen = GUINT32_TO_BE(length+1); -		memcpy(buf, &nlen, sizeof(nlen)); -		buf[4] = CODE_FILE_DATA; -		err = mobilebackup2_send_raw(mobilebackup2, (const char*)buf, 5, &bytes); -		if (err != MOBILEBACKUP2_E_SUCCESS) { -			goto leave_proto_err; -		} -		if (bytes != 5) { -			goto leave_proto_err; -		} - -		/* send file contents */ -		size_t r = fread(buf, 1, sizeof(buf), f); -		if (r <= 0) { -			printf("%s: read error\n", __func__); -			errcode = errno; -			goto leave; -		} -		err = mobilebackup2_send_raw(mobilebackup2, buf, r, &bytes); -		if (err != MOBILEBACKUP2_E_SUCCESS) { -			goto leave_proto_err; -		} -		if (bytes != (uint32_t)r) { -			printf("Error: sent only %d of %d bytes\n", bytes, (int)r); -			goto leave_proto_err; -		} -		sent += r; -	} while (sent < total); -	fclose(f); -	f = NULL; -	errcode = 0; - -leave: -	if (errcode == 0) { -		result = 0; -		nlen = 1; -		nlen = GUINT32_TO_BE(nlen); -		memcpy(buf, &nlen, 4); -		buf[4] = CODE_SUCCESS; -		mobilebackup2_send_raw(mobilebackup2, buf, 5, &bytes); -	} else { -		if (!*errplist) { -			*errplist = plist_new_dict(); -		} -		char *errdesc = strerror(errcode); -		mb2_multi_status_add_file_error(*errplist, path, errno_to_device_error(errcode), errdesc); -		 -		length = strlen(errdesc); -		nlen = GUINT32_TO_BE(length+1); -		memcpy(buf, &nlen, 4); -		buf[4] = CODE_ERROR_LOCAL; -		slen = 5; -		memcpy(buf+slen, errdesc, length); -		slen += length; -		err = mobilebackup2_send_raw(mobilebackup2, (const char*)buf, slen, &bytes); -		if (err != MOBILEBACKUP2_E_SUCCESS) { -			printf("could not send message\n"); -		} -		if (bytes != slen) { -			printf("could only send %d from %d\n", bytes, slen); -		} -	} - -leave_proto_err: -	if (f) -		fclose(f); -	g_free(localfile); -	return result; -} - -static void mb2_handle_send_files(plist_t message, const char *backup_dir) -{ -	uint32_t cnt;  -	uint32_t i = 0; -	uint32_t sent; -	plist_t errplist = NULL; -	double progress = 0; -	 -	if (!message || (plist_get_node_type(message) != PLIST_ARRAY) || (plist_array_get_size(message) < 2) || !backup_dir) return; - -	plist_t files = plist_array_get_item(message, 1); -	cnt = plist_array_get_size(files); -	if (cnt == 0) return; - -	plist_t val = plist_array_get_item(message, 3); -	plist_get_real_val(val, &progress); -	val = NULL; - -	for (i = 0; i < cnt; i++) { -		val = plist_array_get_item(files, i); -		if (plist_get_node_type(val) != PLIST_STRING) { -			continue; -		} -		char *str = NULL; -		plist_get_string_val(val, &str); -		if (!str) -			continue; - -		if (mb2_handle_send_file(backup_dir, str, &errplist) < 0) { -			//printf("Error when sending file '%s' to device\n", str); -			// TODO: perhaps we can continue, we've got a multi status response?! -			break; -		} -	} - -	/* send terminating 0 dword */ -	uint32_t zero = 0; -	mobilebackup2_send_raw(mobilebackup2, (char*)&zero, 4, &sent); - -	if (!errplist) { -		mobilebackup2_send_status_response(mobilebackup2, 0, NULL, plist_new_dict()); -	} else { -		mobilebackup2_send_status_response(mobilebackup2, -13, "Multi status", errplist); -		plist_free(errplist); -	} - -	if (progress > 0) { -		print_progress_real(progress, 1); -		PRINT_VERBOSE(1, "\n"); -	} -} - -static int mb2_handle_receive_files(plist_t message, const char *backup_dir) -{ -	uint64_t backup_real_size = 0; -	uint64_t backup_total_size = 0; -	uint32_t blocksize; -	uint32_t bdone; -	uint32_t rlen; -	uint32_t nlen = 0; -	uint32_t r; -	char buf[32768]; -	char *fname = NULL; -	char *dname = NULL; -	gchar *bname = NULL; -	char code = 0; -	char last_code = 0; -	plist_t node = NULL; -	FILE *f = NULL; -	unsigned int file_count = 0; - -	if (!message || (plist_get_node_type(message) != PLIST_ARRAY) || plist_array_get_size(message) < 4 || !backup_dir) return 0; - -	node = plist_array_get_item(message, 3); -	if (plist_get_node_type(node) == PLIST_UINT) { -		plist_get_uint_val(node, &backup_total_size); -	} -	if (backup_total_size > 0) { -		PRINT_VERBOSE(1, "Receiving backup data\n"); -	} - -	do { -		if (quit_flag) -			break; -		r = 0; -		mobilebackup2_receive_raw(mobilebackup2, (char*)&nlen, 4, &r); -		nlen = GUINT32_FROM_BE(nlen); -		if (nlen == 0) { -			// we're done here -			break; -		} else if (nlen > 4096) { -			// too very long path -			printf("ERROR: %s: too long device filename (%d)!\n", __func__, nlen); -			break; -		} -		if (dname != NULL) -			free(dname); -		dname = (char*)malloc(nlen+1); -		r = 0; -		mobilebackup2_receive_raw(mobilebackup2, dname, nlen, &r); -		if (r != nlen) { -			printf("ERROR: %s: could not read device filename\n", __func__); -			break; -		} -		dname[r] = 0; -		nlen = 0; -		mobilebackup2_receive_raw(mobilebackup2, (char*)&nlen, 4, &r); -		nlen = GUINT32_FROM_BE(nlen); -		if (nlen == 0) { -			printf("ERROR: %s: zero-length backup filename!\n", __func__); -			break; -		} else if (nlen > 4096) { -			printf("ERROR: %s: too long backup filename (%d)!\n", __func__, nlen); -			break; -		} -		fname = (char*)malloc(nlen+1); -		mobilebackup2_receive_raw(mobilebackup2, fname, nlen, &r); -		if (r != nlen) { -			printf("ERROR: %s: could not receive backup filename!\n", __func__); -			break; -		} -		fname[r] = 0; -		if (bname != NULL) -			g_free(bname); -		bname = g_build_path(G_DIR_SEPARATOR_S, backup_dir, fname, NULL); -		free(fname); -		nlen = 0; -		mobilebackup2_receive_raw(mobilebackup2, (char*)&nlen, 4, &r); -		if (r != 4) { -			printf("ERROR: %s: could not receive code length!\n", __func__); -			break; -		} -		nlen = GUINT32_FROM_BE(nlen); -		last_code = code; -		code = 0; -		mobilebackup2_receive_raw(mobilebackup2, &code, 1, &r); -		if (r != 1) { -			printf("ERROR: %s: could not receive code!\n", __func__); -			break; -		} - -		/* TODO remove this */ -		if ((code != CODE_SUCCESS) && (code != CODE_FILE_DATA) && (code != CODE_ERROR_REMOTE)) { -			PRINT_VERBOSE(1, "Found new flag %02x\n", code); -		} - -		remove(bname); -		f = fopen(bname, "wb"); -		while (f && (code == CODE_FILE_DATA)) { -			blocksize = nlen-1; -			bdone = 0; -			rlen = 0; -			while (bdone < blocksize) { -				if ((blocksize - bdone) < sizeof(buf)) { -					rlen = blocksize - bdone; -				} else { -					rlen = sizeof(buf); -				} -				mobilebackup2_receive_raw(mobilebackup2, buf, rlen, &r); -				if ((int)r <= 0) { -					break; -				} -				fwrite(buf, 1, r, f); -				bdone += r; -			} -			if (bdone == blocksize) { -				backup_real_size += blocksize; -			} -			if (backup_total_size > 0) { -				print_progress(backup_real_size, backup_total_size); -			} -			if (quit_flag) -				break; -			nlen = 0; -			mobilebackup2_receive_raw(mobilebackup2, (char*)&nlen, 4, &r); -			nlen = GUINT32_FROM_BE(nlen); -			if (nlen > 0) { -				last_code = code; -				mobilebackup2_receive_raw(mobilebackup2, &code, 1, &r); -			} else { -				break; -			} -		} -		if (f) { -			fclose(f); -			file_count++; -		} else { -			printf("Error opening '%s' for writing: %s\n", bname, strerror(errno)); -		} -		if (nlen == 0) { -			break; -		} - -		/* check if an error message was received */ -		if (code == CODE_ERROR_REMOTE) { -			/* error message */ -			char *msg = (char*)malloc(nlen); -			mobilebackup2_receive_raw(mobilebackup2, msg, nlen-1, &r); -			msg[r] = 0; -			/* If sent using CODE_FILE_DATA, end marker will be CODE_ERROR_REMOTE which is not an error! */ -			if (last_code != CODE_FILE_DATA) { -				fprintf(stdout, "\nReceived an error message from device: %s\n", msg); -			} -			free(msg); -		} -	} while (1); - -	/* if there are leftovers to read, finish up cleanly */ -	if ((int)nlen-1 > 0) { -		PRINT_VERBOSE(1, "\nDiscarding current data hunk.\n"); -		fname = (char*)malloc(nlen-1); -		mobilebackup2_receive_raw(mobilebackup2, fname, nlen-1, &r); -		free(fname); -		remove(bname); -	} - -	/* clean up */ -	if (bname != NULL) -		g_free(bname); - -	if (dname != NULL) -		free(dname); - -	// TODO error handling?! -	mobilebackup2_send_status_response(mobilebackup2, 0, NULL, plist_new_dict()); -	return file_count; -} - -static void mb2_handle_list_directory(plist_t message, const char *backup_dir) -{ -	if (!message || (plist_get_node_type(message) != PLIST_ARRAY) || plist_array_get_size(message) < 2 || !backup_dir) return; - -	plist_t node = plist_array_get_item(message, 1); -	char *str = NULL; -	if (plist_get_node_type(node) == PLIST_STRING) { -		plist_get_string_val(node, &str); -	} -	if (!str) { -		printf("ERROR: Malformed DLContentsOfDirectory message\n"); -		// TODO error handling -		return; -	} - -	gchar *path = g_build_path(G_DIR_SEPARATOR_S, backup_dir, str, NULL); -	free(str); - -	plist_t dirlist = plist_new_dict(); - -	GDir *cur_dir = g_dir_open(path, 0, NULL); -	if (cur_dir) { -		gchar *dir_file; -		while ((dir_file = (gchar *)g_dir_read_name(cur_dir))) { -			gchar *fpath = g_build_filename(path, dir_file, NULL); -			if (fpath) { -				plist_t fdict = plist_new_dict(); -				GStatBuf st; -				g_stat(fpath, &st); -				const char *ftype = "DLFileTypeUnknown"; -				if (g_file_test(fpath, G_FILE_TEST_IS_DIR)) { -					ftype = "DLFileTypeDirectory"; -				} else if (g_file_test(fpath, G_FILE_TEST_IS_REGULAR)) { -					ftype = "DLFileTypeRegular"; -				} -				plist_dict_insert_item(fdict, "DLFileType", plist_new_string(ftype)); -				plist_dict_insert_item(fdict, "DLFileSize", plist_new_uint(st.st_size)); -				plist_dict_insert_item(fdict, "DLFileModificationDate", plist_new_date(st.st_mtime, 0)); - -				plist_dict_insert_item(dirlist, dir_file, fdict); -				g_free(fpath); -			} -		} -		g_dir_close(cur_dir); -	} -	g_free(path); - -	/* TODO error handling */ -	mobilebackup2_error_t err = mobilebackup2_send_status_response(mobilebackup2, 0, NULL, dirlist); -	plist_free(dirlist); -	if (err != MOBILEBACKUP2_E_SUCCESS) { -		printf("Could not send status response, error %d\n", err); -	} -} - -static void mb2_handle_make_directory(plist_t message, const char *backup_dir) -{ -	if (!message || (plist_get_node_type(message) != PLIST_ARRAY) || plist_array_get_size(message) < 2 || !backup_dir) return; - -	plist_t dir = plist_array_get_item(message, 1); -	char *str = NULL; -	int errcode = 0; -	char *errdesc = NULL; -	plist_get_string_val(dir, &str); - -	gchar *newpath = g_build_path(G_DIR_SEPARATOR_S, backup_dir, str, NULL); -	g_free(str); - -	if (mkdir(newpath, 0755) < 0) { -		errdesc = strerror(errno); -		if (errno != EEXIST) { -			printf("mkdir: %s (%d)\n", errdesc, errno); -		} -		errcode = errno_to_device_error(errno); -	} -	g_free(newpath); -	mobilebackup2_error_t err = mobilebackup2_send_status_response(mobilebackup2, errcode, errdesc, NULL); -	if (err != MOBILEBACKUP2_E_SUCCESS) { -		printf("Could not send status response, error %d\n", err); -	} -} - -static void mb2_copy_file_by_path(const gchar *src, const gchar *dst) -{ -	FILE *from, *to; -	char ch; - -	/* open source file */ -	if ((from = fopen(src, "rb")) == NULL) { -		printf("Cannot open source path '%s'.\n", src); -		return; -	} - -	/* open destination file */ -	if ((to = fopen(dst, "wb")) == NULL) { -		printf("Cannot open destination file '%s'.\n", dst); -		return; -	} - -	/* copy the file */ -	while(!feof(from)) { -		ch = fgetc(from); -		if(ferror(from)) { -			printf("Error reading source file.\n"); -			break; -		} -		if(!feof(from)) -			fputc(ch, to); - -		if(ferror(to)) { -			printf("Error writing destination file.\n"); -			break; -		} -	} - -	if(fclose(from) == EOF) { -		printf("Error closing source file.\n"); -	} - -	if(fclose(to) == EOF) { -		printf("Error closing destination file.\n"); -	} -} - -static void mb2_copy_directory_by_path(const gchar *src, const gchar *dst) -{ -	if (!src || !dst) { -		return; -	} - -	/* if src does not exist */ -	if (!g_file_test(src, G_FILE_TEST_EXISTS)) { -		printf("ERROR: Source directory does not exist '%s': %s (%d)\n", src, strerror(errno), errno); -		return; -	} - -	/* if dst directory does not exist */ -	if (!g_file_test(dst, G_FILE_TEST_IS_DIR)) { -		/* create it */ -		if (g_mkdir_with_parents(dst, 0755) < 0) { -			printf("ERROR: Unable to create destination directory '%s': %s (%d)\n", dst, strerror(errno), errno); -			return; -		} -	} - -	/* loop over src directory contents */ -	GDir *cur_dir = g_dir_open(src, 0, NULL); -	if (cur_dir) { -		gchar *dir_file; -		while ((dir_file = (gchar *)g_dir_read_name(cur_dir))) { -			gchar *srcpath = g_build_filename(src, dir_file, NULL); -			gchar *dstpath = g_build_filename(dst, dir_file, NULL); -			if (srcpath && dstpath) { -				/* copy file */ -				mb2_copy_file_by_path(srcpath, dstpath); - -				g_free(srcpath); -				g_free(dstpath); -			} -		} -		g_dir_close(cur_dir); -	} -} - -/** - * signal handler function for cleaning up properly - */ -static void clean_exit(int sig) -{ -	fprintf(stderr, "Exiting...\n"); -	quit_flag++; -} - -static void print_usage(int argc, char **argv) -{ -	char *name = NULL; -	name = strrchr(argv[0], '/'); -	printf("Usage: %s [OPTIONS] CMD DIRECTORY\n", (name ? name + 1: argv[0])); -	printf("Create or restore backup from the current or specified directory.\n\n"); -	printf("commands:\n"); -	printf("  backup\tcreate backup for the device\n"); -	printf("  restore\trestore last backup to the device\n"); -	printf("  info\t\tshow details about last completed backup of device\n"); -	printf("  list\t\tlist files of last completed backup in CSV format\n\n"); -	printf("options:\n"); -	printf("  -d, --debug\t\tenable communication debugging\n"); -	printf("  -u, --uuid UUID\ttarget specific device by its 40-digit device UUID\n"); -	printf("  -h, --help\t\tprints usage information\n"); -	printf("\n"); -} - -int main(int argc, char *argv[]) -{ -	idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; -	int i; -	char uuid[41]; -	uint16_t port = 0; -	uuid[0] = 0; -	int cmd = -1; -	int is_full_backup = 0; -	char *backup_directory = NULL; -	struct stat st; -	plist_t node_tmp = NULL; -	plist_t info_plist = NULL; -	mobilebackup2_error_t err; - -	/* we need to exit cleanly on running backups and restores or we cause havok */ -	signal(SIGINT, clean_exit); -	signal(SIGQUIT, clean_exit); -	signal(SIGTERM, clean_exit); -	signal(SIGPIPE, SIG_IGN); - -	/* parse cmdline args */ -	for (i = 1; i < argc; i++) { -		if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { -			idevice_set_debug_level(1); -			continue; -		} -		else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--uuid")) { -			i++; -			if (!argv[i] || (strlen(argv[i]) != 40)) { -				print_usage(argc, argv); -				return 0; -			} -			strcpy(uuid, argv[i]); -			continue; -		} -		else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { -			print_usage(argc, argv); -			return 0; -		} -		else if (!strcmp(argv[i], "backup")) { -			cmd = CMD_BACKUP; -		} -		else if (!strcmp(argv[i], "restore")) { -			cmd = CMD_RESTORE; -		} -		else if (!strcmp(argv[i], "info")) { -			cmd = CMD_INFO; -			verbose = 0; -		} -		else if (!strcmp(argv[i], "list")) { -			cmd = CMD_LIST; -			verbose = 0; -		} -		else if (backup_directory == NULL) { -			backup_directory = argv[i]; -		} -		else { -			print_usage(argc, argv); -			return 0; -		} -	} - -	/* verify options */ -	if (cmd == -1) { -		printf("No command specified.\n"); -		print_usage(argc, argv); -		return -1; -	} - -	if (backup_directory == NULL) { -		printf("No target backup directory specified.\n"); -		print_usage(argc, argv); -		return -1; -	} - -	/* verify if passed backup directory exists */ -	if (stat(backup_directory, &st) != 0) { -		printf("ERROR: Backup directory \"%s\" does not exist!\n", backup_directory); -		return -1; -	} - -	if (uuid[0] != 0) { -		ret = idevice_new(&phone, uuid); -		if (ret != IDEVICE_E_SUCCESS) { -			printf("No device found with uuid %s, is it plugged in?\n", uuid); -			return -1; -		} -	} -	else -	{ -		ret = idevice_new(&phone, NULL); -		if (ret != IDEVICE_E_SUCCESS) { -			printf("No device found, is it plugged in?\n"); -			return -1; -		} -		char *newuuid = NULL; -		idevice_get_uuid(phone, &newuuid); -		strcpy(uuid, newuuid); -		free(newuuid); -	} - -	/* backup directory must contain an Info.plist */ -	gchar *info_path = g_build_path(G_DIR_SEPARATOR_S, backup_directory, uuid, "Info.plist", NULL); -	if (cmd == CMD_RESTORE) { -		if (stat(info_path, &st) != 0) { -			g_free(info_path); -			printf("ERROR: Backup directory \"%s\" is invalid. No Info.plist found for UUID %s.\n", backup_directory, uuid); -			return -1; -		} -	} - -	PRINT_VERBOSE(1, "Backup directory is \"%s\"\n", backup_directory); - -	if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(phone, &client, "idevicebackup")) { -		idevice_free(phone); -		return -1; -	} - -	/* start notification_proxy */ -	np_client_t np = NULL; -	ret = lockdownd_start_service(client, NP_SERVICE_NAME, &port); -	if ((ret == LOCKDOWN_E_SUCCESS) && port) { -		np_client_new(phone, port, &np); -		np_set_notify_callback(np, notify_cb, NULL); -		const char *noties[5] = { -			NP_SYNC_CANCEL_REQUEST, -			NP_SYNC_SUSPEND_REQUEST, -			NP_SYNC_RESUME_REQUEST, -			NP_BACKUP_DOMAIN_CHANGED, -			NULL -		}; -		np_observe_notifications(np, noties); -	} else { -		printf("ERROR: Could not start service %s.\n", NP_SERVICE_NAME); -	} - -	afc = NULL; -	if (cmd == CMD_BACKUP) { -		/* start AFC, we need this for the lock file */ -		port = 0; -		ret = lockdownd_start_service(client, "com.apple.afc", &port); -		if ((ret == LOCKDOWN_E_SUCCESS) && port) { -			afc_client_new(phone, port, &afc); -		} -	} - -	/* start mobilebackup service and retrieve port */ -	port = 0; -	ret = lockdownd_start_service(client, MOBILEBACKUP2_SERVICE_NAME, &port); -	if ((ret == LOCKDOWN_E_SUCCESS) && port) { -		PRINT_VERBOSE(1, "Started \"%s\" service on port %d.\n", MOBILEBACKUP2_SERVICE_NAME, port); -		mobilebackup2_client_new(phone, port, &mobilebackup2); - -		/* send Hello message */ -		err = mobilebackup2_version_exchange(mobilebackup2); -		if (err != MOBILEBACKUP2_E_SUCCESS) { -			printf("Could not perform backup protocol version exchange, error code %d\n", err); -			cmd = CMD_LEAVE; -			goto checkpoint; -		} - -		/* check abort conditions */ -		if (quit_flag > 0) { -			PRINT_VERBOSE(1, "Aborting as requested by user...\n"); -			cmd = CMD_LEAVE; -			goto checkpoint; -		} - -		/* verify existing Info.plist */ -		if (stat(info_path, &st) == 0) { -			PRINT_VERBOSE(1, "Reading Info.plist from backup.\n"); -			plist_read_from_filename(&info_plist, info_path); - -			if (!info_plist) { -				printf("Could not read Info.plist\n"); -				is_full_backup = 1; -			} -			if (info_plist && (cmd == CMD_BACKUP)) { -				if (mobilebackup_info_is_current_device(info_plist)) { -					/* update the last backup time within Info.plist */ -					//mobilebackup_info_update_last_backup_date(info_plist); -					//remove(info_path); -					//plist_write_to_filename(info_plist, info_path, PLIST_FORMAT_XML); -				} else { -					printf("Aborting backup. Backup is not compatible with the current device.\n"); -					cmd = CMD_LEAVE; -				} -			} else if (info_plist && (cmd == CMD_RESTORE)) { -				if (!mobilebackup_info_is_current_device(info_plist)) { -					printf("Aborting restore. Backup data is not compatible with the current device.\n"); -					cmd = CMD_LEAVE; -				} -			} -		} else { -			if (cmd == CMD_RESTORE) { -				printf("Aborting restore. Info.plist is missing.\n"); -				cmd = CMD_LEAVE; -			} else { -				is_full_backup = 1; -			} -		} - -		uint64_t lockfile = 0; -		if (cmd == CMD_BACKUP) { -			do_post_notification(NP_SYNC_WILL_START); -			afc_file_open(afc, "/com.apple.itunes.lock_sync", AFC_FOPEN_RW, &lockfile); -		} -		if (lockfile) { -			afc_error_t aerr; -			do_post_notification(NP_SYNC_LOCK_REQUEST); -			for (i = 0; i < LOCK_ATTEMPTS; i++) { -				aerr = afc_file_lock(afc, lockfile, AFC_LOCK_EX); -				if (aerr == AFC_E_SUCCESS) { -					do_post_notification(NP_SYNC_DID_START); -					break; -				} else if (aerr == AFC_E_OP_WOULD_BLOCK) { -					usleep(LOCK_WAIT); -					continue; -				} else { -					fprintf(stderr, "ERROR: could not lock file! error code: %d\n", aerr); -					afc_file_close(afc, lockfile); -					lockfile = 0; -					cmd = CMD_LEAVE; -				} -			} -			if (i == LOCK_ATTEMPTS) { -				fprintf(stderr, "ERROR: timeout while locking for sync\n"); -				afc_file_close(afc, lockfile); -				lockfile = 0; -				cmd = CMD_LEAVE; -			} -		} - -checkpoint: - -		switch(cmd) { -			case CMD_BACKUP: -			PRINT_VERBOSE(1, "Starting backup...\n"); - -			/* make sure backup device sub-directory exists */ -			gchar *devbackupdir = g_build_path(G_DIR_SEPARATOR_S, backup_directory, uuid, NULL); -			g_mkdir(devbackupdir, 0755); -			g_free(devbackupdir); - -			/* TODO: check domain com.apple.mobile.backup key RequiresEncrypt and WillEncrypt with lockdown */ -			/* TODO: verify battery on AC enough battery remaining */	 - -			/* re-create Info.plist (Device infos, IC-Info.sidb, photos, app_ids, iTunesPrefs) */ -			if (info_plist) { -				plist_free(info_plist); -				info_plist = NULL; -			} -			info_plist = mobilebackup_factory_info_plist_new(); -			remove(info_path); -			plist_write_to_filename(info_plist, info_path, PLIST_FORMAT_XML); -			g_free(info_path); - -			plist_free(info_plist); -			info_plist = NULL; - -			/* request backup from device with manifest from last backup */ -			PRINT_VERBOSE(1, "Requesting backup from device...\n"); - -			err = mobilebackup2_send_request(mobilebackup2, "Backup", uuid, NULL, NULL); -			if (err == MOBILEBACKUP2_E_SUCCESS) { -				if (is_full_backup) { -					PRINT_VERBOSE(1, "Full backup mode.\n"); -				}	else { -					PRINT_VERBOSE(1, "Incremental backup mode.\n"); -				} -			} else { -				if (err == MOBILEBACKUP2_E_BAD_VERSION) { -					printf("ERROR: Could not start backup process: backup protocol version mismatch!\n"); -				} else if (err == MOBILEBACKUP2_E_REPLY_NOT_OK) { -					printf("ERROR: Could not start backup process: device refused to start the backup process.\n"); -				} else { -					printf("ERROR: Could not start backup process: unspecified error occured\n"); -				} -				cmd = CMD_LEAVE; -			} -			break; -			case CMD_RESTORE: -			/* TODO: verify battery on AC enough battery remaining */ - -			/* verify if Status.plist says we read from an successful backup */ -			if (!mb2_status_check_snapshot_state(backup_directory, uuid, "finished")) { -				printf("ERROR: Cannot ensure we restore from a successful backup. Aborting.\n"); -				cmd = CMD_LEAVE; -				break; -			} - -			PRINT_VERBOSE(1, "Starting Restore...\n"); - -			plist_t opts = plist_new_dict(); -			plist_dict_insert_item(opts, "shouldRestoreSystemFiles", plist_new_bool(0)); -			err = mobilebackup2_send_request(mobilebackup2, "Restore", uuid, uuid, opts); -			plist_free(opts); -			if (err != MOBILEBACKUP2_E_SUCCESS) { -				if (err == MOBILEBACKUP2_E_BAD_VERSION) { -					printf("ERROR: Could not start restore process: backup protocol version mismatch!\n"); -				} else if (err == MOBILEBACKUP2_E_REPLY_NOT_OK) { -					printf("ERROR: Could not start restore process: device refused to start the restore process.\n"); -				} else { -					printf("ERROR: Could not start restore process: unspecified error occured\n"); -				} -				cmd = CMD_LEAVE; -			} -			break; -			case CMD_INFO: -			PRINT_VERBOSE(1, "Requesting backup info from device...\n"); -			err = mobilebackup2_send_request(mobilebackup2, "Info", uuid, NULL, NULL); -			if (err != MOBILEBACKUP2_E_SUCCESS) { -				printf("Error requesting backup info from device, error code %d\n", err); -				cmd = CMD_LEAVE; -			} -			break; -			case CMD_LIST: -			PRINT_VERBOSE(1, "Requesting backup list from device...\n"); -			err = mobilebackup2_send_request(mobilebackup2, "List", uuid, NULL, NULL); -			if (err != MOBILEBACKUP2_E_SUCCESS) { -				printf("Error requesting backup list from device, error code %d\n", err); -				cmd = CMD_LEAVE; -			} -			break; -			default: -			break; -		} - -		/* close down the lockdown connection as it is no longer needed */ -		if (client) { -			lockdownd_client_free(client); -			client = NULL; -		} - -		if (cmd != CMD_LEAVE) { -			/* reset backup status */ -			int backup_ok = 0; -			plist_t message = NULL; - -			char *dlmsg = NULL; -			int file_count = 0; -			int errcode = 0; -			const char *errdesc = NULL; - -			/* process series of DLMessage* operations */ -			do { -				if (dlmsg) { -					free(dlmsg); -					dlmsg = NULL; -				} -				mobilebackup2_receive_message(mobilebackup2, &message, &dlmsg); -				if (!message || !dlmsg) { -					PRINT_VERBOSE(1, "Device is not ready yet. Going to try again in 2 seconds...\n"); -					sleep(2); -					goto files_out; -				} -				 -				if (!strcmp(dlmsg, "DLMessageDownloadFiles")) { -					/* device wants to download files from the computer */ -					mb2_handle_send_files(message, backup_directory); -				} else if (!strcmp(dlmsg, "DLMessageUploadFiles")) { -					/* device wants to send files to the computer */ -					file_count += mb2_handle_receive_files(message, backup_directory); -				} else if (!strcmp(dlmsg, "DLContentsOfDirectory")) { -					/* list directory contents */ -					mb2_handle_list_directory(message, backup_directory); -				} else if (!strcmp(dlmsg, "DLMessageCreateDirectory")) { -					/* make a directory */ -					mb2_handle_make_directory(message, backup_directory); -				} else if (!strcmp(dlmsg, "DLMessageMoveFiles")) { -					/* perform a series of rename operations */ -					plist_t moves = plist_array_get_item(message, 1); -					uint32_t cnt = plist_dict_get_size(moves); -					PRINT_VERBOSE(1, "Moving %d file%s\n", cnt, (cnt == 1) ? "" : "s"); -					plist_dict_iter iter = NULL; -					plist_dict_new_iter(moves, &iter); -					errcode = 0; -					errdesc = NULL; -					if (iter) { -						char *key = NULL; -						plist_t val = NULL; -						do { -							plist_dict_next_item(moves, iter, &key, &val); -							if (key && (plist_get_node_type(val) == PLIST_STRING)) { -								char *str = NULL; -								plist_get_string_val(val, &str); -								if (str) { -									gchar *newpath = g_build_path(G_DIR_SEPARATOR_S, backup_directory, str, NULL); -									g_free(str); -									gchar *oldpath = g_build_path(G_DIR_SEPARATOR_S, backup_directory, key, NULL); - -									remove(newpath); -									//fprintf(stderr, "Moving '%s' to '%s'\n", oldpath, newpath); -									if (rename(oldpath, newpath) < 0) { -										printf("Renameing '%s' to '%s' failed: %s (%d)\n", oldpath, newpath, strerror(errno), errno); -										errcode = -errno; -										errdesc = strerror(errno); -										break; -									} -									g_free(oldpath); -									g_free(newpath); -								} -								free(key); -								key = NULL; -							} -						} while (val); -						free(iter); -					} else { -						errcode = -1; -						errdesc = "Could not create dict iterator"; -						printf("Could not create dict iterator\n"); -					} -					err = mobilebackup2_send_status_response(mobilebackup2, errcode, errdesc, plist_new_dict()); -					if (err != MOBILEBACKUP2_E_SUCCESS) { -						printf("Could not send status response, error %d\n", err); -					} -				} else if (!strcmp(dlmsg, "DLMessageRemoveFiles")) { -					plist_t removes = plist_array_get_item(message, 1); -					uint32_t cnt = plist_array_get_size(removes); -					PRINT_VERBOSE(1, "Removing %d file%s\n", cnt, (cnt == 1) ? "" : "s"); -					uint32_t ii = 0; -					errcode = 0; -					errdesc = NULL; -					for (ii = 0; ii < cnt; ii++) { -						plist_t val = plist_array_get_item(removes, ii); -						if (plist_get_node_type(val) == PLIST_STRING) { -							char *str = NULL; -							plist_get_string_val(val, &str); -							if (str) { -								gchar *newpath = g_build_path(G_DIR_SEPARATOR_S, backup_directory, str, NULL); -								g_free(str); -								if (remove(newpath) < 0) { -									printf("Could not remove '%s': %s (%d)\n", newpath, strerror(errno), errno); -									//errcode = -errno; -									//errdesc = strerror(errno); -								} -								g_free(newpath); -							} -						} -					} -					err = mobilebackup2_send_status_response(mobilebackup2, errcode, errdesc, plist_new_dict()); -					if (err != MOBILEBACKUP2_E_SUCCESS) { -						printf("Could not send status response, error %d\n", err); -					} -				} else if (!strcmp(dlmsg, "DLMessageCopyItem")) { -					plist_t srcpath = plist_array_get_item(message, 1); -					plist_t dstpath = plist_array_get_item(message, 2); -					errcode = 0; -					errdesc = NULL; -					if ((plist_get_node_type(srcpath) == PLIST_STRING) && (plist_get_node_type(dstpath) == PLIST_STRING)) { -						char *src = NULL; -						char *dst = NULL; -						plist_get_string_val(srcpath, &src); -						plist_get_string_val(dstpath, &dst); -						if (src && dst) { -							gchar *oldpath = g_build_path(G_DIR_SEPARATOR_S, backup_directory, src, NULL); -							gchar *newpath = g_build_path(G_DIR_SEPARATOR_S, backup_directory, dst, NULL); - -							PRINT_VERBOSE(1, "Copying '%s' to '%s'\n", src, dst); - -							/* check that src exists */ -							if (g_file_test(oldpath, G_FILE_TEST_IS_DIR)) { -								mb2_copy_directory_by_path(oldpath, newpath); -							} else if (g_file_test(oldpath, G_FILE_TEST_IS_REGULAR)) { -								mb2_copy_file_by_path(oldpath, newpath); -							} - -							g_free(newpath); -							g_free(oldpath); -						} -						g_free(src); -						g_free(dst); -					} - -					err = mobilebackup2_send_status_response(mobilebackup2, errcode, errdesc, plist_new_dict()); -					if (err != MOBILEBACKUP2_E_SUCCESS) { -						printf("Could not send status response, error %d\n", err); -					} -				} else if (!strcmp(dlmsg, "DLMessageProcessMessage")) { -					node_tmp = plist_array_get_item(message, 1); -					if (plist_get_node_type(node_tmp) != PLIST_DICT) { -						printf("Unknown message received!\n"); -					} -					plist_t nn; -					int error_code = -1; -					nn = plist_dict_get_item(node_tmp, "ErrorCode"); -					if (nn && (plist_get_node_type(nn) == PLIST_UINT)) { -						uint64_t ec = 0; -						plist_get_uint_val(nn, &ec); -						error_code = (uint32_t)ec; -						if (error_code == 0) { -							backup_ok = 1; -						} -					} -					nn = plist_dict_get_item(node_tmp, "ErrorDescription"); -					char *str = NULL; -					if (nn && (plist_get_node_type(nn) == PLIST_STRING)) { -						plist_get_string_val(nn, &str); -					} -					if (error_code != 0) { -						if (str) { -							printf("ErrorCode %d: %s\n", error_code, str); -						} else { -							printf("ErrorCode %d: (Unknown)\n", error_code); -						} -					} -					if (str) { -						free(str); -					} -					nn = plist_dict_get_item(node_tmp, "Content"); -					if (nn && (plist_get_node_type(nn) == PLIST_STRING)) { -						str = NULL; -						plist_get_string_val(nn, &str); -						PRINT_VERBOSE(1, "Content:\n"); -						printf("%s", str); -						free(str); -					} -					break; -				} - -				/* print status */ -				/*if (plist_array_get_size(message) >= 4) { -					plist_t pnode = plist_array_get_item(message, 4); -					if (pnode && (plist_get_node_type(pnode) == PLIST_REAL)) { -						double progress = 0.0; -						plist_get_real_val(pnode, &progress); -						printf("Progress: %f\n", progress); -					} -				}*/ - -				if (message) -					plist_free(message); -				message = NULL; - -files_out: -				if (quit_flag > 0) { -					/* need to cancel the backup here */ -					//mobilebackup_send_error(mobilebackup, "Cancelling DLSendFile"); - -					/* remove any atomic Manifest.plist.tmp */ - -					/*manifest_path = mobilebackup_build_path(backup_directory, "Manifest", ".plist.tmp"); -					if (stat(manifest_path, &st) == 0) -						remove(manifest_path);*/ -					break; -				} -			} while (1); - -			if (cmd == CMD_BACKUP) { -				PRINT_VERBOSE(1, "Received %d files from device.\n", file_count); -				if (mb2_status_check_snapshot_state(backup_directory, uuid, "finished")) { -					PRINT_VERBOSE(1, "Backup Successful.\n"); -				} else { -					if (quit_flag) { -						PRINT_VERBOSE(1, "Backup Aborted.\n"); -					} else { -						PRINT_VERBOSE(1, "Backup Failed.\n"); -					} -				} -			} else if (cmd == CMD_RESTORE) { -				// TODO: check for success/failure -				PRINT_VERBOSE(1, "The device should reboot now to complete the process.\nRestore Successful.\n"); -			} -		} -		if (lockfile) { -			afc_file_lock(afc, lockfile, AFC_LOCK_UN); -			afc_file_close(afc, lockfile); -			lockfile = 0; -			do_post_notification(NP_SYNC_DID_FINISH); -		} -	} else { -		printf("ERROR: Could not start service %s.\n", MOBILEBACKUP2_SERVICE_NAME); -		lockdownd_client_free(client); -		client = NULL; -	} - -	if (client) { -		lockdownd_client_free(client); -		client = NULL; -	} - -	if (afc) -		afc_client_free(afc); - -	if (np) -		np_client_free(np); - -	if (mobilebackup2) -		mobilebackup2_client_free(mobilebackup2); - -	idevice_free(phone); - -	return 0; -} - | 
