diff options
| -rw-r--r-- | configure.ac | 3 | ||||
| -rw-r--r-- | dev/Makefile.am | 6 | ||||
| -rw-r--r-- | dev/lckdclient.c | 64 | ||||
| -rw-r--r-- | tools/Makefile.am | 6 | ||||
| -rw-r--r-- | tools/idevicebackup.c | 133 | ||||
| -rw-r--r-- | tools/idevicebackup2.c | 261 |
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) | |||
| 31 | PKG_CHECK_MODULES(libplistmm, libplist++ >= 0.15) | 31 | PKG_CHECK_MODULES(libplistmm, libplist++ >= 0.15) |
| 32 | AC_CHECK_LIB(pthread, [pthread_create, pthread_mutex_lock], [AC_SUBST(libpthread_LIBS,[-lpthread])], [AC_MSG_ERROR([libpthread is required to build libimobiledevice])]) | 32 | AC_CHECK_LIB(pthread, [pthread_create, pthread_mutex_lock], [AC_SUBST(libpthread_LIBS,[-lpthread])], [AC_MSG_ERROR([libpthread is required to build libimobiledevice])]) |
| 33 | 33 | ||
| 34 | PKG_CHECK_MODULES(libglib2, glib-2.0 >= 2.14.1, enable_glib2=yes, enable_glib2=no) | ||
| 35 | AM_CONDITIONAL([HAVE_GLIB2],[test "x$enable_glib2" == "xyes"]) | ||
| 36 | |||
| 37 | # Checks for header files. | 34 | # Checks for header files. |
| 38 | AC_HEADER_STDC | 35 | AC_HEADER_STDC |
| 39 | AC_CHECK_HEADERS([stdint.h stdlib.h string.h gcrypt.h]) | 36 | AC_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 | |||
| 4 | AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS) $(libpthread_LIBS) | 4 | AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS) $(libpthread_LIBS) |
| 5 | 5 | ||
| 6 | if ENABLE_DEVTOOLS | 6 | if ENABLE_DEVTOOLS |
| 7 | noinst_PROGRAMS = ideviceclient afccheck filerelaytest housearresttest | 7 | noinst_PROGRAMS = ideviceclient afccheck filerelaytest housearresttest lckd-client |
| 8 | |||
| 9 | if HAVE_GLIB2 | ||
| 10 | noinst_PROGRAMS += lckd-client | ||
| 11 | endif | ||
| 12 | 8 | ||
| 13 | ideviceclient_SOURCES = ideviceclient.c | 9 | ideviceclient_SOURCES = ideviceclient.c |
| 14 | ideviceclient_CFLAGS = $(AM_CFLAGS) | 10 | ideviceclient_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 | ||
| 31 | static 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 | |||
| 69 | static 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 | |||
| 32 | int main(int argc, char *argv[]) | 79 | int 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 | |||
| 3 | AM_CFLAGS = $(GLOBAL_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(openssl_CFLAGS) $(LFS_CFLAGS) | 3 | AM_CFLAGS = $(GLOBAL_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(openssl_CFLAGS) $(LFS_CFLAGS) |
| 4 | AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS) $(openssl_LIBS) | 4 | AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS) $(openssl_LIBS) |
| 5 | 5 | ||
| 6 | bin_PROGRAMS = idevice_id ideviceinfo idevicepair idevicesyslog ideviceimagemounter idevicescreenshot ideviceenterrecovery idevicedate | 6 | bin_PROGRAMS = idevice_id ideviceinfo idevicepair idevicesyslog ideviceimagemounter idevicescreenshot ideviceenterrecovery idevicedate idevicebackup idevicebackup2 |
| 7 | |||
| 8 | if HAVE_GLIB2 | ||
| 9 | bin_PROGRAMS += idevicebackup idevicebackup2 | ||
| 10 | endif | ||
| 11 | 7 | ||
| 12 | ideviceinfo_SOURCES = ideviceinfo.c | 8 | ideviceinfo_SOURCES = ideviceinfo.c |
| 13 | ideviceinfo_CFLAGS = $(AM_CFLAGS) | 9 | ideviceinfo_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 | ||
| 224 | static 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 | |||
| 234 | char* 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 | |||
| 261 | static 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 | |||
| 225 | static plist_t mobilebackup_factory_info_plist_new() | 278 | static 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 | ||
| 286 | static void mobilebackup_info_update_last_backup_date(plist_t info_plist) | 337 | static 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 | ||
| 399 | static gchar *mobilebackup_build_path(const char *backup_directory, const char *name, const char *extension) | 448 | static 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 | ||
| 425 | static int mobilebackup_read_status(const char *path) | 476 | static 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) | |||
| 510 | static int mobilebackup_delete_backup_file_by_hash(const char *backup_directory, const char *hash) | 561 | static 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> |
| 33 | typedef 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 | ||
| 157 | static 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 | |||
| 167 | static 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 | |||
| 176 | int 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 | |||
| 199 | char* 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 | |||
| 226 | static 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 | |||
| 159 | static plist_t mobilebackup_factory_info_plist_new() | 243 | static 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 | ||
| 487 | static void print_progress(uint64_t current, uint64_t total) | 571 | static 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: | |||
| 664 | leave_proto_err: | 748 | leave_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 | ||
| 975 | static void mb2_copy_file_by_path(const gchar *src, const gchar *dst) | 1059 | static 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 | ||
| 1007 | static void mb2_copy_directory_by_path(const gchar *src, const gchar *dst) | 1091 | static 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()); |
