/libimobiledevice-tools/idevicebackup2/idevicebackup2.cpp
C++ | 2113 lines | 1808 code | 225 blank | 80 comment | 626 complexity | 3aef26d417da14e3bc9879279299e46d MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- #include "iDeviceBackup2.h"
- bool iDeviceBackup2::ParseArguments(int argc, char** argv) {
- cmd = -1;
- /* parse cmdline args */
- int i = 1;
- for (; 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], "--udid")) {
- i++;
- if (!argv[i] || (strlen(argv[i]) != 40)) {
- return false;
- }
- udid = strdup(argv[i]);
- continue;
- }
- else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--source")) {
- i++;
- if (!argv[i] || (strlen(argv[i]) != 40)) {
- return false;
- }
- source_udid = strdup(argv[i]);
- continue;
- }
- else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
- return false;
- }
- else if (!strcmp(argv[i], "backup")) {
- cmd = CMD_BACKUP;
- RequestedOperation = CMD_BACKUP;
- }
- else if (!strcmp(argv[i], "restore")) {
- cmd = CMD_RESTORE;
- RequestedOperation = CMD_RESTORE;
- }
- else if (!strcmp(argv[i], "--system")) {
- cmd_flags |= CMD_FLAG_RESTORE_SYSTEM_FILES;
- }
- else if (!strcmp(argv[i], "--reboot")) {
- cmd_flags |= CMD_FLAG_RESTORE_REBOOT;
- }
- else if (!strcmp(argv[i], "--copy")) {
- cmd_flags |= CMD_FLAG_RESTORE_COPY_BACKUP;
- }
- else if (!strcmp(argv[i], "--settings")) {
- cmd_flags |= CMD_FLAG_RESTORE_SETTINGS;
- }
- else if (!strcmp(argv[i], "--remove")) {
- cmd_flags |= CMD_FLAG_RESTORE_REMOVE_ITEMS;
- }
- else if (!strcmp(argv[i], "--password")) {
- i++;
- if (!argv[i]) {
- return false;
- }
- if (backup_password)
- free(backup_password);
- backup_password = strdup(argv[i]);
- continue;
- }
- else if (!strcmp(argv[i], "info")) {
- cmd = CMD_INFO;
- verbose = 0;
- RequestedOperation = CMD_INFO;
- }
- else if (!strcmp(argv[i], "list")) {
- cmd = CMD_LIST;
- verbose = 0;
- RequestedOperation = CMD_LIST;
- }
- else if (!strcmp(argv[i], "unback")) {
- cmd = CMD_UNBACK;
- RequestedOperation = CMD_UNBACK;
- }
- else if (!strcmp(argv[i], "encryption")) {
- cmd = CMD_CHANGEPW;
- RequestedOperation = CMD_CHANGEPW;
- i++;
- if (!argv[i]) {
- printf("No argument given for encryption command; requires either 'on' or 'off'.\n");
- return false;
- }
- if (!strcmp(argv[i], "on")) {
- cmd_flags |= CMD_FLAG_ENCRYPTION_ENABLE;
- } else if (!strcmp(argv[i], "off")) {
- cmd_flags |= CMD_FLAG_ENCRYPTION_DISABLE;
- } else {
- printf("Invalid argument '%s' for encryption command; must be either 'on' or 'off'.\n", argv[i]);
- }
- // check if a password was given on the command line
- if (newpw) {
- free(newpw);
- newpw = NULL;
- }
- if (backup_password) {
- free(backup_password);
- backup_password = NULL;
- }
- i++;
- if (argv[i]) {
- if (cmd_flags & CMD_FLAG_ENCRYPTION_ENABLE) {
- newpw = strdup(argv[i]);
- } else if (cmd_flags & CMD_FLAG_ENCRYPTION_DISABLE) {
- backup_password = strdup(argv[i]);
- }
- }
- continue;
- }
- else if (!strcmp(argv[i], "changepw")) {
- cmd = CMD_CHANGEPW;
- cmd_flags |= CMD_FLAG_ENCRYPTION_CHANGEPW;
- RequestedOperation = CMD_CHANGEPW;
- // check if passwords were given on command line
- if (newpw) {
- free(newpw);
- newpw = NULL;
- }
- if (backup_password) {
- free(backup_password);
- backup_password = NULL;
- }
- i++;
- if (argv[i]) {
- backup_password = strdup(argv[i]);
- i++;
- if (!argv[i]) {
- printf("Old and new passwords have to be passed as arguments for the changepw command\n");
- return false;
- }
- newpw = strdup(argv[i]);
- }
- continue;
- }
- else if (backup_directory == NULL) {
- backup_directory = argv[i];
- }
- else {
- return false;
- }
- }
- return cmd != -1;
- }
- bool iDeviceBackup2::SetupForDeviceInteraction() {
- if (cmd == CMD_CHANGEPW) {
- backup_directory = strdup(".this_folder_is_not_present_on_purpose");
- } else {
- if (backup_directory == NULL) {
- printf("No target backup directory specified.\n");
- Errors |= NO_BACKUP_DIRECTORY;
- return false;
- }
- /* verify if passed backup directory exists */
- if (stat(backup_directory, &st) != 0) {
- printf("ERROR: Backup directory \"%s\" does not exist!\n", backup_directory);
- Errors |= BACKUP_DIRECTORY_DNE;
- return false;
- }
- }
- if (udid) {
- ret = idevice_new(&device, udid);
- if (ret != IDEVICE_E_SUCCESS) {
- printf("No device found with udid %s, is it plugged in?\n", udid);
- Errors |= CANNOT_CONNECT_TO_DEVICE;
- return false;
- }
- }
- else
- {
- ret = idevice_new(&device, NULL);
- if (ret != IDEVICE_E_SUCCESS) {
- printf("No device found, is it plugged in?\n");
- Errors |= CANNOT_CONNECT_TO_DEVICE;
- return false;
- }
- idevice_get_udid(device, &udid);
- }
- if (!source_udid) {
- source_udid = strdup(udid);
- }
- char *info_path = NULL;
- if (cmd == CMD_CHANGEPW) {
- if (!backup_password || !newpw) {
- printf("ERROR: Pass in password(s) on the command line for changing the password.\n");
- Errors |= MISSING_PASSWORDS_FOR_CHANGE_PASSWORDS;
- return false;
- }
- } else {
- /* backup directory must contain an Info.plist */
- 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, source_udid);
- Errors |= MISSING_INFO_PLIST;
- return false;
- }
- char* manifest_path = build_path(backup_directory, source_udid, "Manifest.plist", NULL);
- if (stat(manifest_path, &st) != 0) {
- free(info_path);
- }
- plist_t manifest_plist = NULL;
- plist_read_from_filename(&manifest_plist, manifest_path);
- if (!manifest_plist) {
- free(info_path);
- free(manifest_path);
- Errors |= MISSING_MANIFEST_PLIST;
- printf("ERROR: Backup directory \"%s\" is invalid. No Manifest.plist found for UDID %s.\n", backup_directory, source_udid);
- return false;
- }
- plist_t node_tmp = plist_dict_get_item(manifest_plist, "IsEncrypted");
- if (node_tmp && (plist_get_node_type(node_tmp) == PLIST_BOOLEAN)) {
- plist_get_bool_val(node_tmp, &is_encrypted);
- }
- plist_free(manifest_plist);
- free(manifest_path);
- }
- PRINT_VERBOSE(1, "Backup directory is \"%s\"\n", backup_directory);
- }
- if (is_encrypted) {
- PRINT_VERBOSE(1, "This is an encrypted backup.\n");
- if (backup_password == NULL) {
- if (!backup_password || (strlen(backup_password) == 0)) {
- if (backup_password) {
- free(backup_password);
- }
- idevice_free(device);
- Errors |= MISSING_PASSWORD_FOR_ENCRYPTED_BACKUP;
- printf("ERROR: a backup password is required to restore an encrypted backup. Cannot continue.\n");
- return -1;
- }
- }
- }
- if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(device, &lockdown, "idevicebackup")) {
- idevice_free(device);
- Errors |= CANNOT_CONNECT_TO_DEVICE;
- return false;
- }
- /* start notification_proxy */
- ret = lockdownd_start_service(lockdown, NP_SERVICE_NAME, &service);
- if ((ret == LOCKDOWN_E_SUCCESS) && service && service->port) {
- np_client_new(device, service, &np);
- np_notify_cb_t callback = notify_cb;
- np_set_notify_callback(np, callback, 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);
- Errors |= COULD_NOT_START_NOTIFICATION_PROXY;
- return false;
- }
- if (cmd == CMD_BACKUP) {
- /* start AFC, we need this for the lock file */
- service->port = 0;
- service->ssl_enabled = 0;
- ret = lockdownd_start_service(lockdown, "com.apple.afc", &service);
- if ((ret == LOCKDOWN_E_SUCCESS) && service->port) {
- afc_client_new(device, service, &afc);
- }
- else {
- Errors |= COULD_NOT_START_AFC;
- }
- }
- if (service) {
- lockdownd_service_descriptor_free(service);
- service = NULL;
- }
- /* start mobilebackup service and retrieve port */
- ret = lockdownd_start_service(lockdown, MOBILEBACKUP2_SERVICE_NAME, &service);
- if ((ret == LOCKDOWN_E_SUCCESS) && service && service->port) {
- PRINT_VERBOSE(1, "Started \"%s\" service on port %d.\n", MOBILEBACKUP2_SERVICE_NAME, service->port);
- mobilebackup2_client_new(device, service, &mobilebackup2);
- if (service) {
- lockdownd_service_descriptor_free(service);
- service = NULL;
- }
- /* send Hello message */
- double local_versions[2] = {2.0, 2.1};
- double remote_version = 0.0;
- err = mobilebackup2_version_exchange(mobilebackup2, local_versions, 2, &remote_version);
- if (err != MOBILEBACKUP2_E_SUCCESS) {
- printf("Could not perform backup protocol version exchange, error code %d\n", err);
- cmd = CMD_LEAVE;
- Errors |= PROTOCOL_VERSION_EXCHANGE_FAILED;
- return false;
- }
- PRINT_VERBOSE(1, "Negotiated Protocol Version %.1f\n", remote_version);
- /* check abort conditions */
- if (quit_flag > 0) {
- PRINT_VERBOSE(1, "Aborting as requested by user...\n");
- cmd = CMD_LEAVE;
- Errors |= USER_CANCELED;
- return false;
- }
- /* verify existing Info.plist */
- if (info_path && (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;
- }
- } else {
- if (cmd == CMD_RESTORE) {
- printf("Aborting restore. Info.plist is missing.\n");
- cmd = CMD_LEAVE;
- Errors |= MISSING_INFO_PLIST;
- } else {
- is_full_backup = 1;
- }
- }
- if (cmd == CMD_BACKUP) {
- do_post_notification(device, 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(device, NP_SYNC_LOCK_REQUEST);
- int i = 0;
- for (; i < LOCK_ATTEMPTS; i++) {
- aerr = afc_file_lock(afc, lockfile, AFC_LOCK_EX);
- if (aerr == AFC_E_SUCCESS) {
- do_post_notification(device, NP_SYNC_DID_START);
- break;
- } else if (aerr == AFC_E_OP_WOULD_BLOCK) {
- sleep(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;
- Errors |= UNABLE_TO_LOCK_SYNC;
- }
- }
-
- plist_t node_tmp = NULL;
- lockdownd_get_value(lockdown, "com.apple.mobile.backup", "WillEncrypt", &node_tmp);
- if (node_tmp) {
- if (plist_get_node_type(node_tmp) == PLIST_BOOLEAN) {
- plist_get_bool_val(node_tmp, &willEncrypt);
- }
- plist_free(node_tmp);
- node_tmp = NULL;
- }
- }
- return true;
- }
- bool iDeviceBackup2::StartOperation() {
- char* info_path;
- switch(cmd) {
- case CMD_BACKUP:
- {
- PRINT_VERBOSE(1, "Starting backup...\n");
- /* make sure backup device sub-directory exists */
- 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 */
- /* 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(udid, lockdown, afc);
- remove(info_path);
- plist_write_to_filename(info_plist, info_path, PLIST_FORMAT_XML);
- free(info_path);
- plist_free(info_plist);
- info_plist = NULL;
- /* request backup from device with manifest from last backup */
- if (willEncrypt) {
- PRINT_VERBOSE(1, "Backup will be encrypted.\n");
- } else {
- PRINT_VERBOSE(1, "Backup will be unencrypted.\n");
- }
- PRINT_VERBOSE(1, "Requesting backup from device...\n");
- 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");
- } 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");
- Errors |= PROTOCOL_VERSION_MISMATCH;
- } else if (err == MOBILEBACKUP2_E_REPLY_NOT_OK) {
- printf("ERROR: Could not start backup process: device refused to start the backup process.\n");
- Errors |= DEVICE_ERROR;
- } else {
- printf("ERROR: Could not start backup process: unspecified error occured\n");
- Errors |= UNKNOWN_ERROR;
- }
- 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, source_udid, "finished")) {
- printf("ERROR: Cannot ensure we restore from a successful backup. Aborting.\n");
- cmd = CMD_LEAVE;
- break;
- }
- PRINT_VERBOSE(1, "Starting Restore...\n");
- opts = plist_new_dict();
- plist_dict_insert_item(opts, "RestoreSystemFiles", plist_new_bool(cmd_flags & CMD_FLAG_RESTORE_SYSTEM_FILES));
- PRINT_VERBOSE(1, "Restoring system files: %s\n", (cmd_flags & CMD_FLAG_RESTORE_SYSTEM_FILES ? "Yes":"No"));
- if ((cmd_flags & CMD_FLAG_RESTORE_REBOOT) == 0)
- plist_dict_insert_item(opts, "RestoreShouldReboot", plist_new_bool(0));
- PRINT_VERBOSE(1, "Rebooting after restore: %s\n", (cmd_flags & CMD_FLAG_RESTORE_REBOOT ? "Yes":"No"));
- if ((cmd_flags & CMD_FLAG_RESTORE_COPY_BACKUP) == 0)
- plist_dict_insert_item(opts, "RestoreDontCopyBackup", plist_new_bool(1));
- PRINT_VERBOSE(1, "Don't copy backup: %s\n", ((cmd_flags & CMD_FLAG_RESTORE_COPY_BACKUP) == 0 ? "Yes":"No"));
- 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"));
- if (cmd_flags & CMD_FLAG_RESTORE_REMOVE_ITEMS)
- plist_dict_insert_item(opts, "RemoveItemsNotRestored", plist_new_bool(1));
- PRINT_VERBOSE(1, "Remove items that are not restored: %s\n", ((cmd_flags & CMD_FLAG_RESTORE_REMOVE_ITEMS) ? "Yes":"No"));
- if (backup_password != NULL) {
- plist_dict_insert_item(opts, "Password", plist_new_string(backup_password));
- }
- PRINT_VERBOSE(1, "Backup password: %s\n", (backup_password == NULL ? "No":"Yes"));
- err = mobilebackup2_send_request(mobilebackup2, "Restore", udid, source_udid, 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");
- Errors |= PROTOCOL_VERSION_MISMATCH;
- } else if (err == MOBILEBACKUP2_E_REPLY_NOT_OK) {
- printf("ERROR: Could not start restore process: device refused to start the restore process.\n");
- Errors |= DEVICE_ERROR;
- } else {
- printf("ERROR: Could not start restore process: unspecified error occured\n");
- Errors |= UNKNOWN_ERROR;
- }
- cmd = CMD_LEAVE;
- }
- }
- break;
- case CMD_INFO:
- {
- PRINT_VERBOSE(1, "Requesting backup info from device...\n");
- 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;
- Errors |= DEVICE_ERROR;
- }
- }
- break;
- case CMD_LIST:
- {
- PRINT_VERBOSE(1, "Requesting backup list from device...\n");
- 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;
- Errors |= DEVICE_ERROR;
- }
- }
- break;
- case CMD_UNBACK:
- {
- PRINT_VERBOSE(1, "Starting to unpack backup...\n");
- 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;
- Errors |= DEVICE_ERROR;
- }
- }
- break;
- case CMD_CHANGEPW:
- {
- opts = plist_new_dict();
- plist_dict_insert_item(opts, "TargetIdentifier", plist_new_string(udid));
- if (cmd_flags & CMD_FLAG_ENCRYPTION_ENABLE) {
- if (!willEncrypt) {
- if (!newpw) {
- printf("No backup password given. Aborting.\n");
- Errors |= MISSING_PASSWORD_FOR_ENCRYPTED_BACKUP;
- }
- } else {
- printf("ERROR: Backup encryption is already enabled. Aborting.\n");
- cmd = CMD_LEAVE;
- if (newpw) {
- free(newpw);
- newpw = NULL;
- }
- }
- } else if (cmd_flags & CMD_FLAG_ENCRYPTION_DISABLE) {
- if (willEncrypt) {
- if (!backup_password) {
- printf("No password provided.");
- Errors |= MISSING_PASSWORD_FOR_ENCRYPTED_BACKUP;
- return false;
- }
- } else {
- printf("ERROR: Backup encryption is not enabled. Aborting.\n");
- cmd = CMD_LEAVE;
- Errors |= MISSING_PASSWORD_FOR_ENCRYPTED_BACKUP;
- if (backup_password) {
- free(backup_password);
- backup_password = NULL;
- }
- }
- } else if (cmd_flags & CMD_FLAG_ENCRYPTION_CHANGEPW) {
- if (willEncrypt) {
- if (!backup_password || !newpw) {
- printf("No password provided.");
- Errors |= MISSING_PASSWORD_FOR_ENCRYPTED_BACKUP;
- return false;
- }
- } else {
- printf("ERROR: Backup encryption is not enabled so can't change password. Aborting.\n");
- Errors |= MISSING_PASSWORD_FOR_ENCRYPTED_BACKUP;
- cmd = CMD_LEAVE;
- if (newpw) {
- free(newpw);
- newpw = NULL;
- }
- if (backup_password) {
- free(backup_password);
- backup_password = NULL;
- }
- }
- }
- if (newpw) {
- plist_dict_insert_item(opts, "NewPassword", plist_new_string(newpw));
- }
- if (backup_password) {
- plist_dict_insert_item(opts, "OldPassword", plist_new_string(backup_password));
- }
- if (newpw || backup_password) {
- mobilebackup2_send_message(mobilebackup2, "ChangePassword", opts);
- /*if (cmd_flags & CMD_FLAG_ENCRYPTION_ENABLE) {
- int retr = 10;
- while ((retr-- >= 0) && !backup_domain_changed) {
- sleep(1);
- }
- }*/
- } else {
- cmd = CMD_LEAVE;
- }
- plist_free(opts);
- }
- break;
- default:
- break;
- }
- /* close down the lockdown connection as it is no longer needed */
- if (lockdown) {
- lockdownd_client_free(lockdown);
- lockdown = NULL;
- }
- return cmd != CMD_LEAVE;
- }
- bool iDeviceBackup2::CompleteOperation() {
- /* reset operation success status */
- int operation_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_set_overall_progress_from_message(message, dlmsg);
- mb2_handle_send_files(mobilebackup2, message, backup_directory);
- } else if (!strcmp(dlmsg, "DLMessageUploadFiles")) {
- /* device wants to send files to the computer */
- mb2_set_overall_progress_from_message(message, dlmsg);
- file_count += mb2_handle_receive_files(mobilebackup2, message, backup_directory);
- } else if (!strcmp(dlmsg, "DLMessageGetFreeDiskSpace")) {
- /* device wants to know how much disk space is available on the computer */
- uint64_t freespace = 0;
- int res = -1;
- #ifdef WIN32
- if (GetDiskFreeSpaceEx(backup_directory, (PULARGE_INTEGER)&freespace, NULL, NULL)) {
- res = 0;
- }
- #else
- struct statvfs fs;
- memset(&fs, '\0', sizeof(fs));
- res = statvfs(backup_directory, &fs);
- if (res == 0) {
- freespace = (uint64_t)fs.f_bavail * (uint64_t)fs.f_bsize;
- }
- #endif
- plist_t freespace_item = plist_new_uint(freespace);
- mobilebackup2_send_status_response(mobilebackup2, res, NULL, freespace_item);
- plist_free(freespace_item);
- } else if (!strcmp(dlmsg, "DLContentsOfDirectory")) {
- /* list directory contents */
- mb2_handle_list_directory(mobilebackup2, message, backup_directory);
- } else if (!strcmp(dlmsg, "DLMessageCreateDirectory")) {
- /* make a directory */
- mb2_handle_make_directory(mobilebackup2, message, backup_directory);
- } else if (!strcmp(dlmsg, "DLMessageMoveFiles") || !strcmp(dlmsg, "DLMessageMoveItems")) {
- MoveItems(message, &err, dlmsg, &errcode, errdesc);
- } else if (!strcmp(dlmsg, "DLMessageRemoveFiles") || !strcmp(dlmsg, "DLMessageRemoveItems")) {
- RemoveItems(message, &err, &errcode, errdesc, dlmsg);
- } else if (!strcmp(dlmsg, "DLMessageCopyItem")) {
- CopyItem(message, &errcode, errdesc);
- } else if (!strcmp(dlmsg, "DLMessageDisconnect")) {
- break;
- } else if (!strcmp(dlmsg, "DLMessageProcessMessage")) {
- ProcessMessage(message, &operation_ok);
- break;
- }
- /* print status */
- if (overall_progress > 0) {
- if(m_progressCallback) {
- m_progressCallback(overall_progress, 0);
- }
- print_progress_real(overall_progress, 0);
- PRINT_VERBOSE(1, " Finished\n");
- }
- 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);
- /* report operation status to user */
- switch (cmd) {
- case CMD_BACKUP:
- PRINT_VERBOSE(1, "Received %d files from device.\n", file_count);
- if (operation_ok && mb2_status_check_snapshot_state(backup_directory, udid, "finished")) {
- PRINT_VERBOSE(1, "Backup Successful.\n");
- } else {
- if (quit_flag) {
- PRINT_VERBOSE(1, "Backup Aborted.\n");
- Errors |= BACKUP_ABORTED;
- } else {
- PRINT_VERBOSE(1, "Backup Failed (Error Code %d).\n", -result_code);
- Errors |= BACKUP_FAILED;
- }
- }
- break;
- case CMD_UNBACK:
- if (quit_flag) {
- PRINT_VERBOSE(1, "Unback Aborted.\n");
- Errors |= UNBACK_ABORTED;
- } else {
- PRINT_VERBOSE(1, "The files can now be found in the \"_unback_\" directory.\n");
- PRINT_VERBOSE(1, "Unback Successful.\n");
- }
- break;
- case CMD_CHANGEPW:
- if (cmd_flags & CMD_FLAG_ENCRYPTION_ENABLE) {
- if (operation_ok) {
- PRINT_VERBOSE(1, "Backup encryption has been enabled successfully.\n");
- } else {
- PRINT_VERBOSE(1, "Could not enable backup encryption.\n");
- Errors |= COULD_NOT_ENABLE_ENCRYPTION;
- }
- } else if (cmd_flags & CMD_FLAG_ENCRYPTION_DISABLE) {
- if (operation_ok) {
- PRINT_VERBOSE(1, "Backup encryption has been disabled successfully.\n");
- } else {
- PRINT_VERBOSE(1, "Could not disable backup encryption.\n");
- Errors |= COULD_NOT_DISABLE_ENCRYPTION;
- }
- } else if (cmd_flags & CMD_FLAG_ENCRYPTION_CHANGEPW) {
- if (operation_ok) {
- PRINT_VERBOSE(1, "Backup encryption password has been changed successfully.\n");
- } else {
- PRINT_VERBOSE(1, "Could not change backup encryption password.\n");
- Errors |= CHANGE_PASSWORD_FAILED;
- }
- }
- break;
- case CMD_RESTORE:
- if (cmd_flags & CMD_FLAG_RESTORE_REBOOT)
- PRINT_VERBOSE(1, "The device should reboot now.\n");
- if (operation_ok) {
- PRINT_VERBOSE(1, "Restore Successful.\n");
- } else {
- PRINT_VERBOSE(1, "Restore Failed (Error Code %d).\n", -result_code);
- Errors |= RESTORE_FAILED;
- }
-
- break;
- case CMD_INFO:
- case CMD_LIST:
- case CMD_LEAVE:
- default:
- if (quit_flag) {
- PRINT_VERBOSE(1, "Operation Aborted.\n");
- } else if (cmd == CMD_LEAVE) {
- PRINT_VERBOSE(1, "Operation Failed.\n");
- } else {
- PRINT_VERBOSE(1, "Operation Successful.\n");
- }
- break;
- }
- if (lockfile) {
- afc_file_lock(afc, lockfile, AFC_LOCK_UN);
- afc_file_close(afc, lockfile);
- lockfile = 0;
- if (cmd == CMD_BACKUP)
- do_post_notification(device, NP_SYNC_DID_FINISH);
- }
- if (lockdown) {
- lockdownd_client_free(lockdown);
- lockdown = NULL;
- }
- if (mobilebackup2) {
- mobilebackup2_client_free(mobilebackup2);
- mobilebackup2 = NULL;
- }
- if (afc) {
- afc_client_free(afc);
- afc = NULL;
- }
- if (np) {
- np_client_free(np);
- np = NULL;
- }
- idevice_free(device);
- device = NULL;
- if (udid) {
- free(udid);
- udid = NULL;
- }
- if (source_udid) {
- free(source_udid);
- source_udid = NULL;
- }
- return true;
- }
- void iDeviceBackup2::ProcessMessage(plist_t message, int *operation_ok) {
- plist_t 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) {
- *operation_ok = 1;
- result_code = 0;
- } else {
- result_code = -error_code;
- }
- }
- 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);
- if(cmd == CMD_INFO) {
- Info = new char[strlen(str) + 1];
- strcpy(Info, str);
- }
- free(str);
- }
- }
- void iDeviceBackup2::CopyItem(plist_t message, int *errcode, const char *errdesc) {
- 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) {
- char *oldpath = build_path(backup_directory, src, NULL);
- char *newpath = build_path(backup_directory, dst, NULL);
- PRINT_VERBOSE(1, "Copying '%s' to '%s'\n", src, dst);
- /* check that src exists */
- if ((stat(oldpath, &st) == 0) && S_ISDIR(st.st_mode)) {
- mb2_copy_directory_by_path(oldpath, newpath);
- } else if ((stat(oldpath, &st) == 0) && S_ISREG(st.st_mode)) {
- mb2_copy_file_by_path(oldpath, newpath);
- }
- free(newpath);
- free(oldpath);
- }
- free(src);
- free(dst);
- }
- plist_t empty_dict = plist_new_dict();
- err = mobilebackup2_send_status_response(mobilebackup2, *errcode, errdesc, empty_dict);
- plist_free(empty_dict);
- if (err != MOBILEBACKUP2_E_SUCCESS) {
- printf("Could not send status response, error %d\n", err);
- }
- }
- void iDeviceBackup2::RemoveItems(plist_t message, mobilebackup2_error_t *err, int *errcode, const char *errdesc, char *dlmsg) {
- struct stat st;
- mb2_set_overall_progress_from_message(message, dlmsg);
- 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) {
- const char *checkfile = strchr(str, '/');
- int suppress_warning = 0;
- if (checkfile) {
- if (strcmp(checkfile+1, "Manifest.mbdx") == 0) {
- suppress_warning = 1;
- }
- }
- char *newpath = build_path(backup_directory, str, NULL);
- free(str);
- #ifdef WIN32
- int res = 0;
- if ((stat(newpath, &st) == 0) && S_ISDIR(st.st_mode))
- res = RemoveDirectory(newpath);
- else
- res = DeleteFile(newpath);
- if (!res) {
- int e = win32err_to_errno(GetLastError());
- if (!suppress_warning)
- printf("Could not remove '%s': %s (%d)\n", newpath, strerror(e), e);
- *errcode = errno_to_device_error(e);
- errdesc = strerror(e);
- }
- #else
- if (remove(newpath) < 0) {
- if (!suppress_warning)
- printf("Could not remove '%s': %s (%d)\n", newpath, strerror(errno), errno);
- errcode = errno_to_device_error(errno);
- errdesc = strerror(errno);
- }
- #endif
- free(newpath);
- }
- }
- }
- plist_t empty_dict = plist_new_dict();
- *err = mobilebackup2_send_status_response(mobilebackup2, *errcode, errdesc, empty_dict);
- plist_free(empty_dict);
- if (err != MOBILEBACKUP2_E_SUCCESS) {
- printf("Could not send status response, error %d\n", err);
- }
- }
- void iDeviceBackup2::MoveItems(plist_t message, mobilebackup2_error_t *err, char *dlmsg, int *errcode, const char *errdesc) {
- /* perform a series of rename operations */
- mb2_set_overall_progress_from_message(message, dlmsg);
- 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) {
- char *newpath = build_path(backup_directory, str, NULL);
- free(str);
- char *oldpath = build_path(backup_directory, key, NULL);
- #ifdef WIN32
- if ((stat(newpath, &st) == 0) && S_ISDIR(st.st_mode))
- RemoveDirectory(newpath);
- else
- DeleteFile(newpath);
- #else
- remove(newpath);
- #endif
- if (rename(oldpath, newpath) < 0) {
- printf("Renameing '%s' to '%s' failed: %s (%d)\n", oldpath, newpath, strerror(errno), errno);
- *errcode = errno_to_device_error(errno);
- errdesc = strerror(errno);
- break;
- }
- free(oldpath);
- 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");
- }
- plist_t empty_dict = plist_new_dict();
- *err = mobilebackup2_send_status_response(mobilebackup2, *errcode, errdesc, empty_dict);
- plist_free(empty_dict);
- if (err != MOBILEBACKUP2_E_SUCCESS) {
- printf("Could not send status response, error %d\n", err);
- }
- }
- /// BEGIN SUPPLEMENTARY HELPER FUNCTIONS
- void iDeviceBackup2::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 if (!strcmp(notification, NP_BACKUP_DOMAIN_CHANGED)) {
- backup_domain_changed = 1;
- } else {
- PRINT_VERBOSE(1, "Unhandled notification '%s' (TODO: implement)\n", notification);
- }
- }
- void iDeviceBackup2::free_dictionary(char **dictionary)
- {
- int i = 0;
- if (!dictionary)
- return;
- for (i = 0; dictionary[i]; i++) {
- free(dictionary[i]);
- }
- free(dictionary);
- }
- void iDeviceBackup2::mobilebackup_afc_get_file_contents(afc_client_t afc, 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);
- }
- char *iDeviceBackup2::str_toupper(char* str)
- {
- char *res = strdup(str);
- unsigned int i;
- for (i = 0; i < strlen(res); i++) {
- res[i] = toupper(res[i]);
- }
- return res;
- }
- int iDeviceBackup2::__mkdir(const char* path, int mode)
- {
- #ifdef WIN32
- return _mkdir(path);
- #else
- return mkdir(path, mode);
- #endif
- }
- int iDeviceBackup2::mkdir_with_parents(const char *dir, int mode)
- {
- if (!dir) return -1;
- if (__mkdir(dir, mode) == 0) {
- return 0;
- } else {
- if (errno == EEXIST) return 0;
- }
- int res;
- char *parent = strdup(dir);
- char *parentdir = dirname(parent);
- if (parentdir) {
- res = mkdir_with_parents(parentdir, mode);
- } else {
- res = -1;
- }
- free(parent);
- if (res == 0) {
- mkdir_with_parents(dir, mode);
- }
- return res;
- }
- char* iDeviceBackup2::build_path(const char* elem, ...)
- {
- if (!elem) return NULL;
- va_list args;
- int len = strlen(elem)+1;
- va_start(args, elem);
- char *arg = va_arg(args, char*);
- while (arg) {
- len += strlen(arg)+1;
- arg = va_arg(args, char*);
- }
- va_end(args);
- char* out = (char*)malloc(len);
- strcpy(out, elem);
- va_start(args, elem);
- arg = va_arg(args, char*);
- while (arg) {
- strcat(out, "/");
- strcat(out, arg);
- arg = va_arg(args, char*);
- }
- va_end(args);
- return out;
- }
- char* iDeviceBackup2::format_size_for_display(uint64_t size)
- {
- char buf[32];
- double sz;
- if (size >= 1000000000LL) {
- sz = ((double)size / 1000000000.0f);
- sprintf(buf, "%0.1f GB", sz);
- } else if (size >= 1000000LL) {
- sz = ((double)size / 1000000.0f);
- sprintf(buf, "%0.1f MB", sz);
- } else if (size >= 1000LL) {
- sz = ((double)size / 1000.0f);
- sprintf(buf, "%0.1f kB", sz);
- } else {
- sprintf(buf, "%d Bytes", (int)size);
- }
- return strdup(buf);
- }
- plist_t iDeviceBackup2::mobilebackup_factory_info_plist_new(const char* udid, lockdownd_client_t lockdown, afc_client_t afc)
- {
- /* gather data from lockdown */
- plist_t value_node = NULL;
- plist_t root_node = NULL;
- char *udid_uppercase = NULL;
- plist_t ret = plist_new_dict();
- /* get basic device information in one go */
- lockdownd_get_value(lockdown, 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));
- plist_dict_insert_item(ret, "Last Backup Date", plist_new_date(time(NULL), 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");
- plist_dict_insert_item(ret, "Target Identifier", plist_new_string(udid));
- plist_dict_insert_item(ret, "Target Type", plist_new_string("Device"));
- /* uppercase */
- udid_uppercase = str_toupper((char*)udid);
- plist_dict_insert_item(ret, "Unique Identifier", plist_new_string(udid_uppercase));
- free(udid_uppercase);
- char *data_buf = NULL;
- uint64_t data_size = 0;
- mobilebackup_afc_get_file_contents(afc, "/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;
- char *fname = (char*)malloc(strlen("/iTunes_Control/iTunes/") + strlen(itunesfiles[i]) + 1);
- strcpy(fname, "/iTunes_Control/iTunes/");
- strcat(fname, itunesfiles[i]);
- mobilebackup_afc_get_file_contents(afc, fname, &data_buf, &data_size);
- 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 = NULL;
- lockdownd_get_value(lockdown, "com.apple.iTunes", NULL, &itunes_settings);
- plist_dict_insert_item(ret, "iTunes Settings", itunes_settings ? itunes_settings : plist_new_dict());
- plist_dict_insert_item(ret, "iTunes Version", plist_new_string("10.0.1"));
- plist_free(root_node);
- return ret;
- }
- void iDeviceBackup2::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;
- }
- void iDeviceBackup2::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);
- }
- }
- int iDeviceBackup2::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;
- }
- int iDeviceBackup2::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;
- }
- int iDeviceBackup2::mb2_status_check_snapshot_state(const char *path, const char *udid, const char *matches)
- {
- int ret = -1;
- plist_t status_plist = NULL;
- char *file_path = build_path(path, udid, "Status.plist", NULL);
- plist_read_from_filename(&status_plist, file_path);
- 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;
- free(sval);
- }
- } else {
- printf("%s: ERROR could not get SnapshotState key from Status.plist!\n", __func__);
- }
- plist_free(status_plist);
- return ret;
- }
- void iDeviceBackup2::do_post_notification(idevice_t device, const char *notification)
- {
- lockdownd_service_descriptor_t service = NULL;
- np_client_t np;
- lockdownd_client_t lockdown = NULL;
- if (lockdownd_client_new_with_handshake(device, &lockdown, "idevicebackup") != LOCKDOWN_E_SUCCESS) {
- return;
- }
- lockdownd_start_service(lockdown, NP_SERVICE_NAME, &service);
- if (service && service->port) {
- np_client_new(device, service, &np);
- if (np) {
- np_post_notification(np, notification);
- np_client_free(np);
- }
- } else {
- printf("Could not start %s\n", NP_SERVICE_NAME);
- }
- if (service) {
- lockdownd_service_descriptor_free(service);
- service = NULL;
- }
- lockdownd_client_free(lockdown);
- }
- void iDeviceBackup2::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");
- }
- }
- void iDeviceBackup2::print_progress(uint64_t current, uint64_t total)
- {
- char *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 = format_size_for_display(current);
- PRINT_VERBOSE(1, " (%s", format_size);
- free(format_size);
- format_size = format_size_for_display(total);
- PRINT_VERBOSE(1, "/%s) ", format_size);
- free(format_size);
- fflush(stdout);
- if (progress == 100) {
- PRINT_VERBOSE(1, "\n");
- }
- if(m_progressCallback) {
- m_progressCallback(current, total);
- }
- }
- void iDeviceBackup2::mb2_set_overall_progress(double progress)
- {
- if (progress > 0.0)
- overall_progress = progress;
- }
- void iDeviceBackup2::mb2_set_overall_progress_from_message(plist_t message, char* identifier)
- {
- plist_t node = NULL;
- double progress = 0.0;
- if (!strcmp(identifier, "DLMessageDownloadFiles")) {
- node = plist_array_get_item(message, 3);
- } else if (!strcmp(identifier, "DLMessageUploadFiles")) {
- node = plist_array_get_item(message, 2);
- } else if (!strcmp(identifier, "DLMessageMoveFiles") || !strcmp(identifier, "DLMessageMoveItems")) {
- node = plist_array_get_item(message, 3);
- } else if (!strcmp(identifier, "DLMessageRemoveFiles") || !strcmp(identifier, "DLMessageRemoveItems")) {
- node = plist_array_get_item(message, 3);
- }
- if (node != NULL) {
- plist_get_real_val(node, &progress);
- mb2_set_overall_progress(progress);
- }
- }
- void iDeviceBackup2::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);
- }
- int iDeviceBackup2::errno_to_device_error(int errno_value)
- {
- switch (errno_value) {
- case ENOENT:
- return -6;
- case EEXIST:
- return -7;
- default:
- return -errno_value;
- }
- }
- int iDeviceBackup2::mb2_handle_send_file(mobilebackup2_client_t mobilebackup2, const char *backup_dir, const char *path, plist_t *errplist)
- {
- uint32_t nlen = 0;
- uint32_t pathlen = strlen(path);
- uint32_t bytes = 0;
- char *localfile = build_path(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 = htobe32(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;
- char *format_size = format_size_for_display(total);
- PRINT_VERBOSE(1, "Sending '%s' (%s)\n", path, format_size);
- 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 = htobe32(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 = htobe32(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 = htobe32(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);
- free(localfile);
- return result;
- }
- void iDeviceBackup2::mb2_handle_send_files(mobilebackup2_client_t mobilebackup2, plist_t message, const char *backup_dir)
- {
- uint32_t cnt;
- uint32_t i = 0;
- uint32_t sent;
- plist_t errplist = NULL;
- 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;
- for (i = 0; i < cnt; i++) {
- plist_t 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(mobilebackup2, backup_dir, str, &errplist) < 0) {
- free(str);
- //printf("Error when sending file '%s' to device\n", str);
- // TODO: perhaps we can continue, we've got a multi status response?!
- break;
- }
- free(str);
- }
- /* send terminating 0 dword */
- uint32_t zero = 0;
- mobilebackup2_send_raw(mobilebackup2, (char*)&zero, 4, &sent);
- if (!errplist) {
- plist_t emptydict = plist_new_dict();
- mobilebackup2_send_status_response(mobilebackup2, 0, NULL, emptydict);
- plist_free(emptydict);
- } else {
- mobilebackup2_send_status_response(mobilebackup2, -13, "Multi status", errplist);
- plist_free(errplist);
- }
- }
- int iDeviceBackup2::mb2_receive_filename(mobilebackup2_client_t mobilebackup2, char** filename)
- {
- uint32_t nlen = 0;
- uint32_t rlen = 0;
- do {
- nlen = 0;
- rlen = 0;
- mobilebackup2_receive_raw(mobilebackup2, (char*)&nlen, 4, &rlen);
- nlen = be32toh(nlen);
- if ((nlen == 0) && (rlen == 4)) {
- // a zero length means no more files to receive
- return 0;
- } else if(rlen == 0) {
- // device needs more time, waiting...
- continue;
- } else if (nlen > 4096) …
Large files files are truncated, but you can click here to view the full file