summaryrefslogtreecommitdiffstats
path: root/src/mobilebackup.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mobilebackup.c')
-rw-r--r--src/mobilebackup.c150
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;
+}