diff options
| -rw-r--r-- | include/libimobiledevice/mobilebackup.h | 9 | ||||
| -rw-r--r-- | src/mobilebackup.c | 114 |
2 files changed, 123 insertions, 0 deletions
diff --git a/include/libimobiledevice/mobilebackup.h b/include/libimobiledevice/mobilebackup.h index 7dbc3fe..bf405f9 100644 --- a/include/libimobiledevice/mobilebackup.h +++ b/include/libimobiledevice/mobilebackup.h | |||
| @@ -47,12 +47,21 @@ typedef int16_t mobilebackup_error_t; | |||
| 47 | typedef struct mobilebackup_client_private mobilebackup_client_private; | 47 | typedef struct mobilebackup_client_private mobilebackup_client_private; |
| 48 | typedef mobilebackup_client_private *mobilebackup_client_t; /**< The client handle. */ | 48 | typedef mobilebackup_client_private *mobilebackup_client_t; /**< The client handle. */ |
| 49 | 49 | ||
| 50 | typedef enum { | ||
| 51 | MB_RESTORE_NOTIFY_SPRINGBOARD = 1 << 0, | ||
| 52 | MB_RESTORE_PRESERVE_SETTINGS = 1 << 1, | ||
| 53 | MB_RESTORE_PRESERVE_CAMERA_ROLL = 1 << 2 | ||
| 54 | } mobilebackup_flags_t; | ||
| 55 | |||
| 50 | mobilebackup_error_t mobilebackup_client_new(idevice_t device, uint16_t port, mobilebackup_client_t * client); | 56 | mobilebackup_error_t mobilebackup_client_new(idevice_t device, uint16_t port, mobilebackup_client_t * client); |
| 51 | mobilebackup_error_t mobilebackup_client_free(mobilebackup_client_t client); | 57 | mobilebackup_error_t mobilebackup_client_free(mobilebackup_client_t client); |
| 52 | mobilebackup_error_t mobilebackup_receive(mobilebackup_client_t client, plist_t *plist); | 58 | mobilebackup_error_t mobilebackup_receive(mobilebackup_client_t client, plist_t *plist); |
| 53 | mobilebackup_error_t mobilebackup_send(mobilebackup_client_t client, plist_t plist); | 59 | mobilebackup_error_t mobilebackup_send(mobilebackup_client_t client, plist_t plist); |
| 54 | mobilebackup_error_t mobilebackup_request_backup(mobilebackup_client_t client, plist_t backup_manifest, const char *base_path, const char *proto_version); | 60 | mobilebackup_error_t mobilebackup_request_backup(mobilebackup_client_t client, plist_t backup_manifest, const char *base_path, const char *proto_version); |
| 55 | mobilebackup_error_t mobilebackup_send_backup_file_received(mobilebackup_client_t client); | 61 | mobilebackup_error_t mobilebackup_send_backup_file_received(mobilebackup_client_t client); |
| 62 | mobilebackup_error_t mobilebackup_request_restore(mobilebackup_client_t client, plist_t backup_manifest, mobilebackup_flags_t flags, const char *proto_version); | ||
| 63 | mobilebackup_error_t mobilebackup_receive_restore_file_received(mobilebackup_client_t client, plist_t *result); | ||
| 64 | mobilebackup_error_t mobilebackup_send_restore_complete(mobilebackup_client_t client); | ||
| 56 | mobilebackup_error_t mobilebackup_send_error(mobilebackup_client_t client, const char *reason); | 65 | mobilebackup_error_t mobilebackup_send_error(mobilebackup_client_t client, const char *reason); |
| 57 | 66 | ||
| 58 | #ifdef __cplusplus | 67 | #ifdef __cplusplus |
diff --git a/src/mobilebackup.c b/src/mobilebackup.c index d71a494..6277d45 100644 --- a/src/mobilebackup.c +++ b/src/mobilebackup.c | |||
| @@ -30,6 +30,8 @@ | |||
| 30 | #define MBACKUP_VERSION_INT1 100 | 30 | #define MBACKUP_VERSION_INT1 100 |
| 31 | #define MBACKUP_VERSION_INT2 0 | 31 | #define MBACKUP_VERSION_INT2 0 |
| 32 | 32 | ||
| 33 | #define IS_FLAG_SET(x, y) ((x & y) == y) | ||
| 34 | |||
| 33 | /** | 35 | /** |
| 34 | * Convert an device_link_service_error_t value to an mobilebackup_error_t value. | 36 | * Convert an device_link_service_error_t value to an mobilebackup_error_t value. |
| 35 | * Used internally to get correct error codes when using device_link_service stuff. | 37 | * Used internally to get correct error codes when using device_link_service stuff. |
| @@ -353,6 +355,118 @@ mobilebackup_error_t mobilebackup_send_backup_file_received(mobilebackup_client_ | |||
| 353 | } | 355 | } |
| 354 | 356 | ||
| 355 | /** | 357 | /** |
| 358 | * Request that a backup should be restored to the connected device. | ||
| 359 | * | ||
| 360 | * @param client The connected MobileBackup client to use. | ||
| 361 | * @param backup_manifest The backup manifest, a plist_t of type PLIST_DICT | ||
| 362 | * containing the backup state to be restored. | ||
| 363 | * @param flags Flags to send with the request. Currently this is a combination | ||
| 364 | * of the following mobilebackup_flags_t: | ||
| 365 | * MB_RESTORE_NOTIFY_SPRINGBOARD - let SpringBoard show a 'Restore' screen | ||
| 366 | * MB_RESTORE_PRESERVE_SETTINGS - do not overwrite any settings | ||
| 367 | * MB_RESTORE_PRESERVE_CAMERA_ROLL - preserve the photos of the camera roll | ||
| 368 | * @param proto_version A string denoting the version of the backup protocol | ||
| 369 | * to use. Latest known version is "1.6". Ideally this value should be | ||
| 370 | * extracted from the given manifest plist. | ||
| 371 | * | ||
| 372 | * @return MOBILEBACKUP_E_SUCCESS on success, MOBILEBACKUP_E_INVALID_ARG if | ||
| 373 | * one of the parameters is invalid, MOBILEBACKUP_E_PLIST_ERROR if | ||
| 374 | * backup_manifest is not of type PLIST_DICT, MOBILEBACKUP_E_MUX_ERROR | ||
| 375 | * if a communication error occurs, or MOBILEBACKUP_E_REPLY_NOT_OK | ||
| 376 | * if the device did not accept the request. | ||
| 377 | */ | ||
| 378 | mobilebackup_error_t mobilebackup_request_restore(mobilebackup_client_t client, plist_t backup_manifest, mobilebackup_flags_t flags, const char *proto_version) | ||
| 379 | { | ||
| 380 | if (!client || !client->parent || !backup_manifest || !proto_version) | ||
| 381 | return MOBILEBACKUP_E_INVALID_ARG; | ||
| 382 | |||
| 383 | if (backup_manifest && (plist_get_node_type(backup_manifest) != PLIST_DICT)) | ||
| 384 | return MOBILEBACKUP_E_PLIST_ERROR; | ||
| 385 | |||
| 386 | mobilebackup_error_t err; | ||
| 387 | |||
| 388 | /* construct request plist */ | ||
| 389 | plist_t dict = plist_new_dict(); | ||
| 390 | plist_dict_insert_item(dict, "BackupManifestKey", plist_copy(backup_manifest)); | ||
| 391 | plist_dict_insert_item(dict, "BackupMessageTypeKey", plist_new_string("BackupMessageRestoreRequest")); | ||
| 392 | plist_dict_insert_item(dict, "BackupProtocolVersion", plist_new_string(proto_version)); | ||
| 393 | /* add flags */ | ||
| 394 | plist_dict_insert_item(dict, "BackupNotifySpringBoard", plist_new_bool(IS_FLAG_SET(flags, MB_RESTORE_NOTIFY_SPRINGBOARD))); | ||
| 395 | plist_dict_insert_item(dict, "BackupPreserveSettings", plist_new_bool(IS_FLAG_SET(flags, MB_RESTORE_PRESERVE_SETTINGS))); | ||
| 396 | plist_dict_insert_item(dict, "BackupPreserveCameraRoll", plist_new_bool(IS_FLAG_SET(flags, MB_RESTORE_PRESERVE_CAMERA_ROLL))); | ||
| 397 | |||
| 398 | /* send request */ | ||
| 399 | err = mobilebackup_send_message(client, NULL, dict); | ||
| 400 | plist_free(dict); | ||
| 401 | dict = NULL; | ||
| 402 | if (err != MOBILEBACKUP_E_SUCCESS) { | ||
| 403 | debug_info("ERROR: Could not send restore request message (%d)!", err); | ||
| 404 | goto leave; | ||
| 405 | } | ||
| 406 | |||
| 407 | /* now receive and hopefully get a BackupMessageRestoreReplyOK */ | ||
| 408 | err = mobilebackup_receive_message(client, "BackupMessageRestoreReplyOK", &dict); | ||
| 409 | if (err != MOBILEBACKUP_E_SUCCESS) { | ||
| 410 | debug_info("ERROR: Could not receive RestoreReplyOK message (%d)!", err); | ||
| 411 | goto leave; | ||
| 412 | } | ||
| 413 | |||
| 414 | plist_t node = plist_dict_get_item(dict, "BackupProtocolVersion"); | ||
| 415 | if (node) { | ||
| 416 | char *str = NULL; | ||
| 417 | plist_get_string_val(node, &str); | ||
| 418 | if (str) { | ||
| 419 | if (strcmp(str, proto_version) != 0) { | ||
| 420 | err = MOBILEBACKUP_E_BAD_VERSION; | ||
| 421 | } | ||
| 422 | free(str); | ||
| 423 | } | ||
| 424 | } | ||
| 425 | |||
| 426 | leave: | ||
| 427 | if (dict) | ||
| 428 | plist_free(dict); | ||
| 429 | return err; | ||
| 430 | } | ||
| 431 | |||
| 432 | /** | ||
| 433 | * Receive a confirmation from the device that it successfully received | ||
| 434 | * a restore file. | ||
| 435 | * | ||
| 436 | * @param client The connected MobileBackup client to use. | ||
| 437 | * @param result Pointer to a plist_t that will be set to the received plist | ||
| 438 | * for further processing. The caller has to free it using plist_free(). | ||
| 439 | * Note that it will be set to NULL if the operation itself fails due to | ||
| 440 | * a communication or plist error. | ||
| 441 | * If this parameter is NULL, it will be ignored. | ||
| 442 | * | ||
| 443 | * @return MOBILEBACKUP_E_SUCCESS on success, MOBILEBACKUP_E_INVALID_ARG if | ||
| 444 | * client is invalid, MOBILEBACKUP_E_REPLY_NOT_OK if the expected | ||
| 445 | * 'BackupMessageRestoreFileReceived' message could not be received, | ||
| 446 | * MOBILEBACKUP_E_PLIST_ERROR if the received message is not a valid backup | ||
| 447 | * message plist, or MOBILEBACKUP_E_MUX_ERROR if a communication error | ||
| 448 | * occurs. | ||
| 449 | */ | ||
| 450 | mobilebackup_error_t mobilebackup_receive_restore_file_received(mobilebackup_client_t client, plist_t *result) | ||
| 451 | { | ||
| 452 | return mobilebackup_receive_message(client, "BackupMessageRestoreFileReceived", result); | ||
| 453 | } | ||
| 454 | |||
| 455 | /** | ||
| 456 | * Tells the device that the restore process is complete. | ||
| 457 | * | ||
| 458 | * @param client The connected MobileBackup client to use. | ||
| 459 | * | ||
| 460 | * @return MOBILEBACKUP_E_SUCCESS on success, MOBILEBACKUP_E_INVALID_ARG if | ||
| 461 | * client is invalid, or MOBILEBACKUP_E_MUX_ERROR if a communication error | ||
| 462 | * occurs. | ||
| 463 | */ | ||
| 464 | mobilebackup_error_t mobilebackup_send_restore_complete(mobilebackup_client_t client) | ||
| 465 | { | ||
| 466 | return mobilebackup_send_message(client, "BackupMessageRestoreComplete", NULL); | ||
| 467 | } | ||
| 468 | |||
| 469 | /** | ||
| 356 | * Sends a backup error message to the device. | 470 | * Sends a backup error message to the device. |
| 357 | * | 471 | * |
| 358 | * @param client The connected MobileBackup client to use. | 472 | * @param client The connected MobileBackup client to use. |
