diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mobilebackup.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/src/mobilebackup.c b/src/mobilebackup.c index 91b9e73..d4f36d6 100644 --- a/src/mobilebackup.c +++ b/src/mobilebackup.c @@ -129,3 +129,153 @@ mobilebackup_error_t mobilebackup_send(mobilebackup_client_t client, plist_t pli return mobilebackup_error(device_link_service_send(client->parent, plist)); } +/** + * Request a backup from the connected device. + * + * @param client The connected MobileBackup client to use. + * @param backup_manifest The backup manifest, a plist_t of type PLIST_DICT + * containing the backup state of the last backup. For a first-time backup + * set this parameter to NULL. + * @param base_path The base path on the device to use for the backup + * operation, usually "/". + * @param proto_version A string denoting the version of the backup protocol + * to use. Latest known version is "1.6" + * + * @return MOBILEBACKUP_E_SUCCESS on success, MOBILEBACKUP_E_INVALID_ARG if + * one of the parameters is invalid, MOBILEBACKUP_E_PLIST_ERROR if + * backup_manifest is not of type PLIST_DICT, MOBILEBACKUP_E_MUX_ERROR + * if a communication error occurs, MOBILEBACKUP_E_REPLY_NOT_OK + */ +mobilebackup_error_t mobilebackup_request_backup(mobilebackup_client_t client, plist_t backup_manifest, const char *base_path, const char *proto_version) +{ + if (!client || !client->parent || !base_path || !proto_version) + return MOBILEBACKUP_E_INVALID_ARG; + + if (backup_manifest && (plist_get_node_type(backup_manifest) != PLIST_DICT)) + return MOBILEBACKUP_E_PLIST_ERROR; + + mobilebackup_error_t err; + + /* construct request plist */ + plist_t dict = plist_new_dict(); + if (backup_manifest) + plist_dict_insert_item(dict, "BackupManifestKey", plist_copy(backup_manifest)); + plist_dict_insert_item(dict, "BackupComputerBasePathKey", plist_new_string(base_path)); + plist_dict_insert_item(dict, "BackupMessageTypeKey", plist_new_string("BackupMessageBackupRequest")); + plist_dict_insert_item(dict, "BackupProtocolVersion", plist_new_string(proto_version)); + + /* send it as DLMessageProcessMessage */ + err = mobilebackup_error(device_link_service_send_process_message(client->parent, dict)); + plist_free(dict); + dict = NULL; + if (err != MOBILEBACKUP_E_SUCCESS) { + debug_info("ERROR: Could not send backup request message (%d)!", err); + goto leave; + } + + /* now receive and hopefully get a BackupMessageBackupReplyOK */ + err = mobilebackup_error(device_link_service_receive_process_message(client->parent, &dict)); + if (err != MOBILEBACKUP_E_SUCCESS) { + debug_info("ERROR: Could not receive BackupReplyOK message (%d)!", err); + goto leave; + } + + plist_t node = plist_dict_get_item(dict, "BackupMessageTypeKey"); + if (!node) { + debug_info("ERROR: BackupMessageTypeKey not found in BackupReplyOK message!"); + err = MOBILEBACKUP_E_PLIST_ERROR; + goto leave; + } + + char *str = NULL; + plist_get_string_val(node, &str); + if (!str || (strcmp(str, "BackupMessageBackupReplyOK") != 0)) { + debug_info("ERROR: BackupMessageTypeKey value does not match 'BackupMessageBackupReplyOK'"); + err = MOBILEBACKUP_E_REPLY_NOT_OK; + if (str) + free(str); + goto leave; + } + free(str); + str = NULL; + + node = plist_dict_get_item(dict, "BackupProtocolVersion"); + if (node) { + plist_get_string_val(node, &str); + if (str) { + if (strcmp(str, proto_version) != 0) { + err = MOBILEBACKUP_E_BAD_VERSION; + } + free(str); + } + } + if (err != MOBILEBACKUP_E_SUCCESS) + goto leave; + + /* BackupMessageBackupReplyOK received, send it back */ + err = mobilebackup_error(device_link_service_send_process_message(client->parent, dict)); + if (err != MOBILEBACKUP_E_SUCCESS) { + debug_info("ERROR: Could not send BackupReplyOK ACK (%d)", err); + } + +leave: + if (dict) + plist_free(dict); + return err; +} + +/** + * Sends a confirmation to the device that a backup file has been received. + * + * @param client The connected MobileBackup client to use. + * + * @return MOBILEBACKUP_E_SUCCESS on success, MOBILEBACKUP_E_INVALID_ARG if + * client is invalid, or MOBILEBACKUP_E_MUX_ERROR if a communication error + * occurs. + */ +mobilebackup_error_t mobilebackup_send_backup_file_received(mobilebackup_client_t client) +{ + if (!client || !client->parent) + return MOBILEBACKUP_E_INVALID_ARG; + + mobilebackup_error_t err; + + /* construct ACK plist */ + plist_t dict = plist_new_dict(); + plist_dict_insert_item(dict, "BackupMessageTypeKey", plist_new_string("kBackupMessageBackupFileReceived")); + + /* send it as DLMessageProcessMessage */ + err = mobilebackup_error(device_link_service_send_process_message(client->parent, dict)); + plist_free(dict); + + return err; +} + +/** + * Sends a backup error message to the device. + * + * @param client The connected MobileBackup client to use. + * @param reason A string describing the reason for the error message. + * + * @return MOBILEBACKUP_E_SUCCESS on success, MOBILEBACKUP_E_INVALID_ARG if + * one of the parameters is invalid, or MOBILEBACKUP_E_MUX_ERROR if a + * communication error occurs. + */ +mobilebackup_error_t mobilebackup_send_error(mobilebackup_client_t client, const char *reason) +{ + if (!client || !client->parent || !reason) + return MOBILEBACKUP_E_INVALID_ARG; + + mobilebackup_error_t err; + + /* construct error plist */ + plist_t dict = plist_new_dict(); + plist_dict_insert_item(dict, "BackupMessageTypeKey", plist_new_string("BackupMessageError")); + plist_dict_insert_item(dict, "BackupErrorReasonKey", plist_new_string(reason)); + + /* send it as DLMessageProcessMessage */ + err = mobilebackup_error(device_link_service_send_process_message(client->parent, dict)); + plist_free(dict); + + return err; +} |