summaryrefslogtreecommitdiffstats
path: root/tools/idevicebackup2.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/idevicebackup2.c')
-rw-r--r--tools/idevicebackup2.c261
1 files changed, 174 insertions, 87 deletions
diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c
index 5d067bf..6e35abd 100644
--- a/tools/idevicebackup2.c
+++ b/tools/idevicebackup2.c
@@ -25,13 +25,9 @@
25#include <errno.h> 25#include <errno.h>
26#include <stdlib.h> 26#include <stdlib.h>
27#include <signal.h> 27#include <signal.h>
28#include <glib.h>
29#include <glib/gstdio.h>
30#include <unistd.h> 28#include <unistd.h>
31 29#include <dirent.h>
32#if !GLIB_CHECK_VERSION(2,25,0) 30#include <libgen.h>
33typedef struct stat GStatBuf;
34#endif
35 31
36#include <libimobiledevice/libimobiledevice.h> 32#include <libimobiledevice/libimobiledevice.h>
37#include <libimobiledevice/lockdown.h> 33#include <libimobiledevice/lockdown.h>
@@ -39,6 +35,8 @@ typedef struct stat GStatBuf;
39#include <libimobiledevice/notification_proxy.h> 35#include <libimobiledevice/notification_proxy.h>
40#include <libimobiledevice/afc.h> 36#include <libimobiledevice/afc.h>
41 37
38#include <endianness.h>
39
42#define MOBILEBACKUP2_SERVICE_NAME "com.apple.mobilebackup2" 40#define MOBILEBACKUP2_SERVICE_NAME "com.apple.mobilebackup2"
43#define NP_SERVICE_NAME "com.apple.mobile.notification_proxy" 41#define NP_SERVICE_NAME "com.apple.mobile.notification_proxy"
44 42
@@ -156,10 +154,95 @@ static void mobilebackup_afc_get_file_contents(const char *filename, char **data
156 afc_file_close(afc, f); 154 afc_file_close(afc, f);
157} 155}
158 156
157static char *str_toupper(char* str)
158{
159 char *res = strdup(str);
160 int i;
161 for (i = 0; i < strlen(res); i++) {
162 res[i] = toupper(res[i]);
163 }
164 return res;
165}
166
167static int __mkdir(const char* path, int mode)
168{
169#ifdef WIN32
170 return mkdir(path);
171#else
172 return mkdir(path, mode);
173#endif
174}
175
176int mkdir_with_parents(const char *dir, int mode)
177{
178 if (!dir) return -1;
179 if (__mkdir(dir, mode) == 0) {
180 return 0;
181 } else {
182 if (errno == EEXIST) return 0;
183 }
184 int res;
185 char *parent = strdup(dir);
186 parent = dirname(parent);
187 if (parent) {
188 res = mkdir_with_parents(parent, mode);
189 } else {
190 res = -1;
191 }
192 free(parent);
193 if (res == 0) {
194 mkdir_with_parents(dir, mode);
195 }
196 return res;
197}
198
199char* build_path(const char* elem, ...)
200{
201 if (!elem) return NULL;
202 va_list args;
203 int len = strlen(elem)+1;
204 va_start(args, elem);
205 char *arg = va_arg(args, char*);
206 while (arg) {
207 len += strlen(arg)+1;
208 arg = va_arg(args, char*);
209 }
210 va_end(args);
211
212 char* out = (char*)malloc(len);
213 strcpy(out, elem);
214
215 va_start(args, elem);
216 arg = va_arg(args, char*);
217 while (arg) {
218 strcat(out, "/");
219 strcat(out, arg);
220 arg = va_arg(args, char*);
221 }
222 va_end(args);
223 return out;
224}
225
226static char* format_size_for_display(uint64_t size)
227{
228 char buf[32];
229 double sz;
230 if (size >= 1000000000LL) {
231 sz = ((double)size / 1000000000.0f);
232 sprintf(buf, "%0.1f GB", sz);
233 } else if (size >= 1000000LL) {
234 sz = ((double)size / 1000000.0f);
235 sprintf(buf, "%0.1f MB", sz);
236 } else if (size >= 1000LL) {
237 sz = ((double)size / 1000.0f);
238 sprintf(buf, "%0.1f kB", sz);
239 }
240 return strdup(buf);
241}
242
159static plist_t mobilebackup_factory_info_plist_new() 243static plist_t mobilebackup_factory_info_plist_new()
160{ 244{
161 /* gather data from lockdown */ 245 /* gather data from lockdown */
162 GTimeVal tv = {0, 0};
163 plist_t value_node = NULL; 246 plist_t value_node = NULL;
164 plist_t root_node = NULL; 247 plist_t root_node = NULL;
165 char *uuid = NULL; 248 char *uuid = NULL;
@@ -189,8 +272,7 @@ static plist_t mobilebackup_factory_info_plist_new()
189 if (value_node) 272 if (value_node)
190 plist_dict_insert_item(ret, "IMEI", plist_copy(value_node)); 273 plist_dict_insert_item(ret, "IMEI", plist_copy(value_node));
191 274
192 g_get_current_time(&tv); 275 plist_dict_insert_item(ret, "Last Backup Date", plist_new_date(time(NULL), 0));
193 plist_dict_insert_item(ret, "Last Backup Date", plist_new_date(tv.tv_sec, 0));
194 276
195 value_node = plist_dict_get_item(root_node, "PhoneNumber"); 277 value_node = plist_dict_get_item(root_node, "PhoneNumber");
196 if (value_node && (plist_get_node_type(value_node) == PLIST_STRING)) { 278 if (value_node && (plist_get_node_type(value_node) == PLIST_STRING)) {
@@ -215,7 +297,7 @@ static plist_t mobilebackup_factory_info_plist_new()
215 plist_dict_insert_item(ret, "Target Type", plist_new_string("Device")); 297 plist_dict_insert_item(ret, "Target Type", plist_new_string("Device"));
216 298
217 /* uppercase */ 299 /* uppercase */
218 uuid_uppercase = g_ascii_strup(uuid, -1); 300 uuid_uppercase = str_toupper(uuid);
219 plist_dict_insert_item(ret, "Unique Identifier", plist_new_string(uuid_uppercase)); 301 plist_dict_insert_item(ret, "Unique Identifier", plist_new_string(uuid_uppercase));
220 free(uuid_uppercase); 302 free(uuid_uppercase);
221 free(uuid); 303 free(uuid);
@@ -246,9 +328,11 @@ static plist_t mobilebackup_factory_info_plist_new()
246 for (i = 0; itunesfiles[i]; i++) { 328 for (i = 0; itunesfiles[i]; i++) {
247 data_buf = NULL; 329 data_buf = NULL;
248 data_size = 0; 330 data_size = 0;
249 gchar *fname = g_strconcat("/iTunes_Control/iTunes/", itunesfiles[i], NULL); 331 char *fname = (char*)malloc(strlen("/iTunes_Control/iTunes/") + strlen(itunesfiles[i]) + 1);
332 strcpy(fname, "/iTunes_Control/iTunes/");
333 strcat(fname, itunesfiles[i]);
250 mobilebackup_afc_get_file_contents(fname, &data_buf, &data_size); 334 mobilebackup_afc_get_file_contents(fname, &data_buf, &data_size);
251 g_free(fname); 335 free(fname);
252 if (data_buf) { 336 if (data_buf) {
253 plist_dict_insert_item(files, itunesfiles[i], plist_new_data(data_buf, data_size)); 337 plist_dict_insert_item(files, itunesfiles[i], plist_new_data(data_buf, data_size));
254 free(data_buf); 338 free(data_buf);
@@ -358,10 +442,10 @@ static int mb2_status_check_snapshot_state(const char *path, const char *uuid, c
358{ 442{
359 int ret = -1; 443 int ret = -1;
360 plist_t status_plist = NULL; 444 plist_t status_plist = NULL;
361 gchar *file_path = g_build_path(G_DIR_SEPARATOR_S, path, uuid, "Status.plist", NULL); 445 char *file_path = build_path(path, uuid, "Status.plist", NULL);
362 446
363 plist_read_from_filename(&status_plist, file_path); 447 plist_read_from_filename(&status_plist, file_path);
364 g_free(file_path); 448 free(file_path);
365 if (!status_plist) { 449 if (!status_plist) {
366 printf("Could not read Status.plist!\n"); 450 printf("Could not read Status.plist!\n");
367 return ret; 451 return ret;
@@ -486,7 +570,7 @@ static void print_progress_real(double progress, int flush)
486 570
487static void print_progress(uint64_t current, uint64_t total) 571static void print_progress(uint64_t current, uint64_t total)
488{ 572{
489 gchar *format_size = NULL; 573 char *format_size = NULL;
490 double progress = ((double)current/(double)total)*100; 574 double progress = ((double)current/(double)total)*100;
491 if (progress < 0) 575 if (progress < 0)
492 return; 576 return;
@@ -496,12 +580,12 @@ static void print_progress(uint64_t current, uint64_t total)
496 580
497 print_progress_real((double)progress, 0); 581 print_progress_real((double)progress, 0);
498 582
499 format_size = g_format_size_for_display(current); 583 format_size = format_size_for_display(current);
500 PRINT_VERBOSE(1, " (%s", format_size); 584 PRINT_VERBOSE(1, " (%s", format_size);
501 g_free(format_size); 585 free(format_size);
502 format_size = g_format_size_for_display(total); 586 format_size = format_size_for_display(total);
503 PRINT_VERBOSE(1, "/%s) ", format_size); 587 PRINT_VERBOSE(1, "/%s) ", format_size);
504 g_free(format_size); 588 free(format_size);
505 589
506 fflush(stdout); 590 fflush(stdout);
507 if (progress == 100) 591 if (progress == 100)
@@ -534,7 +618,7 @@ static int mb2_handle_send_file(const char *backup_dir, const char *path, plist_
534 uint32_t nlen = 0; 618 uint32_t nlen = 0;
535 uint32_t pathlen = strlen(path); 619 uint32_t pathlen = strlen(path);
536 uint32_t bytes = 0; 620 uint32_t bytes = 0;
537 gchar *localfile = g_build_path(G_DIR_SEPARATOR_S, backup_dir, path, NULL); 621 char *localfile = build_path(backup_dir, path, NULL);
538 char buf[32768]; 622 char buf[32768];
539 struct stat fst; 623 struct stat fst;
540 624
@@ -549,7 +633,7 @@ static int mb2_handle_send_file(const char *backup_dir, const char *path, plist_
549 mobilebackup2_error_t err; 633 mobilebackup2_error_t err;
550 634
551 /* send path length */ 635 /* send path length */
552 nlen = GUINT32_TO_BE(pathlen); 636 nlen = htobe32(pathlen);
553 err = mobilebackup2_send_raw(mobilebackup2, (const char*)&nlen, sizeof(nlen), &bytes); 637 err = mobilebackup2_send_raw(mobilebackup2, (const char*)&nlen, sizeof(nlen), &bytes);
554 if (err != MOBILEBACKUP2_E_SUCCESS) { 638 if (err != MOBILEBACKUP2_E_SUCCESS) {
555 goto leave_proto_err; 639 goto leave_proto_err;
@@ -578,9 +662,9 @@ static int mb2_handle_send_file(const char *backup_dir, const char *path, plist_
578 662
579 total = fst.st_size; 663 total = fst.st_size;
580 664
581 gchar *format_size = g_format_size_for_display(total); 665 char *format_size = format_size_for_display(total);
582 PRINT_VERBOSE(1, "Sending '%s' (%s)\n", path, format_size); 666 PRINT_VERBOSE(1, "Sending '%s' (%s)\n", path, format_size);
583 g_free(format_size); 667 free(format_size);
584 668
585 if (total == 0) { 669 if (total == 0) {
586 errcode = 0; 670 errcode = 0;
@@ -598,7 +682,7 @@ static int mb2_handle_send_file(const char *backup_dir, const char *path, plist_
598 do { 682 do {
599 length = ((total-sent) < (off_t)sizeof(buf)) ? (uint32_t)total-sent : (uint32_t)sizeof(buf); 683 length = ((total-sent) < (off_t)sizeof(buf)) ? (uint32_t)total-sent : (uint32_t)sizeof(buf);
600 /* send data size (file size + 1) */ 684 /* send data size (file size + 1) */
601 nlen = GUINT32_TO_BE(length+1); 685 nlen = htobe32(length+1);
602 memcpy(buf, &nlen, sizeof(nlen)); 686 memcpy(buf, &nlen, sizeof(nlen));
603 buf[4] = CODE_FILE_DATA; 687 buf[4] = CODE_FILE_DATA;
604 err = mobilebackup2_send_raw(mobilebackup2, (const char*)buf, 5, &bytes); 688 err = mobilebackup2_send_raw(mobilebackup2, (const char*)buf, 5, &bytes);
@@ -634,7 +718,7 @@ leave:
634 if (errcode == 0) { 718 if (errcode == 0) {
635 result = 0; 719 result = 0;
636 nlen = 1; 720 nlen = 1;
637 nlen = GUINT32_TO_BE(nlen); 721 nlen = htobe32(nlen);
638 memcpy(buf, &nlen, 4); 722 memcpy(buf, &nlen, 4);
639 buf[4] = CODE_SUCCESS; 723 buf[4] = CODE_SUCCESS;
640 mobilebackup2_send_raw(mobilebackup2, buf, 5, &bytes); 724 mobilebackup2_send_raw(mobilebackup2, buf, 5, &bytes);
@@ -646,7 +730,7 @@ leave:
646 mb2_multi_status_add_file_error(*errplist, path, errno_to_device_error(errcode), errdesc); 730 mb2_multi_status_add_file_error(*errplist, path, errno_to_device_error(errcode), errdesc);
647 731
648 length = strlen(errdesc); 732 length = strlen(errdesc);
649 nlen = GUINT32_TO_BE(length+1); 733 nlen = htobe32(length+1);
650 memcpy(buf, &nlen, 4); 734 memcpy(buf, &nlen, 4);
651 buf[4] = CODE_ERROR_LOCAL; 735 buf[4] = CODE_ERROR_LOCAL;
652 slen = 5; 736 slen = 5;
@@ -664,7 +748,7 @@ leave:
664leave_proto_err: 748leave_proto_err:
665 if (f) 749 if (f)
666 fclose(f); 750 fclose(f);
667 g_free(localfile); 751 free(localfile);
668 return result; 752 return result;
669} 753}
670 754
@@ -726,7 +810,7 @@ static int mb2_handle_receive_files(plist_t message, const char *backup_dir)
726 char buf[32768]; 810 char buf[32768];
727 char *fname = NULL; 811 char *fname = NULL;
728 char *dname = NULL; 812 char *dname = NULL;
729 gchar *bname = NULL; 813 char *bname = NULL;
730 char code = 0; 814 char code = 0;
731 char last_code = 0; 815 char last_code = 0;
732 plist_t node = NULL; 816 plist_t node = NULL;
@@ -748,7 +832,7 @@ static int mb2_handle_receive_files(plist_t message, const char *backup_dir)
748 break; 832 break;
749 r = 0; 833 r = 0;
750 mobilebackup2_receive_raw(mobilebackup2, (char*)&nlen, 4, &r); 834 mobilebackup2_receive_raw(mobilebackup2, (char*)&nlen, 4, &r);
751 nlen = GUINT32_FROM_BE(nlen); 835 nlen = be32toh(nlen);
752 if (nlen == 0) { 836 if (nlen == 0) {
753 // we're done here 837 // we're done here
754 break; 838 break;
@@ -769,7 +853,7 @@ static int mb2_handle_receive_files(plist_t message, const char *backup_dir)
769 dname[r] = 0; 853 dname[r] = 0;
770 nlen = 0; 854 nlen = 0;
771 mobilebackup2_receive_raw(mobilebackup2, (char*)&nlen, 4, &r); 855 mobilebackup2_receive_raw(mobilebackup2, (char*)&nlen, 4, &r);
772 nlen = GUINT32_FROM_BE(nlen); 856 nlen = be32toh(nlen);
773 if (nlen == 0) { 857 if (nlen == 0) {
774 printf("ERROR: %s: zero-length backup filename!\n", __func__); 858 printf("ERROR: %s: zero-length backup filename!\n", __func__);
775 break; 859 break;
@@ -785,8 +869,8 @@ static int mb2_handle_receive_files(plist_t message, const char *backup_dir)
785 } 869 }
786 fname[r] = 0; 870 fname[r] = 0;
787 if (bname != NULL) 871 if (bname != NULL)
788 g_free(bname); 872 free(bname);
789 bname = g_build_path(G_DIR_SEPARATOR_S, backup_dir, fname, NULL); 873 bname = build_path(backup_dir, fname, NULL);
790 free(fname); 874 free(fname);
791 nlen = 0; 875 nlen = 0;
792 mobilebackup2_receive_raw(mobilebackup2, (char*)&nlen, 4, &r); 876 mobilebackup2_receive_raw(mobilebackup2, (char*)&nlen, 4, &r);
@@ -794,7 +878,7 @@ static int mb2_handle_receive_files(plist_t message, const char *backup_dir)
794 printf("ERROR: %s: could not receive code length!\n", __func__); 878 printf("ERROR: %s: could not receive code length!\n", __func__);
795 break; 879 break;
796 } 880 }
797 nlen = GUINT32_FROM_BE(nlen); 881 nlen = be32toh(nlen);
798 last_code = code; 882 last_code = code;
799 code = 0; 883 code = 0;
800 mobilebackup2_receive_raw(mobilebackup2, &code, 1, &r); 884 mobilebackup2_receive_raw(mobilebackup2, &code, 1, &r);
@@ -837,7 +921,7 @@ static int mb2_handle_receive_files(plist_t message, const char *backup_dir)
837 break; 921 break;
838 nlen = 0; 922 nlen = 0;
839 mobilebackup2_receive_raw(mobilebackup2, (char*)&nlen, 4, &r); 923 mobilebackup2_receive_raw(mobilebackup2, (char*)&nlen, 4, &r);
840 nlen = GUINT32_FROM_BE(nlen); 924 nlen = be32toh(nlen);
841 if (nlen > 0) { 925 if (nlen > 0) {
842 last_code = code; 926 last_code = code;
843 mobilebackup2_receive_raw(mobilebackup2, &code, 1, &r); 927 mobilebackup2_receive_raw(mobilebackup2, &code, 1, &r);
@@ -880,7 +964,7 @@ static int mb2_handle_receive_files(plist_t message, const char *backup_dir)
880 964
881 /* clean up */ 965 /* clean up */
882 if (bname != NULL) 966 if (bname != NULL)
883 g_free(bname); 967 free(bname);
884 968
885 if (dname != NULL) 969 if (dname != NULL)
886 free(dname); 970 free(dname);
@@ -905,37 +989,37 @@ static void mb2_handle_list_directory(plist_t message, const char *backup_dir)
905 return; 989 return;
906 } 990 }
907 991
908 gchar *path = g_build_path(G_DIR_SEPARATOR_S, backup_dir, str, NULL); 992 char *path = build_path(backup_dir, str, NULL);
909 free(str); 993 free(str);
910 994
911 plist_t dirlist = plist_new_dict(); 995 plist_t dirlist = plist_new_dict();
912 996
913 GDir *cur_dir = g_dir_open(path, 0, NULL); 997 DIR* cur_dir = opendir(path);
914 if (cur_dir) { 998 if (cur_dir) {
915 gchar *dir_file; 999 struct dirent* ep;
916 while ((dir_file = (gchar *)g_dir_read_name(cur_dir))) { 1000 while ((ep = readdir(cur_dir))) {
917 gchar *fpath = g_build_filename(path, dir_file, NULL); 1001 char *fpath = build_path(path, ep->d_name, NULL);
918 if (fpath) { 1002 if (fpath) {
919 plist_t fdict = plist_new_dict(); 1003 plist_t fdict = plist_new_dict();
920 GStatBuf st; 1004 struct stat st;
921 g_stat(fpath, &st); 1005 stat(fpath, &st);
922 const char *ftype = "DLFileTypeUnknown"; 1006 const char *ftype = "DLFileTypeUnknown";
923 if (g_file_test(fpath, G_FILE_TEST_IS_DIR)) { 1007 if (S_ISDIR(st.st_mode)) {
924 ftype = "DLFileTypeDirectory"; 1008 ftype = "DLFileTypeDirectory";
925 } else if (g_file_test(fpath, G_FILE_TEST_IS_REGULAR)) { 1009 } else if (S_ISREG(st.st_mode)) {
926 ftype = "DLFileTypeRegular"; 1010 ftype = "DLFileTypeRegular";
927 } 1011 }
928 plist_dict_insert_item(fdict, "DLFileType", plist_new_string(ftype)); 1012 plist_dict_insert_item(fdict, "DLFileType", plist_new_string(ftype));
929 plist_dict_insert_item(fdict, "DLFileSize", plist_new_uint(st.st_size)); 1013 plist_dict_insert_item(fdict, "DLFileSize", plist_new_uint(st.st_size));
930 plist_dict_insert_item(fdict, "DLFileModificationDate", plist_new_date(st.st_mtime, 0)); 1014 plist_dict_insert_item(fdict, "DLFileModificationDate", plist_new_date(st.st_mtime, 0));
931 1015
932 plist_dict_insert_item(dirlist, dir_file, fdict); 1016 plist_dict_insert_item(dirlist, ep->d_name, fdict);
933 g_free(fpath); 1017 free(fpath);
934 } 1018 }
935 } 1019 }
936 g_dir_close(cur_dir); 1020 closedir(cur_dir);
937 } 1021 }
938 g_free(path); 1022 free(path);
939 1023
940 /* TODO error handling */ 1024 /* TODO error handling */
941 mobilebackup2_error_t err = mobilebackup2_send_status_response(mobilebackup2, 0, NULL, dirlist); 1025 mobilebackup2_error_t err = mobilebackup2_send_status_response(mobilebackup2, 0, NULL, dirlist);
@@ -955,24 +1039,24 @@ static void mb2_handle_make_directory(plist_t message, const char *backup_dir)
955 char *errdesc = NULL; 1039 char *errdesc = NULL;
956 plist_get_string_val(dir, &str); 1040 plist_get_string_val(dir, &str);
957 1041
958 gchar *newpath = g_build_path(G_DIR_SEPARATOR_S, backup_dir, str, NULL); 1042 char *newpath = build_path(backup_dir, str, NULL);
959 g_free(str); 1043 free(str);
960 1044
961 if (g_mkdir_with_parents(newpath, 0755) < 0) { 1045 if (mkdir_with_parents(newpath, 0755) < 0) {
962 errdesc = strerror(errno); 1046 errdesc = strerror(errno);
963 if (errno != EEXIST) { 1047 if (errno != EEXIST) {
964 printf("mkdir: %s (%d)\n", errdesc, errno); 1048 printf("mkdir: %s (%d)\n", errdesc, errno);
965 } 1049 }
966 errcode = errno_to_device_error(errno); 1050 errcode = errno_to_device_error(errno);
967 } 1051 }
968 g_free(newpath); 1052 free(newpath);
969 mobilebackup2_error_t err = mobilebackup2_send_status_response(mobilebackup2, errcode, errdesc, NULL); 1053 mobilebackup2_error_t err = mobilebackup2_send_status_response(mobilebackup2, errcode, errdesc, NULL);
970 if (err != MOBILEBACKUP2_E_SUCCESS) { 1054 if (err != MOBILEBACKUP2_E_SUCCESS) {
971 printf("Could not send status response, error %d\n", err); 1055 printf("Could not send status response, error %d\n", err);
972 } 1056 }
973} 1057}
974 1058
975static void mb2_copy_file_by_path(const gchar *src, const gchar *dst) 1059static void mb2_copy_file_by_path(const char *src, const char *dst)
976{ 1060{
977 FILE *from, *to; 1061 FILE *from, *to;
978 char buf[BUFSIZ]; 1062 char buf[BUFSIZ];
@@ -1004,43 +1088,45 @@ static void mb2_copy_file_by_path(const gchar *src, const gchar *dst)
1004 } 1088 }
1005} 1089}
1006 1090
1007static void mb2_copy_directory_by_path(const gchar *src, const gchar *dst) 1091static void mb2_copy_directory_by_path(const char *src, const char *dst)
1008{ 1092{
1009 if (!src || !dst) { 1093 if (!src || !dst) {
1010 return; 1094 return;
1011 } 1095 }
1012 1096
1097 struct stat st;
1098
1013 /* if src does not exist */ 1099 /* if src does not exist */
1014 if (!g_file_test(src, G_FILE_TEST_EXISTS)) { 1100 if ((stat(src, &st) < 0) || !S_ISDIR(st.st_mode)) {
1015 printf("ERROR: Source directory does not exist '%s': %s (%d)\n", src, strerror(errno), errno); 1101 printf("ERROR: Source directory does not exist '%s': %s (%d)\n", src, strerror(errno), errno);
1016 return; 1102 return;
1017 } 1103 }
1018 1104
1019 /* if dst directory does not exist */ 1105 /* if dst directory does not exist */
1020 if (!g_file_test(dst, G_FILE_TEST_IS_DIR)) { 1106 if ((stat(dst, &st) < 0) || !S_ISDIR(st.st_mode)) {
1021 /* create it */ 1107 /* create it */
1022 if (g_mkdir_with_parents(dst, 0755) < 0) { 1108 if (mkdir_with_parents(dst, 0755) < 0) {
1023 printf("ERROR: Unable to create destination directory '%s': %s (%d)\n", dst, strerror(errno), errno); 1109 printf("ERROR: Unable to create destination directory '%s': %s (%d)\n", dst, strerror(errno), errno);
1024 return; 1110 return;
1025 } 1111 }
1026 } 1112 }
1027 1113
1028 /* loop over src directory contents */ 1114 /* loop over src directory contents */
1029 GDir *cur_dir = g_dir_open(src, 0, NULL); 1115 DIR *cur_dir = opendir(src);
1030 if (cur_dir) { 1116 if (cur_dir) {
1031 gchar *dir_file; 1117 struct dirent* ep;
1032 while ((dir_file = (gchar *)g_dir_read_name(cur_dir))) { 1118 while ((ep = readdir(cur_dir))) {
1033 gchar *srcpath = g_build_filename(src, dir_file, NULL); 1119 char *srcpath = build_path(src, ep->d_name, NULL);
1034 gchar *dstpath = g_build_filename(dst, dir_file, NULL); 1120 char *dstpath = build_path(dst, ep->d_name, NULL);
1035 if (srcpath && dstpath) { 1121 if (srcpath && dstpath) {
1036 /* copy file */ 1122 /* copy file */
1037 mb2_copy_file_by_path(srcpath, dstpath); 1123 mb2_copy_file_by_path(srcpath, dstpath);
1038 1124
1039 g_free(srcpath); 1125 free(srcpath);
1040 g_free(dstpath); 1126 free(dstpath);
1041 } 1127 }
1042 } 1128 }
1043 g_dir_close(cur_dir); 1129 closedir(cur_dir);
1044 } 1130 }
1045} 1131}
1046 1132
@@ -1196,10 +1282,10 @@ int main(int argc, char *argv[])
1196 } 1282 }
1197 1283
1198 /* backup directory must contain an Info.plist */ 1284 /* backup directory must contain an Info.plist */
1199 gchar *info_path = g_build_path(G_DIR_SEPARATOR_S, backup_directory, uuid, "Info.plist", NULL); 1285 char *info_path = build_path(backup_directory, uuid, "Info.plist", NULL);
1200 if (cmd == CMD_RESTORE) { 1286 if (cmd == CMD_RESTORE) {
1201 if (stat(info_path, &st) != 0) { 1287 if (stat(info_path, &st) != 0) {
1202 g_free(info_path); 1288 free(info_path);
1203 printf("ERROR: Backup directory \"%s\" is invalid. No Info.plist found for UUID %s.\n", backup_directory, uuid); 1289 printf("ERROR: Backup directory \"%s\" is invalid. No Info.plist found for UUID %s.\n", backup_directory, uuid);
1204 return -1; 1290 return -1;
1205 } 1291 }
@@ -1328,9 +1414,9 @@ checkpoint:
1328 PRINT_VERBOSE(1, "Starting backup...\n"); 1414 PRINT_VERBOSE(1, "Starting backup...\n");
1329 1415
1330 /* make sure backup device sub-directory exists */ 1416 /* make sure backup device sub-directory exists */
1331 gchar *devbackupdir = g_build_path(G_DIR_SEPARATOR_S, backup_directory, uuid, NULL); 1417 char *devbackupdir = build_path(backup_directory, uuid, NULL);
1332 g_mkdir(devbackupdir, 0755); 1418 __mkdir(devbackupdir, 0755);
1333 g_free(devbackupdir); 1419 free(devbackupdir);
1334 1420
1335 /* TODO: check domain com.apple.mobile.backup key RequiresEncrypt and WillEncrypt with lockdown */ 1421 /* TODO: check domain com.apple.mobile.backup key RequiresEncrypt and WillEncrypt with lockdown */
1336 /* TODO: verify battery on AC enough battery remaining */ 1422 /* TODO: verify battery on AC enough battery remaining */
@@ -1343,7 +1429,7 @@ checkpoint:
1343 info_plist = mobilebackup_factory_info_plist_new(); 1429 info_plist = mobilebackup_factory_info_plist_new();
1344 remove(info_path); 1430 remove(info_path);
1345 plist_write_to_filename(info_plist, info_path, PLIST_FORMAT_XML); 1431 plist_write_to_filename(info_plist, info_path, PLIST_FORMAT_XML);
1346 g_free(info_path); 1432 free(info_path);
1347 1433
1348 plist_free(info_plist); 1434 plist_free(info_plist);
1349 info_plist = NULL; 1435 info_plist = NULL;
@@ -1493,9 +1579,9 @@ checkpoint:
1493 char *str = NULL; 1579 char *str = NULL;
1494 plist_get_string_val(val, &str); 1580 plist_get_string_val(val, &str);
1495 if (str) { 1581 if (str) {
1496 gchar *newpath = g_build_path(G_DIR_SEPARATOR_S, backup_directory, str, NULL); 1582 char *newpath = build_path(backup_directory, str, NULL);
1497 g_free(str); 1583 free(str);
1498 gchar *oldpath = g_build_path(G_DIR_SEPARATOR_S, backup_directory, key, NULL); 1584 char *oldpath = build_path(backup_directory, key, NULL);
1499 1585
1500 remove(newpath); 1586 remove(newpath);
1501 if (rename(oldpath, newpath) < 0) { 1587 if (rename(oldpath, newpath) < 0) {
@@ -1504,8 +1590,8 @@ checkpoint:
1504 errdesc = strerror(errno); 1590 errdesc = strerror(errno);
1505 break; 1591 break;
1506 } 1592 }
1507 g_free(oldpath); 1593 free(oldpath);
1508 g_free(newpath); 1594 free(newpath);
1509 } 1595 }
1510 free(key); 1596 free(key);
1511 key = NULL; 1597 key = NULL;
@@ -1534,14 +1620,14 @@ checkpoint:
1534 char *str = NULL; 1620 char *str = NULL;
1535 plist_get_string_val(val, &str); 1621 plist_get_string_val(val, &str);
1536 if (str) { 1622 if (str) {
1537 gchar *newpath = g_build_path(G_DIR_SEPARATOR_S, backup_directory, str, NULL); 1623 char *newpath = build_path(backup_directory, str, NULL);
1538 g_free(str); 1624 free(str);
1539 if (remove(newpath) < 0) { 1625 if (remove(newpath) < 0) {
1540 printf("Could not remove '%s': %s (%d)\n", newpath, strerror(errno), errno); 1626 printf("Could not remove '%s': %s (%d)\n", newpath, strerror(errno), errno);
1541 errcode = errno_to_device_error(errno); 1627 errcode = errno_to_device_error(errno);
1542 errdesc = strerror(errno); 1628 errdesc = strerror(errno);
1543 } 1629 }
1544 g_free(newpath); 1630 free(newpath);
1545 } 1631 }
1546 } 1632 }
1547 } 1633 }
@@ -1560,23 +1646,24 @@ checkpoint:
1560 plist_get_string_val(srcpath, &src); 1646 plist_get_string_val(srcpath, &src);
1561 plist_get_string_val(dstpath, &dst); 1647 plist_get_string_val(dstpath, &dst);
1562 if (src && dst) { 1648 if (src && dst) {
1563 gchar *oldpath = g_build_path(G_DIR_SEPARATOR_S, backup_directory, src, NULL); 1649 char *oldpath = build_path(backup_directory, src, NULL);
1564 gchar *newpath = g_build_path(G_DIR_SEPARATOR_S, backup_directory, dst, NULL); 1650 char *newpath = build_path(backup_directory, dst, NULL);
1651 struct stat st;
1565 1652
1566 PRINT_VERBOSE(1, "Copying '%s' to '%s'\n", src, dst); 1653 PRINT_VERBOSE(1, "Copying '%s' to '%s'\n", src, dst);
1567 1654
1568 /* check that src exists */ 1655 /* check that src exists */
1569 if (g_file_test(oldpath, G_FILE_TEST_IS_DIR)) { 1656 if ((stat(oldpath, &st) == 0) && S_ISDIR(st.st_mode)) {
1570 mb2_copy_directory_by_path(oldpath, newpath); 1657 mb2_copy_directory_by_path(oldpath, newpath);
1571 } else if (g_file_test(oldpath, G_FILE_TEST_IS_REGULAR)) { 1658 } else if ((stat(oldpath, &st) == 0) && S_ISREG(st.st_mode)) {
1572 mb2_copy_file_by_path(oldpath, newpath); 1659 mb2_copy_file_by_path(oldpath, newpath);
1573 } 1660 }
1574 1661
1575 g_free(newpath); 1662 free(newpath);
1576 g_free(oldpath); 1663 free(oldpath);
1577 } 1664 }
1578 g_free(src); 1665 free(src);
1579 g_free(dst); 1666 free(dst);
1580 } 1667 }
1581 1668
1582 err = mobilebackup2_send_status_response(mobilebackup2, errcode, errdesc, plist_new_dict()); 1669 err = mobilebackup2_send_status_response(mobilebackup2, errcode, errdesc, plist_new_dict());