summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2010-11-22 23:27:19 +0100
committerGravatar Martin Szulecki2011-04-11 17:05:57 +0200
commit18e4f053bced9ead787e23e0526cb758a9979af1 (patch)
treee4baa3e8b9d35e6f7112f6f1263e69853a2fb913
parentae7013d7d8355da926c0818182dd500589b48ed6 (diff)
downloadlibimobiledevice-18e4f053bced9ead787e23e0526cb758a9979af1.tar.gz
libimobiledevice-18e4f053bced9ead787e23e0526cb758a9979af1.tar.bz2
mobilebackup2: added info and list commands, started restore implementation
-rw-r--r--tools/idevicebackup4.c388
1 files changed, 45 insertions, 343 deletions
diff --git a/tools/idevicebackup4.c b/tools/idevicebackup4.c
index a44abb6..8c4fe79 100644
--- a/tools/idevicebackup4.c
+++ b/tools/idevicebackup4.c
@@ -54,6 +54,8 @@ static int quit_flag = 0;
enum cmd_mode {
CMD_BACKUP,
CMD_RESTORE,
+ CMD_INFO,
+ CMD_LIST,
CMD_LEAVE
};
@@ -1140,6 +1142,12 @@ int main(int argc, char *argv[])
else if (!strcmp(argv[i], "restore")) {
cmd = CMD_RESTORE;
}
+ else if (!strcmp(argv[i], "info")) {
+ cmd = CMD_INFO;
+ }
+ else if (!strcmp(argv[i], "list")) {
+ cmd = CMD_LIST;
+ }
else if (backup_directory == NULL) {
backup_directory = argv[i];
}
@@ -1369,12 +1377,6 @@ checkpoint:
plist_free(info_plist);
info_plist = NULL;
- /* close down the lockdown connection as it is no longer needed */
- if (client) {
- lockdownd_client_free(client);
- client = NULL;
- }
-
/* create Status.plist with failed status for now */
//mobilebackup_write_status(backup_directory, 0);
@@ -1398,7 +1400,44 @@ checkpoint:
}
break;
}
+ break;
+ case CMD_RESTORE:
+ /* TODO: verify battery on AC enough battery remaining */
+ printf("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) {
+ cmd = CMD_LEAVE;
+ }
+ break;
+ case CMD_INFO:
+ printf("Requesting backup info from device...\n");
+ err = mobilebackup2_send_request(mobilebackup2, "Info", uuid, NULL, NULL);
+ if (err != MOBILEBACKUP2_E_SUCCESS) {
+ cmd = CMD_LEAVE;
+ }
+ break;
+ case CMD_LIST:
+ printf("Requesting backup list from device...\n");
+ err = mobilebackup2_send_request(mobilebackup2, "List", uuid, NULL, NULL);
+ if (err != MOBILEBACKUP2_E_SUCCESS) {
+ 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;
@@ -1769,343 +1808,6 @@ files_out:
} else {
printf("Backup Failed.\n");
}
-
- break;
- case CMD_RESTORE:
- /* close down the lockdown connection as it is no longer needed */
- if (client) {
- lockdownd_client_free(client);
- client = NULL;
- }
-
- /* TODO: verify battery on AC enough battery remaining */
-
- /* verify if Status.plist says we read from an successful backup */
-#if 0
- if (mobilebackup_read_status(backup_directory) <= 0) {
- printf("ERROR: Cannot ensure we restore from a successful backup. Aborting.\n");
- break;
- }
- /* now make sure backup integrity is ok! verify all files */
- printf("Reading existing Manifest.\n");
- plist_read_from_filename(&manifest_plist, manifest_path);
- if (!manifest_plist) {
- printf("Could not read Manifest.plist. Aborting.\n");
- break;
- }
-
- printf("Verifying backup integrity, please wait.\n");
- char *bin = NULL;
- uint64_t binsize = 0;
- node = plist_dict_get_item(manifest_plist, "Data");
- if (!node || (plist_get_node_type(node) != PLIST_DATA)) {
- printf("Could not read Data key from Manifest.plist!\n");
- break;
- }
- plist_get_data_val(node, &bin, &binsize);
- plist_t backup_data = NULL;
- if (bin) {
- char *auth_ver = NULL;
- unsigned char *auth_sig = NULL;
- uint64_t auth_sig_len = 0;
- /* verify AuthSignature */
- node = plist_dict_get_item(manifest_plist, "AuthVersion");
- plist_get_string_val(node, &auth_ver);
- if (auth_ver && (strcmp(auth_ver, "2.0") == 0)) {
- node = plist_dict_get_item(manifest_plist, "AuthSignature");
- if (node && (plist_get_node_type(node) == PLIST_DATA)) {
- plist_get_data_val(node, (char**)&auth_sig, &auth_sig_len);
- }
- if (auth_sig && (auth_sig_len == 20)) {
- /* calculate the sha1, then compare */
- unsigned char data_sha1[20];
- sha1_of_data(bin, binsize, data_sha1);
- if (compare_hash(auth_sig, data_sha1, 20)) {
- printf("AuthSignature is valid\n");
- } else {
- printf("ERROR: AuthSignature is NOT VALID\n");
- }
- } else {
- printf("Could not get AuthSignature from manifest!\n");
- }
- g_free(auth_sig);
- } else if (auth_ver) {
- printf("Unknown AuthVersion '%s', cannot verify AuthSignature\n", auth_ver);
- }
- plist_from_bin(bin, (uint32_t)binsize, &backup_data);
- g_free(bin);
- }
- if (!backup_data) {
- printf("Could not read plist from Manifest.plist Data key!\n");
- break;
- }
- plist_t files = plist_dict_get_item(backup_data, "Files");
- if (files && (plist_get_node_type(files) == PLIST_DICT)) {
- plist_dict_iter iter = NULL;
- plist_dict_new_iter(files, &iter);
- if (iter) {
- /* loop over Files entries in Manifest data plist */
- char *hash = NULL;
- int file_ok = 0;
- int total_files = plist_dict_get_size(files);
- int cur_file = 1;
- node = NULL;
- plist_dict_next_item(files, iter, &hash, &node);
- while (node) {
- printf("Verifying file %d/%d (%d%%) \r", cur_file, total_files, (cur_file*100/total_files));
- cur_file++;
- /* make sure both .mddata/.mdinfo files are available for each entry */
- file_ok = mobilebackup_check_file_integrity(backup_directory, hash, node);
- node = NULL;
- free(hash);
- hash = NULL;
- if (!file_ok) {
- break;
- }
- plist_dict_next_item(files, iter, &hash, &node);
- }
- printf("\n");
- free(iter);
- if (!file_ok) {
- plist_free(backup_data);
- break;
- }
- printf("All backup files appear to be valid\n");
- }
- }
-
- printf("Requesting restore from device...\n");
-
- /* request restore from device with manifest (BackupMessageRestoreMigrate) */
- int restore_flags = MB_RESTORE_NOTIFY_SPRINGBOARD | MB_RESTORE_PRESERVE_SETTINGS | MB_RESTORE_PRESERVE_CAMERA_ROLL;
- err = mobilebackup_request_restore(mobilebackup, manifest_plist, restore_flags, "1.6");
- if (err != MOBILEBACKUP_E_SUCCESS) {
- if (err == MOBILEBACKUP_E_BAD_VERSION) {
- printf("ERROR: Could not start restore process: backup protocol version mismatch!\n");
- } else if (err == MOBILEBACKUP_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 (%d)\n", err);
- }
- plist_free(backup_data);
- break;
- }
-
- printf("Entered restore mode.\n");
-
- int restore_ok = 0;
-
- if (files && (plist_get_node_type(files) == PLIST_DICT)) {
- plist_dict_iter iter = NULL;
- plist_dict_new_iter(files, &iter);
- if (iter) {
- /* loop over Files entries in Manifest data plist */
- char *hash = NULL;
- plist_t file_info = NULL;
- char *file_info_path = NULL;
- int total_files = plist_dict_get_size(files);
- int cur_file = 0;
- uint64_t file_offset = 0;
- uint8_t is_encrypted = 0;
- plist_t tmp_node = NULL;
- plist_t file_path_node = NULL;
- plist_t send_file_node = NULL;
- node = NULL;
- plist_dict_next_item(files, iter, &hash, &node);
- while (node) {
- /* TODO: read mddata/mdinfo files and send to device using DLSendFile */
- file_info_path = mobilebackup_build_path(backup_directory, hash, ".mdinfo");
- plist_read_from_filename(&file_info, file_info_path);
-
- /* get encryption state */
- tmp_node = plist_dict_get_item(file_info, "IsEncrypted");
- plist_get_bool_val(tmp_node, &is_encrypted);
- tmp_node = NULL;
-
- /* get real file path from metadata */
- tmp_node = plist_dict_get_item(file_info, "Metadata");
- plist_get_data_val(tmp_node, &buffer, &length);
- tmp_node = NULL;
- plist_from_bin(buffer, length, &tmp_node);
- file_path_node = plist_dict_get_item(tmp_node, "Path");
- plist_get_string_val(file_path_node, &file_path);
-
- printf("Restoring file %s %d/%d (%d%%)... ", file_path, cur_file, total_files, (cur_file*100/total_files));
-
- /* add additional device link file information keys */
- plist_dict_insert_item(file_info, "DLFileAttributesKey", plist_copy(node));
- plist_dict_insert_item(file_info, "DLFileSource", plist_new_string(file_info_path));
- plist_dict_insert_item(file_info, "DLFileDest", plist_new_string("/tmp/RestoreFile.plist"));
- plist_dict_insert_item(file_info, "DLFileIsEncrypted", plist_new_bool(is_encrypted));
- plist_dict_insert_item(file_info, "DLFileOffsetKey", plist_new_uint(file_offset));
- plist_dict_insert_item(file_info, "DLFileStatusKey", plist_new_uint(file_status));
-
- /* read data from file */
- free(file_info_path);
- file_info_path = mobilebackup_build_path(backup_directory, hash, ".mddata");
- buffer_read_from_filename(file_info_path, &buffer, &length);
- free(file_info_path);
-
- /* send DLSendFile messages */
- file_offset = 0;
- do {
- if ((length-file_offset) <= 8192)
- file_status = DEVICE_LINK_FILE_STATUS_LAST_HUNK;
- else
- file_status = DEVICE_LINK_FILE_STATUS_HUNK;
-
- plist_dict_remove_item(file_info, "DLFileOffsetKey");
- plist_dict_insert_item(file_info, "DLFileOffsetKey", plist_new_uint(file_offset));
-
- plist_dict_remove_item(file_info, "DLFileStatusKey");
- plist_dict_insert_item(file_info, "DLFileStatusKey", plist_new_uint(file_status));
-
- send_file_node = plist_new_array();
-
- plist_array_append_item(send_file_node, plist_new_string("DLSendFile"));
-
- if (file_status == DEVICE_LINK_FILE_STATUS_LAST_HUNK)
- plist_array_append_item(send_file_node, plist_new_data(buffer+file_offset, length-file_offset));
- else
- plist_array_append_item(send_file_node, plist_new_data(buffer+file_offset, 8192));
-
- plist_array_append_item(send_file_node, plist_copy(file_info));
-
- err = mobilebackup_send(mobilebackup, send_file_node);
- if (err != MOBILEBACKUP_E_SUCCESS) {
- printf("ERROR: Unable to send file hunk due to error %d. Aborting...\n", err);
- file_status = DEVICE_LINK_FILE_STATUS_NONE;
- }
-
- if (file_status == DEVICE_LINK_FILE_STATUS_LAST_HUNK) {
- /* TODO: if all hunks of a file are sent, device must send ack */
- err = mobilebackup_receive_restore_file_received(mobilebackup, NULL);
- if (err != MOBILEBACKUP_E_SUCCESS) {
- printf("ERROR: Did not receive an ack for the sent file due to error %d. Aborting...\n", err);
- file_status = DEVICE_LINK_FILE_STATUS_NONE;
- }
- }
-
- file_offset += 8192;
-
- if (file_status == DEVICE_LINK_FILE_STATUS_LAST_HUNK)
- printf("DONE\n");
-
- plist_free(send_file_node);
-
- if (file_status == DEVICE_LINK_FILE_STATUS_NONE)
- break;
-
- } while((file_offset < length));
-
- free(hash);
- node = NULL;
- hash = NULL;
-
- restore_ok = 1;
- if (file_status == DEVICE_LINK_FILE_STATUS_NONE) {
- restore_ok = 0;
- break;
- }
-
- cur_file++;
- plist_dict_next_item(files, iter, &hash, &node);
- }
- free(iter);
-
- printf("Restored %d files on device.\n", cur_file);
- }
- }
- /* TODO: observe notification_proxy id com.apple.mobile.application_installed */
- /* TODO: loop over Applications entries in Manifest data plist */
- plist_t applications = plist_dict_get_item(backup_data, "Applications");
- if (applications && (plist_get_node_type(applications) == PLIST_DICT) && restore_ok) {
- plist_dict_iter iter = NULL;
- plist_dict_new_iter(applications, &iter);
- if (iter) {
- /* loop over Application entries in Manifest data plist */
- char *hash = NULL;
- int total_files = plist_dict_get_size(applications);
- int cur_file = 1;
- plist_t tmp_node = NULL;
- plist_t dict = NULL;
- plist_t array = NULL;
- node = NULL;
- plist_dict_next_item(applications, iter, &hash, &node);
- while (node) {
- printf("Restoring Application %s %d/%d (%d%%)...", hash, cur_file, total_files, (cur_file*100/total_files));
- /* FIXME: receive com.apple.mobile.application_installed notification */
- /* send AppInfo entry */
- tmp_node = plist_dict_get_item(node, "AppInfo");
-
- dict = plist_new_dict();
- plist_dict_insert_item(dict, "AppInfo", plist_copy(tmp_node));
- plist_dict_insert_item(dict, "BackupMessageTypeKey", plist_new_string("BackupMessageRestoreApplicationSent"));
-
- array = plist_new_array();
- plist_array_append_item(array, plist_new_string("DLMessageProcessMessage"));
- plist_array_append_item(array, dict);
-
- err = mobilebackup_send(mobilebackup, array);
- if (err != MOBILEBACKUP_E_SUCCESS) {
- printf("ERROR: Unable to restore application %s due to error %d. Aborting...\n", hash, err);
- restore_ok = 0;
- }
-
- plist_free(array);
- array = NULL;
- dict = NULL;
-
- /* receive BackupMessageRestoreApplicationReceived from device */
- if (restore_ok) {
- err = mobilebackup_receive_restore_application_received(mobilebackup, NULL);
- if (err != MOBILEBACKUP_E_SUCCESS) {
- printf("ERROR: Failed to receive an ack from the device for this application due to error %d. Aborting...\n", err);
- restore_ok = 0;
- }
- }
-
- tmp_node = NULL;
- node = NULL;
- free(hash);
- hash = NULL;
-
- if (restore_ok) {
- printf("DONE\n");
- cur_file++;
- plist_dict_next_item(applications, iter, &hash, &node);
- } else
- break;
- }
- free(iter);
-
- if (restore_ok)
- printf("All applications restored.\n");
- else
- printf("Failed to restore applications.\n");
- }
- }
-
- plist_free(backup_data);
-
- /* signal restore finished message to device; BackupMessageRestoreComplete */
- if (restore_ok) {
- err = mobilebackup_send_restore_complete(mobilebackup);
- if (err != MOBILEBACKUP_E_SUCCESS) {
- printf("ERROR: Could not send BackupMessageRestoreComplete, error code %d\n", err);
- }
- }
-
- if (restore_ok) {
- printf("Restore Successful.\n");
- } else {
- printf("Restore Failed.\n");
- }
-#endif
- break;
- case CMD_LEAVE:
- default:
- break;
}
if (lockfile) {
afc_file_lock(afc, lockfile, AFC_LOCK_UN);