summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.ac3
-rw-r--r--dev/Makefile.am6
-rw-r--r--dev/lckdclient.c64
-rw-r--r--tools/Makefile.am6
-rw-r--r--tools/idevicebackup.c133
-rw-r--r--tools/idevicebackup2.c261
6 files changed, 322 insertions, 151 deletions
diff --git a/configure.ac b/configure.ac
index 299b6ee..9fba4cc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -31,9 +31,6 @@ PKG_CHECK_MODULES(libplist, libplist >= 0.15)
31PKG_CHECK_MODULES(libplistmm, libplist++ >= 0.15) 31PKG_CHECK_MODULES(libplistmm, libplist++ >= 0.15)
32AC_CHECK_LIB(pthread, [pthread_create, pthread_mutex_lock], [AC_SUBST(libpthread_LIBS,[-lpthread])], [AC_MSG_ERROR([libpthread is required to build libimobiledevice])]) 32AC_CHECK_LIB(pthread, [pthread_create, pthread_mutex_lock], [AC_SUBST(libpthread_LIBS,[-lpthread])], [AC_MSG_ERROR([libpthread is required to build libimobiledevice])])
33 33
34PKG_CHECK_MODULES(libglib2, glib-2.0 >= 2.14.1, enable_glib2=yes, enable_glib2=no)
35AM_CONDITIONAL([HAVE_GLIB2],[test "x$enable_glib2" == "xyes"])
36
37# Checks for header files. 34# Checks for header files.
38AC_HEADER_STDC 35AC_HEADER_STDC
39AC_CHECK_HEADERS([stdint.h stdlib.h string.h gcrypt.h]) 36AC_CHECK_HEADERS([stdint.h stdlib.h string.h gcrypt.h])
diff --git a/dev/Makefile.am b/dev/Makefile.am
index c1d2b45..bc3843b 100644
--- a/dev/Makefile.am
+++ b/dev/Makefile.am
@@ -4,11 +4,7 @@ AM_CFLAGS = $(GLOBAL_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(LFS_CFLAGS
4AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS) $(libpthread_LIBS) 4AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS) $(libpthread_LIBS)
5 5
6if ENABLE_DEVTOOLS 6if ENABLE_DEVTOOLS
7noinst_PROGRAMS = ideviceclient afccheck filerelaytest housearresttest 7noinst_PROGRAMS = ideviceclient afccheck filerelaytest housearresttest lckd-client
8
9if HAVE_GLIB2
10noinst_PROGRAMS += lckd-client
11endif
12 8
13ideviceclient_SOURCES = ideviceclient.c 9ideviceclient_SOURCES = ideviceclient.c
14ideviceclient_CFLAGS = $(AM_CFLAGS) 10ideviceclient_CFLAGS = $(AM_CFLAGS)
diff --git a/dev/lckdclient.c b/dev/lckdclient.c
index 773de9f..5ca72f8 100644
--- a/dev/lckdclient.c
+++ b/dev/lckdclient.c
@@ -22,13 +22,60 @@
22#include <stdio.h> 22#include <stdio.h>
23#include <stdlib.h> 23#include <stdlib.h>
24#include <string.h> 24#include <string.h>
25#include <glib.h>
26#include <readline/readline.h> 25#include <readline/readline.h>
27#include <readline/history.h> 26#include <readline/history.h>
28 27
29#include <libimobiledevice/libimobiledevice.h> 28#include <libimobiledevice/libimobiledevice.h>
30#include <libimobiledevice/lockdown.h> 29#include <libimobiledevice/lockdown.h>
31 30
31static char** get_tokens(const char *str)
32{
33 char *strcp = strdup(str);
34 char *p;
35 char res_max = 8;
36 char **result = NULL;
37 int cnt = 0;
38
39 p = strtok(strcp, " ");
40 if (!p) {
41 result = (char**)malloc(2 * sizeof(char*));
42 result[0] = strdup(str);
43 result[1] = NULL;
44 return result;
45 }
46
47 result = (char**)malloc(res_max * sizeof(char*));
48 memset(result, 0, res_max * sizeof(char*));
49
50 while (p) {
51 if (cnt >= res_max) {
52 res_max += 8;
53 result = (char**)realloc(result, res_max * sizeof(char*));
54 }
55 result[cnt] = strdup(p);
56 cnt++;
57 p = strtok(NULL, " ");
58 }
59
60 if (cnt >= res_max) {
61 res_max += 1;
62 result = (char**)realloc(result, res_max * sizeof(char*));
63 result[cnt] = NULL;
64 }
65
66 return result;
67}
68
69static void strfreev(char **strs)
70{
71 int i = 0;
72 while (strs && strs[i]) {
73 free(strs[i]);
74 i++;
75 }
76 free(strs);
77}
78
32int main(int argc, char *argv[]) 79int main(int argc, char *argv[])
33{ 80{
34 lockdownd_client_t client = NULL; 81 lockdownd_client_t client = NULL;
@@ -54,25 +101,22 @@ int main(int argc, char *argv[])
54 } 101 }
55 102
56 using_history(); 103 using_history();
57 int loop = TRUE; 104 int loop = 1;
58 while (loop) { 105 while (loop) {
59 char *cmd = readline("> "); 106 char *cmd = readline("> ");
60 if (cmd) { 107 if (cmd) {
61 108
62 gchar **args = g_strsplit(cmd, " ", 0); 109 char **args = get_tokens(cmd);
63 110
64 int len = 0; 111 int len = 0;
65 if (args) { 112 while (args && args[len]) {
66 while (*(args + len)) { 113 len++;
67 g_strstrip(*(args + len));
68 len++;
69 }
70 } 114 }
71 115
72 if (len > 0) { 116 if (len > 0) {
73 add_history(cmd); 117 add_history(cmd);
74 if (!strcmp(*args, "quit")) 118 if (!strcmp(*args, "quit"))
75 loop = FALSE; 119 loop = 0;
76 120
77 if (!strcmp(*args, "get") && len >= 2) { 121 if (!strcmp(*args, "get") && len >= 2) {
78 plist_t value = NULL; 122 plist_t value = NULL;
@@ -102,7 +146,7 @@ int main(int argc, char *argv[])
102 } 146 }
103 } 147 }
104 } 148 }
105 g_strfreev(args); 149 strfreev(args);
106 } 150 }
107 free(cmd); 151 free(cmd);
108 cmd = NULL; 152 cmd = NULL;
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 19b2f92..20003aa 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -3,11 +3,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include
3AM_CFLAGS = $(GLOBAL_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(openssl_CFLAGS) $(LFS_CFLAGS) 3AM_CFLAGS = $(GLOBAL_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(openssl_CFLAGS) $(LFS_CFLAGS)
4AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS) $(openssl_LIBS) 4AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS) $(openssl_LIBS)
5 5
6bin_PROGRAMS = idevice_id ideviceinfo idevicepair idevicesyslog ideviceimagemounter idevicescreenshot ideviceenterrecovery idevicedate 6bin_PROGRAMS = idevice_id ideviceinfo idevicepair idevicesyslog ideviceimagemounter idevicescreenshot ideviceenterrecovery idevicedate idevicebackup idevicebackup2
7
8if HAVE_GLIB2
9bin_PROGRAMS += idevicebackup idevicebackup2
10endif
11 7
12ideviceinfo_SOURCES = ideviceinfo.c 8ideviceinfo_SOURCES = ideviceinfo.c
13ideviceinfo_CFLAGS = $(AM_CFLAGS) 9ideviceinfo_CFLAGS = $(AM_CFLAGS)
diff --git a/tools/idevicebackup.c b/tools/idevicebackup.c
index f744e70..25f8014 100644
--- a/tools/idevicebackup.c
+++ b/tools/idevicebackup.c
@@ -29,7 +29,6 @@
29#include <errno.h> 29#include <errno.h>
30#include <stdlib.h> 30#include <stdlib.h>
31#include <signal.h> 31#include <signal.h>
32#include <glib.h>
33#ifdef HAVE_OPENSSL 32#ifdef HAVE_OPENSSL
34#include <openssl/sha.h> 33#include <openssl/sha.h>
35#else 34#else
@@ -222,10 +221,63 @@ static void notify_cb(const char *notification, void *userdata)
222 } 221 }
223} 222}
224 223
224static char *str_toupper(char* str)
225{
226 char *res = strdup(str);
227 int i;
228 for (i = 0; i < strlen(res); i++) {
229 res[i] = toupper(res[i]);
230 }
231 return res;
232}
233
234char* build_path(const char* elem, ...)
235{
236 if (!elem) return NULL;
237 va_list args;
238 int len = strlen(elem)+1;
239 va_start(args, elem);
240 char *arg = va_arg(args, char*);
241 while (arg) {
242 len += strlen(arg)+1;
243 arg = va_arg(args, char*);
244 }
245 va_end(args);
246
247 char* out = (char*)malloc(len);
248 strcpy(out, elem);
249
250 va_start(args, elem);
251 arg = va_arg(args, char*);
252 while (arg) {
253 strcat(out, "/");
254 strcat(out, arg);
255 arg = va_arg(args, char*);
256 }
257 va_end(args);
258 return out;
259}
260
261static char* format_size_for_display(uint64_t size)
262{
263 char buf[32];
264 double sz;
265 if (size >= 1000000000LL) {
266 sz = ((double)size / 1000000000.0f);
267 sprintf(buf, "%0.1f GB", sz);
268 } else if (size >= 1000000LL) {
269 sz = ((double)size / 1000000.0f);
270 sprintf(buf, "%0.1f MB", sz);
271 } else if (size >= 1000LL) {
272 sz = ((double)size / 1000.0f);
273 sprintf(buf, "%0.1f kB", sz);
274 }
275 return strdup(buf);
276}
277
225static plist_t mobilebackup_factory_info_plist_new() 278static plist_t mobilebackup_factory_info_plist_new()
226{ 279{
227 /* gather data from lockdown */ 280 /* gather data from lockdown */
228 GTimeVal tv = {0, 0};
229 plist_t value_node = NULL; 281 plist_t value_node = NULL;
230 plist_t root_node = NULL; 282 plist_t root_node = NULL;
231 char *uuid = NULL; 283 char *uuid = NULL;
@@ -251,8 +303,7 @@ static plist_t mobilebackup_factory_info_plist_new()
251 if (value_node) 303 if (value_node)
252 plist_dict_insert_item(ret, "IMEI", plist_copy(value_node)); 304 plist_dict_insert_item(ret, "IMEI", plist_copy(value_node));
253 305
254 g_get_current_time(&tv); 306 plist_dict_insert_item(ret, "Last Backup Date", plist_new_date(time(NULL), 0));
255 plist_dict_insert_item(ret, "Last Backup Date", plist_new_date(tv.tv_sec, tv.tv_usec));
256 307
257 value_node = plist_dict_get_item(root_node, "ProductType"); 308 value_node = plist_dict_get_item(root_node, "ProductType");
258 plist_dict_insert_item(ret, "Product Type", plist_copy(value_node)); 309 plist_dict_insert_item(ret, "Product Type", plist_copy(value_node));
@@ -268,7 +319,7 @@ static plist_t mobilebackup_factory_info_plist_new()
268 plist_dict_insert_item(ret, "Target Identifier", plist_new_string(uuid)); 319 plist_dict_insert_item(ret, "Target Identifier", plist_new_string(uuid));
269 320
270 /* uppercase */ 321 /* uppercase */
271 uuid_uppercase = g_ascii_strup(uuid, -1); 322 uuid_uppercase = str_toupper(uuid);
272 plist_dict_insert_item(ret, "Unique Identifier", plist_new_string(uuid_uppercase)); 323 plist_dict_insert_item(ret, "Unique Identifier", plist_new_string(uuid_uppercase));
273 free(uuid_uppercase); 324 free(uuid_uppercase);
274 free(uuid); 325 free(uuid);
@@ -285,15 +336,13 @@ static plist_t mobilebackup_factory_info_plist_new()
285 336
286static void mobilebackup_info_update_last_backup_date(plist_t info_plist) 337static void mobilebackup_info_update_last_backup_date(plist_t info_plist)
287{ 338{
288 GTimeVal tv = {0, 0};
289 plist_t node = NULL; 339 plist_t node = NULL;
290 340
291 if (!info_plist) 341 if (!info_plist)
292 return; 342 return;
293 343
294 g_get_current_time(&tv);
295 node = plist_dict_get_item(info_plist, "Last Backup Date"); 344 node = plist_dict_get_item(info_plist, "Last Backup Date");
296 plist_set_date_val(node, tv.tv_sec, tv.tv_usec); 345 plist_set_date_val(node, time(NULL), 0);
297 346
298 node = NULL; 347 node = NULL;
299} 348}
@@ -396,11 +445,13 @@ static int plist_strcmp(plist_t node, const char *str)
396 return ret; 445 return ret;
397} 446}
398 447
399static gchar *mobilebackup_build_path(const char *backup_directory, const char *name, const char *extension) 448static char *mobilebackup_build_path(const char *backup_directory, const char *name, const char *extension)
400{ 449{
401 gchar *filename = g_strconcat(name, extension, NULL); 450 char* filename = (char*)malloc(strlen(name)+strlen(extension)+1);
402 gchar *path = g_build_path(G_DIR_SEPARATOR_S, backup_directory, filename, NULL); 451 strcpy(filename, name);
403 g_free(filename); 452 strcat(filename, extension);
453 char *path = build_path(backup_directory, filename, NULL);
454 free(filename);
404 return path; 455 return path;
405} 456}
406 457
@@ -409,7 +460,7 @@ static void mobilebackup_write_status(const char *path, int status)
409 struct stat st; 460 struct stat st;
410 plist_t status_plist = plist_new_dict(); 461 plist_t status_plist = plist_new_dict();
411 plist_dict_insert_item(status_plist, "Backup Success", plist_new_bool(status)); 462 plist_dict_insert_item(status_plist, "Backup Success", plist_new_bool(status));
412 gchar *file_path = mobilebackup_build_path(path, "Status", ".plist"); 463 char *file_path = mobilebackup_build_path(path, "Status", ".plist");
413 464
414 if (stat(file_path, &st) == 0) 465 if (stat(file_path, &st) == 0)
415 remove(file_path); 466 remove(file_path);
@@ -419,17 +470,17 @@ static void mobilebackup_write_status(const char *path, int status)
419 plist_free(status_plist); 470 plist_free(status_plist);
420 status_plist = NULL; 471 status_plist = NULL;
421 472
422 g_free(file_path); 473 free(file_path);
423} 474}
424 475
425static int mobilebackup_read_status(const char *path) 476static int mobilebackup_read_status(const char *path)
426{ 477{
427 int ret = -1; 478 int ret = -1;
428 plist_t status_plist = NULL; 479 plist_t status_plist = NULL;
429 gchar *file_path = mobilebackup_build_path(path, "Status", ".plist"); 480 char *file_path = mobilebackup_build_path(path, "Status", ".plist");
430 481
431 plist_read_from_filename(&status_plist, file_path); 482 plist_read_from_filename(&status_plist, file_path);
432 g_free(file_path); 483 free(file_path);
433 if (!status_plist) { 484 if (!status_plist) {
434 printf("Could not read Status.plist!\n"); 485 printf("Could not read Status.plist!\n");
435 return ret; 486 return ret;
@@ -510,14 +561,14 @@ static int mobilebackup_info_is_current_device(plist_t info)
510static int mobilebackup_delete_backup_file_by_hash(const char *backup_directory, const char *hash) 561static int mobilebackup_delete_backup_file_by_hash(const char *backup_directory, const char *hash)
511{ 562{
512 int ret = 0; 563 int ret = 0;
513 gchar *path = mobilebackup_build_path(backup_directory, hash, ".mddata"); 564 char *path = mobilebackup_build_path(backup_directory, hash, ".mddata");
514 printf("Removing \"%s\" ", path); 565 printf("Removing \"%s\" ", path);
515 if (!remove( path )) 566 if (!remove( path ))
516 ret = 1; 567 ret = 1;
517 else 568 else
518 ret = 0; 569 ret = 0;
519 570
520 g_free(path); 571 free(path);
521 572
522 if (!ret) 573 if (!ret)
523 return ret; 574 return ret;
@@ -529,7 +580,7 @@ static int mobilebackup_delete_backup_file_by_hash(const char *backup_directory,
529 else 580 else
530 ret = 0; 581 ret = 0;
531 582
532 g_free(path); 583 free(path);
533 584
534 return ret; 585 return ret;
535} 586}
@@ -666,9 +717,9 @@ static int mobilebackup_check_file_integrity(const char *backup_directory, const
666 hash_ok = 1; 717 hash_ok = 1;
667 } 718 }
668 719
669 g_free(domain); 720 free(domain);
670 g_free(version); 721 free(version);
671 g_free(destpath); 722 free(destpath);
672 723
673 if (!hash_ok) { 724 if (!hash_ok) {
674 printf("\r\n"); 725 printf("\r\n");
@@ -680,7 +731,7 @@ static int mobilebackup_check_file_integrity(const char *backup_directory, const
680 printf("\n"); 731 printf("\n");
681 res = 0; 732 res = 0;
682 } 733 }
683 g_free(data_hash); 734 free(data_hash);
684 plist_free(mdinfo); 735 plist_free(mdinfo);
685 return res; 736 return res;
686} 737}
@@ -841,7 +892,7 @@ int main(int argc, char *argv[])
841 char *info_path = mobilebackup_build_path(backup_directory, "Info", ".plist"); 892 char *info_path = mobilebackup_build_path(backup_directory, "Info", ".plist");
842 if (cmd == CMD_RESTORE) { 893 if (cmd == CMD_RESTORE) {
843 if (stat(info_path, &st) != 0) { 894 if (stat(info_path, &st) != 0) {
844 g_free(info_path); 895 free(info_path);
845 printf("ERROR: Backup directory \"%s\" is invalid. No Info.plist found.\n", backup_directory); 896 printf("ERROR: Backup directory \"%s\" is invalid. No Info.plist found.\n", backup_directory);
846 return -1; 897 return -1;
847 } 898 }
@@ -1010,7 +1061,7 @@ int main(int argc, char *argv[])
1010 info_plist = mobilebackup_factory_info_plist_new(); 1061 info_plist = mobilebackup_factory_info_plist_new();
1011 plist_write_to_filename(info_plist, info_path, PLIST_FORMAT_XML); 1062 plist_write_to_filename(info_plist, info_path, PLIST_FORMAT_XML);
1012 } 1063 }
1013 g_free(info_path); 1064 free(info_path);
1014 1065
1015 plist_free(info_plist); 1066 plist_free(info_plist);
1016 info_plist = NULL; 1067 info_plist = NULL;
@@ -1060,7 +1111,7 @@ int main(int argc, char *argv[])
1060 char *filename_mddata = NULL; 1111 char *filename_mddata = NULL;
1061 char *filename_source = NULL; 1112 char *filename_source = NULL;
1062 char *format_size = NULL; 1113 char *format_size = NULL;
1063 gboolean is_manifest = FALSE; 1114 int is_manifest = 0;
1064 uint8_t b = 0; 1115 uint8_t b = 0;
1065 1116
1066 /* process series of DLSendFile messages */ 1117 /* process series of DLSendFile messages */
@@ -1085,9 +1136,9 @@ int main(int argc, char *argv[])
1085 node = plist_dict_get_item(node_tmp, "BackupTotalSizeKey"); 1136 node = plist_dict_get_item(node_tmp, "BackupTotalSizeKey");
1086 if (node) { 1137 if (node) {
1087 plist_get_uint_val(node, &backup_total_size); 1138 plist_get_uint_val(node, &backup_total_size);
1088 format_size = g_format_size_for_display(backup_total_size); 1139 format_size = format_size_for_display(backup_total_size);
1089 printf("Backup data requires %s on the disk.\n", format_size); 1140 printf("Backup data requires %s on the disk.\n", format_size);
1090 g_free(format_size); 1141 free(format_size);
1091 } 1142 }
1092 } 1143 }
1093 1144
@@ -1102,7 +1153,7 @@ int main(int argc, char *argv[])
1102 if (node) { 1153 if (node) {
1103 plist_get_bool_val(node, &b); 1154 plist_get_bool_val(node, &b);
1104 } 1155 }
1105 is_manifest = (b == 1) ? TRUE: FALSE; 1156 is_manifest = (b == 1) ? 1 : 0;
1106 1157
1107 if ((hunk_index == 0) && (!is_manifest)) { 1158 if ((hunk_index == 0) && (!is_manifest)) {
1108 /* get source filename */ 1159 /* get source filename */
@@ -1115,17 +1166,17 @@ int main(int argc, char *argv[])
1115 plist_get_uint_val(node, &file_size); 1166 plist_get_uint_val(node, &file_size);
1116 backup_real_size += file_size; 1167 backup_real_size += file_size;
1117 1168
1118 format_size = g_format_size_for_display(backup_real_size); 1169 format_size = format_size_for_display(backup_real_size);
1119 printf("(%s", format_size); 1170 printf("(%s", format_size);
1120 g_free(format_size); 1171 free(format_size);
1121 1172
1122 format_size = g_format_size_for_display(backup_total_size); 1173 format_size = format_size_for_display(backup_total_size);
1123 printf("/%s): ", format_size); 1174 printf("/%s): ", format_size);
1124 g_free(format_size); 1175 free(format_size);
1125 1176
1126 format_size = g_format_size_for_display(file_size); 1177 format_size = format_size_for_display(file_size);
1127 printf("Receiving file %s (%s)... \n", filename_source, format_size); 1178 printf("Receiving file %s (%s)... \n", filename_source, format_size);
1128 g_free(format_size); 1179 free(format_size);
1129 1180
1130 if (filename_source) 1181 if (filename_source)
1131 free(filename_source); 1182 free(filename_source);
@@ -1148,7 +1199,7 @@ int main(int argc, char *argv[])
1148 node = plist_dict_get_item(node_tmp, "BackupFileInfo"); 1199 node = plist_dict_get_item(node_tmp, "BackupFileInfo");
1149 plist_write_to_filename(node, filename_mdinfo, PLIST_FORMAT_BINARY); 1200 plist_write_to_filename(node, filename_mdinfo, PLIST_FORMAT_BINARY);
1150 1201
1151 g_free(filename_mdinfo); 1202 free(filename_mdinfo);
1152 } 1203 }
1153 1204
1154 file_index++; 1205 file_index++;
@@ -1182,7 +1233,7 @@ int main(int argc, char *argv[])
1182 free(buffer); 1233 free(buffer);
1183 buffer = NULL; 1234 buffer = NULL;
1184 1235
1185 g_free(filename_mddata); 1236 free(filename_mddata);
1186 } 1237 }
1187 1238
1188 if ((!is_manifest)) { 1239 if ((!is_manifest)) {
@@ -1220,7 +1271,7 @@ files_out:
1220 1271
1221 /* remove any atomic Manifest.plist.tmp */ 1272 /* remove any atomic Manifest.plist.tmp */
1222 if (manifest_path) 1273 if (manifest_path)
1223 g_free(manifest_path); 1274 free(manifest_path);
1224 1275
1225 manifest_path = mobilebackup_build_path(backup_directory, "Manifest", ".plist.tmp"); 1276 manifest_path = mobilebackup_build_path(backup_directory, "Manifest", ".plist.tmp");
1226 if (stat(manifest_path, &st) == 0) 1277 if (stat(manifest_path, &st) == 0)
@@ -1330,12 +1381,12 @@ files_out:
1330 } else { 1381 } else {
1331 printf("Could not get AuthSignature from manifest!\n"); 1382 printf("Could not get AuthSignature from manifest!\n");
1332 } 1383 }
1333 g_free(auth_sig); 1384 free(auth_sig);
1334 } else if (auth_ver) { 1385 } else if (auth_ver) {
1335 printf("Unknown AuthVersion '%s', cannot verify AuthSignature\n", auth_ver); 1386 printf("Unknown AuthVersion '%s', cannot verify AuthSignature\n", auth_ver);
1336 } 1387 }
1337 plist_from_bin(bin, (uint32_t)binsize, &backup_data); 1388 plist_from_bin(bin, (uint32_t)binsize, &backup_data);
1338 g_free(bin); 1389 free(bin);
1339 } 1390 }
1340 if (!backup_data) { 1391 if (!backup_data) {
1341 printf("Could not read plist from Manifest.plist Data key!\n"); 1392 printf("Could not read plist from Manifest.plist Data key!\n");
@@ -1615,7 +1666,7 @@ files_out:
1615 do_post_notification(NP_SYNC_DID_FINISH); 1666 do_post_notification(NP_SYNC_DID_FINISH);
1616 } 1667 }
1617 if (manifest_path) 1668 if (manifest_path)
1618 g_free(manifest_path); 1669 free(manifest_path);
1619 } else { 1670 } else {
1620 printf("ERROR: Could not start service %s.\n", MOBILEBACKUP_SERVICE_NAME); 1671 printf("ERROR: Could not start service %s.\n", MOBILEBACKUP_SERVICE_NAME);
1621 lockdownd_client_free(client); 1672 lockdownd_client_free(client);
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());