summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2011-01-08 12:58:22 +0100
committerGravatar Martin Szulecki2011-04-11 19:42:19 +0200
commit9c21226c99fd1887950fd82205cf8bf7e5a5ef10 (patch)
tree5493d7e73023890a2ddb5355d4f52fa560a10587
parentf6dc731a57cb162220433cc77f65999a2d5fd04d (diff)
downloadlibimobiledevice-9c21226c99fd1887950fd82205cf8bf7e5a5ef10.tar.gz
libimobiledevice-9c21226c99fd1887950fd82205cf8bf7e5a5ef10.tar.bz2
idevicebackup4: fix DLMessageDownloadFiles handling
Large files were not sent correctly to the device, they must be sent in chunks, otherwise the device gets stuck and reboots before the restore process is complete.
-rw-r--r--tools/idevicebackup4.c92
1 files changed, 52 insertions, 40 deletions
diff --git a/tools/idevicebackup4.c b/tools/idevicebackup4.c
index ef3fdd0..55b7802 100644
--- a/tools/idevicebackup4.c
+++ b/tools/idevicebackup4.c
@@ -42,8 +42,9 @@
42#define LOCK_ATTEMPTS 50 42#define LOCK_ATTEMPTS 50
43#define LOCK_WAIT 200000 43#define LOCK_WAIT 200000
44 44
45#define CODE_NULL 0x00 45#define CODE_SUCCESS 0x00
46#define CODE_ERROR_MSG 0x0b 46#define CODE_ERROR_LOCAL 0x06
47#define CODE_ERROR_REMOTE 0x0b
47#define CODE_FILE_DATA 0x0c 48#define CODE_FILE_DATA 0x0c
48 49
49static mobilebackup2_client_t mobilebackup2 = NULL; 50static mobilebackup2_client_t mobilebackup2 = NULL;
@@ -823,35 +824,38 @@ static int handle_send_file(const char *backup_dir, const char *path, plist_t *e
823{ 824{
824 uint32_t nlen = 0; 825 uint32_t nlen = 0;
825 uint32_t pathlen = strlen(path); 826 uint32_t pathlen = strlen(path);
826 int bytes = 0; 827 uint32_t bytes = 0;
827 gchar *localfile = g_build_path(G_DIR_SEPARATOR_S, backup_dir, path, NULL); 828 gchar *localfile = g_build_path(G_DIR_SEPARATOR_S, backup_dir, path, NULL);
828 char buf[16384]; 829 char buf[32768];
829 struct stat fst; 830 struct stat fst;
830 831
831 FILE *f = NULL; 832 FILE *f = NULL;
832 uint32_t slen = 0; 833 uint32_t slen = 0;
833 int errcode = -1; 834 int errcode = -1;
834 int e = -1; 835 int result = -1;
836 uint32_t length;
837 off_t total;
838 off_t sent;
835 839
836 mobilebackup2_error_t err; 840 mobilebackup2_error_t err;
837 841
838 /* send path length */ 842 /* send path length */
839 nlen = GUINT32_TO_BE(pathlen); 843 nlen = GUINT32_TO_BE(pathlen);
840 err = mobilebackup2_send_raw(mobilebackup2, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes); 844 err = mobilebackup2_send_raw(mobilebackup2, (const char*)&nlen, sizeof(nlen), &bytes);
841 if (err != MOBILEBACKUP2_E_SUCCESS) { 845 if (err != MOBILEBACKUP2_E_SUCCESS) {
842 goto leave_proto_err; 846 goto leave_proto_err;
843 } 847 }
844 if (bytes != sizeof(nlen)) { 848 if (bytes != (uint32_t)sizeof(nlen)) {
845 err = MOBILEBACKUP2_E_MUX_ERROR; 849 err = MOBILEBACKUP2_E_MUX_ERROR;
846 goto leave_proto_err; 850 goto leave_proto_err;
847 } 851 }
848 852
849 /* send path */ 853 /* send path */
850 err = mobilebackup2_send_raw(mobilebackup2, path, pathlen, (uint32_t*)&bytes); 854 err = mobilebackup2_send_raw(mobilebackup2, path, pathlen, &bytes);
851 if (err != MOBILEBACKUP2_E_SUCCESS) { 855 if (err != MOBILEBACKUP2_E_SUCCESS) {
852 goto leave_proto_err; 856 goto leave_proto_err;
853 } 857 }
854 if ((uint32_t)bytes != pathlen) { 858 if (bytes != pathlen) {
855 err = MOBILEBACKUP2_E_MUX_ERROR; 859 err = MOBILEBACKUP2_E_MUX_ERROR;
856 goto leave_proto_err; 860 goto leave_proto_err;
857 } 861 }
@@ -862,6 +866,17 @@ static int handle_send_file(const char *backup_dir, const char *path, plist_t *e
862 goto leave; 866 goto leave;
863 } 867 }
864 868
869 total = fst.st_size;
870
871 gchar *format_size = g_format_size_for_display(total);
872 printf("Sending file '%s': (%s)\n", path, format_size);
873 g_free(format_size);
874
875 if (total == 0) {
876 errcode = 0;
877 goto leave;
878 }
879
865 f = fopen(localfile, "rb"); 880 f = fopen(localfile, "rb");
866 if (!f) { 881 if (!f) {
867 printf("%s: Error opening local file '%s': %d\n", __func__, localfile, errno); 882 printf("%s: Error opening local file '%s': %d\n", __func__, localfile, errno);
@@ -869,53 +884,50 @@ static int handle_send_file(const char *backup_dir, const char *path, plist_t *e
869 goto leave; 884 goto leave;
870 } 885 }
871 886
872 printf("Sending file '%s'\n", path); 887 sent = 0;
873 888 do {
874 /* send data size (file size + 1) */ 889 length = ((total-sent) < (off_t)sizeof(buf)) ? (uint32_t)total-sent : (uint32_t)sizeof(buf);
875 uint32_t length = (uint32_t)fst.st_size; 890 /* send data size (file size + 1) */
876 nlen = GUINT32_TO_BE(length+1); 891 nlen = GUINT32_TO_BE(length+1);
877 memcpy(buf, &nlen, sizeof(nlen)); 892 memcpy(buf, &nlen, sizeof(nlen));
878 /* unknown special byte */ 893 buf[4] = CODE_FILE_DATA;
879 buf[4] = 0x0C; 894 err = mobilebackup2_send_raw(mobilebackup2, (const char*)buf, 5, &bytes);
880 err = mobilebackup2_send_raw(mobilebackup2, (const char*)buf, 5, (uint32_t*)&bytes); 895 if (err != MOBILEBACKUP2_E_SUCCESS) {
881 if (err != MOBILEBACKUP2_E_SUCCESS) { 896 goto leave_proto_err;
882 goto leave_proto_err; 897 }
883 } 898 if (bytes != 5) {
884 if (bytes != 5) { 899 goto leave_proto_err;
885 goto leave_proto_err; 900 }
886 }
887 901
888 /* send file contents */ 902 /* send file contents */
889 uint32_t sent = 0;
890 while (sent < length) {
891 size_t r = fread(buf, 1, sizeof(buf), f); 903 size_t r = fread(buf, 1, sizeof(buf), f);
892 if (r <= 0) { 904 if (r <= 0) {
893 printf("%s: read error\n", __func__); 905 printf("%s: read error\n", __func__);
894 errcode = errno; 906 errcode = errno;
895 goto leave; 907 goto leave;
896 } 908 }
897 err = mobilebackup2_send_raw(mobilebackup2, buf, r, (uint32_t*)&bytes); 909 err = mobilebackup2_send_raw(mobilebackup2, buf, r, &bytes);
898 if (err != MOBILEBACKUP2_E_SUCCESS) { 910 if (err != MOBILEBACKUP2_E_SUCCESS) {
899 goto leave_proto_err; 911 goto leave_proto_err;
900 } 912 }
901 if ((uint32_t)bytes != r) { 913 if (bytes != (uint32_t)r) {
902 printf("sent only %d from %d\n", bytes, r); 914 printf("Error: sent only %d of %d bytes\n", bytes, (int)r);
903 goto leave_proto_err; 915 goto leave_proto_err;
904 } 916 }
905 sent += r; 917 sent += r;
906 } 918 } while (sent < total);
907 fclose(f); 919 fclose(f);
908 f = NULL; 920 f = NULL;
909 errcode = 0; 921 errcode = 0;
910 922
911leave: 923leave:
912 if (errcode == 0) { 924 if (errcode == 0) {
913 e = 0; 925 result = 0;
914 nlen = 1; 926 nlen = 1;
915 nlen = GUINT32_TO_BE(nlen); 927 nlen = GUINT32_TO_BE(nlen);
916 memcpy(buf, &nlen, 4); 928 memcpy(buf, &nlen, 4);
917 buf[4] = 0; 929 buf[4] = CODE_SUCCESS;
918 mobilebackup2_send_raw(mobilebackup2, buf, 5, &sent); 930 mobilebackup2_send_raw(mobilebackup2, buf, 5, &bytes);
919 } else { 931 } else {
920 if (!*errplist) { 932 if (!*errplist) {
921 *errplist = plist_new_dict(); 933 *errplist = plist_new_dict();
@@ -926,15 +938,15 @@ leave:
926 length = strlen(errdesc); 938 length = strlen(errdesc);
927 nlen = GUINT32_TO_BE(length+1); 939 nlen = GUINT32_TO_BE(length+1);
928 memcpy(buf, &nlen, 4); 940 memcpy(buf, &nlen, 4);
929 buf[4] = 0x06; 941 buf[4] = CODE_ERROR_LOCAL;
930 slen = 5; 942 slen = 5;
931 memcpy(buf+slen, errdesc, length); 943 memcpy(buf+slen, errdesc, length);
932 slen += length; 944 slen += length;
933 err = mobilebackup2_send_raw(mobilebackup2, (const char*)buf, slen, (uint32_t*)&bytes); 945 err = mobilebackup2_send_raw(mobilebackup2, (const char*)buf, slen, &bytes);
934 if (err != MOBILEBACKUP2_E_SUCCESS) { 946 if (err != MOBILEBACKUP2_E_SUCCESS) {
935 printf("could not send message\n"); 947 printf("could not send message\n");
936 } 948 }
937 if ((uint32_t)bytes != slen) { 949 if (bytes != slen) {
938 printf("could only send %d from %d\n", bytes, slen); 950 printf("could only send %d from %d\n", bytes, slen);
939 } 951 }
940 } 952 }
@@ -943,7 +955,7 @@ leave_proto_err:
943 if (f) 955 if (f)
944 fclose(f); 956 fclose(f);
945 g_free(localfile); 957 g_free(localfile);
946 return e; 958 return result;
947} 959}
948 960
949static void handle_send_files(plist_t message, const char *backup_dir) 961static void handle_send_files(plist_t message, const char *backup_dir)
@@ -1050,7 +1062,7 @@ static int handle_receive_files(plist_t message, const char *backup_dir)
1050 mobilebackup2_receive_raw(mobilebackup2, &code, 1, &r); 1062 mobilebackup2_receive_raw(mobilebackup2, &code, 1, &r);
1051 1063
1052 /* TODO remove this */ 1064 /* TODO remove this */
1053 if ((code != 0) && (code != CODE_FILE_DATA) && (code != CODE_ERROR_MSG)) { 1065 if ((code != CODE_SUCCESS) && (code != CODE_FILE_DATA) && (code != CODE_ERROR_REMOTE)) {
1054 printf("Found new flag %02x\n", code); 1066 printf("Found new flag %02x\n", code);
1055 } 1067 }
1056 1068
@@ -1103,7 +1115,7 @@ static int handle_receive_files(plist_t message, const char *backup_dir)
1103 } 1115 }
1104 1116
1105 /* check if an error message was received */ 1117 /* check if an error message was received */
1106 if (code == CODE_ERROR_MSG) { 1118 if (code == CODE_ERROR_REMOTE) {
1107 /* error message */ 1119 /* error message */
1108 char *msg = (char*)malloc(nlen); 1120 char *msg = (char*)malloc(nlen);
1109 mobilebackup2_receive_raw(mobilebackup2, msg, nlen-1, &r); 1121 mobilebackup2_receive_raw(mobilebackup2, msg, nlen-1, &r);