summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Martin Szulecki2013-01-07 22:29:24 +0100
committerGravatar Martin Szulecki2013-01-07 22:29:24 +0100
commit9dcab806cc3c136c37e165b03bf2d29c4afaeaa6 (patch)
tree44313e26ae77c34b1494c80b798d722e313ae187
parent18e24e587d2cce6214a9da111d7d720c196a169a (diff)
downloadlibimobiledevice-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.c103
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
763static 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
763static int mb2_handle_receive_files(plist_t message, const char *backup_dir) 809static 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");