diff options
Diffstat (limited to 'tools/idevicebackup4.c')
| -rw-r--r-- | tools/idevicebackup4.c | 502 |
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 | ||
| 77 | static 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 | |||
| 82 | static 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 | |||
| 93 | static 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 | |||
| 142 | static 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 | |||
| 151 | static void notify_cb(const char *notification, void *userdata) | 76 | static 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 | ||
| 369 | static 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 | |||
| 385 | static void buffer_read_from_filename(const char *filename, char **buffer, uint64_t *length) | 293 | static 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 | ||
| 472 | static 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 | |||
| 487 | static int mobilebackup_status_check_snapshot_state(const char *path, const char *uuid, const char *matches) | 380 | static 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 | ||
| 602 | static 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 | |||
| 754 | static void do_post_notification(const char *notification) | 467 | static 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 | |||
| 1951 | files_out: | 1487 | files_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")) { |
