summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2012-11-29 16:46:30 +0100
committerGravatar Nikias Bassen2012-11-29 16:46:30 +0100
commited47413660eb3f49e55b795513990269491ad0c7 (patch)
tree8711e4b8dd292e6b4934eaee95d84122766f44ba
parent14bacd927e8621d723a3d67c49f43a0485c3eff4 (diff)
downloadlibimobiledevice-ed47413660eb3f49e55b795513990269491ad0c7.tar.gz
libimobiledevice-ed47413660eb3f49e55b795513990269491ad0c7.tar.bz2
idevicebackup2: add --source option to allow using backup directories from other devices
-rw-r--r--tools/idevicebackup2.c115
1 files changed, 39 insertions, 76 deletions
diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c
index 0a06f3f..7256ee9 100644
--- a/tools/idevicebackup2.c
+++ b/tools/idevicebackup2.c
@@ -472,67 +472,6 @@ static int mb2_status_check_snapshot_state(const char *path, const char *udid, c
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 UDID */
- 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;
@@ -1186,6 +1125,7 @@ static void print_usage(int argc, char **argv)
printf("options:\n");
printf(" -d, --debug\t\tenable communication debugging\n");
printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n");
+ printf(" -s, --source UDID\tuse backup data from device specified by UDID\n");
printf(" -h, --help\t\tprints usage information\n");
printf("\n");
}
@@ -1195,6 +1135,7 @@ int main(int argc, char *argv[])
idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR;
int i;
char* udid = NULL;
+ char* source_udid = NULL;
uint16_t port = 0;
int cmd = -1;
int cmd_flags = 0;
@@ -1229,6 +1170,15 @@ int main(int argc, char *argv[])
udid = strdup(argv[i]);
continue;
}
+ else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--source")) {
+ i++;
+ if (!argv[i] || (strlen(argv[i]) != 40)) {
+ print_usage(argc, argv);
+ return 0;
+ }
+ source_udid = strdup(argv[i]);
+ continue;
+ }
else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
print_usage(argc, argv);
return 0;
@@ -1307,12 +1257,16 @@ int main(int argc, char *argv[])
idevice_get_udid(device, &udid);
}
+ if (!source_udid) {
+ source_udid = strdup(udid);
+ }
+
/* backup directory must contain an Info.plist */
- char *info_path = build_path(backup_directory, udid, "Info.plist", NULL);
+ char *info_path = build_path(backup_directory, source_udid, "Info.plist", NULL);
if (cmd == CMD_RESTORE) {
if (stat(info_path, &st) != 0) {
free(info_path);
- printf("ERROR: Backup directory \"%s\" is invalid. No Info.plist found for UDID %s.\n", backup_directory, udid);
+ printf("ERROR: Backup directory \"%s\" is invalid. No Info.plist found for UDID %s.\n", backup_directory, source_udid);
return -1;
}
}
@@ -1387,12 +1341,6 @@ int main(int argc, char *argv[])
printf("Could not read Info.plist\n");
is_full_backup = 1;
}
- if (info_plist && ((cmd == CMD_BACKUP) || (cmd == CMD_RESTORE))) {
- if (!mobilebackup_info_is_current_device(info_plist)) {
- printf("Aborting. 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");
@@ -1440,10 +1388,22 @@ checkpoint:
PRINT_VERBOSE(1, "Starting backup...\n");
/* make sure backup device sub-directory exists */
- char *devbackupdir = build_path(backup_directory, udid, NULL);
+ char* devbackupdir = build_path(backup_directory, source_udid, NULL);
__mkdir(devbackupdir, 0755);
free(devbackupdir);
+ if (strcmp(source_udid, udid) != 0) {
+ /* handle different source backup directory */
+ // make sure target backup device sub-directory exists
+ devbackupdir = build_path(backup_directory, udid, NULL);
+ __mkdir(devbackupdir, 0755);
+ free(devbackupdir);
+
+ // use Info.plist path in target backup folder */
+ free(info_path);
+ info_path = build_path(backup_directory, udid, "Info.plist", NULL);
+ }
+
/* TODO: check domain com.apple.mobile.backup key RequiresEncrypt and WillEncrypt with lockdown */
/* TODO: verify battery on AC enough battery remaining */
@@ -1463,7 +1423,7 @@ checkpoint:
/* request backup from device with manifest from last backup */
PRINT_VERBOSE(1, "Requesting backup from device...\n");
- err = mobilebackup2_send_request(mobilebackup2, "Backup", udid, NULL, NULL);
+ err = mobilebackup2_send_request(mobilebackup2, "Backup", udid, source_udid, NULL);
if (err == MOBILEBACKUP2_E_SUCCESS) {
if (is_full_backup) {
PRINT_VERBOSE(1, "Full backup mode.\n");
@@ -1485,7 +1445,7 @@ checkpoint:
/* 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, udid, "finished")) {
+ if (!mb2_status_check_snapshot_state(backup_directory, source_udid, "finished")) {
printf("ERROR: Cannot ensure we restore from a successful backup. Aborting.\n");
cmd = CMD_LEAVE;
break;
@@ -1505,7 +1465,7 @@ checkpoint:
plist_dict_insert_item(opts, "RestorePreserveSettings", plist_new_bool((cmd_flags & CMD_FLAG_RESTORE_SETTINGS) == 0));
PRINT_VERBOSE(1, "Preserve settings of device: %s\n", ((cmd_flags & CMD_FLAG_RESTORE_SETTINGS) == 0 ? "Yes":"No"));
- err = mobilebackup2_send_request(mobilebackup2, "Restore", udid, udid, opts);
+ err = mobilebackup2_send_request(mobilebackup2, "Restore", udid, source_udid, opts);
plist_free(opts);
if (err != MOBILEBACKUP2_E_SUCCESS) {
if (err == MOBILEBACKUP2_E_BAD_VERSION) {
@@ -1520,7 +1480,7 @@ checkpoint:
break;
case CMD_INFO:
PRINT_VERBOSE(1, "Requesting backup info from device...\n");
- err = mobilebackup2_send_request(mobilebackup2, "Info", udid, NULL, NULL);
+ err = mobilebackup2_send_request(mobilebackup2, "Info", udid, source_udid, NULL);
if (err != MOBILEBACKUP2_E_SUCCESS) {
printf("Error requesting backup info from device, error code %d\n", err);
cmd = CMD_LEAVE;
@@ -1528,7 +1488,7 @@ checkpoint:
break;
case CMD_LIST:
PRINT_VERBOSE(1, "Requesting backup list from device...\n");
- err = mobilebackup2_send_request(mobilebackup2, "List", udid, NULL, NULL);
+ err = mobilebackup2_send_request(mobilebackup2, "List", udid, source_udid, NULL);
if (err != MOBILEBACKUP2_E_SUCCESS) {
printf("Error requesting backup list from device, error code %d\n", err);
cmd = CMD_LEAVE;
@@ -1536,7 +1496,7 @@ checkpoint:
break;
case CMD_UNBACK:
PRINT_VERBOSE(1, "Starting to unpack backup...\n");
- err = mobilebackup2_send_request(mobilebackup2, "Unback", udid, NULL, NULL);
+ err = mobilebackup2_send_request(mobilebackup2, "Unback", udid, source_udid, NULL);
if (err != MOBILEBACKUP2_E_SUCCESS) {
printf("Error requesting unback operation from device, error code %d\n", err);
cmd = CMD_LEAVE;
@@ -1889,6 +1849,9 @@ files_out:
if (udid) {
free(udid);
}
+ if (source_udid) {
+ free(source_udid);
+ }
return 0;
}