diff options
| author | 2010-11-22 23:27:19 +0100 | |
|---|---|---|
| committer | 2011-04-11 17:05:57 +0200 | |
| commit | 18e4f053bced9ead787e23e0526cb758a9979af1 (patch) | |
| tree | e4baa3e8b9d35e6f7112f6f1263e69853a2fb913 /tools | |
| parent | ae7013d7d8355da926c0818182dd500589b48ed6 (diff) | |
| download | libimobiledevice-18e4f053bced9ead787e23e0526cb758a9979af1.tar.gz libimobiledevice-18e4f053bced9ead787e23e0526cb758a9979af1.tar.bz2 | |
mobilebackup2: added info and list commands, started restore implementation
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/idevicebackup4.c | 388 |
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; | |||
| 54 | enum cmd_mode { | 54 | enum cmd_mode { |
| 55 | CMD_BACKUP, | 55 | CMD_BACKUP, |
| 56 | CMD_RESTORE, | 56 | CMD_RESTORE, |
| 57 | CMD_INFO, | ||
| 58 | CMD_LIST, | ||
| 57 | CMD_LEAVE | 59 | CMD_LEAVE |
| 58 | }; | 60 | }; |
| 59 | 61 | ||
| @@ -1140,6 +1142,12 @@ int main(int argc, char *argv[]) | |||
| 1140 | else if (!strcmp(argv[i], "restore")) { | 1142 | else if (!strcmp(argv[i], "restore")) { |
| 1141 | cmd = CMD_RESTORE; | 1143 | cmd = CMD_RESTORE; |
| 1142 | } | 1144 | } |
| 1145 | else if (!strcmp(argv[i], "info")) { | ||
| 1146 | cmd = CMD_INFO; | ||
| 1147 | } | ||
| 1148 | else if (!strcmp(argv[i], "list")) { | ||
| 1149 | cmd = CMD_LIST; | ||
| 1150 | } | ||
| 1143 | else if (backup_directory == NULL) { | 1151 | else if (backup_directory == NULL) { |
| 1144 | backup_directory = argv[i]; | 1152 | backup_directory = argv[i]; |
| 1145 | } | 1153 | } |
| @@ -1369,12 +1377,6 @@ checkpoint: | |||
| 1369 | plist_free(info_plist); | 1377 | plist_free(info_plist); |
| 1370 | info_plist = NULL; | 1378 | info_plist = NULL; |
| 1371 | 1379 | ||
| 1372 | /* close down the lockdown connection as it is no longer needed */ | ||
| 1373 | if (client) { | ||
| 1374 | lockdownd_client_free(client); | ||
| 1375 | client = NULL; | ||
| 1376 | } | ||
| 1377 | |||
| 1378 | /* create Status.plist with failed status for now */ | 1380 | /* create Status.plist with failed status for now */ |
| 1379 | //mobilebackup_write_status(backup_directory, 0); | 1381 | //mobilebackup_write_status(backup_directory, 0); |
| 1380 | 1382 | ||
| @@ -1398,7 +1400,44 @@ checkpoint: | |||
| 1398 | } | 1400 | } |
| 1399 | break; | 1401 | break; |
| 1400 | } | 1402 | } |
| 1403 | break; | ||
| 1404 | case CMD_RESTORE: | ||
| 1405 | /* TODO: verify battery on AC enough battery remaining */ | ||
| 1406 | printf("Starting Restore...\n"); | ||
| 1407 | |||
| 1408 | plist_t opts = plist_new_dict(); | ||
| 1409 | plist_dict_insert_item(opts, "shouldRestoreSystemFiles", plist_new_bool(0)); | ||
| 1410 | err = mobilebackup2_send_request(mobilebackup2, "Restore", uuid, uuid, opts); | ||
| 1411 | plist_free(opts); | ||
| 1412 | if (err != MOBILEBACKUP2_E_SUCCESS) { | ||
| 1413 | cmd = CMD_LEAVE; | ||
| 1414 | } | ||
| 1415 | break; | ||
| 1416 | case CMD_INFO: | ||
| 1417 | printf("Requesting backup info from device...\n"); | ||
| 1418 | err = mobilebackup2_send_request(mobilebackup2, "Info", uuid, NULL, NULL); | ||
| 1419 | if (err != MOBILEBACKUP2_E_SUCCESS) { | ||
| 1420 | cmd = CMD_LEAVE; | ||
| 1421 | } | ||
| 1422 | break; | ||
| 1423 | case CMD_LIST: | ||
| 1424 | printf("Requesting backup list from device...\n"); | ||
| 1425 | err = mobilebackup2_send_request(mobilebackup2, "List", uuid, NULL, NULL); | ||
| 1426 | if (err != MOBILEBACKUP2_E_SUCCESS) { | ||
| 1427 | cmd = CMD_LEAVE; | ||
| 1428 | } | ||
| 1429 | break; | ||
| 1430 | default: | ||
| 1431 | break; | ||
| 1432 | } | ||
| 1401 | 1433 | ||
| 1434 | /* close down the lockdown connection as it is no longer needed */ | ||
| 1435 | if (client) { | ||
| 1436 | lockdownd_client_free(client); | ||
| 1437 | client = NULL; | ||
| 1438 | } | ||
| 1439 | |||
| 1440 | if (cmd != CMD_LEAVE) { | ||
| 1402 | /* reset backup status */ | 1441 | /* reset backup status */ |
| 1403 | int backup_ok = 0; | 1442 | int backup_ok = 0; |
| 1404 | plist_t message = NULL; | 1443 | plist_t message = NULL; |
| @@ -1769,343 +1808,6 @@ files_out: | |||
| 1769 | } else { | 1808 | } else { |
| 1770 | printf("Backup Failed.\n"); | 1809 | printf("Backup Failed.\n"); |
| 1771 | } | 1810 | } |
| 1772 | |||
| 1773 | break; | ||
| 1774 | case CMD_RESTORE: | ||
| 1775 | /* close down the lockdown connection as it is no longer needed */ | ||
| 1776 | if (client) { | ||
| 1777 | lockdownd_client_free(client); | ||
| 1778 | client = NULL; | ||
| 1779 | } | ||
| 1780 | |||
| 1781 | /* TODO: verify battery on AC enough battery remaining */ | ||
| 1782 | |||
| 1783 | /* verify if Status.plist says we read from an successful backup */ | ||
| 1784 | #if 0 | ||
| 1785 | if (mobilebackup_read_status(backup_directory) <= 0) { | ||
| 1786 | printf("ERROR: Cannot ensure we restore from a successful backup. Aborting.\n"); | ||
| 1787 | break; | ||
| 1788 | } | ||
| 1789 | /* now make sure backup integrity is ok! verify all files */ | ||
| 1790 | printf("Reading existing Manifest.\n"); | ||
| 1791 | plist_read_from_filename(&manifest_plist, manifest_path); | ||
| 1792 | if (!manifest_plist) { | ||
| 1793 | printf("Could not read Manifest.plist. Aborting.\n"); | ||
| 1794 | break; | ||
| 1795 | } | ||
| 1796 | |||
| 1797 | printf("Verifying backup integrity, please wait.\n"); | ||
| 1798 | char *bin = NULL; | ||
| 1799 | uint64_t binsize = 0; | ||
| 1800 | node = plist_dict_get_item(manifest_plist, "Data"); | ||
| 1801 | if (!node || (plist_get_node_type(node) != PLIST_DATA)) { | ||
| 1802 | printf("Could not read Data key from Manifest.plist!\n"); | ||
| 1803 | break; | ||
| 1804 | } | ||
| 1805 | plist_get_data_val(node, &bin, &binsize); | ||
| 1806 | plist_t backup_data = NULL; | ||
| 1807 | if (bin) { | ||
| 1808 | char *auth_ver = NULL; | ||
| 1809 | unsigned char *auth_sig = NULL; | ||
| 1810 | uint64_t auth_sig_len = 0; | ||
| 1811 | /* verify AuthSignature */ | ||
| 1812 | node = plist_dict_get_item(manifest_plist, "AuthVersion"); | ||
| 1813 | plist_get_string_val(node, &auth_ver); | ||
| 1814 | if (auth_ver && (strcmp(auth_ver, "2.0") == 0)) { | ||
| 1815 | node = plist_dict_get_item(manifest_plist, "AuthSignature"); | ||
| 1816 | if (node && (plist_get_node_type(node) == PLIST_DATA)) { | ||
| 1817 | plist_get_data_val(node, (char**)&auth_sig, &auth_sig_len); | ||
| 1818 | } | ||
| 1819 | if (auth_sig && (auth_sig_len == 20)) { | ||
| 1820 | /* calculate the sha1, then compare */ | ||
| 1821 | unsigned char data_sha1[20]; | ||
| 1822 | sha1_of_data(bin, binsize, data_sha1); | ||
| 1823 | if (compare_hash(auth_sig, data_sha1, 20)) { | ||
| 1824 | printf("AuthSignature is valid\n"); | ||
| 1825 | } else { | ||
| 1826 | printf("ERROR: AuthSignature is NOT VALID\n"); | ||
| 1827 | } | ||
| 1828 | } else { | ||
| 1829 | printf("Could not get AuthSignature from manifest!\n"); | ||
| 1830 | } | ||
| 1831 | g_free(auth_sig); | ||
| 1832 | } else if (auth_ver) { | ||
| 1833 | printf("Unknown AuthVersion '%s', cannot verify AuthSignature\n", auth_ver); | ||
| 1834 | } | ||
| 1835 | plist_from_bin(bin, (uint32_t)binsize, &backup_data); | ||
| 1836 | g_free(bin); | ||
| 1837 | } | ||
| 1838 | if (!backup_data) { | ||
| 1839 | printf("Could not read plist from Manifest.plist Data key!\n"); | ||
| 1840 | break; | ||
| 1841 | } | ||
| 1842 | plist_t files = plist_dict_get_item(backup_data, "Files"); | ||
| 1843 | if (files && (plist_get_node_type(files) == PLIST_DICT)) { | ||
| 1844 | plist_dict_iter iter = NULL; | ||
| 1845 | plist_dict_new_iter(files, &iter); | ||
| 1846 | if (iter) { | ||
| 1847 | /* loop over Files entries in Manifest data plist */ | ||
| 1848 | char *hash = NULL; | ||
| 1849 | int file_ok = 0; | ||
| 1850 | int total_files = plist_dict_get_size(files); | ||
| 1851 | int cur_file = 1; | ||
| 1852 | node = NULL; | ||
| 1853 | plist_dict_next_item(files, iter, &hash, &node); | ||
| 1854 | while (node) { | ||
| 1855 | printf("Verifying file %d/%d (%d%%) \r", cur_file, total_files, (cur_file*100/total_files)); | ||
| 1856 | cur_file++; | ||
| 1857 | /* make sure both .mddata/.mdinfo files are available for each entry */ | ||
| 1858 | file_ok = mobilebackup_check_file_integrity(backup_directory, hash, node); | ||
| 1859 | node = NULL; | ||
| 1860 | free(hash); | ||
| 1861 | hash = NULL; | ||
| 1862 | if (!file_ok) { | ||
| 1863 | break; | ||
| 1864 | } | ||
| 1865 | plist_dict_next_item(files, iter, &hash, &node); | ||
| 1866 | } | ||
| 1867 | printf("\n"); | ||
| 1868 | free(iter); | ||
| 1869 | if (!file_ok) { | ||
| 1870 | plist_free(backup_data); | ||
| 1871 | break; | ||
| 1872 | } | ||
| 1873 | printf("All backup files appear to be valid\n"); | ||
| 1874 | } | ||
| 1875 | } | ||
| 1876 | |||
| 1877 | printf("Requesting restore from device...\n"); | ||
| 1878 | |||
| 1879 | /* request restore from device with manifest (BackupMessageRestoreMigrate) */ | ||
| 1880 | int restore_flags = MB_RESTORE_NOTIFY_SPRINGBOARD | MB_RESTORE_PRESERVE_SETTINGS | MB_RESTORE_PRESERVE_CAMERA_ROLL; | ||
| 1881 | err = mobilebackup_request_restore(mobilebackup, manifest_plist, restore_flags, "1.6"); | ||
| 1882 | if (err != MOBILEBACKUP_E_SUCCESS) { | ||
| 1883 | if (err == MOBILEBACKUP_E_BAD_VERSION) { | ||
| 1884 | printf("ERROR: Could not start restore process: backup protocol version mismatch!\n"); | ||
| 1885 | } else if (err == MOBILEBACKUP_E_REPLY_NOT_OK) { | ||
| 1886 | printf("ERROR: Could not start restore process: device refused to start the restore process.\n"); | ||
| 1887 | } else { | ||
| 1888 | printf("ERROR: Could not start restore process: unspecified error occured (%d)\n", err); | ||
| 1889 | } | ||
| 1890 | plist_free(backup_data); | ||
| 1891 | break; | ||
| 1892 | } | ||
| 1893 | |||
| 1894 | printf("Entered restore mode.\n"); | ||
| 1895 | |||
| 1896 | int restore_ok = 0; | ||
| 1897 | |||
| 1898 | if (files && (plist_get_node_type(files) == PLIST_DICT)) { | ||
| 1899 | plist_dict_iter iter = NULL; | ||
| 1900 | plist_dict_new_iter(files, &iter); | ||
| 1901 | if (iter) { | ||
| 1902 | /* loop over Files entries in Manifest data plist */ | ||
| 1903 | char *hash = NULL; | ||
| 1904 | plist_t file_info = NULL; | ||
| 1905 | char *file_info_path = NULL; | ||
| 1906 | int total_files = plist_dict_get_size(files); | ||
| 1907 | int cur_file = 0; | ||
| 1908 | uint64_t file_offset = 0; | ||
| 1909 | uint8_t is_encrypted = 0; | ||
| 1910 | plist_t tmp_node = NULL; | ||
| 1911 | plist_t file_path_node = NULL; | ||
| 1912 | plist_t send_file_node = NULL; | ||
| 1913 | node = NULL; | ||
| 1914 | plist_dict_next_item(files, iter, &hash, &node); | ||
| 1915 | while (node) { | ||
| 1916 | /* TODO: read mddata/mdinfo files and send to device using DLSendFile */ | ||
| 1917 | file_info_path = mobilebackup_build_path(backup_directory, hash, ".mdinfo"); | ||
| 1918 | plist_read_from_filename(&file_info, file_info_path); | ||
| 1919 | |||
| 1920 | /* get encryption state */ | ||
| 1921 | tmp_node = plist_dict_get_item(file_info, "IsEncrypted"); | ||
| 1922 | plist_get_bool_val(tmp_node, &is_encrypted); | ||
| 1923 | tmp_node = NULL; | ||
| 1924 | |||
| 1925 | /* get real file path from metadata */ | ||
| 1926 | tmp_node = plist_dict_get_item(file_info, "Metadata"); | ||
| 1927 | plist_get_data_val(tmp_node, &buffer, &length); | ||
| 1928 | tmp_node = NULL; | ||
| 1929 | plist_from_bin(buffer, length, &tmp_node); | ||
| 1930 | file_path_node = plist_dict_get_item(tmp_node, "Path"); | ||
| 1931 | plist_get_string_val(file_path_node, &file_path); | ||
| 1932 | |||
| 1933 | printf("Restoring file %s %d/%d (%d%%)... ", file_path, cur_file, total_files, (cur_file*100/total_files)); | ||
| 1934 | |||
| 1935 | /* add additional device link file information keys */ | ||
| 1936 | plist_dict_insert_item(file_info, "DLFileAttributesKey", plist_copy(node)); | ||
| 1937 | plist_dict_insert_item(file_info, "DLFileSource", plist_new_string(file_info_path)); | ||
| 1938 | plist_dict_insert_item(file_info, "DLFileDest", plist_new_string("/tmp/RestoreFile.plist")); | ||
| 1939 | plist_dict_insert_item(file_info, "DLFileIsEncrypted", plist_new_bool(is_encrypted)); | ||
| 1940 | plist_dict_insert_item(file_info, "DLFileOffsetKey", plist_new_uint(file_offset)); | ||
| 1941 | plist_dict_insert_item(file_info, "DLFileStatusKey", plist_new_uint(file_status)); | ||
| 1942 | |||
| 1943 | /* read data from file */ | ||
| 1944 | free(file_info_path); | ||
| 1945 | file_info_path = mobilebackup_build_path(backup_directory, hash, ".mddata"); | ||
| 1946 | buffer_read_from_filename(file_info_path, &buffer, &length); | ||
| 1947 | free(file_info_path); | ||
| 1948 | |||
| 1949 | /* send DLSendFile messages */ | ||
| 1950 | file_offset = 0; | ||
| 1951 | do { | ||
| 1952 | if ((length-file_offset) <= 8192) | ||
| 1953 | file_status = DEVICE_LINK_FILE_STATUS_LAST_HUNK; | ||
| 1954 | else | ||
| 1955 | file_status = DEVICE_LINK_FILE_STATUS_HUNK; | ||
| 1956 | |||
| 1957 | plist_dict_remove_item(file_info, "DLFileOffsetKey"); | ||
| 1958 | plist_dict_insert_item(file_info, "DLFileOffsetKey", plist_new_uint(file_offset)); | ||
| 1959 | |||
| 1960 | plist_dict_remove_item(file_info, "DLFileStatusKey"); | ||
| 1961 | plist_dict_insert_item(file_info, "DLFileStatusKey", plist_new_uint(file_status)); | ||
| 1962 | |||
| 1963 | send_file_node = plist_new_array(); | ||
| 1964 | |||
| 1965 | plist_array_append_item(send_file_node, plist_new_string("DLSendFile")); | ||
| 1966 | |||
| 1967 | if (file_status == DEVICE_LINK_FILE_STATUS_LAST_HUNK) | ||
| 1968 | plist_array_append_item(send_file_node, plist_new_data(buffer+file_offset, length-file_offset)); | ||
| 1969 | else | ||
| 1970 | plist_array_append_item(send_file_node, plist_new_data(buffer+file_offset, 8192)); | ||
| 1971 | |||
| 1972 | plist_array_append_item(send_file_node, plist_copy(file_info)); | ||
| 1973 | |||
| 1974 | err = mobilebackup_send(mobilebackup, send_file_node); | ||
| 1975 | if (err != MOBILEBACKUP_E_SUCCESS) { | ||
| 1976 | printf("ERROR: Unable to send file hunk due to error %d. Aborting...\n", err); | ||
| 1977 | file_status = DEVICE_LINK_FILE_STATUS_NONE; | ||
| 1978 | } | ||
| 1979 | |||
| 1980 | if (file_status == DEVICE_LINK_FILE_STATUS_LAST_HUNK) { | ||
| 1981 | /* TODO: if all hunks of a file are sent, device must send ack */ | ||
| 1982 | err = mobilebackup_receive_restore_file_received(mobilebackup, NULL); | ||
| 1983 | if (err != MOBILEBACKUP_E_SUCCESS) { | ||
| 1984 | printf("ERROR: Did not receive an ack for the sent file due to error %d. Aborting...\n", err); | ||
| 1985 | file_status = DEVICE_LINK_FILE_STATUS_NONE; | ||
| 1986 | } | ||
| 1987 | } | ||
| 1988 | |||
| 1989 | file_offset += 8192; | ||
| 1990 | |||
| 1991 | if (file_status == DEVICE_LINK_FILE_STATUS_LAST_HUNK) | ||
| 1992 | printf("DONE\n"); | ||
| 1993 | |||
| 1994 | plist_free(send_file_node); | ||
| 1995 | |||
| 1996 | if (file_status == DEVICE_LINK_FILE_STATUS_NONE) | ||
| 1997 | break; | ||
| 1998 | |||
| 1999 | } while((file_offset < length)); | ||
| 2000 | |||
| 2001 | free(hash); | ||
| 2002 | node = NULL; | ||
| 2003 | hash = NULL; | ||
| 2004 | |||
| 2005 | restore_ok = 1; | ||
| 2006 | if (file_status == DEVICE_LINK_FILE_STATUS_NONE) { | ||
| 2007 | restore_ok = 0; | ||
| 2008 | break; | ||
| 2009 | } | ||
| 2010 | |||
| 2011 | cur_file++; | ||
| 2012 | plist_dict_next_item(files, iter, &hash, &node); | ||
| 2013 | } | ||
| 2014 | free(iter); | ||
| 2015 | |||
| 2016 | printf("Restored %d files on device.\n", cur_file); | ||
| 2017 | } | ||
| 2018 | } | ||
| 2019 | /* TODO: observe notification_proxy id com.apple.mobile.application_installed */ | ||
| 2020 | /* TODO: loop over Applications entries in Manifest data plist */ | ||
| 2021 | plist_t applications = plist_dict_get_item(backup_data, "Applications"); | ||
| 2022 | if (applications && (plist_get_node_type(applications) == PLIST_DICT) && restore_ok) { | ||
| 2023 | plist_dict_iter iter = NULL; | ||
| 2024 | plist_dict_new_iter(applications, &iter); | ||
| 2025 | if (iter) { | ||
| 2026 | /* loop over Application entries in Manifest data plist */ | ||
| 2027 | char *hash = NULL; | ||
| 2028 | int total_files = plist_dict_get_size(applications); | ||
| 2029 | int cur_file = 1; | ||
| 2030 | plist_t tmp_node = NULL; | ||
| 2031 | plist_t dict = NULL; | ||
| 2032 | plist_t array = NULL; | ||
| 2033 | node = NULL; | ||
| 2034 | plist_dict_next_item(applications, iter, &hash, &node); | ||
| 2035 | while (node) { | ||
| 2036 | printf("Restoring Application %s %d/%d (%d%%)...", hash, cur_file, total_files, (cur_file*100/total_files)); | ||
| 2037 | /* FIXME: receive com.apple.mobile.application_installed notification */ | ||
| 2038 | /* send AppInfo entry */ | ||
| 2039 | tmp_node = plist_dict_get_item(node, "AppInfo"); | ||
| 2040 | |||
| 2041 | dict = plist_new_dict(); | ||
| 2042 | plist_dict_insert_item(dict, "AppInfo", plist_copy(tmp_node)); | ||
| 2043 | plist_dict_insert_item(dict, "BackupMessageTypeKey", plist_new_string("BackupMessageRestoreApplicationSent")); | ||
| 2044 | |||
| 2045 | array = plist_new_array(); | ||
| 2046 | plist_array_append_item(array, plist_new_string("DLMessageProcessMessage")); | ||
| 2047 | plist_array_append_item(array, dict); | ||
| 2048 | |||
| 2049 | err = mobilebackup_send(mobilebackup, array); | ||
| 2050 | if (err != MOBILEBACKUP_E_SUCCESS) { | ||
| 2051 | printf("ERROR: Unable to restore application %s due to error %d. Aborting...\n", hash, err); | ||
| 2052 | restore_ok = 0; | ||
| 2053 | } | ||
| 2054 | |||
| 2055 | plist_free(array); | ||
| 2056 | array = NULL; | ||
| 2057 | dict = NULL; | ||
| 2058 | |||
| 2059 | /* receive BackupMessageRestoreApplicationReceived from device */ | ||
| 2060 | if (restore_ok) { | ||
| 2061 | err = mobilebackup_receive_restore_application_received(mobilebackup, NULL); | ||
| 2062 | if (err != MOBILEBACKUP_E_SUCCESS) { | ||
| 2063 | printf("ERROR: Failed to receive an ack from the device for this application due to error %d. Aborting...\n", err); | ||
| 2064 | restore_ok = 0; | ||
| 2065 | } | ||
| 2066 | } | ||
| 2067 | |||
| 2068 | tmp_node = NULL; | ||
| 2069 | node = NULL; | ||
| 2070 | free(hash); | ||
| 2071 | hash = NULL; | ||
| 2072 | |||
| 2073 | if (restore_ok) { | ||
| 2074 | printf("DONE\n"); | ||
| 2075 | cur_file++; | ||
| 2076 | plist_dict_next_item(applications, iter, &hash, &node); | ||
| 2077 | } else | ||
| 2078 | break; | ||
| 2079 | } | ||
| 2080 | free(iter); | ||
| 2081 | |||
| 2082 | if (restore_ok) | ||
| 2083 | printf("All applications restored.\n"); | ||
| 2084 | else | ||
| 2085 | printf("Failed to restore applications.\n"); | ||
| 2086 | } | ||
| 2087 | } | ||
| 2088 | |||
| 2089 | plist_free(backup_data); | ||
| 2090 | |||
| 2091 | /* signal restore finished message to device; BackupMessageRestoreComplete */ | ||
| 2092 | if (restore_ok) { | ||
| 2093 | err = mobilebackup_send_restore_complete(mobilebackup); | ||
| 2094 | if (err != MOBILEBACKUP_E_SUCCESS) { | ||
| 2095 | printf("ERROR: Could not send BackupMessageRestoreComplete, error code %d\n", err); | ||
| 2096 | } | ||
| 2097 | } | ||
| 2098 | |||
| 2099 | if (restore_ok) { | ||
| 2100 | printf("Restore Successful.\n"); | ||
| 2101 | } else { | ||
| 2102 | printf("Restore Failed.\n"); | ||
| 2103 | } | ||
| 2104 | #endif | ||
| 2105 | break; | ||
| 2106 | case CMD_LEAVE: | ||
| 2107 | default: | ||
| 2108 | break; | ||
| 2109 | } | 1811 | } |
| 2110 | if (lockfile) { | 1812 | if (lockfile) { |
| 2111 | afc_file_lock(afc, lockfile, AFC_LOCK_UN); | 1813 | afc_file_lock(afc, lockfile, AFC_LOCK_UN); |
