diff options
| -rw-r--r-- | tools/idevicebackup4.c | 92 |
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 | ||
| 49 | static mobilebackup2_client_t mobilebackup2 = NULL; | 50 | static 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 | ||
| 911 | leave: | 923 | leave: |
| 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 | ||
| 949 | static void handle_send_files(plist_t message, const char *backup_dir) | 961 | static 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); |
