diff options
| author | 2013-01-07 22:29:24 +0100 | |
|---|---|---|
| committer | 2013-01-07 22:29:24 +0100 | |
| commit | 9dcab806cc3c136c37e165b03bf2d29c4afaeaa6 (patch) | |
| tree | 44313e26ae77c34b1494c80b798d722e313ae187 | |
| parent | 18e24e587d2cce6214a9da111d7d720c196a169a (diff) | |
| download | libimobiledevice-9dcab806cc3c136c37e165b03bf2d29c4afaeaa6.tar.gz libimobiledevice-9dcab806cc3c136c37e165b03bf2d29c4afaeaa6.tar.bz2 | |
idevicebackup2: Fix nasty "too long filename received" bug
If the device is sending files to the host, it sometimes requires a bit more
time to process them before sending. This appeared to happen mostly for larger
sqlite databases which appear to get some preprocessing on the device.
In such a "wait" situation, we receive no data and need to retry reading the
filename length again. Due to a code bug though which didn't reset the last
read length to zero, this length was incorrectly alternating between 1 and
16777216 due to the byte swapping. This ulitmativly lead to a broken backup
process. Now we properly wait for the device to preprocess any file before
sending the filename to the host.
| -rw-r--r-- | tools/idevicebackup2.c | 103 |
1 files changed, 68 insertions, 35 deletions
diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c index ad3f0f6..c32e2e4 100644 --- a/tools/idevicebackup2.c +++ b/tools/idevicebackup2.c | |||
| @@ -760,6 +760,52 @@ static void mb2_handle_send_files(plist_t message, const char *backup_dir) | |||
| 760 | } | 760 | } |
| 761 | } | 761 | } |
| 762 | 762 | ||
| 763 | static int mb2_receive_filename(char** filename) | ||
| 764 | { | ||
| 765 | uint32_t nlen = 0; | ||
| 766 | uint32_t rlen = 0; | ||
| 767 | |||
| 768 | do { | ||
| 769 | nlen = 0; | ||
| 770 | rlen = 0; | ||
| 771 | mobilebackup2_receive_raw(mobilebackup2, (char*)&nlen, 4, &rlen); | ||
| 772 | nlen = be32toh(nlen); | ||
| 773 | |||
| 774 | if ((nlen == 0) && (rlen == 4)) { | ||
| 775 | // a zero length means no more files to receive | ||
| 776 | return 0; | ||
| 777 | } else if(rlen == 0) { | ||
| 778 | // device needs more time, waiting... | ||
| 779 | continue; | ||
| 780 | } else if (nlen > 4096) { | ||
| 781 | // filename length is too large | ||
| 782 | printf("ERROR: %s: too large filename length (%d)!\n", __func__, nlen); | ||
| 783 | return 0; | ||
| 784 | } | ||
| 785 | |||
| 786 | if (*filename != NULL) { | ||
| 787 | free(*filename); | ||
| 788 | *filename = NULL; | ||
| 789 | } | ||
| 790 | |||
| 791 | *filename = (char*)malloc(nlen+1); | ||
| 792 | |||
| 793 | rlen = 0; | ||
| 794 | mobilebackup2_receive_raw(mobilebackup2, *filename, nlen, &rlen); | ||
| 795 | if (rlen != nlen) { | ||
| 796 | printf("ERROR: %s: could not read filename\n", __func__); | ||
| 797 | return 0; | ||
| 798 | } | ||
| 799 | |||
| 800 | char* p = *filename; | ||
| 801 | p[rlen] = 0; | ||
| 802 | |||
| 803 | break; | ||
| 804 | } while(1 && !quit_flag); | ||
| 805 | |||
| 806 | return nlen; | ||
| 807 | } | ||
| 808 | |||
| 763 | static int mb2_handle_receive_files(plist_t message, const char *backup_dir) | 809 | static int mb2_handle_receive_files(plist_t message, const char *backup_dir) |
| 764 | { | 810 | { |
| 765 | uint64_t backup_real_size = 0; | 811 | uint64_t backup_real_size = 0; |
| @@ -792,48 +838,30 @@ static int mb2_handle_receive_files(plist_t message, const char *backup_dir) | |||
| 792 | do { | 838 | do { |
| 793 | if (quit_flag) | 839 | if (quit_flag) |
| 794 | break; | 840 | break; |
| 795 | r = 0; | 841 | |
| 796 | mobilebackup2_receive_raw(mobilebackup2, (char*)&nlen, 4, &r); | 842 | nlen = mb2_receive_filename(&dname); |
| 797 | nlen = be32toh(nlen); | ||
| 798 | if (nlen == 0) { | ||
| 799 | // we're done here | ||
| 800 | break; | ||
| 801 | } else if (nlen > 4096) { | ||
| 802 | // too very long path | ||
| 803 | printf("ERROR: %s: too long device filename (%d)!\n", __func__, nlen); | ||
| 804 | break; | ||
| 805 | } | ||
| 806 | if (dname != NULL) | ||
| 807 | free(dname); | ||
| 808 | dname = (char*)malloc(nlen+1); | ||
| 809 | r = 0; | ||
| 810 | mobilebackup2_receive_raw(mobilebackup2, dname, nlen, &r); | ||
| 811 | if (r != nlen) { | ||
| 812 | printf("ERROR: %s: could not read device filename\n", __func__); | ||
| 813 | break; | ||
| 814 | } | ||
| 815 | dname[r] = 0; | ||
| 816 | nlen = 0; | ||
| 817 | mobilebackup2_receive_raw(mobilebackup2, (char*)&nlen, 4, &r); | ||
| 818 | nlen = be32toh(nlen); | ||
| 819 | if (nlen == 0) { | 843 | if (nlen == 0) { |
| 820 | printf("ERROR: %s: zero-length backup filename!\n", __func__); | ||
| 821 | break; | ||
| 822 | } else if (nlen > 4096) { | ||
| 823 | printf("ERROR: %s: too long backup filename (%d)!\n", __func__, nlen); | ||
| 824 | break; | 844 | break; |
| 825 | } | 845 | } |
| 826 | fname = (char*)malloc(nlen+1); | 846 | |
| 827 | mobilebackup2_receive_raw(mobilebackup2, fname, nlen, &r); | 847 | nlen = mb2_receive_filename(&fname); |
| 828 | if (r != nlen) { | 848 | if (!nlen) { |
| 829 | printf("ERROR: %s: could not receive backup filename!\n", __func__); | ||
| 830 | break; | 849 | break; |
| 831 | } | 850 | } |
| 832 | fname[r] = 0; | 851 | |
| 833 | if (bname != NULL) | 852 | if (bname != NULL) { |
| 834 | free(bname); | 853 | free(bname); |
| 854 | bname = NULL; | ||
| 855 | } | ||
| 856 | |||
| 835 | bname = build_path(backup_dir, fname, NULL); | 857 | bname = build_path(backup_dir, fname, NULL); |
| 836 | free(fname); | 858 | |
| 859 | if (fname != NULL) { | ||
| 860 | free(fname); | ||
| 861 | fname = NULL; | ||
| 862 | } | ||
| 863 | |||
| 864 | r = 0; | ||
| 837 | nlen = 0; | 865 | nlen = 0; |
| 838 | mobilebackup2_receive_raw(mobilebackup2, (char*)&nlen, 4, &r); | 866 | mobilebackup2_receive_raw(mobilebackup2, (char*)&nlen, 4, &r); |
| 839 | if (r != 4) { | 867 | if (r != 4) { |
| @@ -841,8 +869,10 @@ static int mb2_handle_receive_files(plist_t message, const char *backup_dir) | |||
| 841 | break; | 869 | break; |
| 842 | } | 870 | } |
| 843 | nlen = be32toh(nlen); | 871 | nlen = be32toh(nlen); |
| 872 | |||
| 844 | last_code = code; | 873 | last_code = code; |
| 845 | code = 0; | 874 | code = 0; |
| 875 | |||
| 846 | mobilebackup2_receive_raw(mobilebackup2, &code, 1, &r); | 876 | mobilebackup2_receive_raw(mobilebackup2, &code, 1, &r); |
| 847 | if (r != 1) { | 877 | if (r != 1) { |
| 848 | printf("ERROR: %s: could not receive code!\n", __func__); | 878 | printf("ERROR: %s: could not receive code!\n", __func__); |
| @@ -915,6 +945,9 @@ static int mb2_handle_receive_files(plist_t message, const char *backup_dir) | |||
| 915 | } | 945 | } |
| 916 | } while (1); | 946 | } while (1); |
| 917 | 947 | ||
| 948 | if (fname != NULL) | ||
| 949 | free(fname); | ||
| 950 | |||
| 918 | /* if there are leftovers to read, finish up cleanly */ | 951 | /* if there are leftovers to read, finish up cleanly */ |
| 919 | if ((int)nlen-1 > 0) { | 952 | if ((int)nlen-1 > 0) { |
| 920 | PRINT_VERBOSE(1, "\nDiscarding current data hunk.\n"); | 953 | PRINT_VERBOSE(1, "\nDiscarding current data hunk.\n"); |
