summaryrefslogtreecommitdiffstats
path: root/tools/idevicebackup4.c
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2011-01-10 21:13:17 +0100
committerGravatar Martin Szulecki2011-04-11 19:42:20 +0200
commit3c1c61fe8d968f6350eb7612c5f5ffbfe8ea03d7 (patch)
tree6c5cc11ae539430c1bfcec7da9cb36820c441f19 /tools/idevicebackup4.c
parentca931097ff93286d65ecab3ab07156601c2e252f (diff)
downloadlibimobiledevice-3c1c61fe8d968f6350eb7612c5f5ffbfe8ea03d7.tar.gz
libimobiledevice-3c1c61fe8d968f6350eb7612c5f5ffbfe8ea03d7.tar.bz2
idevicebackup4: clean up more stuff
Diffstat (limited to 'tools/idevicebackup4.c')
-rw-r--r--tools/idevicebackup4.c502
1 files changed, 1 insertions, 501 deletions
diff --git a/tools/idevicebackup4.c b/tools/idevicebackup4.c
index af798c0..f306260 100644
--- a/tools/idevicebackup4.c
+++ b/tools/idevicebackup4.c
@@ -73,81 +73,6 @@ enum device_link_file_status_t {
73 DEVICE_LINK_FILE_STATUS_LAST_HUNK 73 DEVICE_LINK_FILE_STATUS_LAST_HUNK
74}; 74};
75 75
76#if 0
77static void sha1_of_data(const char *input, uint32_t size, unsigned char *hash_out)
78{
79 gcry_md_hash_buffer(GCRY_MD_SHA1, hash_out, input, size);
80}
81
82static int compare_hash(const unsigned char *hash1, const unsigned char *hash2, int hash_len)
83{
84 int i;
85 for (i = 0; i < hash_len; i++) {
86 if (hash1[i] != hash2[i]) {
87 return 0;
88 }
89 }
90 return 1;
91}
92
93static void compute_datahash(const char *path, const char *destpath, uint8_t greylist, const char *domain, const char *appid, const char *version, unsigned char *hash_out)
94{
95 gcry_md_hd_t hd = NULL;
96 gcry_md_open(&hd, GCRY_MD_SHA1, 0);
97 if (!hd) {
98 printf("ERROR: Could not initialize libgcrypt/SHA1\n");
99 return;
100 }
101 gcry_md_reset(hd);
102
103 FILE *f = fopen(path, "rb");
104 if (f) {
105 unsigned char buf[16384];
106 size_t len;
107 while ((len = fread(buf, 1, 16384, f)) > 0) {
108 gcry_md_write(hd, buf, len);
109 }
110 fclose(f);
111 gcry_md_write(hd, destpath, strlen(destpath));
112 gcry_md_write(hd, ";", 1);
113 if (greylist == 1) {
114 gcry_md_write(hd, "true", 4);
115 } else {
116 gcry_md_write(hd, "false", 5);
117 }
118 gcry_md_write(hd, ";", 1);
119 if (domain) {
120 gcry_md_write(hd, domain, strlen(domain));
121 } else {
122 gcry_md_write(hd, "(null)", 6);
123 }
124 gcry_md_write(hd, ";", 1);
125 if (appid) {
126 gcry_md_write(hd, appid, strlen(appid));
127 } else {
128 gcry_md_write(hd, "(null)", 6);
129 }
130 gcry_md_write(hd, ";", 1);
131 if (version) {
132 gcry_md_write(hd, version, strlen(version));
133 } else {
134 gcry_md_write(hd, "(null)", 6);
135 }
136 unsigned char *newhash = gcry_md_read(hd, GCRY_MD_SHA1);
137 memcpy(hash_out, newhash, 20);
138 }
139 gcry_md_close(hd);
140}
141
142static void print_hash(const unsigned char *hash, int len)
143{
144 int i;
145 for (i = 0; i < len; i++) {
146 printf("%02x", hash[i]);
147 }
148}
149#endif
150
151static void notify_cb(const char *notification, void *userdata) 76static void notify_cb(const char *notification, void *userdata)
152{ 77{
153 if (!strcmp(notification, NP_SYNC_CANCEL_REQUEST)) { 78 if (!strcmp(notification, NP_SYNC_CANCEL_REQUEST)) {
@@ -365,23 +290,6 @@ static plist_t mobilebackup_factory_info_plist_new()
365 return ret; 290 return ret;
366} 291}
367 292
368#if 0
369static void mobilebackup_info_update_last_backup_date(plist_t info_plist)
370{
371 GTimeVal tv = {0, 0};
372 plist_t node = NULL;
373
374 if (!info_plist)
375 return;
376
377 g_get_current_time(&tv);
378 node = plist_dict_get_item(info_plist, "Last Backup Date");
379 plist_set_date_val(node, tv.tv_sec, tv.tv_usec);
380
381 node = NULL;
382}
383#endif
384
385static void buffer_read_from_filename(const char *filename, char **buffer, uint64_t *length) 293static void buffer_read_from_filename(const char *filename, char **buffer, uint64_t *length)
386{ 294{
387 FILE *f; 295 FILE *f;
@@ -469,21 +377,6 @@ static int plist_write_to_filename(plist_t plist, const char *filename, enum pli
469 return 1; 377 return 1;
470} 378}
471 379
472static int plist_strcmp(plist_t node, const char *str)
473{
474 char *buffer = NULL;
475 int ret = 0;
476
477 if (plist_get_node_type(node) != PLIST_STRING)
478 return ret;
479
480 plist_get_string_val(node, &buffer);
481 ret = strcmp(buffer, str);
482 free(buffer);
483
484 return ret;
485}
486
487static int mobilebackup_status_check_snapshot_state(const char *path, const char *uuid, const char *matches) 380static int mobilebackup_status_check_snapshot_state(const char *path, const char *uuid, const char *matches)
488{ 381{
489 int ret = -1; 382 int ret = -1;
@@ -571,186 +464,6 @@ static int mobilebackup_info_is_current_device(plist_t info)
571 return ret; 464 return ret;
572} 465}
573 466
574/*static int mobilebackup_delete_backup_file_by_hash(const char *backup_directory, const char *hash)
575{
576 int ret = 0;
577 gchar *path = mobilebackup_build_path(backup_directory, hash, ".mddata");
578 printf("Removing \"%s\" ", path);
579 if (!remove( path ))
580 ret = 1;
581 else
582 ret = 0;
583
584 g_free(path);
585
586 if (!ret)
587 return ret;
588
589 path = mobilebackup_build_path(backup_directory, hash, ".mdinfo");
590 printf("and \"%s\"... ", path);
591 if (!remove( path ))
592 ret = 1;
593 else
594 ret = 0;
595
596 g_free(path);
597
598 return ret;
599}*/
600
601#if 0
602static int mobilebackup_check_file_integrity(const char *backup_directory, const char *hash, plist_t filedata)
603{
604 char *datapath;
605 char *infopath;
606 plist_t mdinfo = NULL;
607 struct stat st;
608 unsigned char file_hash[20];
609
610 datapath = mobilebackup_build_path(backup_directory, hash, ".mddata");
611 if (stat(datapath, &st) != 0) {
612 printf("\r\n");
613 printf("ERROR: '%s.mddata' is missing!\n", hash);
614 free(datapath);
615 return 0;
616 }
617
618 infopath = mobilebackup_build_path(backup_directory, hash, ".mdinfo");
619 plist_read_from_filename(&mdinfo, infopath);
620 free(infopath);
621 if (!mdinfo) {
622 printf("\r\n");
623 printf("ERROR: '%s.mdinfo' is missing or corrupted!\n", hash);
624 free(datapath);
625 return 0;
626 }
627
628 /* sha1 hash verification */
629 plist_t node = plist_dict_get_item(filedata, "DataHash");
630 if (!node || (plist_get_node_type(node) != PLIST_DATA)) {
631 printf("\r\n");
632 printf("ERROR: Could not get DataHash for file entry '%s'\n", hash);
633 plist_free(mdinfo);
634 free(datapath);
635 return 0;
636 }
637
638 node = plist_dict_get_item(mdinfo, "Metadata");
639 if (!node && (plist_get_node_type(node) != PLIST_DATA)) {
640 printf("\r\n");
641 printf("ERROR: Could not find Metadata in plist '%s.mdinfo'\n", hash);
642 plist_free(mdinfo);
643 free(datapath);
644 return 0;
645 }
646
647 char *meta_bin = NULL;
648 uint64_t meta_bin_size = 0;
649 plist_get_data_val(node, &meta_bin, &meta_bin_size);
650 plist_t metadata = NULL;
651 if (meta_bin) {
652 plist_from_bin(meta_bin, (uint32_t)meta_bin_size, &metadata);
653 }
654 if (!metadata) {
655 printf("\r\n");
656 printf("ERROR: Could not get Metadata from plist '%s.mdinfo'\n", hash);
657 plist_free(mdinfo);
658 free(datapath);
659 return 0;
660 }
661
662 char *version = NULL;
663 node = plist_dict_get_item(metadata, "Version");
664 if (node && (plist_get_node_type(node) == PLIST_STRING)) {
665 plist_get_string_val(node, &version);
666 }
667
668 char *destpath = NULL;
669 node = plist_dict_get_item(metadata, "Path");
670 if (node && (plist_get_node_type(node) == PLIST_STRING)) {
671 plist_get_string_val(node, &destpath);
672 }
673
674 uint8_t greylist = 0;
675 node = plist_dict_get_item(metadata, "Greylist");
676 if (node && (plist_get_node_type(node) == PLIST_BOOLEAN)) {
677 plist_get_bool_val(node, &greylist);
678 }
679
680 char *domain = NULL;
681 node = plist_dict_get_item(metadata, "Domain");
682 if (node && (plist_get_node_type(node) == PLIST_STRING)) {
683 plist_get_string_val(node, &domain);
684 }
685
686 char *fnstr = malloc(strlen(domain) + 1 + strlen(destpath) + 1);
687 strcpy(fnstr, domain);
688 strcat(fnstr, "-");
689 strcat(fnstr, destpath);
690 unsigned char fnhash[20];
691 char fnamehash[41];
692 char *p = fnamehash;
693 sha1_of_data(fnstr, strlen(fnstr), fnhash);
694 free(fnstr);
695 int i;
696 for ( i = 0; i < 20; i++, p += 2 ) {
697 snprintf (p, 3, "%02x", (unsigned char)fnhash[i] );
698 }
699 if (strcmp(fnamehash, hash)) {
700 printf("\r\n");
701 printf("WARNING: filename hash does not match for entry '%s'\n", hash);
702 }
703
704 char *auth_version = NULL;
705 node = plist_dict_get_item(mdinfo, "AuthVersion");
706 if (node && (plist_get_node_type(node) == PLIST_STRING)) {
707 plist_get_string_val(node, &auth_version);
708 }
709
710 if (strcmp(auth_version, "1.0")) {
711 printf("\r\n");
712 printf("WARNING: Unknown AuthVersion '%s', DataHash cannot be verified!\n", auth_version);
713 }
714
715 node = plist_dict_get_item(filedata, "DataHash");
716 if (!node || (plist_get_node_type(node) != PLIST_DATA)) {
717 printf("\r\n");
718 printf("WARNING: Could not get DataHash key from file info data for entry '%s'\n", hash);
719 }
720
721 int res = 1;
722 unsigned char *data_hash = NULL;
723 uint64_t data_hash_len = 0;
724 plist_get_data_val(node, (char**)&data_hash, &data_hash_len);
725 int hash_ok = 0;
726 if (data_hash && (data_hash_len == 20)) {
727 compute_datahash(datapath, destpath, greylist, domain, NULL, version, file_hash);
728 hash_ok = compare_hash(data_hash, file_hash, 20);
729 } else if (data_hash_len == 0) {
730 /* no datahash present */
731 hash_ok = 1;
732 }
733
734 g_free(domain);
735 g_free(version);
736 g_free(destpath);
737
738 if (!hash_ok) {
739 printf("\r\n");
740 printf("ERROR: The hash for '%s.mddata' does not match DataHash entry in Manifest\n", hash);
741 printf("datahash: ");
742 print_hash(data_hash, 20);
743 printf("\nfilehash: ");
744 print_hash(file_hash, 20);
745 printf("\n");
746 res = 0;
747 }
748 g_free(data_hash);
749 plist_free(mdinfo);
750 return res;
751}
752#endif
753
754static void do_post_notification(const char *notification) 467static void do_post_notification(const char *notification)
755{ 468{
756 uint16_t nport = 0; 469 uint16_t nport = 0;
@@ -1263,16 +976,8 @@ int main(int argc, char *argv[])
1263 int is_full_backup = 0; 976 int is_full_backup = 0;
1264 char *backup_directory = NULL; 977 char *backup_directory = NULL;
1265 struct stat st; 978 struct stat st;
1266 //plist_t node = NULL;
1267 plist_t node_tmp = NULL; 979 plist_t node_tmp = NULL;
1268 //plist_t manifest_plist = NULL;
1269 plist_t info_plist = NULL; 980 plist_t info_plist = NULL;
1270 //char *buffer = NULL;
1271 //char *file_path = NULL;
1272 //uint64_t length = 0;
1273 //uint64_t backup_total_size = 0;
1274 //enum device_link_file_status_t file_status = DEVICE_LINK_FILE_STATUS_NONE;
1275// uint64_t c = 0;
1276 mobilebackup2_error_t err; 981 mobilebackup2_error_t err;
1277 982
1278 /* we need to exit cleanly on running backups and restores or we cause havok */ 983 /* we need to exit cleanly on running backups and restores or we cause havok */
@@ -1506,20 +1211,7 @@ checkpoint:
1506 /* TODO: check domain com.apple.mobile.backup key RequiresEncrypt and WillEncrypt with lockdown */ 1211 /* TODO: check domain com.apple.mobile.backup key RequiresEncrypt and WillEncrypt with lockdown */
1507 /* TODO: verify battery on AC enough battery remaining */ 1212 /* TODO: verify battery on AC enough battery remaining */
1508 1213
1509 /* read the last Manifest.plist */ 1214 /* re-create Info.plist (Device infos, IC-Info.sidb, photos, app_ids, iTunesPrefs) */
1510 /*
1511 if (!is_full_backup) {
1512 printf("Reading existing Manifest.\n");
1513 plist_read_from_filename(&manifest_plist, manifest_path);
1514 if (!manifest_plist) {
1515 printf("Could not read Manifest.plist, switching to full backup mode.\n");
1516 is_full_backup = 1;
1517 }
1518 }*/
1519
1520 /* Info.plist (Device infos, IC-Info.sidb, photos, app_ids, iTunesPrefs) */
1521
1522 /* re-create Info.plist */
1523 if (info_plist) { 1215 if (info_plist) {
1524 plist_free(info_plist); 1216 plist_free(info_plist);
1525 info_plist = NULL; 1217 info_plist = NULL;
@@ -1532,9 +1224,6 @@ checkpoint:
1532 plist_free(info_plist); 1224 plist_free(info_plist);
1533 info_plist = NULL; 1225 info_plist = NULL;
1534 1226
1535 /* create Status.plist with failed status for now */
1536 //mobilebackup_write_status(backup_directory, 0);
1537
1538 /* request backup from device with manifest from last backup */ 1227 /* request backup from device with manifest from last backup */
1539 printf("Requesting backup from device...\n"); 1228 printf("Requesting backup from device...\n");
1540 1229
@@ -1613,20 +1302,8 @@ checkpoint:
1613 int backup_ok = 0; 1302 int backup_ok = 0;
1614 plist_t message = NULL; 1303 plist_t message = NULL;
1615 1304
1616 /* TODO receive and save DLSendFile files and metadata, ACK each */
1617 char *dlmsg = NULL; 1305 char *dlmsg = NULL;
1618 /*uint64_t file_size = 0;
1619 uint64_t file_size_current = 0;*/
1620 int file_count = 0; 1306 int file_count = 0;
1621 /*int hunk_index = 0;
1622 uint64_t backup_real_size = 0;
1623 char *file_ext = NULL;
1624 char *filename_mdinfo = NULL;
1625 char *filename_mddata = NULL;
1626 char *filename_source = NULL;
1627 char *format_size = NULL;
1628 gboolean is_manifest = FALSE;
1629 uint8_t b = 0;*/
1630 int errcode = 0; 1307 int errcode = 0;
1631 const char *errdesc = NULL; 1308 const char *errdesc = NULL;
1632 1309
@@ -1643,8 +1320,6 @@ checkpoint:
1643 goto files_out; 1320 goto files_out;
1644 } 1321 }
1645 1322
1646 //node = plist_array_get_item(message, 0);
1647
1648 if (!strcmp(dlmsg, "DLMessageDownloadFiles")) { 1323 if (!strcmp(dlmsg, "DLMessageDownloadFiles")) {
1649 /* device wants to download files from the computer */ 1324 /* device wants to download files from the computer */
1650 handle_send_files(message, backup_directory); 1325 handle_send_files(message, backup_directory);
@@ -1805,149 +1480,10 @@ checkpoint:
1805 } 1480 }
1806 }*/ 1481 }*/
1807 1482
1808#if 0
1809 /* get out if we don't get a DLSendFile */
1810 if (plist_strcmp(node, "DLSendFile"))
1811 break;
1812
1813 node_tmp = plist_array_get_item(message, 2);
1814
1815 /* first message hunk contains total backup size */
1816 if ((hunk_index == 0) && (file_index == 0)) {
1817 node = plist_dict_get_item(node_tmp, "BackupTotalSizeKey");
1818 if (node) {
1819 plist_get_uint_val(node, &backup_total_size);
1820 format_size = g_format_size_for_display(backup_total_size);
1821 printf("Backup data requires %s on the disk.\n", format_size);
1822 g_free(format_size);
1823 }
1824 }
1825
1826 /* check DLFileStatusKey (codes: 1 = Hunk, 2 = Last Hunk) */
1827 node = plist_dict_get_item(node_tmp, "DLFileStatusKey");
1828 plist_get_uint_val(node, &c);
1829 file_status = c;
1830
1831 /* get source filename */
1832 node = plist_dict_get_item(node_tmp, "BackupManifestKey");
1833 b = 0;
1834 if (node) {
1835 plist_get_bool_val(node, &b);
1836 }
1837 is_manifest = (b == 1) ? TRUE: FALSE;
1838
1839 if ((hunk_index == 0) && (!is_manifest)) {
1840 /* get source filename */
1841 node = plist_dict_get_item(node_tmp, "DLFileSource");
1842 plist_get_string_val(node, &filename_source);
1843
1844 /* increase received size */
1845 node = plist_dict_get_item(node_tmp, "DLFileAttributesKey");
1846 node = plist_dict_get_item(node, "FileSize");
1847 plist_get_uint_val(node, &file_size);
1848 backup_real_size += file_size;
1849
1850 format_size = g_format_size_for_display(backup_real_size);
1851 printf("(%s", format_size);
1852 g_free(format_size);
1853
1854 format_size = g_format_size_for_display(backup_total_size);
1855 printf("/%s): ", format_size);
1856 g_free(format_size);
1857
1858 format_size = g_format_size_for_display(file_size);
1859 printf("Receiving file %s (%s)... \n", filename_source, format_size);
1860 g_free(format_size);
1861
1862 if (filename_source)
1863 free(filename_source);
1864 }
1865
1866 /* check if we completed a file */
1867 if ((file_status == DEVICE_LINK_FILE_STATUS_LAST_HUNK) && (!is_manifest)) {
1868 /* save <hash>.mdinfo */
1869 node = plist_dict_get_item(node_tmp, "BackupFileInfo");
1870 if (node) {
1871 node = plist_dict_get_item(node_tmp, "DLFileDest");
1872 plist_get_string_val(node, &file_path);
1873
1874 filename_mdinfo = mobilebackup_build_path(backup_directory, file_path, ".mdinfo");
1875
1876 /* remove any existing file */
1877 if (stat(filename_mdinfo, &st) == 0)
1878 remove(filename_mdinfo);
1879
1880 node = plist_dict_get_item(node_tmp, "BackupFileInfo");
1881 plist_write_to_filename(node, filename_mdinfo, PLIST_FORMAT_BINARY);
1882
1883 g_free(filename_mdinfo);
1884 }
1885
1886 file_index++;
1887 }
1888
1889 /* save <hash>.mddata */
1890 node = plist_dict_get_item(node_tmp, "BackupFileInfo");
1891 if (node_tmp) {
1892 node = plist_dict_get_item(node_tmp, "DLFileDest");
1893 plist_get_string_val(node, &file_path);
1894
1895 filename_mddata = mobilebackup_build_path(backup_directory, file_path, is_manifest ? NULL: ".mddata");
1896
1897 /* if this is the first hunk, remove any existing file */
1898 if ((hunk_index == 0) && (stat(filename_mddata, &st) == 0))
1899 remove(filename_mddata);
1900
1901 /* get file data hunk */
1902 node_tmp = plist_array_get_item(message, 1);
1903 plist_get_data_val(node_tmp, &buffer, &length);
1904
1905 buffer_write_to_filename(filename_mddata, buffer, length);
1906 if (!is_manifest)
1907 file_size_current += length;
1908
1909 /* activate currently sent manifest */
1910 if ((file_status == DEVICE_LINK_FILE_STATUS_LAST_HUNK) && (is_manifest)) {
1911 rename(filename_mddata, manifest_path);
1912 }
1913
1914 free(buffer);
1915 buffer = NULL;
1916
1917 g_free(filename_mddata);
1918 }
1919
1920 if ((!is_manifest)) {
1921 if (hunk_index == 0 && file_status == DEVICE_LINK_FILE_STATUS_LAST_HUNK) {
1922 print_progress(100);
1923 } else {
1924 if (file_size > 0)
1925 print_progress((double)((file_size_current*100)/file_size));
1926 }
1927 }
1928
1929 hunk_index++;
1930
1931 if (file_ext)
1932 free(file_ext);
1933#endif
1934 if (message) 1483 if (message)
1935 plist_free(message); 1484 plist_free(message);
1936 message = NULL; 1485 message = NULL;
1937 1486
1938#if 0
1939 if (file_status == DEVICE_LINK_FILE_STATUS_LAST_HUNK) {
1940 /* acknowlegdge that we received the file */
1941 mobilebackup_send_backup_file_received(mobilebackup);
1942 /* reset hunk_index */
1943 hunk_index = 0;
1944 if (!is_manifest) {
1945 file_size_current = 0;
1946 file_size = 0;
1947 }
1948 }
1949#endif
1950
1951files_out: 1487files_out:
1952 if (quit_flag > 0) { 1488 if (quit_flag > 0) {
1953 /* need to cancel the backup here */ 1489 /* need to cancel the backup here */
@@ -1962,42 +1498,6 @@ files_out:
1962 } 1498 }
1963 } while (1); 1499 } while (1);
1964 1500
1965#if 0
1966 if (!quit_flag && !plist_strcmp(node, "DLMessageProcessMessage")) {
1967 node_tmp = plist_array_get_item(message, 1);
1968 node = plist_dict_get_item(node_tmp, "BackupMessageTypeKey");
1969 /* check if we received the final "backup finished" message */
1970 if (node && !plist_strcmp(node, "BackupMessageBackupFinished")) {
1971 /* backup finished */
1972
1973 /* process BackupFilesToDeleteKey */
1974 node = plist_dict_get_item(node_tmp, "BackupFilesToDeleteKey");
1975 if (node) {
1976 length = plist_array_get_size(node);
1977 i = 0;
1978 while ((node_tmp = plist_array_get_item(node, i++)) != NULL) {
1979 plist_get_string_val(node_tmp, &file_path);
1980
1981 if (mobilebackup_delete_backup_file_by_hash(backup_directory, file_path)) {
1982 printf("DONE\n");
1983 } else
1984 printf("FAILED\n");
1985 }
1986 }
1987
1988 /* save last valid Manifest.plist */
1989 node_tmp = plist_array_get_item(message, 1);
1990 manifest_plist = plist_dict_get_item(node_tmp, "BackupManifestKey");
1991 if (manifest_plist) {
1992 remove(manifest_path);
1993 printf("Storing Manifest.plist...\n");
1994 plist_write_to_filename(manifest_plist, manifest_path, PLIST_FORMAT_XML);
1995 }
1996
1997 backup_ok = 1;
1998 }
1999 }
2000#endif
2001 if (cmd == CMD_BACKUP) { 1501 if (cmd == CMD_BACKUP) {
2002 printf("Received %d files from device.\n", file_count); 1502 printf("Received %d files from device.\n", file_count);
2003 if (mobilebackup_status_check_snapshot_state(backup_directory, uuid, "finished")) { 1503 if (mobilebackup_status_check_snapshot_state(backup_directory, uuid, "finished")) {