summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile.am12
-rw-r--r--tools/afcclient.c214
-rw-r--r--tools/idevicebackup.c19
-rw-r--r--tools/idevicebackup2.c94
-rw-r--r--tools/idevicebtlogger.c4
-rw-r--r--tools/idevicecrashreport.c144
-rw-r--r--tools/idevicedate.c6
-rw-r--r--tools/idevicedebug.c4
-rw-r--r--tools/idevicedebugserverproxy.c4
-rw-r--r--tools/idevicedevmodectl.c6
-rw-r--r--tools/idevicediagnostics.c4
-rw-r--r--tools/ideviceenterrecovery.c4
-rw-r--r--tools/ideviceimagemounter.c45
-rw-r--r--tools/ideviceinfo.c4
-rw-r--r--tools/idevicename.c4
-rw-r--r--tools/idevicenotificationproxy.c26
-rw-r--r--tools/idevicepair.c6
-rw-r--r--tools/ideviceprovision.c33
-rw-r--r--tools/idevicescreenshot.c4
-rw-r--r--tools/idevicesetlocation.c30
-rw-r--r--tools/idevicesyslog.c688
21 files changed, 938 insertions, 417 deletions
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 7c9060b..24cfc66 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -35,7 +35,7 @@ bin_PROGRAMS = \
35 afcclient 35 afcclient
36 36
37idevicebtlogger_SOURCES = idevicebtlogger.c 37idevicebtlogger_SOURCES = idevicebtlogger.c
38iidevicebtlogger_CFLAGS = $(AM_CFLAGS) 38idevicebtlogger_CFLAGS = $(AM_CFLAGS)
39idevicebtlogger_LDFLAGS = $(top_builddir)/common/libinternalcommon.la $(AM_LDFLAGS) 39idevicebtlogger_LDFLAGS = $(top_builddir)/common/libinternalcommon.la $(AM_LDFLAGS)
40idevicebtlogger_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la 40idevicebtlogger_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la
41 41
@@ -51,8 +51,8 @@ idevicename_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la
51 51
52idevicepair_SOURCES = idevicepair.c 52idevicepair_SOURCES = idevicepair.c
53idevicepair_CFLAGS = $(AM_CFLAGS) 53idevicepair_CFLAGS = $(AM_CFLAGS)
54idevicepair_LDFLAGS = $(AM_LDFLAGS) $(libusbmuxd_LIBS) $(ssl_lib_LIBS) 54idevicepair_LDFLAGS = $(AM_LDFLAGS) $(libusbmuxd_LIBS)
55idevicepair_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la $(top_builddir)/common/libinternalcommon.la $(limd_glue_LIBS) 55idevicepair_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la $(top_builddir)/common/libinternalcommon.la $(limd_glue_LIBS) $(ssl_lib_LIBS)
56 56
57idevicesyslog_SOURCES = idevicesyslog.c 57idevicesyslog_SOURCES = idevicesyslog.c
58idevicesyslog_CFLAGS = $(AM_CFLAGS) $(limd_glue_CFLAGS) 58idevicesyslog_CFLAGS = $(AM_CFLAGS) $(limd_glue_CFLAGS)
@@ -76,7 +76,7 @@ idevicebackup2_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la
76 76
77ideviceimagemounter_SOURCES = ideviceimagemounter.c 77ideviceimagemounter_SOURCES = ideviceimagemounter.c
78ideviceimagemounter_CFLAGS = $(AM_CFLAGS) $(limd_glue_CFLAGS) $(libtatsu_CFLAGS) 78ideviceimagemounter_CFLAGS = $(AM_CFLAGS) $(limd_glue_CFLAGS) $(libtatsu_CFLAGS)
79ideviceimagemounter_LDFLAGS = $(AM_LDFLAGS) $(limd_glue_LIBS) $(ssl_lib_LIBS) $(libtatsu_LIBS) 79ideviceimagemounter_LDFLAGS = $(AM_LDFLAGS) $(limd_glue_LIBS) $(libtatsu_LIBS)
80ideviceimagemounter_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la 80ideviceimagemounter_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la
81 81
82idevicescreenshot_SOURCES = idevicescreenshot.c 82idevicescreenshot_SOURCES = idevicescreenshot.c
@@ -135,8 +135,8 @@ idevicesetlocation_LDFLAGS = $(AM_LDFLAGS)
135idevicesetlocation_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la 135idevicesetlocation_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la
136 136
137afcclient_SOURCES = afcclient.c 137afcclient_SOURCES = afcclient.c
138afcclient_CFLAGS = $(AM_CFLAGS) 138afcclient_CFLAGS = $(AM_CFLAGS) $(limd_glue_CFLAGS)
139afcclient_LDFLAGS = $(AM_LDFLAGS) 139afcclient_LDFLAGS = $(AM_LDFLAGS) $(limd_glue_LIBS)
140if HAVE_READLINE 140if HAVE_READLINE
141 afcclient_CFLAGS += $(readline_CFLAGS) 141 afcclient_CFLAGS += $(readline_CFLAGS)
142 afcclient_LDFLAGS += $(readline_LIBS) 142 afcclient_LDFLAGS += $(readline_LIBS)
diff --git a/tools/afcclient.c b/tools/afcclient.c
index 8f49831..2667e52 100644
--- a/tools/afcclient.c
+++ b/tools/afcclient.c
@@ -38,8 +38,9 @@
38#include <unistd.h> 38#include <unistd.h>
39#include <dirent.h> 39#include <dirent.h>
40#include <time.h> 40#include <time.h>
41#include <sys/stat.h>
41 42
42#ifdef WIN32 43#ifdef _WIN32
43#include <windows.h> 44#include <windows.h>
44#include <sys/time.h> 45#include <sys/time.h>
45#include <conio.h> 46#include <conio.h>
@@ -95,7 +96,7 @@ static size_t curdir_len = 0;
95static int file_exists(const char* path) 96static int file_exists(const char* path)
96{ 97{
97 struct stat tst; 98 struct stat tst;
98#ifdef WIN32 99#ifdef _WIN32
99 return (stat(path, &tst) == 0); 100 return (stat(path, &tst) == 0);
100#else 101#else
101 return (lstat(path, &tst) == 0); 102 return (lstat(path, &tst) == 0);
@@ -105,7 +106,7 @@ static int file_exists(const char* path)
105static int is_directory(const char* path) 106static int is_directory(const char* path)
106{ 107{
107 struct stat tst; 108 struct stat tst;
108#ifdef WIN32 109#ifdef _WIN32
109 return (stat(path, &tst) == 0) && S_ISDIR(tst.st_mode); 110 return (stat(path, &tst) == 0) && S_ISDIR(tst.st_mode);
110#else 111#else
111 return (lstat(path, &tst) == 0) && S_ISDIR(tst.st_mode); 112 return (lstat(path, &tst) == 0) && S_ISDIR(tst.st_mode);
@@ -138,8 +139,9 @@ static void print_usage(int argc, char **argv, int is_error)
138} 139}
139 140
140#ifndef HAVE_READLINE 141#ifndef HAVE_READLINE
141#ifdef WIN32 142#ifdef _WIN32
142#define BS_CC '\b' 143#define BS_CC '\b'
144#define getch _getch
143#else 145#else
144#define BS_CC 0x7f 146#define BS_CC 0x7f
145#define getch getchar 147#define getch getchar
@@ -154,12 +156,18 @@ static void get_input(char *buf, int maxlen)
154 break; 156 break;
155 } 157 }
156 if (isprint(c)) { 158 if (isprint(c)) {
157 if (len < maxlen-1) 159 if (len < maxlen-1) {
158 buf[len++] = c; 160 buf[len++] = c;
161#ifdef _WIN32
162 fputc(c, stdout);
163#endif
164 }
159 } else if (c == BS_CC) { 165 } else if (c == BS_CC) {
160 if (len > 0) { 166 if (len > 0) {
161 fputs("\b \b", stdout); 167 fputs("\b \b", stdout);
162 len--; 168 len--;
169 } else {
170 fputc(0x07, stdout);
163 } 171 }
164 } 172 }
165 } 173 }
@@ -175,7 +183,7 @@ int stop_requested = 0;
175static void handle_signal(int sig) 183static void handle_signal(int sig)
176{ 184{
177 stop_requested++; 185 stop_requested++;
178#ifdef WIN32 186#ifdef _WIN32
179 GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); 187 GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
180#else 188#else
181 kill(getpid(), SIGINT); 189 kill(getpid(), SIGINT);
@@ -364,62 +372,55 @@ static char* get_realpath(const char* path)
364 372
365static void handle_devinfo(afc_client_t afc, int argc, char** argv) 373static void handle_devinfo(afc_client_t afc, int argc, char** argv)
366{ 374{
367 char **info = NULL; 375 plist_t info = NULL;
368 afc_error_t err = afc_get_device_info(afc, &info); 376 afc_error_t err = afc_get_device_info_plist(afc, &info);
369 if (err == AFC_E_SUCCESS && info) { 377 if (err == AFC_E_SUCCESS && info) {
370 int i; 378 if (argc > 0 && !strcmp(argv[0], "--plain")) {
371 for (i = 0; info[i]; i += 2) { 379 plist_write_to_stream(info, stdout, PLIST_FORMAT_LIMD, PLIST_OPT_NONE);
372 printf("%s: %s\n", info[i], info[i+1]); 380 } else {
381 plist_write_to_stream(info, stdout, PLIST_FORMAT_JSON, PLIST_OPT_NONE);
373 } 382 }
374 } else { 383 } else {
375 printf("Error: Failed to get device info: %s (%d)\n", afc_strerror(err), err); 384 printf("Error: Failed to get device info: %s (%d)\n", afc_strerror(err), err);
376 } 385 }
377 afc_dictionary_free(info); 386 plist_free(info);
378} 387}
379 388
380static int get_file_info_stat(afc_client_t afc, const char* path, struct afc_file_stat *stbuf) 389static int get_file_info_stat(afc_client_t afc, const char* path, struct afc_file_stat *stbuf)
381{ 390{
382 char **info = NULL; 391 plist_t info = NULL;
383 afc_error_t ret = afc_get_file_info(afc, path, &info); 392 afc_error_t ret = afc_get_file_info_plist(afc, path, &info);
384 memset(stbuf, 0, sizeof(struct afc_file_stat)); 393 memset(stbuf, 0, sizeof(struct afc_file_stat));
385 if (ret != AFC_E_SUCCESS) { 394 if (ret != AFC_E_SUCCESS) {
386 return -1; 395 return -1;
387 } else if (!info) { 396 } else if (!info) {
388 return -1; 397 return -1;
389 } else {
390 // get file attributes from info list
391 int i;
392 for (i = 0; info[i]; i += 2) {
393 if (!strcmp(info[i], "st_size")) {
394 stbuf->st_size = atoll(info[i+1]);
395 } else if (!strcmp(info[i], "st_blocks")) {
396 stbuf->st_blocks = atoi(info[i+1]);
397 } else if (!strcmp(info[i], "st_ifmt")) {
398 if (!strcmp(info[i+1], "S_IFREG")) {
399 stbuf->st_mode = S_IFREG;
400 } else if (!strcmp(info[i+1], "S_IFDIR")) {
401 stbuf->st_mode = S_IFDIR;
402 } else if (!strcmp(info[i+1], "S_IFLNK")) {
403 stbuf->st_mode = S_IFLNK;
404 } else if (!strcmp(info[i+1], "S_IFBLK")) {
405 stbuf->st_mode = S_IFBLK;
406 } else if (!strcmp(info[i+1], "S_IFCHR")) {
407 stbuf->st_mode = S_IFCHR;
408 } else if (!strcmp(info[i+1], "S_IFIFO")) {
409 stbuf->st_mode = S_IFIFO;
410 } else if (!strcmp(info[i+1], "S_IFSOCK")) {
411 stbuf->st_mode = S_IFSOCK;
412 }
413 } else if (!strcmp(info[i], "st_nlink")) {
414 stbuf->st_nlink = atoi(info[i+1]);
415 } else if (!strcmp(info[i], "st_mtime")) {
416 stbuf->st_mtime = (time_t)(atoll(info[i+1]) / 1000000000);
417 } else if (!strcmp(info[i], "st_birthtime")) { /* available on iOS 7+ */
418 stbuf->st_birthtime = (time_t)(atoll(info[i+1]) / 1000000000);
419 }
420 }
421 afc_dictionary_free(info);
422 } 398 }
399 stbuf->st_size = plist_dict_get_uint(info, "st_size");
400 stbuf->st_blocks = plist_dict_get_uint(info, "st_blocks");
401 const char* s_ifmt = plist_get_string_ptr(plist_dict_get_item(info, "st_ifmt"), NULL);
402 if (s_ifmt) {
403 if (!strcmp(s_ifmt, "S_IFREG")) {
404 stbuf->st_mode = S_IFREG;
405 } else if (!strcmp(s_ifmt, "S_IFDIR")) {
406 stbuf->st_mode = S_IFDIR;
407 } else if (!strcmp(s_ifmt, "S_IFLNK")) {
408 stbuf->st_mode = S_IFLNK;
409 } else if (!strcmp(s_ifmt, "S_IFBLK")) {
410 stbuf->st_mode = S_IFBLK;
411 } else if (!strcmp(s_ifmt, "S_IFCHR")) {
412 stbuf->st_mode = S_IFCHR;
413 } else if (!strcmp(s_ifmt, "S_IFIFO")) {
414 stbuf->st_mode = S_IFIFO;
415 } else if (!strcmp(s_ifmt, "S_IFSOCK")) {
416 stbuf->st_mode = S_IFSOCK;
417 }
418 }
419 stbuf->st_nlink = plist_dict_get_uint(info, "st_nlink");
420 stbuf->st_mtime = (time_t)(plist_dict_get_uint(info, "st_mtime") / 1000000000);
421 /* available on iOS 7+ */
422 stbuf->st_birthtime = (time_t)(plist_dict_get_uint(info, "st_birthtime") / 1000000000);
423 plist_free(info);
423 return 0; 424 return 0;
424} 425}
425 426
@@ -430,22 +431,23 @@ static void handle_file_info(afc_client_t afc, int argc, char** argv)
430 return; 431 return;
431 } 432 }
432 433
433 char **info = NULL; 434 plist_t info = NULL;
434 char* abspath = get_absolute_path(argv[0]); 435 char* abspath = get_absolute_path(argv[0]);
435 if (!abspath) { 436 if (!abspath) {
436 printf("Error: Invalid argument\n"); 437 printf("Error: Invalid argument\n");
437 return; 438 return;
438 } 439 }
439 afc_error_t err = afc_get_file_info(afc, abspath, &info); 440 afc_error_t err = afc_get_file_info_plist(afc, abspath, &info);
440 if (err == AFC_E_SUCCESS && info) { 441 if (err == AFC_E_SUCCESS && info) {
441 int i; 442 if (argc > 1 && !strcmp(argv[1], "--plain")) {
442 for (i = 0; info[i]; i += 2) { 443 plist_write_to_stream(info, stdout, PLIST_FORMAT_LIMD, PLIST_OPT_NONE);
443 printf("%s: %s\n", info[i], info[i+1]); 444 } else {
445 plist_write_to_stream(info, stdout, PLIST_FORMAT_JSON, PLIST_OPT_NONE);
444 } 446 }
445 } else { 447 } else {
446 printf("Error: Failed to get file info for %s: %s (%d)\n", argv[0], afc_strerror(err), err); 448 printf("Error: Failed to get file info for %s: %s (%d)\n", argv[0], afc_strerror(err), err);
447 } 449 }
448 afc_dictionary_free(info); 450 plist_free(info);
449 free(abspath); 451 free(abspath);
450} 452}
451 453
@@ -483,7 +485,7 @@ static void print_file_info(afc_client_t afc, const char* path, int list_verbose
483 printf(" "); 485 printf(" ");
484 printf("%10lld", (long long)st.st_size); 486 printf("%10lld", (long long)st.st_size);
485 printf(" "); 487 printf(" ");
486#ifdef WIN32 488#ifdef _WIN32
487 strftime(timebuf, 64, "%d %b %Y %H:%M:%S", localtime(&t)); 489 strftime(timebuf, 64, "%d %b %Y %H:%M:%S", localtime(&t));
488#else 490#else
489 strftime(timebuf, 64, "%d %h %Y %H:%M:%S", localtime(&t)); 491 strftime(timebuf, 64, "%d %h %Y %H:%M:%S", localtime(&t));
@@ -774,7 +776,7 @@ static uint8_t get_single_file(afc_client_t afc, const char *srcpath, const char
774 776
775static int __mkdir(const char* path) 777static int __mkdir(const char* path)
776{ 778{
777#ifdef WIN32 779#ifdef _WIN32
778 return mkdir(path); 780 return mkdir(path);
779#else 781#else
780 return mkdir(path, 0755); 782 return mkdir(path, 0755);
@@ -783,28 +785,19 @@ static int __mkdir(const char* path)
783 785
784static uint8_t get_file(afc_client_t afc, const char *srcpath, const char *dstpath, uint8_t force_overwrite, uint8_t recursive_get) 786static uint8_t get_file(afc_client_t afc, const char *srcpath, const char *dstpath, uint8_t force_overwrite, uint8_t recursive_get)
785{ 787{
786 char **info = NULL; 788 plist_t info = NULL;
787 uint64_t file_size = 0; 789 uint64_t file_size = 0;
788 afc_error_t err = afc_get_file_info(afc, srcpath, &info); 790 afc_error_t err = afc_get_file_info_plist(afc, srcpath, &info);
789 if (err == AFC_E_OBJECT_NOT_FOUND) { 791 if (err == AFC_E_OBJECT_NOT_FOUND) {
790 printf("Error: Failed to read from file '%s': %s (%d)\n", srcpath, afc_strerror(err), err); 792 printf("Error: Failed to read from file '%s': %s (%d)\n", srcpath, afc_strerror(err), err);
791 return 0; 793 return 0;
792 } 794 }
793 uint8_t is_dir = 0; 795 uint8_t is_dir = 0;
794 if (info) { 796 if (info) {
795 char **p = info; 797 file_size = plist_dict_get_uint(info, "st_size");
796 while (p && *p) { 798 const char* ifmt = plist_get_string_ptr(plist_dict_get_item(info, "st_ifmt"), NULL);
797 if (!strcmp(*p, "st_size")) { 799 is_dir = (ifmt && !strcmp(ifmt, "S_IFDIR"));
798 p++; 800 plist_free(info);
799 file_size = (uint64_t) strtoull(*p, NULL, 10);
800 }
801 if (!strcmp(*p, "st_ifmt")) {
802 p++;
803 is_dir = !strcmp(*p, "S_IFDIR");
804 }
805 p++;
806 }
807 afc_dictionary_free(info);
808 } 801 }
809 uint8_t succeed = 1; 802 uint8_t succeed = 1;
810 if (is_dir) { 803 if (is_dir) {
@@ -837,7 +830,7 @@ static uint8_t get_file(afc_client_t afc, const char *srcpath, const char *dstpa
837 p++; 830 p++;
838 continue; 831 continue;
839 } 832 }
840 size_t len = srcpath_is_root ? strlen(*p) + 1 : srcpath_len + 1 + strlen(*p) + 1; 833 size_t len = srcpath_is_root ? (strlen(*p) + 2) : (srcpath_len + 1 + strlen(*p) + 1);
841 char *testpath = (char *) malloc(len); 834 char *testpath = (char *) malloc(len);
842 if (srcpath_is_root) { 835 if (srcpath_is_root) {
843 snprintf(testpath, len, "/%s", *p); 836 snprintf(testpath, len, "/%s", *p);
@@ -845,7 +838,7 @@ static uint8_t get_file(afc_client_t afc, const char *srcpath, const char *dstpa
845 snprintf(testpath, len, "%s/%s", srcpath, *p); 838 snprintf(testpath, len, "%s/%s", srcpath, *p);
846 } 839 }
847 uint8_t dst_is_root = strcmp(srcpath, "/") == 0; 840 uint8_t dst_is_root = strcmp(srcpath, "/") == 0;
848 size_t dst_len = dst_is_root ? strlen(*p) + 1 : strlen(dstpath) + 1 + strlen(*p) + 1; 841 size_t dst_len = dst_is_root ? (strlen(*p) + 2) : (strlen(dstpath) + 1 + strlen(*p) + 1);
849 char *newdst = (char *) malloc(dst_len); 842 char *newdst = (char *) malloc(dst_len);
850 if (dst_is_root) { 843 if (dst_is_root) {
851 snprintf(newdst, dst_len, "/%s", *p); 844 snprintf(newdst, dst_len, "/%s", *p);
@@ -921,9 +914,9 @@ static void handle_get(afc_client_t afc, int argc, char **argv)
921 914
922 // target is a directory, put file under this target 915 // target is a directory, put file under this target
923 if (is_directory(dstpath)) { 916 if (is_directory(dstpath)) {
924 const char *basen = path_get_basename(argv[0]); 917 const char *basen = path_get_basename(srcpath);
925 uint8_t dst_is_root = strcmp(dstpath, "/") == 0; 918 uint8_t dst_is_root = strcmp(dstpath, "/") == 0;
926 size_t len = dst_is_root ? (strlen(basen) + 1) : (strlen(dstpath) + 1 + strlen(basen) + 1); 919 size_t len = dst_is_root ? (strlen(basen) + 2) : (strlen(dstpath) + 1 + strlen(basen) + 1);
927 char *newdst = (char *) malloc(len); 920 char *newdst = (char *) malloc(len);
928 if (dst_is_root) { 921 if (dst_is_root) {
929 snprintf(newdst, len, "/%s", basen); 922 snprintf(newdst, len, "/%s", basen);
@@ -944,11 +937,11 @@ static void handle_get(afc_client_t afc, int argc, char **argv)
944 937
945static uint8_t put_single_file(afc_client_t afc, const char *srcpath, const char *dstpath, uint8_t force_overwrite) 938static uint8_t put_single_file(afc_client_t afc, const char *srcpath, const char *dstpath, uint8_t force_overwrite)
946{ 939{
947 char **info = NULL; 940 plist_t info = NULL;
948 afc_error_t ret = afc_get_file_info(afc, dstpath, &info); 941 afc_error_t ret = afc_get_file_info_plist(afc, dstpath, &info);
949 // file exists, only overwrite with '-f' option was set 942 // file exists, only overwrite with '-f' option was set
950 if (ret == AFC_E_SUCCESS && info) { 943 if (ret == AFC_E_SUCCESS && info) {
951 afc_dictionary_free(info); 944 plist_free(info);
952 if (!force_overwrite) { 945 if (!force_overwrite) {
953 printf("Error: Failed to write into existing file without '-f' option: %s\n", dstpath); 946 printf("Error: Failed to write into existing file without '-f' option: %s\n", dstpath);
954 return 0; 947 return 0;
@@ -1016,6 +1009,9 @@ static uint8_t put_single_file(afc_client_t afc, const char *srcpath, const char
1016 } 1009 }
1017 } 1010 }
1018 } 1011 }
1012 if (progress) {
1013 printf("\n");
1014 }
1019 free(buf); 1015 free(buf);
1020 afc_file_close(afc, fh); 1016 afc_file_close(afc, fh);
1021 fclose(f); 1017 fclose(f);
@@ -1029,10 +1025,11 @@ static uint8_t put_file(afc_client_t afc, const char *srcpath, const char *dstpa
1029 printf("Error: Failed to put directory without '-r' option: %s\n", srcpath); 1025 printf("Error: Failed to put directory without '-r' option: %s\n", srcpath);
1030 return 0; 1026 return 0;
1031 } 1027 }
1032 char **info = NULL; 1028 plist_t info = NULL;
1033 afc_error_t err = afc_get_file_info(afc, dstpath, &info); 1029 afc_error_t err = afc_get_file_info_plist(afc, dstpath, &info);
1034 //create if target directory does not exist 1030 //create if target directory does not exist
1035 afc_dictionary_free(info); 1031 plist_free(info);
1032 info = NULL;
1036 if (err == AFC_E_OBJECT_NOT_FOUND) { 1033 if (err == AFC_E_OBJECT_NOT_FOUND) {
1037 err = afc_make_directory(afc, dstpath); 1034 err = afc_make_directory(afc, dstpath);
1038 if (err != AFC_E_SUCCESS) { 1035 if (err != AFC_E_SUCCESS) {
@@ -1043,19 +1040,12 @@ static uint8_t put_file(afc_client_t afc, const char *srcpath, const char *dstpa
1043 printf("Error: Failed to put existing directory without '-f' option: %s\n", dstpath); 1040 printf("Error: Failed to put existing directory without '-f' option: %s\n", dstpath);
1044 return 0; 1041 return 0;
1045 } 1042 }
1046 afc_get_file_info(afc, dstpath, &info); 1043 afc_get_file_info_plist(afc, dstpath, &info);
1047 uint8_t is_dir = 0; 1044 uint8_t is_dir = 0;
1048 if (info) { 1045 if (info) {
1049 char **p = info; 1046 const char* ifmt = plist_get_string_ptr(plist_dict_get_item(info, "st_ifmt"), NULL);
1050 while (p && *p) { 1047 is_dir = (ifmt && !strcmp(ifmt, "S_IFDIR"));
1051 if (!strcmp(*p, "st_ifmt")) { 1048 plist_free(info);
1052 p++;
1053 is_dir = !strcmp(*p, "S_IFDIR");
1054 break;
1055 }
1056 p++;
1057 }
1058 afc_dictionary_free(info);
1059 } 1049 }
1060 if (!is_dir) { 1050 if (!is_dir) {
1061 printf("Error: Failed to create or access directory: '%s'\n", dstpath); 1051 printf("Error: Failed to create or access directory: '%s'\n", dstpath);
@@ -1073,7 +1063,7 @@ static uint8_t put_file(afc_client_t afc, const char *srcpath, const char *dstpa
1073 char *fpath = string_build_path(srcpath, ep->d_name, NULL); 1063 char *fpath = string_build_path(srcpath, ep->d_name, NULL);
1074 if (fpath) { 1064 if (fpath) {
1075 uint8_t dst_is_root = strcmp(dstpath, "/") == 0; 1065 uint8_t dst_is_root = strcmp(dstpath, "/") == 0;
1076 size_t len = dst_is_root ? strlen(ep->d_name) + 1 : strlen(dstpath) + 1 + strlen(ep->d_name) + 1; 1066 size_t len = dst_is_root ? (strlen(ep->d_name) + 2) : (strlen(dstpath) + 1 + strlen(ep->d_name) + 1);
1077 char *newdst = (char *) malloc(len); 1067 char *newdst = (char *) malloc(len);
1078 if (dst_is_root) { 1068 if (dst_is_root) {
1079 snprintf(newdst, len, "/%s", ep->d_name); 1069 snprintf(newdst, len, "/%s", ep->d_name);
@@ -1147,8 +1137,8 @@ static void handle_put(afc_client_t afc, int argc, char **argv)
1147 printf("Error: Invalid number of arguments\n"); 1137 printf("Error: Invalid number of arguments\n");
1148 return; 1138 return;
1149 } 1139 }
1150 char **info = NULL; 1140 plist_t info = NULL;
1151 afc_error_t err = afc_get_file_info(afc, dstpath, &info); 1141 afc_error_t err = afc_get_file_info_plist(afc, dstpath, &info);
1152 // target does not exist, put directly 1142 // target does not exist, put directly
1153 if (err == AFC_E_OBJECT_NOT_FOUND) { 1143 if (err == AFC_E_OBJECT_NOT_FOUND) {
1154 put_file(afc, srcpath, dstpath, force_overwrite, recursive_put); 1144 put_file(afc, srcpath, dstpath, force_overwrite, recursive_put);
@@ -1157,22 +1147,15 @@ static void handle_put(afc_client_t afc, int argc, char **argv)
1157 } else { 1147 } else {
1158 uint8_t is_dir = 0; 1148 uint8_t is_dir = 0;
1159 if (info) { 1149 if (info) {
1160 char **p = info; 1150 const char* ifmt = plist_get_string_ptr(plist_dict_get_item(info, "st_ifmt"), NULL);
1161 while (p && *p) { 1151 is_dir = (ifmt && !strcmp(ifmt, "S_IFDIR"));
1162 if (!strcmp(*p, "st_ifmt")) { 1152 plist_free(info);
1163 p++;
1164 is_dir = !strcmp(*p, "S_IFDIR");
1165 break;
1166 }
1167 p++;
1168 }
1169 afc_dictionary_free(info);
1170 } 1153 }
1171 // target is a directory, try to put under this directory 1154 // target is a directory, try to put under this directory
1172 if (is_dir) { 1155 if (is_dir) {
1173 const char *basen = path_get_basename(srcpath); 1156 const char *basen = path_get_basename(srcpath);
1174 uint8_t dst_is_root = strcmp(dstpath, "/") == 0; 1157 uint8_t dst_is_root = strcmp(dstpath, "/") == 0;
1175 size_t len = dst_is_root ? strlen(basen) + 1 : strlen(dstpath) + 1 + strlen(basen) + 1; 1158 size_t len = dst_is_root ? (strlen(basen) + 2) : (strlen(dstpath) + 1 + strlen(basen) + 1);
1176 char *newdst = (char *) malloc(len); 1159 char *newdst = (char *) malloc(len);
1177 if (dst_is_root) { 1160 if (dst_is_root) {
1178 snprintf(newdst, len, "/%s", basen); 1161 snprintf(newdst, len, "/%s", basen);
@@ -1227,19 +1210,12 @@ static void handle_cd(afc_client_t afc, int argc, char** argv)
1227 1210
1228 char* path = get_realpath(argv[0]); 1211 char* path = get_realpath(argv[0]);
1229 int is_dir = 0; 1212 int is_dir = 0;
1230 char **info = NULL; 1213 plist_t info = NULL;
1231 afc_error_t err = afc_get_file_info(afc, path, &info); 1214 afc_error_t err = afc_get_file_info_plist(afc, path, &info);
1232 if (err == AFC_E_SUCCESS && info) { 1215 if (err == AFC_E_SUCCESS && info) {
1233 int i; 1216 const char* ifmt = plist_get_string_ptr(plist_dict_get_item(info, "st_ifmt"), NULL);
1234 for (i = 0; info[i]; i += 2) { 1217 is_dir = (ifmt && !strcmp(ifmt, "S_IFDIR"));
1235 if (!strcmp(info[i], "st_ifmt")) { 1218 plist_free(info);
1236 if (!strcmp(info[i+1], "S_IFDIR")) {
1237 is_dir = 1;
1238 }
1239 break;
1240 }
1241 }
1242 afc_dictionary_free(info);
1243 } else { 1219 } else {
1244 printf("Error: Failed to get file info for %s: %s (%d)\n", path, afc_strerror(err), err); 1220 printf("Error: Failed to get file info for %s: %s (%d)\n", path, afc_strerror(err), err);
1245 free(path); 1221 free(path);
@@ -1483,7 +1459,7 @@ int main(int argc, char** argv)
1483 }; 1459 };
1484 1460
1485 signal(SIGTERM, handle_signal); 1461 signal(SIGTERM, handle_signal);
1486#ifndef WIN32 1462#ifndef _WIN32
1487 signal(SIGQUIT, handle_signal); 1463 signal(SIGQUIT, handle_signal);
1488 signal(SIGPIPE, SIG_IGN); 1464 signal(SIGPIPE, SIG_IGN);
1489#endif 1465#endif
@@ -1561,7 +1537,7 @@ int main(int argc, char** argv)
1561 idevice_events_subscribe(&context, device_event_cb, NULL); 1537 idevice_events_subscribe(&context, device_event_cb, NULL);
1562 1538
1563 while (!connected && !stop_requested) { 1539 while (!connected && !stop_requested) {
1564#ifdef WIN32 1540#ifdef _WIN32
1565 Sleep(100); 1541 Sleep(100);
1566#else 1542#else
1567 usleep(100000); 1543 usleep(100000);
diff --git a/tools/idevicebackup.c b/tools/idevicebackup.c
index c0537b8..363abad 100644
--- a/tools/idevicebackup.c
+++ b/tools/idevicebackup.c
@@ -35,6 +35,7 @@
35#include <unistd.h> 35#include <unistd.h>
36#include <ctype.h> 36#include <ctype.h>
37#include <time.h> 37#include <time.h>
38#include <sys/stat.h>
38 39
39#include <libimobiledevice/libimobiledevice.h> 40#include <libimobiledevice/libimobiledevice.h>
40#include <libimobiledevice/lockdown.h> 41#include <libimobiledevice/lockdown.h>
@@ -51,7 +52,7 @@
51#define LOCK_ATTEMPTS 50 52#define LOCK_ATTEMPTS 50
52#define LOCK_WAIT 200000 53#define LOCK_WAIT 200000
53 54
54#ifdef WIN32 55#ifdef _WIN32
55#include <windows.h> 56#include <windows.h>
56#define sleep(x) Sleep(x*1000) 57#define sleep(x) Sleep(x*1000)
57#endif 58#endif
@@ -175,7 +176,13 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid)
175 if (value_node) 176 if (value_node)
176 plist_dict_set_item(ret, "IMEI", plist_copy(value_node)); 177 plist_dict_set_item(ret, "IMEI", plist_copy(value_node));
177 178
178 plist_dict_set_item(ret, "Last Backup Date", plist_new_date(time(NULL) - MAC_EPOCH, 0)); 179 plist_dict_set_item(ret, "Last Backup Date",
180#ifdef HAVE_PLIST_UNIX_DATE
181 plist_new_unix_date(time(NULL))
182#else
183 plist_new_date(time(NULL) - MAC_EPOCH, 0)
184#endif
185 );
179 186
180 value_node = plist_dict_get_item(root_node, "ProductType"); 187 value_node = plist_dict_get_item(root_node, "ProductType");
181 plist_dict_set_item(ret, "Product Type", plist_copy(value_node)); 188 plist_dict_set_item(ret, "Product Type", plist_copy(value_node));
@@ -212,7 +219,11 @@ static void mobilebackup_info_update_last_backup_date(plist_t info_plist)
212 return; 219 return;
213 220
214 node = plist_dict_get_item(info_plist, "Last Backup Date"); 221 node = plist_dict_get_item(info_plist, "Last Backup Date");
222#ifdef HAVE_PLIST_UNIX_DATE
223 plist_set_unix_date_val(node, time(NULL));
224#else
215 plist_set_date_val(node, time(NULL) - MAC_EPOCH, 0); 225 plist_set_date_val(node, time(NULL) - MAC_EPOCH, 0);
226#endif
216 227
217 node = NULL; 228 node = NULL;
218} 229}
@@ -642,7 +653,7 @@ int main(int argc, char *argv[])
642 /* we need to exit cleanly on running backups and restores or we cause havok */ 653 /* we need to exit cleanly on running backups and restores or we cause havok */
643 signal(SIGINT, clean_exit); 654 signal(SIGINT, clean_exit);
644 signal(SIGTERM, clean_exit); 655 signal(SIGTERM, clean_exit);
645#ifndef WIN32 656#ifndef _WIN32
646 signal(SIGQUIT, clean_exit); 657 signal(SIGQUIT, clean_exit);
647 signal(SIGPIPE, SIG_IGN); 658 signal(SIGPIPE, SIG_IGN);
648#endif 659#endif
@@ -1352,7 +1363,7 @@ files_out:
1352 file_info_path = mobilebackup_build_path(backup_directory, hash, ".mddata"); 1363 file_info_path = mobilebackup_build_path(backup_directory, hash, ".mddata");
1353 1364
1354 /* determine file size */ 1365 /* determine file size */
1355#ifdef WIN32 1366#ifdef _WIN32
1356 struct _stati64 fst; 1367 struct _stati64 fst;
1357 if (_stati64(file_info_path, &fst) != 0) 1368 if (_stati64(file_info_path, &fst) != 0)
1358#else 1369#else
diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c
index c73b269..12d6083 100644
--- a/tools/idevicebackup2.c
+++ b/tools/idevicebackup2.c
@@ -54,7 +54,7 @@
54#define LOCK_ATTEMPTS 50 54#define LOCK_ATTEMPTS 50
55#define LOCK_WAIT 200000 55#define LOCK_WAIT 200000
56 56
57#ifdef WIN32 57#ifdef _WIN32
58#include <windows.h> 58#include <windows.h>
59#include <conio.h> 59#include <conio.h>
60#define sleep(x) Sleep(x*1000) 60#define sleep(x) Sleep(x*1000)
@@ -74,6 +74,7 @@
74 74
75static int verbose = 1; 75static int verbose = 1;
76static int quit_flag = 0; 76static int quit_flag = 0;
77static int passcode_requested = 0;
77 78
78#define PRINT_VERBOSE(min_level, ...) if (verbose >= min_level) { printf(__VA_ARGS__); }; 79#define PRINT_VERBOSE(min_level, ...) if (verbose >= min_level) { printf(__VA_ARGS__); };
79 80
@@ -115,6 +116,10 @@ static void notify_cb(const char *notification, void *userdata)
115 quit_flag++; 116 quit_flag++;
116 } else if (!strcmp(notification, NP_BACKUP_DOMAIN_CHANGED)) { 117 } else if (!strcmp(notification, NP_BACKUP_DOMAIN_CHANGED)) {
117 backup_domain_changed = 1; 118 backup_domain_changed = 1;
119 } else if (!strcmp(notification, "com.apple.LocalAuthentication.ui.presented")) {
120 passcode_requested = 1;
121 } else if (!strcmp(notification, "com.apple.LocalAuthentication.ui.dismissed")) {
122 passcode_requested = 0;
118 } else { 123 } else {
119 PRINT_VERBOSE(1, "Unhandled notification '%s' (TODO: implement)\n", notification); 124 PRINT_VERBOSE(1, "Unhandled notification '%s' (TODO: implement)\n", notification);
120 } 125 }
@@ -126,21 +131,15 @@ static void mobilebackup_afc_get_file_contents(afc_client_t afc, const char *fil
126 return; 131 return;
127 } 132 }
128 133
129 char **fileinfo = NULL; 134 plist_t fileinfo = NULL;
130 uint32_t fsize = 0; 135 uint32_t fsize = 0;
131 136
132 afc_get_file_info(afc, filename, &fileinfo); 137 afc_get_file_info_plist(afc, filename, &fileinfo);
133 if (!fileinfo) { 138 if (!fileinfo) {
134 return; 139 return;
135 } 140 }
136 int i; 141 fsize = plist_dict_get_uint(fileinfo, "st_size");
137 for (i = 0; fileinfo[i]; i+=2) { 142 plist_free(fileinfo);
138 if (!strcmp(fileinfo[i], "st_size")) {
139 fsize = atol(fileinfo[i+1]);
140 break;
141 }
142 }
143 afc_dictionary_free(fileinfo);
144 143
145 if (fsize == 0) { 144 if (fsize == 0) {
146 return; 145 return;
@@ -173,7 +172,7 @@ static void mobilebackup_afc_get_file_contents(afc_client_t afc, const char *fil
173 172
174static int __mkdir(const char* path, int mode) 173static int __mkdir(const char* path, int mode)
175{ 174{
176#ifdef WIN32 175#ifdef _WIN32
177 return mkdir(path); 176 return mkdir(path);
178#else 177#else
179 return mkdir(path, mode); 178 return mkdir(path, mode);
@@ -202,7 +201,7 @@ static int mkdir_with_parents(const char *dir, int mode)
202 return res; 201 return res;
203} 202}
204 203
205#ifdef WIN32 204#ifdef _WIN32
206static int win32err_to_errno(int err_value) 205static int win32err_to_errno(int err_value)
207{ 206{
208 switch (err_value) { 207 switch (err_value) {
@@ -219,7 +218,7 @@ static int win32err_to_errno(int err_value)
219static int remove_file(const char* path) 218static int remove_file(const char* path)
220{ 219{
221 int e = 0; 220 int e = 0;
222#ifdef WIN32 221#ifdef _WIN32
223 if (!DeleteFile(path)) { 222 if (!DeleteFile(path)) {
224 e = win32err_to_errno(GetLastError()); 223 e = win32err_to_errno(GetLastError());
225 } 224 }
@@ -234,7 +233,7 @@ static int remove_file(const char* path)
234static int remove_directory(const char* path) 233static int remove_directory(const char* path)
235{ 234{
236 int e = 0; 235 int e = 0;
237#ifdef WIN32 236#ifdef _WIN32
238 if (!RemoveDirectory(path)) { 237 if (!RemoveDirectory(path)) {
239 e = win32err_to_errno(GetLastError()); 238 e = win32err_to_errno(GetLastError());
240 } 239 }
@@ -455,7 +454,13 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid, idevice_t d
455 /* Installed Applications */ 454 /* Installed Applications */
456 plist_dict_set_item(ret, "Installed Applications", installed_apps); 455 plist_dict_set_item(ret, "Installed Applications", installed_apps);
457 456
458 plist_dict_set_item(ret, "Last Backup Date", plist_new_date(time(NULL) - MAC_EPOCH, 0)); 457 plist_dict_set_item(ret, "Last Backup Date",
458#ifdef HAVE_PLIST_UNIX_DATE
459 plist_new_unix_date(time(NULL))
460#else
461 plist_new_date(time(NULL) - MAC_EPOCH, 0)
462#endif
463 );
459 464
460 value_node = plist_dict_get_item(root_node, "MobileEquipmentIdentifier"); 465 value_node = plist_dict_get_item(root_node, "MobileEquipmentIdentifier");
461 if (value_node) 466 if (value_node)
@@ -768,7 +773,7 @@ static int mb2_handle_send_file(mobilebackup2_client_t mobilebackup2, const char
768 uint32_t bytes = 0; 773 uint32_t bytes = 0;
769 char *localfile = string_build_path(backup_dir, path, NULL); 774 char *localfile = string_build_path(backup_dir, path, NULL);
770 char buf[32768]; 775 char buf[32768];
771#ifdef WIN32 776#ifdef _WIN32
772 struct _stati64 fst; 777 struct _stati64 fst;
773#else 778#else
774 struct stat fst; 779 struct stat fst;
@@ -779,7 +784,7 @@ static int mb2_handle_send_file(mobilebackup2_client_t mobilebackup2, const char
779 int errcode = -1; 784 int errcode = -1;
780 int result = -1; 785 int result = -1;
781 uint32_t length; 786 uint32_t length;
782#ifdef WIN32 787#ifdef _WIN32
783 uint64_t total; 788 uint64_t total;
784 uint64_t sent; 789 uint64_t sent;
785#else 790#else
@@ -810,7 +815,7 @@ static int mb2_handle_send_file(mobilebackup2_client_t mobilebackup2, const char
810 goto leave_proto_err; 815 goto leave_proto_err;
811 } 816 }
812 817
813#ifdef WIN32 818#ifdef _WIN32
814 if (_stati64(localfile, &fst) < 0) 819 if (_stati64(localfile, &fst) < 0)
815#else 820#else
816 if (stat(localfile, &fst) < 0) 821 if (stat(localfile, &fst) < 0)
@@ -1218,7 +1223,12 @@ static void mb2_handle_list_directory(mobilebackup2_client_t mobilebackup2, plis
1218 plist_dict_set_item(fdict, "DLFileType", plist_new_string(ftype)); 1223 plist_dict_set_item(fdict, "DLFileType", plist_new_string(ftype));
1219 plist_dict_set_item(fdict, "DLFileSize", plist_new_uint(st.st_size)); 1224 plist_dict_set_item(fdict, "DLFileSize", plist_new_uint(st.st_size));
1220 plist_dict_set_item(fdict, "DLFileModificationDate", 1225 plist_dict_set_item(fdict, "DLFileModificationDate",
1221 plist_new_date(st.st_mtime - MAC_EPOCH, 0)); 1226#ifdef HAVE_PLIST_UNIX_DATE
1227 plist_new_unix_date(st.st_mtime)
1228#else
1229 plist_new_date(st.st_mtime - MAC_EPOCH, 0)
1230#endif
1231 );
1222 1232
1223 plist_dict_set_item(dirlist, ep->d_name, fdict); 1233 plist_dict_set_item(dirlist, ep->d_name, fdict);
1224 free(fpath); 1234 free(fpath);
@@ -1343,7 +1353,7 @@ static void mb2_copy_directory_by_path(const char *src, const char *dst)
1343 } 1353 }
1344} 1354}
1345 1355
1346#ifdef WIN32 1356#ifdef _WIN32
1347#define BS_CC '\b' 1357#define BS_CC '\b'
1348#define my_getch getch 1358#define my_getch getch
1349#else 1359#else
@@ -1463,8 +1473,6 @@ static void print_usage(int argc, char **argv, int is_error)
1463 ); 1473 );
1464} 1474}
1465 1475
1466#define DEVICE_VERSION(maj, min, patch) ((((maj) & 0xFF) << 16) | (((min) & 0xFF) << 8) | ((patch) & 0xFF))
1467
1468int main(int argc, char *argv[]) 1476int main(int argc, char *argv[])
1469{ 1477{
1470 idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; 1478 idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR;
@@ -1530,7 +1538,7 @@ int main(int argc, char *argv[])
1530 /* we need to exit cleanly on running backups and restores or we cause havok */ 1538 /* we need to exit cleanly on running backups and restores or we cause havok */
1531 signal(SIGINT, clean_exit); 1539 signal(SIGINT, clean_exit);
1532 signal(SIGTERM, clean_exit); 1540 signal(SIGTERM, clean_exit);
1533#ifndef WIN32 1541#ifndef _WIN32
1534 signal(SIGQUIT, clean_exit); 1542 signal(SIGQUIT, clean_exit);
1535 signal(SIGPIPE, SIG_IGN); 1543 signal(SIGPIPE, SIG_IGN);
1536#endif 1544#endif
@@ -1844,34 +1852,20 @@ int main(int argc, char *argv[])
1844 } 1852 }
1845 1853
1846 /* get ProductVersion */ 1854 /* get ProductVersion */
1847 char *product_version = NULL; 1855 int device_version = idevice_get_device_version(device);
1848 int device_version = 0;
1849 node_tmp = NULL;
1850 lockdownd_get_value(lockdown, NULL, "ProductVersion", &node_tmp);
1851 if (node_tmp) {
1852 if (plist_get_node_type(node_tmp) == PLIST_STRING) {
1853 plist_get_string_val(node_tmp, &product_version);
1854 }
1855 plist_free(node_tmp);
1856 node_tmp = NULL;
1857 }
1858 if (product_version) {
1859 int vers[3] = { 0, 0, 0 };
1860 if (sscanf(product_version, "%d.%d.%d", &vers[0], &vers[1], &vers[2]) >= 2) {
1861 device_version = DEVICE_VERSION(vers[0], vers[1], vers[2]);
1862 }
1863 }
1864 1856
1865 /* start notification_proxy */ 1857 /* start notification_proxy */
1866 ldret = lockdownd_start_service(lockdown, NP_SERVICE_NAME, &service); 1858 ldret = lockdownd_start_service(lockdown, NP_SERVICE_NAME, &service);
1867 if ((ldret == LOCKDOWN_E_SUCCESS) && service && service->port) { 1859 if ((ldret == LOCKDOWN_E_SUCCESS) && service && service->port) {
1868 np_client_new(device, service, &np); 1860 np_client_new(device, service, &np);
1869 np_set_notify_callback(np, notify_cb, NULL); 1861 np_set_notify_callback(np, notify_cb, NULL);
1870 const char *noties[5] = { 1862 const char *noties[7] = {
1871 NP_SYNC_CANCEL_REQUEST, 1863 NP_SYNC_CANCEL_REQUEST,
1872 NP_SYNC_SUSPEND_REQUEST, 1864 NP_SYNC_SUSPEND_REQUEST,
1873 NP_SYNC_RESUME_REQUEST, 1865 NP_SYNC_RESUME_REQUEST,
1874 NP_BACKUP_DOMAIN_CHANGED, 1866 NP_BACKUP_DOMAIN_CHANGED,
1867 "com.apple.LocalAuthentication.ui.presented",
1868 "com.apple.LocalAuthentication.ui.dismissed",
1875 NULL 1869 NULL
1876 }; 1870 };
1877 np_observe_notifications(np, noties); 1871 np_observe_notifications(np, noties);
@@ -2058,6 +2052,16 @@ checkpoint:
2058 } else { 2052 } else {
2059 PRINT_VERBOSE(1, "Incremental backup mode.\n"); 2053 PRINT_VERBOSE(1, "Incremental backup mode.\n");
2060 } 2054 }
2055 if (device_version >= IDEVICE_DEVICE_VERSION(16,1,0)) {
2056 /* let's wait 2 second to see if the device passcode is requested */
2057 int retries = 20;
2058 while (retries-- > 0 && !passcode_requested) {
2059 usleep(100000);
2060 }
2061 if (passcode_requested) {
2062 printf("*** Waiting for passcode to be entered on the device ***\n");
2063 }
2064 }
2061 } else { 2065 } else {
2062 if (err == MOBILEBACKUP2_E_BAD_VERSION) { 2066 if (err == MOBILEBACKUP2_E_BAD_VERSION) {
2063 printf("ERROR: Could not start backup process: backup protocol version mismatch!\n"); 2067 printf("ERROR: Could not start backup process: backup protocol version mismatch!\n");
@@ -2229,7 +2233,7 @@ checkpoint:
2229 if (newpw || backup_password) { 2233 if (newpw || backup_password) {
2230 mobilebackup2_send_message(mobilebackup2, "ChangePassword", opts); 2234 mobilebackup2_send_message(mobilebackup2, "ChangePassword", opts);
2231 uint8_t passcode_hint = 0; 2235 uint8_t passcode_hint = 0;
2232 if (device_version >= DEVICE_VERSION(13,0,0)) { 2236 if (device_version >= IDEVICE_DEVICE_VERSION(13,0,0)) {
2233 diagnostics_relay_client_t diag = NULL; 2237 diagnostics_relay_client_t diag = NULL;
2234 if (diagnostics_relay_client_start_service(device, &diag, TOOL_NAME) == DIAGNOSTICS_RELAY_E_SUCCESS) { 2238 if (diagnostics_relay_client_start_service(device, &diag, TOOL_NAME) == DIAGNOSTICS_RELAY_E_SUCCESS) {
2235 plist_t dict = NULL; 2239 plist_t dict = NULL;
@@ -2307,7 +2311,7 @@ checkpoint:
2307 /* device wants to know how much disk space is available on the computer */ 2311 /* device wants to know how much disk space is available on the computer */
2308 uint64_t freespace = 0; 2312 uint64_t freespace = 0;
2309 int res = -1; 2313 int res = -1;
2310#ifdef WIN32 2314#ifdef _WIN32
2311 if (GetDiskFreeSpaceEx(backup_directory, (PULARGE_INTEGER)&freespace, NULL, NULL)) { 2315 if (GetDiskFreeSpaceEx(backup_directory, (PULARGE_INTEGER)&freespace, NULL, NULL)) {
2312 res = 0; 2316 res = 0;
2313 } 2317 }
@@ -2316,7 +2320,7 @@ checkpoint:
2316 memset(&fs, '\0', sizeof(fs)); 2320 memset(&fs, '\0', sizeof(fs));
2317 res = statvfs(backup_directory, &fs); 2321 res = statvfs(backup_directory, &fs);
2318 if (res == 0) { 2322 if (res == 0) {
2319 freespace = (uint64_t)fs.f_bavail * (uint64_t)fs.f_bsize; 2323 freespace = (uint64_t)fs.f_bavail * (uint64_t)fs.f_frsize;
2320 } 2324 }
2321#endif 2325#endif
2322 plist_t freespace_item = plist_new_uint(freespace); 2326 plist_t freespace_item = plist_new_uint(freespace);
diff --git a/tools/idevicebtlogger.c b/tools/idevicebtlogger.c
index 8de6b22..ca68b59 100644
--- a/tools/idevicebtlogger.c
+++ b/tools/idevicebtlogger.c
@@ -36,7 +36,7 @@
36#include <assert.h> 36#include <assert.h>
37#include <fcntl.h> 37#include <fcntl.h>
38 38
39#ifdef WIN32 39#ifdef _WIN32
40#include <windows.h> 40#include <windows.h>
41#define sleep(x) Sleep(x*1000) 41#define sleep(x) Sleep(x*1000)
42#else 42#else
@@ -334,7 +334,7 @@ int main(int argc, char *argv[])
334 334
335 signal(SIGINT, clean_exit); 335 signal(SIGINT, clean_exit);
336 signal(SIGTERM, clean_exit); 336 signal(SIGTERM, clean_exit);
337#ifndef WIN32 337#ifndef _WIN32
338 signal(SIGQUIT, clean_exit); 338 signal(SIGQUIT, clean_exit);
339 signal(SIGPIPE, SIG_IGN); 339 signal(SIGPIPE, SIG_IGN);
340#endif 340#endif
diff --git a/tools/idevicecrashreport.c b/tools/idevicecrashreport.c
index 09bd537..b9869ae 100644
--- a/tools/idevicecrashreport.c
+++ b/tools/idevicecrashreport.c
@@ -31,7 +31,8 @@
31#include <string.h> 31#include <string.h>
32#include <unistd.h> 32#include <unistd.h>
33#include <getopt.h> 33#include <getopt.h>
34#ifndef WIN32 34#include <sys/stat.h>
35#ifndef _WIN32
35#include <signal.h> 36#include <signal.h>
36#endif 37#endif
37#include <libimobiledevice-glue/utils.h> 38#include <libimobiledevice-glue/utils.h>
@@ -42,7 +43,7 @@
42#include <libimobiledevice/afc.h> 43#include <libimobiledevice/afc.h>
43#include <plist/plist.h> 44#include <plist/plist.h>
44 45
45#ifdef WIN32 46#ifdef _WIN32
46#include <windows.h> 47#include <windows.h>
47#define S_IFLNK S_IFREG 48#define S_IFLNK S_IFREG
48#define S_IFSOCK S_IFREG 49#define S_IFSOCK S_IFREG
@@ -54,11 +55,12 @@
54const char* target_directory = NULL; 55const char* target_directory = NULL;
55static int extract_raw_crash_reports = 0; 56static int extract_raw_crash_reports = 0;
56static int keep_crash_reports = 0; 57static int keep_crash_reports = 0;
58static int remove_all = 0;
57 59
58static int file_exists(const char* path) 60static int file_exists(const char* path)
59{ 61{
60 struct stat tst; 62 struct stat tst;
61#ifdef WIN32 63#ifdef _WIN32
62 return (stat(path, &tst) == 0); 64 return (stat(path, &tst) == 0);
63#else 65#else
64 return (lstat(path, &tst) == 0); 66 return (lstat(path, &tst) == 0);
@@ -144,7 +146,7 @@ static int afc_client_copy_and_remove_crash_reports(afc_client_t afc, const char
144 continue; 146 continue;
145 } 147 }
146 148
147 char **fileinfo = NULL; 149 plist_t fileinfo = NULL;
148 struct stat stbuf; 150 struct stat stbuf;
149 memset(&stbuf, '\0', sizeof(struct stat)); 151 memset(&stbuf, '\0', sizeof(struct stat));
150 152
@@ -152,7 +154,7 @@ static int afc_client_copy_and_remove_crash_reports(afc_client_t afc, const char
152 strcpy(((char*)source_filename) + device_directory_length, list[k]); 154 strcpy(((char*)source_filename) + device_directory_length, list[k]);
153 155
154 /* assemble absolute target filename */ 156 /* assemble absolute target filename */
155#ifdef WIN32 157#ifdef _WIN32
156 /* replace every ':' with '-' since ':' is an illegal character for file names in windows */ 158 /* replace every ':' with '-' since ':' is an illegal character for file names in windows */
157 char* current_pos = strchr(list[k], ':'); 159 char* current_pos = strchr(list[k], ':');
158 while (current_pos) { 160 while (current_pos) {
@@ -171,88 +173,93 @@ static int afc_client_copy_and_remove_crash_reports(afc_client_t afc, const char
171 } 173 }
172 174
173 /* get file information */ 175 /* get file information */
174 afc_get_file_info(afc, source_filename, &fileinfo); 176 afc_get_file_info_plist(afc, source_filename, &fileinfo);
175 if (!fileinfo) { 177 if (!fileinfo) {
176 printf("Failed to read information for '%s'. Skipping...\n", source_filename); 178 printf("Failed to read information for '%s'. Skipping...\n", source_filename);
177 continue; 179 continue;
178 } 180 }
179 181
180 /* parse file information */ 182 /* parse file information */
181 int i; 183 stbuf.st_size = plist_dict_get_uint(fileinfo, "st_size");
182 for (i = 0; fileinfo[i]; i+=2) { 184 const char* s_ifmt = plist_get_string_ptr(plist_dict_get_item(fileinfo, "st_ifmt"), NULL);
183 if (!strcmp(fileinfo[i], "st_size")) { 185 if (s_ifmt) {
184 stbuf.st_size = atoll(fileinfo[i+1]); 186 if (!strcmp(s_ifmt, "S_IFREG")) {
185 } else if (!strcmp(fileinfo[i], "st_ifmt")) { 187 stbuf.st_mode = S_IFREG;
186 if (!strcmp(fileinfo[i+1], "S_IFREG")) { 188 } else if (!strcmp(s_ifmt, "S_IFDIR")) {
187 stbuf.st_mode = S_IFREG; 189 stbuf.st_mode = S_IFDIR;
188 } else if (!strcmp(fileinfo[i+1], "S_IFDIR")) { 190 } else if (!strcmp(s_ifmt, "S_IFLNK")) {
189 stbuf.st_mode = S_IFDIR; 191 stbuf.st_mode = S_IFLNK;
190 } else if (!strcmp(fileinfo[i+1], "S_IFLNK")) { 192 } else if (!strcmp(s_ifmt, "S_IFBLK")) {
191 stbuf.st_mode = S_IFLNK; 193 stbuf.st_mode = S_IFBLK;
192 } else if (!strcmp(fileinfo[i+1], "S_IFBLK")) { 194 } else if (!strcmp(s_ifmt, "S_IFCHR")) {
193 stbuf.st_mode = S_IFBLK; 195 stbuf.st_mode = S_IFCHR;
194 } else if (!strcmp(fileinfo[i+1], "S_IFCHR")) { 196 } else if (!strcmp(s_ifmt, "S_IFIFO")) {
195 stbuf.st_mode = S_IFCHR; 197 stbuf.st_mode = S_IFIFO;
196 } else if (!strcmp(fileinfo[i+1], "S_IFIFO")) { 198 } else if (!strcmp(s_ifmt, "S_IFSOCK")) {
197 stbuf.st_mode = S_IFIFO; 199 stbuf.st_mode = S_IFSOCK;
198 } else if (!strcmp(fileinfo[i+1], "S_IFSOCK")) { 200 }
199 stbuf.st_mode = S_IFSOCK; 201 }
200 } 202 stbuf.st_nlink = plist_dict_get_uint(fileinfo, "st_nlink");
201 } else if (!strcmp(fileinfo[i], "st_nlink")) { 203 stbuf.st_mtime = (time_t)(plist_dict_get_uint(fileinfo, "st_mtime") / 1000000000);
202 stbuf.st_nlink = atoi(fileinfo[i+1]); 204 const char* linktarget = plist_get_string_ptr(plist_dict_get_item(fileinfo, "LinkTarget"), NULL);
203 } else if (!strcmp(fileinfo[i], "st_mtime")) { 205 if (linktarget && !remove_all) {
204 stbuf.st_mtime = (time_t)(atoll(fileinfo[i+1]) / 1000000000); 206 /* report latest crash report filename */
205 } else if (!strcmp(fileinfo[i], "LinkTarget")) { 207 printf("Link: %s\n", (char*)target_filename + strlen(target_directory));
206 /* report latest crash report filename */ 208
207 printf("Link: %s\n", (char*)target_filename + strlen(target_directory)); 209 /* remove any previous symlink */
208 210 if (file_exists(target_filename)) {
209 /* remove any previous symlink */ 211 remove(target_filename);
210 if (file_exists(target_filename)) { 212 }
211 remove(target_filename);
212 }
213 213
214#ifndef WIN32 214#ifndef _WIN32
215 /* use relative filename */ 215 /* use relative filename */
216 char* b = strrchr(fileinfo[i+1], '/'); 216 const char* b = strrchr(linktarget, '/');
217 if (b == NULL) { 217 if (b == NULL) {
218 b = fileinfo[i+1]; 218 b = linktarget;
219 } else { 219 } else {
220 b++; 220 b++;
221 } 221 }
222 222
223 /* create a symlink pointing to latest log */ 223 /* create a symlink pointing to latest log */
224 if (symlink(b, target_filename) < 0) { 224 if (symlink(b, target_filename) < 0) {
225 fprintf(stderr, "Can't create symlink to %s\n", b); 225 fprintf(stderr, "Can't create symlink to %s\n", b);
226 } 226 }
227#endif 227#endif
228 228
229 if (!keep_crash_reports) 229 if (!keep_crash_reports)
230 afc_remove_path(afc, source_filename); 230 afc_remove_path(afc, source_filename);
231 231
232 res = 0; 232 res = 0;
233 }
234 } 233 }
235 234
236 /* free file information */ 235 /* free file information */
237 afc_dictionary_free(fileinfo); 236 plist_free(fileinfo);
238 237
239 /* recurse into child directories */ 238 /* recurse into child directories */
240 if (S_ISDIR(stbuf.st_mode)) { 239 if (S_ISDIR(stbuf.st_mode)) {
241#ifdef WIN32 240 if (!remove_all) {
242 mkdir(target_filename); 241#ifdef _WIN32
242 mkdir(target_filename);
243#else 243#else
244 mkdir(target_filename, 0755); 244 mkdir(target_filename, 0755);
245#endif 245#endif
246 }
246 res = afc_client_copy_and_remove_crash_reports(afc, source_filename, target_filename, filename_filter); 247 res = afc_client_copy_and_remove_crash_reports(afc, source_filename, target_filename, filename_filter);
247 248
248 /* remove directory from device */ 249 /* remove directory from device */
249 if (!keep_crash_reports) 250 if (!remove_all && !keep_crash_reports)
250 afc_remove_path(afc, source_filename); 251 afc_remove_path(afc, source_filename);
251 } else if (S_ISREG(stbuf.st_mode)) { 252 } else if (S_ISREG(stbuf.st_mode)) {
252 if (filename_filter != NULL && strstr(source_filename, filename_filter) == NULL) { 253 if (filename_filter != NULL && strstr(source_filename, filename_filter) == NULL) {
253 continue; 254 continue;
254 } 255 }
255 256
257 if (remove_all) {
258 printf("Remove: %s\n", source_filename);
259 afc_remove_path(afc, source_filename);
260 continue;
261 }
262
256 /* copy file to host */ 263 /* copy file to host */
257 afc_error = afc_file_open(afc, source_filename, AFC_FOPEN_RDONLY, &handle); 264 afc_error = afc_file_open(afc, source_filename, AFC_FOPEN_RDONLY, &handle);
258 if(afc_error != AFC_E_SUCCESS) { 265 if(afc_error != AFC_E_SUCCESS) {
@@ -331,6 +338,7 @@ static void print_usage(int argc, char **argv, int is_error)
331 " -f, --filter NAME filter crash reports by NAME (case sensitive)\n" 338 " -f, --filter NAME filter crash reports by NAME (case sensitive)\n"
332 " -h, --help prints usage information\n" 339 " -h, --help prints usage information\n"
333 " -v, --version prints version information\n" 340 " -v, --version prints version information\n"
341 " --remove-all remove all crash logs found\n"
334 "\n" 342 "\n"
335 "Homepage: <" PACKAGE_URL ">\n" 343 "Homepage: <" PACKAGE_URL ">\n"
336 "Bug Reports: <" PACKAGE_BUGREPORT ">\n" 344 "Bug Reports: <" PACKAGE_BUGREPORT ">\n"
@@ -361,10 +369,11 @@ int main(int argc, char* argv[])
361 { "filter", required_argument, NULL, 'f' }, 369 { "filter", required_argument, NULL, 'f' },
362 { "extract", no_argument, NULL, 'e' }, 370 { "extract", no_argument, NULL, 'e' },
363 { "keep", no_argument, NULL, 'k' }, 371 { "keep", no_argument, NULL, 'k' },
372 { "remove-all", no_argument, NULL, 1 },
364 { NULL, 0, NULL, 0} 373 { NULL, 0, NULL, 0}
365 }; 374 };
366 375
367#ifndef WIN32 376#ifndef _WIN32
368 signal(SIGPIPE, SIG_IGN); 377 signal(SIGPIPE, SIG_IGN);
369#endif 378#endif
370 379
@@ -405,6 +414,9 @@ int main(int argc, char* argv[])
405 case 'k': 414 case 'k':
406 keep_crash_reports = 1; 415 keep_crash_reports = 1;
407 break; 416 break;
417 case 1:
418 remove_all = 1;
419 break;
408 default: 420 default:
409 print_usage(argc, argv, 1); 421 print_usage(argc, argv, 1);
410 return 2; 422 return 2;
@@ -414,12 +426,16 @@ int main(int argc, char* argv[])
414 argv += optind; 426 argv += optind;
415 427
416 /* ensure a target directory was supplied */ 428 /* ensure a target directory was supplied */
417 if (!argv[0]) { 429 if (!remove_all) {
418 fprintf(stderr, "ERROR: missing target directory.\n"); 430 if (!argv[0]) {
419 print_usage(argc+optind, argv-optind, 1); 431 fprintf(stderr, "ERROR: missing target directory.\n");
420 return 2; 432 print_usage(argc+optind, argv-optind, 1);
433 return 2;
434 }
435 target_directory = argv[0];
436 } else {
437 target_directory = ".";
421 } 438 }
422 target_directory = argv[0];
423 439
424 /* check if target directory exists */ 440 /* check if target directory exists */
425 if (!file_exists(target_directory)) { 441 if (!file_exists(target_directory)) {
diff --git a/tools/idevicedate.c b/tools/idevicedate.c
index d05f63e..31b0cf7 100644
--- a/tools/idevicedate.c
+++ b/tools/idevicedate.c
@@ -33,7 +33,7 @@
33#if HAVE_LANGINFO_CODESET 33#if HAVE_LANGINFO_CODESET
34#include <langinfo.h> 34#include <langinfo.h>
35#endif 35#endif
36#ifndef WIN32 36#ifndef _WIN32
37#include <signal.h> 37#include <signal.h>
38#endif 38#endif
39 39
@@ -43,7 +43,7 @@
43#ifdef _DATE_FMT 43#ifdef _DATE_FMT
44#define DATE_FMT_LANGINFO nl_langinfo (_DATE_FMT) 44#define DATE_FMT_LANGINFO nl_langinfo (_DATE_FMT)
45#else 45#else
46#ifdef WIN32 46#ifdef _WIN32
47#define DATE_FMT_LANGINFO "%a %b %#d %H:%M:%S %Z %Y" 47#define DATE_FMT_LANGINFO "%a %b %#d %H:%M:%S %Z %Y"
48#else 48#else
49#define DATE_FMT_LANGINFO "%a %b %e %H:%M:%S %Z %Y" 49#define DATE_FMT_LANGINFO "%a %b %e %H:%M:%S %Z %Y"
@@ -104,7 +104,7 @@ int main(int argc, char *argv[])
104 { NULL, 0, NULL, 0} 104 { NULL, 0, NULL, 0}
105 }; 105 };
106 106
107#ifndef WIN32 107#ifndef _WIN32
108 signal(SIGPIPE, SIG_IGN); 108 signal(SIGPIPE, SIG_IGN);
109#endif 109#endif
110 /* parse cmdline args */ 110 /* parse cmdline args */
diff --git a/tools/idevicedebug.c b/tools/idevicedebug.c
index 36c594e..3f2e289 100644
--- a/tools/idevicedebug.c
+++ b/tools/idevicedebug.c
@@ -34,7 +34,7 @@
34#include <libgen.h> 34#include <libgen.h>
35#include <getopt.h> 35#include <getopt.h>
36 36
37#ifdef WIN32 37#ifdef _WIN32
38#include <windows.h> 38#include <windows.h>
39#define sleep(x) Sleep(x*1000) 39#define sleep(x) Sleep(x*1000)
40#endif 40#endif
@@ -239,7 +239,7 @@ int main(int argc, char *argv[])
239 /* map signals */ 239 /* map signals */
240 signal(SIGINT, on_signal); 240 signal(SIGINT, on_signal);
241 signal(SIGTERM, on_signal); 241 signal(SIGTERM, on_signal);
242#ifndef WIN32 242#ifndef _WIN32
243 signal(SIGQUIT, on_signal); 243 signal(SIGQUIT, on_signal);
244 signal(SIGPIPE, SIG_IGN); 244 signal(SIGPIPE, SIG_IGN);
245#endif 245#endif
diff --git a/tools/idevicedebugserverproxy.c b/tools/idevicedebugserverproxy.c
index 9fe7051..fb082b3 100644
--- a/tools/idevicedebugserverproxy.c
+++ b/tools/idevicedebugserverproxy.c
@@ -32,7 +32,7 @@
32#include <getopt.h> 32#include <getopt.h>
33#include <errno.h> 33#include <errno.h>
34#include <signal.h> 34#include <signal.h>
35#ifdef WIN32 35#ifdef _WIN32
36#include <winsock2.h> 36#include <winsock2.h>
37#include <windows.h> 37#include <windows.h>
38#else 38#else
@@ -219,7 +219,7 @@ int main(int argc, char *argv[])
219 { NULL, 0, NULL, 0} 219 { NULL, 0, NULL, 0}
220 }; 220 };
221 221
222#ifndef WIN32 222#ifndef _WIN32
223 struct sigaction sa; 223 struct sigaction sa;
224 struct sigaction si; 224 struct sigaction si;
225 memset(&sa, '\0', sizeof(struct sigaction)); 225 memset(&sa, '\0', sizeof(struct sigaction));
diff --git a/tools/idevicedevmodectl.c b/tools/idevicedevmodectl.c
index bd1de6a..6bf1a1c 100644
--- a/tools/idevicedevmodectl.c
+++ b/tools/idevicedevmodectl.c
@@ -32,11 +32,11 @@
32#include <sys/stat.h> 32#include <sys/stat.h>
33#include <unistd.h> 33#include <unistd.h>
34#include <errno.h> 34#include <errno.h>
35#ifndef WIN32 35#ifndef _WIN32
36#include <signal.h> 36#include <signal.h>
37#endif 37#endif
38 38
39#ifdef WIN32 39#ifdef _WIN32
40#include <windows.h> 40#include <windows.h>
41#define __usleep(x) Sleep(x/1000) 41#define __usleep(x) Sleep(x/1000)
42#else 42#else
@@ -259,7 +259,7 @@ int main(int argc, char *argv[])
259 { NULL, 0, NULL, 0} 259 { NULL, 0, NULL, 0}
260 }; 260 };
261 261
262#ifndef WIN32 262#ifndef _WIN32
263 signal(SIGPIPE, SIG_IGN); 263 signal(SIGPIPE, SIG_IGN);
264#endif 264#endif
265 /* parse cmdline args */ 265 /* parse cmdline args */
diff --git a/tools/idevicediagnostics.c b/tools/idevicediagnostics.c
index e699bc4..365c0a4 100644
--- a/tools/idevicediagnostics.c
+++ b/tools/idevicediagnostics.c
@@ -31,7 +31,7 @@
31#include <getopt.h> 31#include <getopt.h>
32#include <errno.h> 32#include <errno.h>
33#include <time.h> 33#include <time.h>
34#ifndef WIN32 34#ifndef _WIN32
35#include <signal.h> 35#include <signal.h>
36#endif 36#endif
37 37
@@ -113,7 +113,7 @@ int main(int argc, char **argv)
113 { NULL, 0, NULL, 0} 113 { NULL, 0, NULL, 0}
114 }; 114 };
115 115
116#ifndef WIN32 116#ifndef _WIN32
117 signal(SIGPIPE, SIG_IGN); 117 signal(SIGPIPE, SIG_IGN);
118#endif 118#endif
119 /* parse cmdline args */ 119 /* parse cmdline args */
diff --git a/tools/ideviceenterrecovery.c b/tools/ideviceenterrecovery.c
index 29cc5c9..65eb882 100644
--- a/tools/ideviceenterrecovery.c
+++ b/tools/ideviceenterrecovery.c
@@ -30,7 +30,7 @@
30#include <stdlib.h> 30#include <stdlib.h>
31#include <getopt.h> 31#include <getopt.h>
32#include <errno.h> 32#include <errno.h>
33#ifndef WIN32 33#ifndef _WIN32
34#include <signal.h> 34#include <signal.h>
35#endif 35#endif
36 36
@@ -70,7 +70,7 @@ int main(int argc, char *argv[])
70 { NULL, 0, NULL, 0} 70 { NULL, 0, NULL, 0}
71 }; 71 };
72 72
73#ifndef WIN32 73#ifndef _WIN32
74 signal(SIGPIPE, SIG_IGN); 74 signal(SIGPIPE, SIG_IGN);
75#endif 75#endif
76 /* parse cmdline args */ 76 /* parse cmdline args */
diff --git a/tools/ideviceimagemounter.c b/tools/ideviceimagemounter.c
index 511583e..b319d05 100644
--- a/tools/ideviceimagemounter.c
+++ b/tools/ideviceimagemounter.c
@@ -36,7 +36,8 @@
36#include <time.h> 36#include <time.h>
37#include <sys/time.h> 37#include <sys/time.h>
38#include <inttypes.h> 38#include <inttypes.h>
39#ifndef WIN32 39#include <sys/stat.h>
40#ifndef _WIN32
40#include <signal.h> 41#include <signal.h>
41#endif 42#endif
42 43
@@ -87,7 +88,7 @@ static void print_usage(int argc, char **argv, int is_error)
87 " mount PATH Mount the developer disk image at PATH.\n" 88 " mount PATH Mount the developer disk image at PATH.\n"
88 " For iOS 17+, PATH is a directory containing a .dmg image,\n" 89 " For iOS 17+, PATH is a directory containing a .dmg image,\n"
89 " a BuildManifest.plist, and a Firmware sub-directory;\n" 90 " a BuildManifest.plist, and a Firmware sub-directory;\n"
90 " for older versions PATH is a .dmg filename with a" 91 " for older versions PATH is a .dmg filename with a\n"
91 " .dmg.signature in the same directory, or with another\n" 92 " .dmg.signature in the same directory, or with another\n"
92 " parameter pointing to a file elsewhere.\n" 93 " parameter pointing to a file elsewhere.\n"
93 " list List mounted disk images.\n" 94 " list List mounted disk images.\n"
@@ -183,7 +184,7 @@ int main(int argc, char **argv)
183 size_t image_size = 0; 184 size_t image_size = 0;
184 char *image_sig_path = NULL; 185 char *image_sig_path = NULL;
185 186
186#ifndef WIN32 187#ifndef _WIN32
187 signal(SIGPIPE, SIG_IGN); 188 signal(SIGPIPE, SIG_IGN);
188#endif 189#endif
189 parse_opts(argc, argv); 190 parse_opts(argc, argv);
@@ -267,23 +268,14 @@ int main(int argc, char **argv)
267 goto leave; 268 goto leave;
268 } 269 }
269 270
270 plist_t pver = NULL; 271 unsigned int device_version = idevice_get_device_version(device);
271 char *product_version = NULL; 272
272 lockdownd_get_value(lckd, NULL, "ProductVersion", &pver);
273 if (pver && plist_get_node_type(pver) == PLIST_STRING) {
274 plist_get_string_val(pver, &product_version);
275 }
276 disk_image_upload_type_t disk_image_upload_type = DISK_IMAGE_UPLOAD_TYPE_AFC; 273 disk_image_upload_type_t disk_image_upload_type = DISK_IMAGE_UPLOAD_TYPE_AFC;
277 int product_version_major = 0; 274 if (device_version >= IDEVICE_DEVICE_VERSION(7,0,0)) {
278 int product_version_minor = 0; 275 disk_image_upload_type = DISK_IMAGE_UPLOAD_TYPE_UPLOAD_IMAGE;
279 if (product_version) {
280 if (sscanf(product_version, "%d.%d.%*d", &product_version_major, &product_version_minor) == 2) {
281 if (product_version_major >= 7)
282 disk_image_upload_type = DISK_IMAGE_UPLOAD_TYPE_UPLOAD_IMAGE;
283 }
284 } 276 }
285 277
286 if (product_version_major >= 16) { 278 if (device_version >= IDEVICE_DEVICE_VERSION(16,0,0)) {
287 uint8_t dev_mode_status = 0; 279 uint8_t dev_mode_status = 0;
288 plist_t val = NULL; 280 plist_t val = NULL;
289 ldret = lockdownd_get_value(lckd, "com.apple.security.mac.amfi", "DeveloperModeStatus", &val); 281 ldret = lockdownd_get_value(lckd, "com.apple.security.mac.amfi", "DeveloperModeStatus", &val);
@@ -336,7 +328,7 @@ int main(int argc, char **argv)
336 goto leave; 328 goto leave;
337 } 329 }
338 image_size = fst.st_size; 330 image_size = fst.st_size;
339 if (product_version_major < 17 && stat(image_sig_path, &fst) != 0) { 331 if (device_version < IDEVICE_DEVICE_VERSION(17,0,0) && stat(image_sig_path, &fst) != 0) {
340 fprintf(stderr, "ERROR: stat: %s: %s\n", image_sig_path, strerror(errno)); 332 fprintf(stderr, "ERROR: stat: %s: %s\n", image_sig_path, strerror(errno));
341 goto leave; 333 goto leave;
342 } 334 }
@@ -351,7 +343,7 @@ int main(int argc, char **argv)
351 if (cmd == CMD_LIST) { 343 if (cmd == CMD_LIST) {
352 /* list mounts mode */ 344 /* list mounts mode */
353 if (!imagetype) { 345 if (!imagetype) {
354 if (product_version_major < 17) { 346 if (device_version < IDEVICE_DEVICE_VERSION(17,0,0)) {
355 imagetype = "Developer"; 347 imagetype = "Developer";
356 } else { 348 } else {
357 imagetype = "Personalized"; 349 imagetype = "Personalized";
@@ -371,7 +363,7 @@ int main(int argc, char **argv)
371 struct stat fst; 363 struct stat fst;
372 plist_t mount_options = NULL; 364 plist_t mount_options = NULL;
373 365
374 if (product_version_major < 17) { 366 if (device_version < IDEVICE_DEVICE_VERSION(17,0,0)) {
375 f = fopen(image_sig_path, "rb"); 367 f = fopen(image_sig_path, "rb");
376 if (!f) { 368 if (!f) {
377 fprintf(stderr, "Error opening signature file '%s': %s\n", image_sig_path, strerror(errno)); 369 fprintf(stderr, "Error opening signature file '%s': %s\n", image_sig_path, strerror(errno));
@@ -606,20 +598,13 @@ int main(int argc, char **argv)
606 case DISK_IMAGE_UPLOAD_TYPE_AFC: 598 case DISK_IMAGE_UPLOAD_TYPE_AFC:
607 default: 599 default:
608 printf("Uploading %s --> afc:///%s\n", image_path, targetname); 600 printf("Uploading %s --> afc:///%s\n", image_path, targetname);
609 char **strs = NULL; 601 plist_t fileinfo = NULL;
610 if (afc_get_file_info(afc, PKG_PATH, &strs) != AFC_E_SUCCESS) { 602 if (afc_get_file_info_plist(afc, PKG_PATH, &fileinfo) != AFC_E_SUCCESS) {
611 if (afc_make_directory(afc, PKG_PATH) != AFC_E_SUCCESS) { 603 if (afc_make_directory(afc, PKG_PATH) != AFC_E_SUCCESS) {
612 fprintf(stderr, "WARNING: Could not create directory '%s' on device!\n", PKG_PATH); 604 fprintf(stderr, "WARNING: Could not create directory '%s' on device!\n", PKG_PATH);
613 } 605 }
614 } 606 }
615 if (strs) { 607 plist_free(fileinfo);
616 int i = 0;
617 while (strs[i]) {
618 free(strs[i]);
619 i++;
620 }
621 free(strs);
622 }
623 608
624 uint64_t af = 0; 609 uint64_t af = 0;
625 if ((afc_file_open(afc, targetname, AFC_FOPEN_WRONLY, &af) != 610 if ((afc_file_open(afc, targetname, AFC_FOPEN_WRONLY, &af) !=
diff --git a/tools/ideviceinfo.c b/tools/ideviceinfo.c
index fd45763..20cc916 100644
--- a/tools/ideviceinfo.c
+++ b/tools/ideviceinfo.c
@@ -31,7 +31,7 @@
31#include <errno.h> 31#include <errno.h>
32#include <stdlib.h> 32#include <stdlib.h>
33#include <getopt.h> 33#include <getopt.h>
34#ifndef WIN32 34#ifndef _WIN32
35#include <signal.h> 35#include <signal.h>
36#endif 36#endif
37 37
@@ -152,7 +152,7 @@ int main(int argc, char *argv[])
152 { NULL, 0, NULL, 0} 152 { NULL, 0, NULL, 0}
153 }; 153 };
154 154
155#ifndef WIN32 155#ifndef _WIN32
156 signal(SIGPIPE, SIG_IGN); 156 signal(SIGPIPE, SIG_IGN);
157#endif 157#endif
158 158
diff --git a/tools/idevicename.c b/tools/idevicename.c
index 69b76f6..248bda3 100644
--- a/tools/idevicename.c
+++ b/tools/idevicename.c
@@ -30,7 +30,7 @@
30#include <unistd.h> 30#include <unistd.h>
31#include <stdlib.h> 31#include <stdlib.h>
32#include <getopt.h> 32#include <getopt.h>
33#ifndef WIN32 33#ifndef _WIN32
34#include <signal.h> 34#include <signal.h>
35#endif 35#endif
36 36
@@ -72,7 +72,7 @@ int main(int argc, char** argv)
72 const char* udid = NULL; 72 const char* udid = NULL;
73 int use_network = 0; 73 int use_network = 0;
74 74
75#ifndef WIN32 75#ifndef _WIN32
76 signal(SIGPIPE, SIG_IGN); 76 signal(SIGPIPE, SIG_IGN);
77#endif 77#endif
78 78
diff --git a/tools/idevicenotificationproxy.c b/tools/idevicenotificationproxy.c
index d1e25c1..192192a 100644
--- a/tools/idevicenotificationproxy.c
+++ b/tools/idevicenotificationproxy.c
@@ -2,7 +2,8 @@
2 * idevicenotificationproxy.c 2 * idevicenotificationproxy.c
3 * Simple client for the notification_proxy service 3 * Simple client for the notification_proxy service
4 * 4 *
5 * Copyright (c) 2009-2015 Martin Szulecki All Rights Reserved. 5 * Copyright (c) 2018-2024 Nikias Bassen, All Rights Reserved.
6 * Copyright (c) 2009-2015 Martin Szulecki, All Rights Reserved.
6 * 7 *
7 * This library is free software; you can redistribute it and/or 8 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public 9 * modify it under the terms of the GNU Lesser General Public
@@ -32,7 +33,7 @@
32#include <errno.h> 33#include <errno.h>
33#include <signal.h> 34#include <signal.h>
34 35
35#ifdef WIN32 36#ifdef _WIN32
36#include <windows.h> 37#include <windows.h>
37#define sleep(x) Sleep(x*1000) 38#define sleep(x) Sleep(x*1000)
38#else 39#else
@@ -75,6 +76,7 @@ static void print_usage(int argc, char **argv, int is_error)
75 "\n" 76 "\n"
76 "The following OPTIONS are accepted:\n" 77 "The following OPTIONS are accepted:\n"
77 " -u, --udid UDID target specific device by UDID\n" 78 " -u, --udid UDID target specific device by UDID\n"
79 " -i, --insecure use insecure notification proxy (non-paired device)\n"
78 " -n, --network connect to network device\n" 80 " -n, --network connect to network device\n"
79 " -d, --debug enable communication debugging\n" 81 " -d, --debug enable communication debugging\n"
80 " -h, --help prints usage information\n" 82 " -h, --help prints usage information\n"
@@ -102,6 +104,7 @@ int main(int argc, char *argv[])
102 int i = 0; 104 int i = 0;
103 const char* udid = NULL; 105 const char* udid = NULL;
104 int use_network = 0; 106 int use_network = 0;
107 int insecure = 0;
105 int cmd = CMD_NONE; 108 int cmd = CMD_NONE;
106 char* cmd_arg = NULL; 109 char* cmd_arg = NULL;
107 110
@@ -114,6 +117,7 @@ int main(int argc, char *argv[])
114 { "debug", no_argument, NULL, 'd' }, 117 { "debug", no_argument, NULL, 'd' },
115 { "help", no_argument, NULL, 'h' }, 118 { "help", no_argument, NULL, 'h' },
116 { "udid", required_argument, NULL, 'u' }, 119 { "udid", required_argument, NULL, 'u' },
120 { "insecure", no_argument, NULL, 'i' },
117 { "network", no_argument, NULL, 'n' }, 121 { "network", no_argument, NULL, 'n' },
118 { "version", no_argument, NULL, 'v' }, 122 { "version", no_argument, NULL, 'v' },
119 { NULL, 0, NULL, 0} 123 { NULL, 0, NULL, 0}
@@ -121,13 +125,13 @@ int main(int argc, char *argv[])
121 125
122 signal(SIGINT, clean_exit); 126 signal(SIGINT, clean_exit);
123 signal(SIGTERM, clean_exit); 127 signal(SIGTERM, clean_exit);
124#ifndef WIN32 128#ifndef _WIN32
125 signal(SIGQUIT, clean_exit); 129 signal(SIGQUIT, clean_exit);
126 signal(SIGPIPE, SIG_IGN); 130 signal(SIGPIPE, SIG_IGN);
127#endif 131#endif
128 132
129 /* parse cmdline args */ 133 /* parse cmdline args */
130 while ((c = getopt_long(argc, argv, "dhu:nv", longopts, NULL)) != -1) { 134 while ((c = getopt_long(argc, argv, "dhu:inv", longopts, NULL)) != -1) {
131 switch (c) { 135 switch (c) {
132 case 'd': 136 case 'd':
133 idevice_set_debug_level(1); 137 idevice_set_debug_level(1);
@@ -143,6 +147,9 @@ int main(int argc, char *argv[])
143 case 'n': 147 case 'n':
144 use_network = 1; 148 use_network = 1;
145 break; 149 break;
150 case 'i':
151 insecure = 1;
152 break;
146 case 'h': 153 case 'h':
147 print_usage(argc, argv, 0); 154 print_usage(argc, argv, 0);
148 return 0; 155 return 0;
@@ -214,12 +221,17 @@ int main(int argc, char *argv[])
214 goto cleanup; 221 goto cleanup;
215 } 222 }
216 223
217 if (LOCKDOWN_E_SUCCESS != (ret = lockdownd_client_new_with_handshake(device, &client, TOOL_NAME))) { 224 if (insecure) {
218 fprintf(stderr, "ERROR: Could not connect to lockdownd, error code %d\n", ret); 225 ret = lockdownd_client_new(device, &client, TOOL_NAME);
226 } else {
227 ret = lockdownd_client_new_with_handshake(device, &client, TOOL_NAME);
228 }
229 if (LOCKDOWN_E_SUCCESS != ret) {
230 fprintf(stderr, "ERROR: Could not connect to lockdownd: %s (%d)\n", lockdownd_strerror(ret), ret);
219 goto cleanup; 231 goto cleanup;
220 } 232 }
221 233
222 ret = lockdownd_start_service(client, NP_SERVICE_NAME, &service); 234 ret = lockdownd_start_service(client, (insecure) ? "com.apple.mobile.insecure_notification_proxy" : NP_SERVICE_NAME, &service);
223 235
224 lockdownd_client_free(client); 236 lockdownd_client_free(client);
225 237
diff --git a/tools/idevicepair.c b/tools/idevicepair.c
index 94d3f04..884c690 100644
--- a/tools/idevicepair.c
+++ b/tools/idevicepair.c
@@ -32,7 +32,7 @@
32#include <getopt.h> 32#include <getopt.h>
33#include <ctype.h> 33#include <ctype.h>
34#include <unistd.h> 34#include <unistd.h>
35#ifdef WIN32 35#ifdef _WIN32
36#include <windows.h> 36#include <windows.h>
37#include <conio.h> 37#include <conio.h>
38#else 38#else
@@ -50,7 +50,7 @@ static char *udid = NULL;
50 50
51#ifdef HAVE_WIRELESS_PAIRING 51#ifdef HAVE_WIRELESS_PAIRING
52 52
53#ifdef WIN32 53#ifdef _WIN32
54#define BS_CC '\b' 54#define BS_CC '\b'
55#define my_getch getch 55#define my_getch getch
56#else 56#else
@@ -293,7 +293,7 @@ int main(int argc, char **argv)
293 } 293 }
294 } 294 }
295 295
296#ifndef WIN32 296#ifndef _WIN32
297 signal(SIGPIPE, SIG_IGN); 297 signal(SIGPIPE, SIG_IGN);
298#endif 298#endif
299 299
diff --git a/tools/ideviceprovision.c b/tools/ideviceprovision.c
index 4080a28..94f4ec5 100644
--- a/tools/ideviceprovision.c
+++ b/tools/ideviceprovision.c
@@ -32,11 +32,12 @@
32#include <getopt.h> 32#include <getopt.h>
33#include <sys/stat.h> 33#include <sys/stat.h>
34#include <errno.h> 34#include <errno.h>
35#ifndef WIN32 35#ifndef _WIN32
36#include <signal.h> 36#include <signal.h>
37#endif 37#endif
38 38
39#ifdef WIN32 39#ifdef _WIN32
40#include <winsock2.h>
40#include <windows.h> 41#include <windows.h>
41#else 42#else
42#include <arpa/inet.h> 43#include <arpa/inet.h>
@@ -314,7 +315,7 @@ int main(int argc, char *argv[])
314 { NULL, 0, NULL, 0} 315 { NULL, 0, NULL, 0}
315 }; 316 };
316 317
317#ifndef WIN32 318#ifndef _WIN32
318 signal(SIGPIPE, SIG_IGN); 319 signal(SIGPIPE, SIG_IGN);
319#endif 320#endif
320 /* parse cmdline args */ 321 /* parse cmdline args */
@@ -475,27 +476,7 @@ int main(int argc, char *argv[])
475 return -1; 476 return -1;
476 } 477 }
477 478
478 plist_t pver = NULL; 479 unsigned int device_version = idevice_get_device_version(device);
479 char *pver_s = NULL;
480 lockdownd_get_value(client, NULL, "ProductVersion", &pver);
481 if (pver && plist_get_node_type(pver) == PLIST_STRING) {
482 plist_get_string_val(pver, &pver_s);
483 }
484 plist_free(pver);
485 int product_version_major = 0;
486 int product_version_minor = 0;
487 int product_version_patch = 0;
488 if (pver_s) {
489 sscanf(pver_s, "%d.%d.%d", &product_version_major, &product_version_minor, &product_version_patch);
490 free(pver_s);
491 }
492 if (product_version_major == 0) {
493 fprintf(stderr, "ERROR: Could not determine the device's ProductVersion\n");
494 lockdownd_client_free(client);
495 idevice_free(device);
496 return -1;
497 }
498 int product_version = ((product_version_major & 0xFF) << 16) | ((product_version_minor & 0xFF) << 8) | (product_version_patch & 0xFF);
499 480
500 lockdownd_error_t lerr = lockdownd_start_service(client, MISAGENT_SERVICE_NAME, &service); 481 lockdownd_error_t lerr = lockdownd_start_service(client, MISAGENT_SERVICE_NAME, &service);
501 if (lerr != LOCKDOWN_E_SUCCESS) { 482 if (lerr != LOCKDOWN_E_SUCCESS) {
@@ -546,7 +527,7 @@ int main(int argc, char *argv[])
546 { 527 {
547 plist_t profiles = NULL; 528 plist_t profiles = NULL;
548 misagent_error_t merr; 529 misagent_error_t merr;
549 if (product_version < 0x090300) { 530 if (device_version < IDEVICE_DEVICE_VERSION(9,3,0)) {
550 merr = misagent_copy(mis, &profiles); 531 merr = misagent_copy(mis, &profiles);
551 } else { 532 } else {
552 merr = misagent_copy_all(mis, &profiles); 533 merr = misagent_copy_all(mis, &profiles);
@@ -631,7 +612,7 @@ int main(int argc, char *argv[])
631 /* remove all provisioning profiles */ 612 /* remove all provisioning profiles */
632 plist_t profiles = NULL; 613 plist_t profiles = NULL;
633 misagent_error_t merr; 614 misagent_error_t merr;
634 if (product_version < 0x090300) { 615 if (device_version < IDEVICE_DEVICE_VERSION(9,3,0)) {
635 merr = misagent_copy(mis, &profiles); 616 merr = misagent_copy(mis, &profiles);
636 } else { 617 } else {
637 merr = misagent_copy_all(mis, &profiles); 618 merr = misagent_copy_all(mis, &profiles);
diff --git a/tools/idevicescreenshot.c b/tools/idevicescreenshot.c
index 0e694c7..bfaa059 100644
--- a/tools/idevicescreenshot.c
+++ b/tools/idevicescreenshot.c
@@ -32,7 +32,7 @@
32#include <errno.h> 32#include <errno.h>
33#include <time.h> 33#include <time.h>
34#include <unistd.h> 34#include <unistd.h>
35#ifndef WIN32 35#ifndef _WIN32
36#include <signal.h> 36#include <signal.h>
37#endif 37#endif
38 38
@@ -142,7 +142,7 @@ int main(int argc, char **argv)
142 { NULL, 0, NULL, 0} 142 { NULL, 0, NULL, 0}
143 }; 143 };
144 144
145#ifndef WIN32 145#ifndef _WIN32
146 signal(SIGPIPE, SIG_IGN); 146 signal(SIGPIPE, SIG_IGN);
147#endif 147#endif
148 /* parse cmdline args */ 148 /* parse cmdline args */
diff --git a/tools/idevicesetlocation.c b/tools/idevicesetlocation.c
index 69fbaf5..dca8830 100644
--- a/tools/idevicesetlocation.c
+++ b/tools/idevicesetlocation.c
@@ -113,7 +113,7 @@ int main(int argc, char **argv)
113 113
114 if ((argc > 2) || (argc < 1)) { 114 if ((argc > 2) || (argc < 1)) {
115 print_usage(argc+optind, argv-optind, 1); 115 print_usage(argc+optind, argv-optind, 1);
116 return -1; 116 return 1;
117 } 117 }
118 118
119 if (argc == 2) { 119 if (argc == 2) {
@@ -123,7 +123,7 @@ int main(int argc, char **argv)
123 mode = RESET_LOCATION; 123 mode = RESET_LOCATION;
124 } else { 124 } else {
125 print_usage(argc+optind, argv-optind, 1); 125 print_usage(argc+optind, argv-optind, 1);
126 return -1; 126 return 1;
127 } 127 }
128 } 128 }
129 129
@@ -135,19 +135,30 @@ int main(int argc, char **argv)
135 } else { 135 } else {
136 printf("ERROR: No device found!\n"); 136 printf("ERROR: No device found!\n");
137 } 137 }
138 return -1; 138 return 1;
139 } 139 }
140 140
141 lockdownd_client_t lockdown; 141 lockdownd_client_t lockdown = NULL;
142 lockdownd_client_new_with_handshake(device, &lockdown, TOOL_NAME); 142 lockdownd_error_t lerr = lockdownd_client_new_with_handshake(device, &lockdown, TOOL_NAME);
143 if (lerr != LOCKDOWN_E_SUCCESS) {
144 idevice_free(device);
145 printf("ERROR: Could not connect to lockdownd: %s (%d)\n", lockdownd_strerror(lerr), lerr);
146 return 1;
147 }
143 148
144 lockdownd_service_descriptor_t svc = NULL; 149 lockdownd_service_descriptor_t svc = NULL;
145 lockdownd_error_t lerr = lockdownd_start_service(lockdown, DT_SIMULATELOCATION_SERVICE, &svc); 150 lerr = lockdownd_start_service(lockdown, DT_SIMULATELOCATION_SERVICE, &svc);
146 if (lerr != LOCKDOWN_E_SUCCESS) { 151 if (lerr != LOCKDOWN_E_SUCCESS) {
152 unsigned int device_version = idevice_get_device_version(device);
147 lockdownd_client_free(lockdown); 153 lockdownd_client_free(lockdown);
148 idevice_free(device); 154 idevice_free(device);
149 printf("ERROR: Could not start the simulatelocation service: %s\nMake sure a developer disk image is mounted!\n", lockdownd_strerror(lerr)); 155 printf("ERROR: Could not start the simulatelocation service: %s\n", lockdownd_strerror(lerr));
150 return -1; 156 if (device_version >= IDEVICE_DEVICE_VERSION(17,0,0)) {
157 printf("Note: This tool is currently not supported on iOS 17+\n");
158 } else {
159 printf("Make sure a developer disk image is mounted!\n");
160 }
161 return 1;
151 } 162 }
152 lockdownd_client_free(lockdown); 163 lockdownd_client_free(lockdown);
153 164
@@ -158,10 +169,9 @@ int main(int argc, char **argv)
158 lockdownd_service_descriptor_free(svc); 169 lockdownd_service_descriptor_free(svc);
159 170
160 if (serr != SERVICE_E_SUCCESS) { 171 if (serr != SERVICE_E_SUCCESS) {
161 lockdownd_client_free(lockdown);
162 idevice_free(device); 172 idevice_free(device);
163 printf("ERROR: Could not connect to simulatelocation service (%d)\n", serr); 173 printf("ERROR: Could not connect to simulatelocation service (%d)\n", serr);
164 return -1; 174 return 1;
165 } 175 }
166 176
167 uint32_t l; 177 uint32_t l;
diff --git a/tools/idevicesyslog.c b/tools/idevicesyslog.c
index a0e641d..88af4c1 100644
--- a/tools/idevicesyslog.c
+++ b/tools/idevicesyslog.c
@@ -33,8 +33,9 @@
33#include <stdlib.h> 33#include <stdlib.h>
34#include <unistd.h> 34#include <unistd.h>
35#include <getopt.h> 35#include <getopt.h>
36#include <time.h>
36 37
37#ifdef WIN32 38#ifdef _WIN32
38#include <windows.h> 39#include <windows.h>
39#define sleep(x) Sleep(x*1000) 40#define sleep(x) Sleep(x*1000)
40#endif 41#endif
@@ -42,10 +43,12 @@
42#include <libimobiledevice/libimobiledevice.h> 43#include <libimobiledevice/libimobiledevice.h>
43#include <libimobiledevice/syslog_relay.h> 44#include <libimobiledevice/syslog_relay.h>
44#include <libimobiledevice-glue/termcolors.h> 45#include <libimobiledevice-glue/termcolors.h>
46#include <libimobiledevice/ostrace.h>
45 47
46static int quit_flag = 0; 48static int quit_flag = 0;
47static int exit_on_disconnect = 0; 49static int exit_on_disconnect = 0;
48static int show_device_name = 0; 50static int show_device_name = 0;
51static int force_syslog_relay = 0;
49 52
50static char* udid = NULL; 53static char* udid = NULL;
51static char** proc_filters = NULL; 54static char** proc_filters = NULL;
@@ -58,6 +61,9 @@ static int num_pid_filters = 0;
58static char** msg_filters = NULL; 61static char** msg_filters = NULL;
59static int num_msg_filters = 0; 62static int num_msg_filters = 0;
60 63
64static char** msg_reverse_filters = NULL;
65static int num_msg_reverse_filters = 0;
66
61static char** trigger_filters = NULL; 67static char** trigger_filters = NULL;
62static int num_trigger_filters = 0; 68static int num_trigger_filters = 0;
63static char** untrigger_filters = NULL; 69static char** untrigger_filters = NULL;
@@ -66,11 +72,16 @@ static int triggered = 0;
66 72
67static idevice_t device = NULL; 73static idevice_t device = NULL;
68static syslog_relay_client_t syslog = NULL; 74static syslog_relay_client_t syslog = NULL;
75static ostrace_client_t ostrace = NULL;
69 76
70static const char QUIET_FILTER[] = "CircleJoinRequested|CommCenter|HeuristicInterpreter|MobileMail|PowerUIAgent|ProtectedCloudKeySyncing|SpringBoard|UserEventAgent|WirelessRadioManagerd|accessoryd|accountsd|aggregated|analyticsd|appstored|apsd|assetsd|assistant_service|backboardd|biometrickitd|bluetoothd|calaccessd|callservicesd|cloudd|com.apple.Safari.SafeBrowsing.Service|contextstored|corecaptured|coreduetd|corespeechd|cdpd|dasd|dataaccessd|distnoted|dprivacyd|duetexpertd|findmydeviced|fmfd|fmflocatord|gpsd|healthd|homed|identityservicesd|imagent|itunescloudd|itunesstored|kernel|locationd|maild|mDNSResponder|mediaremoted|mediaserverd|mobileassetd|nanoregistryd|nanotimekitcompaniond|navd|nsurlsessiond|passd|pasted|photoanalysisd|powerd|powerlogHelperd|ptpd|rapportd|remindd|routined|runningboardd|searchd|sharingd|suggestd|symptomsd|timed|thermalmonitord|useractivityd|vmd|wifid|wirelessproxd"; 77static const char QUIET_FILTER[] = "CircleJoinRequested|CommCenter|HeuristicInterpreter|MobileMail|PowerUIAgent|ProtectedCloudKeySyncing|SpringBoard|UserEventAgent|WirelessRadioManagerd|accessoryd|accountsd|aggregated|analyticsd|appstored|apsd|assetsd|assistant_service|backboardd|biometrickitd|bluetoothd|calaccessd|callservicesd|cloudd|com.apple.Safari.SafeBrowsing.Service|contextstored|corecaptured|coreduetd|corespeechd|cdpd|dasd|dataaccessd|distnoted|dprivacyd|duetexpertd|findmydeviced|fmfd|fmflocatord|gpsd|healthd|homed|identityservicesd|imagent|itunescloudd|itunesstored|kernel|locationd|maild|mDNSResponder|mediaremoted|mediaserverd|mobileassetd|nanoregistryd|nanotimekitcompaniond|navd|nsurlsessiond|passd|pasted|photoanalysisd|powerd|powerlogHelperd|ptpd|rapportd|remindd|routined|runningboardd|searchd|sharingd|suggestd|symptomsd|timed|thermalmonitord|useractivityd|vmd|wifid|wirelessproxd";
71 78
72static int use_network = 0; 79static int use_network = 0;
73 80
81static long long start_time = -1;
82static long long size_limit = -1;
83static long long age_limit = -1;
84
74static char *line = NULL; 85static char *line = NULL;
75static int line_buffer_size = 0; 86static int line_buffer_size = 0;
76static int lp = 0; 87static int lp = 0;
@@ -129,6 +140,70 @@ static int find_char(char c, char** p, const char* end)
129 140
130static void stop_logging(void); 141static void stop_logging(void);
131 142
143static int message_filter_matching(const char* message)
144{
145 if (num_msg_filters > 0) {
146 int found = 0;
147 int i;
148 for (i = 0; i < num_msg_filters; i++) {
149 if (strstr(message, msg_filters[i])) {
150 found = 1;
151 break;
152 }
153 }
154 if (!found) {
155 return 0;
156 }
157 }
158 if (num_msg_reverse_filters > 0) {
159 int found = 0;
160 int i;
161 for (i = 0; i < num_msg_reverse_filters; i++) {
162 if (strstr(message, msg_reverse_filters[i])) {
163 found = 1;
164 break;
165 }
166 }
167 if (found) {
168 return 0;
169 }
170 }
171 return 1;
172}
173
174static int process_filter_matching(int pid, const char* process_name, int process_name_length)
175{
176 int proc_matched = 0;
177 if (num_pid_filters > 0) {
178 int found = proc_filter_excluding;
179 int i = 0;
180 for (i = 0; i < num_pid_filters; i++) {
181 if (pid == pid_filters[i]) {
182 found = !proc_filter_excluding;
183 break;
184 }
185 }
186 if (found) {
187 proc_matched = 1;
188 }
189 }
190 if (num_proc_filters > 0 && !proc_matched) {
191 int found = proc_filter_excluding;
192 int i = 0;
193 for (i = 0; i < num_proc_filters; i++) {
194 if (!proc_filters[i]) continue;
195 if (strncmp(proc_filters[i], process_name, process_name_length) == 0) {
196 found = !proc_filter_excluding;
197 break;
198 }
199 }
200 if (found) {
201 proc_matched = 1;
202 }
203 }
204 return proc_matched;
205}
206
132static void syslog_callback(char c, void *user_data) 207static void syslog_callback(char c, void *user_data)
133{ 208{
134 if (lp >= line_buffer_size-1) { 209 if (lp >= line_buffer_size-1) {
@@ -202,20 +277,9 @@ static void syslog_callback(char c, void *user_data)
202 } 277 }
203 278
204 /* check message filters */ 279 /* check message filters */
205 if (num_msg_filters > 0) { 280 shall_print = message_filter_matching(device_name_end+1);
206 int found = 0; 281 if (!shall_print) {
207 int i; 282 break;
208 for (i = 0; i < num_msg_filters; i++) {
209 if (strstr(device_name_end+1, msg_filters[i])) {
210 found = 1;
211 break;
212 }
213 }
214 if (!found) {
215 shall_print = 0;
216 break;
217 }
218 shall_print = 1;
219 } 283 }
220 284
221 /* process name */ 285 /* process name */
@@ -235,39 +299,10 @@ static void syslog_callback(char c, void *user_data)
235 proc_name_end = p; 299 proc_name_end = p;
236 p++; 300 p++;
237 301
238 int proc_matched = 0; 302 /* match pid / process name */
239 if (num_pid_filters > 0) { 303 char* endp = NULL;
240 char* endp = NULL; 304 int pid_value = (int)strtol(pid_start, &endp, 10);
241 int pid_value = (int)strtol(pid_start, &endp, 10); 305 if (process_filter_matching(pid_value, process_name_start, process_name_end-process_name_start)) {
242 if (endp && (*endp == ']')) {
243 int found = proc_filter_excluding;
244 int i = 0;
245 for (i = 0; i < num_pid_filters; i++) {
246 if (pid_value == pid_filters[i]) {
247 found = !proc_filter_excluding;
248 break;
249 }
250 }
251 if (found) {
252 proc_matched = 1;
253 }
254 }
255 }
256 if (num_proc_filters > 0 && !proc_matched) {
257 int found = proc_filter_excluding;
258 int i = 0;
259 for (i = 0; i < num_proc_filters; i++) {
260 if (!proc_filters[i]) continue;
261 if (strncmp(proc_filters[i], process_name_start, process_name_end-process_name_start) == 0) {
262 found = !proc_filter_excluding;
263 break;
264 }
265 }
266 if (found) {
267 proc_matched = 1;
268 }
269 }
270 if (proc_matched) {
271 shall_print = 1; 306 shall_print = 1;
272 } else { 307 } else {
273 if (num_pid_filters > 0 || num_proc_filters > 0) { 308 if (num_pid_filters > 0 || num_proc_filters > 0) {
@@ -331,7 +366,7 @@ static void syslog_callback(char c, void *user_data)
331 } 366 }
332 } while (0); 367 } while (0);
333 368
334 if ((num_msg_filters == 0 && num_proc_filters == 0 && num_pid_filters == 0 && num_trigger_filters == 0 && num_untrigger_filters == 0) || shall_print) { 369 if ((num_msg_filters == 0 && num_msg_reverse_filters == 0 && num_proc_filters == 0 && num_pid_filters == 0 && num_trigger_filters == 0 && num_untrigger_filters == 0) || shall_print) {
335 fwrite(linep, 1, lp, stdout); 370 fwrite(linep, 1, lp, stdout);
336 cprintf(COLOR_RESET); 371 cprintf(COLOR_RESET);
337 fflush(stdout); 372 fflush(stdout);
@@ -345,12 +380,231 @@ static void syslog_callback(char c, void *user_data)
345 } 380 }
346} 381}
347 382
348static int start_logging(void) 383static void ostrace_syslog_callback(const void* buf, size_t len, void* user_data)
349{ 384{
350 idevice_error_t ret = idevice_new_with_options(&device, udid, (use_network) ? IDEVICE_LOOKUP_NETWORK : IDEVICE_LOOKUP_USBMUX); 385 if (len < 0x81) {
351 if (ret != IDEVICE_E_SUCCESS) { 386 fprintf(stderr, "Error: not enough data in callback function?!\n");
352 fprintf(stderr, "Device with udid %s not found!?\n", udid); 387 return;
353 return -1; 388 }
389
390 struct ostrace_packet_header_t *trace_hdr = (struct ostrace_packet_header_t*)buf;
391
392 if (trace_hdr->marker != 2 || (trace_hdr->type != 8 && trace_hdr->type != 2)) {
393 fprintf(stderr, "unexpected packet data %02x %08x\n", trace_hdr->marker, trace_hdr->type);
394 }
395
396 const char* dataptr = (const char*)buf + trace_hdr->header_size;
397 const char* process_name = dataptr;
398 const char* image_name = (trace_hdr->imagepath_len > 0) ? dataptr + trace_hdr->procpath_len : NULL;
399 const char* message = (trace_hdr->message_len > 0) ? dataptr + trace_hdr->procpath_len + trace_hdr->imagepath_len : NULL;
400 //const char* subsystem = (trace_hdr->subsystem_len > 0) ? dataptr + trace_hdr->procpath_len + trace_hdr->imagepath_len + trace_hdr->message_len : NULL;
401 //const char* category = (trace_hdr->category_len > 0) ? dataptr + trace_hdr->procpath_len + trace_hdr->imagepath_len + trace_hdr->message_len + trace_hdr->subsystem_len : NULL;
402
403 int shall_print = 1;
404 int trigger_off = 0;
405 const char* process_name_short = (process_name) ? strrchr(process_name, '/') : "";
406 process_name_short = (process_name_short) ? process_name_short+1 : process_name;
407 const char* image_name_short = (image_name) ? strrchr(image_name, '/') : NULL;
408 image_name_short = (image_name_short) ? image_name_short+1 : process_name;
409 if (image_name_short && !strcmp(image_name_short, process_name_short)) {
410 image_name_short = NULL;
411 }
412
413 do {
414 /* check if we have any triggers/untriggers */
415 if (num_untrigger_filters > 0 && triggered) {
416 int found = 0;
417 int i;
418 for (i = 0; i < num_untrigger_filters; i++) {
419 if (strstr(message, untrigger_filters[i])) {
420 found = 1;
421 break;
422 }
423 }
424 if (!found) {
425 shall_print = 1;
426 } else {
427 shall_print = 1;
428 trigger_off = 1;
429 }
430 } else if (num_trigger_filters > 0 && !triggered) {
431 int found = 0;
432 int i;
433 for (i = 0; i < num_trigger_filters; i++) {
434 if (strstr(message, trigger_filters[i])) {
435 found = 1;
436 break;
437 }
438 }
439 if (!found) {
440 shall_print = 0;
441 break;
442 }
443 triggered = 1;
444 shall_print = 1;
445 } else if (num_trigger_filters == 0 && num_untrigger_filters > 0 && !triggered) {
446 shall_print = 0;
447 quit_flag++;
448 break;
449 }
450
451 /* check message filters */
452 shall_print = message_filter_matching(message);
453 if (!shall_print) {
454 break;
455 }
456
457 /* check process filters */
458 if (process_filter_matching(trace_hdr->pid, process_name_short, strlen(process_name_short))) {
459 shall_print = 1;
460 } else {
461 if (num_pid_filters > 0 || num_proc_filters > 0) {
462 shall_print = 0;
463 }
464 }
465 if (!shall_print) {
466 break;
467 }
468 } while (0);
469
470 if (!shall_print) {
471 return;
472 }
473
474 const char* level_str = "Unknown";
475 const char* level_color = FG_YELLOW;
476 switch (trace_hdr->level) {
477 case 0:
478 level_str = "Notice";
479 level_color = FG_GREEN;
480 break;
481 case 0x01:
482 level_str = "Info";
483 level_color = FG_WHITE;
484 break;
485 case 0x02:
486 level_str = "Debug";
487 level_color = FG_MAGENTA;
488 break;
489 case 0x10:
490 level_str = "Error";
491 level_color = FG_RED;
492 break;
493 case 0x11:
494 level_str = "Fault";
495 level_color = FG_RED;
496 default:
497 break;
498 }
499
500 char datebuf[24];
501 struct tm *tp;
502 time_t time_sec = (time_t)trace_hdr->time_sec;
503#ifdef HAVE_LOCALTIME_R
504 struct tm tp_ = {0, };
505 tp = localtime_r(&time_sec, &tp_);
506#else
507 tp = localtime(&time_sec);
508#endif
509#ifdef _WIN32
510 strftime(datebuf, 16, "%b %#d %H:%M:%S", tp);
511#else
512 strftime(datebuf, 16, "%b %e %H:%M:%S", tp);
513#endif
514 snprintf(datebuf+15, 9, ".%06u", trace_hdr->time_usec);
515
516 /* write date and time */
517 cprintf(FG_LIGHT_GRAY "%s ", datebuf);
518
519 if (show_device_name) {
520 /* write device name TODO do we need this? */
521 //cprintf(FG_DARK_YELLOW "%s ", device_name);
522 }
523
524 /* write process name */
525 cprintf(FG_BRIGHT_CYAN "%s" FG_CYAN, process_name_short);
526 if (image_name_short) {
527 cprintf("(%s)", image_name_short);
528 }
529 cprintf("[%d]" COLOR_RESET " ", trace_hdr->pid);
530
531 /* write log level */
532 cprintf(level_color);
533 cprintf("<%s>:" COLOR_RESET " ", level_str);
534
535 /* write message */
536 cprintf(FG_WHITE);
537 cprintf("%s" COLOR_RESET "\n", message);
538 fflush(stdout);
539
540 if (trigger_off) {
541 triggered = 0;
542 }
543}
544
545static plist_t get_pid_list()
546{
547 plist_t list = NULL;
548 ostrace_client_t ostrace_tmp = NULL;
549 ostrace_client_start_service(device, &ostrace_tmp, TOOL_NAME);
550 if (ostrace_tmp) {
551 ostrace_get_pid_list(ostrace_tmp, &list);
552 ostrace_client_free(ostrace_tmp);
553 }
554 return list;
555}
556
557static int pid_valid(int pid)
558{
559 plist_t list = get_pid_list();
560 if (!list) return 0;
561 char valbuf[16];
562 snprintf(valbuf, 16, "%d", pid);
563 return (plist_dict_get_item(list, valbuf)) ? 1 : 0;
564}
565
566static int pid_for_proc(const char* procname)
567{
568 int result = -1;
569 plist_t list = get_pid_list();
570 if (!list) {
571 return result;
572 }
573 plist_dict_iter iter = NULL;
574 plist_dict_new_iter(list, &iter);
575 if (iter) {
576 plist_t node = NULL;
577 do {
578 char* key = NULL;
579 node = NULL;
580 plist_dict_next_item(list, iter, &key, &node);
581 if (!key) {
582 break;
583 }
584 if (PLIST_IS_DICT(node)) {
585 plist_t pname = plist_dict_get_item(node, "ProcessName");
586 if (PLIST_IS_STRING(pname)) {
587 if (!strcmp(plist_get_string_ptr(pname, NULL), procname)) {
588 result = (int)strtol(key, NULL, 10);
589 }
590 }
591 }
592 free(key);
593 } while (node);
594 plist_mem_free(iter);
595 }
596 plist_free(list);
597 return result;
598}
599
600static int connect_service(int ostrace_required)
601{
602 if (!device) {
603 idevice_error_t ret = idevice_new_with_options(&device, udid, (use_network) ? IDEVICE_LOOKUP_NETWORK : IDEVICE_LOOKUP_USBMUX);
604 if (ret != IDEVICE_E_SUCCESS) {
605 fprintf(stderr, "Device with udid %s not found!?\n", udid);
606 return -1;
607 }
354 } 608 }
355 609
356 lockdownd_client_t lockdown = NULL; 610 lockdownd_client_t lockdown = NULL;
@@ -361,14 +615,28 @@ static int start_logging(void)
361 device = NULL; 615 device = NULL;
362 return -1; 616 return -1;
363 } 617 }
364
365 /* start syslog_relay service */
366 lockdownd_service_descriptor_t svc = NULL; 618 lockdownd_service_descriptor_t svc = NULL;
367 lerr = lockdownd_start_service(lockdown, SYSLOG_RELAY_SERVICE_NAME, &svc); 619
620 const char* service_name = OSTRACE_SERVICE_NAME;
621 int use_ostrace = 1;
622 if (idevice_get_device_version(device) < IDEVICE_DEVICE_VERSION(9,0,0) || force_syslog_relay) {
623 service_name = SYSLOG_RELAY_SERVICE_NAME;
624 use_ostrace = 0;
625 }
626 if (ostrace_required && !use_ostrace) {
627 fprintf(stderr, "ERROR: This operation requires iOS 9 or later.\n");
628 lockdownd_client_free(lockdown);
629 idevice_free(device);
630 device = NULL;
631 return -1;
632 }
633
634 /* start syslog_relay/os_trace_relay service */
635 lerr = lockdownd_start_service(lockdown, service_name, &svc);
368 if (lerr == LOCKDOWN_E_PASSWORD_PROTECTED) { 636 if (lerr == LOCKDOWN_E_PASSWORD_PROTECTED) {
369 fprintf(stderr, "*** Device is passcode protected, enter passcode on the device to continue ***\n"); 637 fprintf(stderr, "*** Device is passcode protected, enter passcode on the device to continue ***\n");
370 while (!quit_flag) { 638 while (!quit_flag) {
371 lerr = lockdownd_start_service(lockdown, SYSLOG_RELAY_SERVICE_NAME, &svc); 639 lerr = lockdownd_start_service(lockdown, service_name, &svc);
372 if (lerr != LOCKDOWN_E_PASSWORD_PROTECTED) { 640 if (lerr != LOCKDOWN_E_PASSWORD_PROTECTED) {
373 break; 641 break;
374 } 642 }
@@ -376,32 +644,84 @@ static int start_logging(void)
376 } 644 }
377 } 645 }
378 if (lerr != LOCKDOWN_E_SUCCESS) { 646 if (lerr != LOCKDOWN_E_SUCCESS) {
379 fprintf(stderr, "ERROR: Could not connect to lockdownd: %d\n", lerr); 647 fprintf(stderr, "ERROR: Could not start %s service: %s (%d)\n", service_name, lockdownd_strerror(lerr), lerr);
380 idevice_free(device); 648 idevice_free(device);
381 device = NULL; 649 device = NULL;
382 return -1; 650 return -1;
383 } 651 }
384 lockdownd_client_free(lockdown); 652 lockdownd_client_free(lockdown);
385 653
386 /* connect to syslog_relay service */ 654 if (use_ostrace) {
387 syslog_relay_error_t serr = SYSLOG_RELAY_E_UNKNOWN_ERROR; 655 /* connect to os_trace_relay service */
388 serr = syslog_relay_client_new(device, svc, &syslog); 656 ostrace_error_t serr = OSTRACE_E_UNKNOWN_ERROR;
389 lockdownd_service_descriptor_free(svc); 657 serr = ostrace_client_new(device, svc, &ostrace);
390 if (serr != SYSLOG_RELAY_E_SUCCESS) { 658 lockdownd_service_descriptor_free(svc);
391 fprintf(stderr, "ERROR: Could not start service com.apple.syslog_relay.\n"); 659 if (serr != OSTRACE_E_SUCCESS) {
392 idevice_free(device); 660 fprintf(stderr, "ERROR: Could not connect to %s service (%d)\n", service_name, serr);
393 device = NULL; 661 idevice_free(device);
662 device = NULL;
663 return -1;
664 }
665 } else {
666 /* connect to syslog_relay service */
667 syslog_relay_error_t serr = SYSLOG_RELAY_E_UNKNOWN_ERROR;
668 serr = syslog_relay_client_new(device, svc, &syslog);
669 lockdownd_service_descriptor_free(svc);
670 if (serr != SYSLOG_RELAY_E_SUCCESS) {
671 fprintf(stderr, "ERROR: Could not connect to %s service (%d)\n", service_name, serr);
672 idevice_free(device);
673 device = NULL;
674 return -1;
675 }
676 }
677 return 0;
678}
679
680static int start_logging(void)
681{
682 if (connect_service(0) < 0) {
394 return -1; 683 return -1;
395 } 684 }
396 685
397 /* start capturing syslog */ 686 /* start capturing syslog */
398 serr = syslog_relay_start_capture_raw(syslog, syslog_callback, NULL); 687 if (ostrace) {
399 if (serr != SYSLOG_RELAY_E_SUCCESS) { 688 plist_t options = plist_new_dict();
400 fprintf(stderr, "ERROR: Unable tot start capturing syslog.\n"); 689 if (num_proc_filters == 0 && num_pid_filters == 1 && !proc_filter_excluding) {
401 syslog_relay_client_free(syslog); 690 if (pid_filters[0] > 0) {
402 syslog = NULL; 691 if (!pid_valid(pid_filters[0])) {
403 idevice_free(device); 692 fprintf(stderr, "NOTE: A process with pid doesn't exists!\n");
404 device = NULL; 693 }
694 }
695 plist_dict_set_item(options, "Pid", plist_new_int(pid_filters[0]));
696 } else if (num_proc_filters == 1 && num_pid_filters == 0 && !proc_filter_excluding) {
697 int pid = pid_for_proc(proc_filters[0]);
698 if (!strcmp(proc_filters[0], "kernel")) {
699 pid = 0;
700 }
701 if (pid >= 0) {
702 plist_dict_set_item(options, "Pid", plist_new_int(pid));
703 }
704 }
705 ostrace_error_t serr = ostrace_start_activity(ostrace, options, ostrace_syslog_callback, NULL);
706 if (serr != OSTRACE_E_SUCCESS) {
707 fprintf(stderr, "ERROR: Unable to start capturing syslog.\n");
708 ostrace_client_free(ostrace);
709 ostrace = NULL;
710 idevice_free(device);
711 device = NULL;
712 return -1;
713 }
714 } else if (syslog) {
715 syslog_relay_error_t serr = syslog_relay_start_capture_raw(syslog, syslog_callback, NULL);
716 if (serr != SYSLOG_RELAY_E_SUCCESS) {
717 fprintf(stderr, "ERROR: Unable to start capturing syslog.\n");
718 syslog_relay_client_free(syslog);
719 syslog = NULL;
720 idevice_free(device);
721 device = NULL;
722 return -1;
723 }
724 } else {
405 return -1; 725 return -1;
406 } 726 }
407 727
@@ -419,6 +739,11 @@ static void stop_logging(void)
419 syslog_relay_client_free(syslog); 739 syslog_relay_client_free(syslog);
420 syslog = NULL; 740 syslog = NULL;
421 } 741 }
742 if (ostrace) {
743 ostrace_stop_activity(ostrace);
744 ostrace_client_free(ostrace);
745 ostrace = NULL;
746 }
422 747
423 if (device) { 748 if (device) {
424 idevice_free(device); 749 idevice_free(device);
@@ -426,6 +751,77 @@ static void stop_logging(void)
426 } 751 }
427} 752}
428 753
754static int write_callback(const void* buf, size_t len, void *user_data)
755{
756 FILE* f = (FILE*)user_data;
757 ssize_t res = fwrite(buf, 1, len, f);
758 if (res < 0) {
759 return -1;
760 }
761 if (quit_flag > 0) {
762 return -1;
763 }
764 return 0;
765}
766
767static void print_sorted_pidlist(plist_t list)
768{
769 struct listelem;
770 struct listelem {
771 int val;
772 struct listelem *next;
773 };
774 struct listelem* sortedlist = NULL;
775
776 plist_dict_iter iter = NULL;
777 plist_dict_new_iter(list, &iter);
778 if (iter) {
779 plist_t node = NULL;
780 do {
781 char* key = NULL;
782 node = NULL;
783 plist_dict_next_item(list, iter, &key, &node);
784 if (key) {
785 int pidval = (int)strtol(key, NULL, 10);
786 struct listelem* elem = (struct listelem*)malloc(sizeof(struct listelem));
787 elem->val = pidval;
788 elem->next = NULL;
789 struct listelem* prev = NULL;
790 struct listelem* curr = sortedlist;
791
792 while (curr && pidval > curr->val) {
793 prev = curr;
794 curr = curr->next;
795 }
796
797 elem->next = curr;
798 if (prev == NULL) {
799 sortedlist = elem;
800 } else {
801 prev->next = elem;
802 }
803 free(key);
804 }
805 } while (node);
806 plist_mem_free(iter);
807 }
808 struct listelem *listp = sortedlist;
809 char pidstr[16];
810 while (listp) {
811 snprintf(pidstr, 16, "%d", listp->val);
812 plist_t node = plist_dict_get_item(list, pidstr);
813 if (PLIST_IS_DICT(node)) {
814 plist_t pname = plist_dict_get_item(node, "ProcessName");
815 if (PLIST_IS_STRING(pname)) {
816 printf("%d %s\n", listp->val, plist_get_string_ptr(pname, NULL));
817 }
818 }
819 struct listelem *curr = listp;
820 listp = listp->next;
821 free(curr);
822 }
823}
824
429static void device_event_cb(const idevice_event_t* event, void* userdata) 825static void device_event_cb(const idevice_event_t* event, void* userdata)
430{ 826{
431 if (use_network && event->conn_type != CONNECTION_NETWORK) { 827 if (use_network && event->conn_type != CONNECTION_NETWORK) {
@@ -435,7 +831,7 @@ static void device_event_cb(const idevice_event_t* event, void* userdata)
435 return; 831 return;
436 } 832 }
437 if (event->event == IDEVICE_DEVICE_ADD) { 833 if (event->event == IDEVICE_DEVICE_ADD) {
438 if (!syslog) { 834 if (!syslog && !ostrace) {
439 if (!udid) { 835 if (!udid) {
440 udid = strdup(event->udid); 836 udid = strdup(event->udid);
441 } 837 }
@@ -446,7 +842,7 @@ static void device_event_cb(const idevice_event_t* event, void* userdata)
446 } 842 }
447 } 843 }
448 } else if (event->event == IDEVICE_DEVICE_REMOVE) { 844 } else if (event->event == IDEVICE_DEVICE_REMOVE) {
449 if (syslog && (strcmp(udid, event->udid) == 0)) { 845 if ((syslog || ostrace) && (strcmp(udid, event->udid) == 0)) {
450 stop_logging(); 846 stop_logging();
451 fprintf(stdout, "[disconnected:%s]\n", udid); 847 fprintf(stdout, "[disconnected:%s]\n", udid);
452 if (exit_on_disconnect) { 848 if (exit_on_disconnect) {
@@ -484,9 +880,20 @@ static void print_usage(int argc, char **argv, int is_error)
484 " -o, --output FILE write to FILE instead of stdout\n" 880 " -o, --output FILE write to FILE instead of stdout\n"
485 " (existing FILE will be overwritten)\n" 881 " (existing FILE will be overwritten)\n"
486 " --colors force writing colored output, e.g. for --output\n" 882 " --colors force writing colored output, e.g. for --output\n"
883 " --syslog-relay force use of syslog_relay service\n"
884 "\n"
885 "COMMANDS:\n"
886 " pidlist Print pid and name of all running processes.\n"
887 " archive PATH Request a logarchive and write it to PATH.\n"
888 " Output can be piped to another process using - as PATH.\n"
889 " The file data will be in .tar format.\n"
890 " --start-time VALUE start time of the log data as UNIX timestamp\n"
891 " --age-limit VALUE maximum age of the log data\n"
892 " --size-limit VALUE limit the size of the archive\n"
487 "\n" 893 "\n"
488 "FILTER OPTIONS:\n" 894 "FILTER OPTIONS:\n"
489 " -m, --match STRING only print messages that contain STRING\n" 895 " -m, --match STRING only print messages that contain STRING\n"
896 " -M, --unmatch STRING print messages that not contain STRING\n"
490 " -t, --trigger STRING start logging when matching STRING\n" 897 " -t, --trigger STRING start logging when matching STRING\n"
491 " -T, --untrigger STRING stop logging when matching STRING\n" 898 " -T, --untrigger STRING stop logging when matching STRING\n"
492 " -p, --process PROCESS only print messages from matching process(es)\n" 899 " -p, --process PROCESS only print messages from matching process(es)\n"
@@ -530,6 +937,12 @@ int main(int argc, char *argv[])
530 { "quiet-list", no_argument, NULL, 1 }, 937 { "quiet-list", no_argument, NULL, 1 },
531 { "no-colors", no_argument, NULL, 2 }, 938 { "no-colors", no_argument, NULL, 2 },
532 { "colors", no_argument, NULL, 3 }, 939 { "colors", no_argument, NULL, 3 },
940 { "syslog_relay", no_argument, NULL, 4 },
941 { "syslog-relay", no_argument, NULL, 4 },
942 { "legacy", no_argument, NULL, 4 },
943 { "start-time", required_argument, NULL, 5 },
944 { "size-limit", required_argument, NULL, 6 },
945 { "age-limit", required_argument, NULL, 7 },
533 { "output", required_argument, NULL, 'o' }, 946 { "output", required_argument, NULL, 'o' },
534 { "version", no_argument, NULL, 'v' }, 947 { "version", no_argument, NULL, 'v' },
535 { NULL, 0, NULL, 0} 948 { NULL, 0, NULL, 0}
@@ -537,12 +950,12 @@ int main(int argc, char *argv[])
537 950
538 signal(SIGINT, clean_exit); 951 signal(SIGINT, clean_exit);
539 signal(SIGTERM, clean_exit); 952 signal(SIGTERM, clean_exit);
540#ifndef WIN32 953#ifndef _WIN32
541 signal(SIGQUIT, clean_exit); 954 signal(SIGQUIT, clean_exit);
542 signal(SIGPIPE, SIG_IGN); 955 signal(SIGPIPE, SIG_IGN);
543#endif 956#endif
544 957
545 while ((c = getopt_long(argc, argv, "dhu:nxt:T:m:e:p:qkKo:v", longopts, NULL)) != -1) { 958 while ((c = getopt_long(argc, argv, "dhu:nxt:T:m:M:e:p:qkKo:v", longopts, NULL)) != -1) {
546 switch (c) { 959 switch (c) {
547 case 'd': 960 case 'd':
548 idevice_set_debug_level(1); 961 idevice_set_debug_level(1);
@@ -593,6 +1006,22 @@ int main(int argc, char *argv[])
593 num_msg_filters++; 1006 num_msg_filters++;
594 } 1007 }
595 break; 1008 break;
1009 case 'M':
1010 if (!*optarg) {
1011 fprintf(stderr, "ERROR: reverse message filter string must not be empty!\n");
1012 print_usage(argc, argv, 1);
1013 return 2;
1014 } else {
1015 char **new_msg_filters = realloc(msg_reverse_filters, sizeof(char*) * (num_msg_reverse_filters+1));
1016 if (!new_msg_filters) {
1017 fprintf(stderr, "ERROR: realloc() failed\n");
1018 exit(EXIT_FAILURE);
1019 }
1020 msg_reverse_filters = new_msg_filters;
1021 msg_reverse_filters[num_msg_reverse_filters] = strdup(optarg);
1022 num_msg_reverse_filters++;
1023 }
1024 break;
596 case 't': 1025 case 't':
597 if (!*optarg) { 1026 if (!*optarg) {
598 fprintf(stderr, "ERROR: trigger filter string must not be empty!\n"); 1027 fprintf(stderr, "ERROR: trigger filter string must not be empty!\n");
@@ -647,6 +1076,18 @@ int main(int argc, char *argv[])
647 case 3: 1076 case 3:
648 force_colors = 1; 1077 force_colors = 1;
649 break; 1078 break;
1079 case 4:
1080 force_syslog_relay = 1;
1081 break;
1082 case 5:
1083 start_time = strtoll(optarg, NULL, 10);
1084 break;
1085 case 6:
1086 size_limit = strtoll(optarg, NULL, 10);
1087 break;
1088 case 7:
1089 age_limit = strtoll(optarg, NULL, 10);
1090 break;
650 case 'o': 1091 case 'o':
651 if (!*optarg) { 1092 if (!*optarg) {
652 fprintf(stderr, "ERROR: --output option requires an argument!\n"); 1093 fprintf(stderr, "ERROR: --output option requires an argument!\n");
@@ -719,14 +1160,92 @@ int main(int argc, char *argv[])
719 argc -= optind; 1160 argc -= optind;
720 argv += optind; 1161 argv += optind;
721 1162
1163 if (argc > 0) {
1164 if (!strcmp(argv[0], "pidlist")) {
1165 if (connect_service(1) < 0) {
1166 return 1;
1167 }
1168 plist_t list = NULL;
1169 ostrace_get_pid_list(ostrace, &list);
1170 ostrace_client_free(ostrace);
1171 ostrace = NULL;
1172 idevice_free(device);
1173 device = NULL;
1174 if (!list) {
1175 return 1;
1176 }
1177 print_sorted_pidlist(list);
1178 plist_free(list);
1179 return 0;
1180 } else if (!strcmp(argv[0], "archive")) {
1181 if (force_syslog_relay) {
1182 force_syslog_relay = 0;
1183 }
1184 if (argc < 2) {
1185 fprintf(stderr, "Please specify an output filename.\n");
1186 return 1;
1187 }
1188 FILE* outf = NULL;
1189 if (!strcmp(argv[1], "-")) {
1190 if (isatty(1)) {
1191 fprintf(stderr, "Refusing to directly write to stdout. Pipe the output to another process.\n");
1192 return 1;
1193 }
1194 outf = stdout;
1195 } else {
1196 outf = fopen(argv[1], "w");
1197 }
1198 if (!outf) {
1199 fprintf(stderr, "Failed to open %s: %s\n", argv[1], strerror(errno));
1200 return 1;
1201 }
1202 if (connect_service(1) < 0) {
1203 if (outf != stdout) {
1204 fclose(outf);
1205 }
1206 return 1;
1207 }
1208 plist_t options = plist_new_dict();
1209 if (start_time > 0) {
1210 plist_dict_set_item(options, "StartTime", plist_new_int(start_time));
1211 }
1212 if (size_limit > 0) {
1213 plist_dict_set_item(options, "SizeLimit", plist_new_int(size_limit));
1214 }
1215 if (age_limit > 0) {
1216 plist_dict_set_item(options, "AgeLimit", plist_new_int(age_limit));
1217 }
1218 ostrace_create_archive(ostrace, options, write_callback, outf);
1219 ostrace_client_free(ostrace);
1220 ostrace = NULL;
1221 idevice_free(device);
1222 device = NULL;
1223 if (outf != stdout) {
1224 fclose(outf);
1225 }
1226 return 0;
1227 } else {
1228 fprintf(stderr, "Unknown command '%s'. See --help for valid commands.\n", argv[0]);
1229 return 1;
1230 }
1231 }
1232
722 int num = 0; 1233 int num = 0;
723 idevice_info_t *devices = NULL; 1234 idevice_info_t *devices = NULL;
724 idevice_get_device_list_extended(&devices, &num); 1235 idevice_get_device_list_extended(&devices, &num);
1236 int count = 0;
1237 for (int i = 0; i < num; i++) {
1238 if (devices[i]->conn_type == CONNECTION_NETWORK && use_network) {
1239 count++;
1240 } else if (devices[i]->conn_type == CONNECTION_USBMUXD) {
1241 count++;
1242 }
1243 }
725 idevice_device_list_extended_free(devices); 1244 idevice_device_list_extended_free(devices);
726 if (num == 0) { 1245 if (count == 0) {
727 if (!udid) { 1246 if (!udid) {
728 fprintf(stderr, "No device found. Plug in a device or pass UDID with -u to wait for device to be available.\n"); 1247 fprintf(stderr, "No device found. Plug in a device or pass UDID with -u to wait for device to become available.\n");
729 return -1; 1248 return 1;
730 } 1249 }
731 1250
732 fprintf(stderr, "Waiting for device with UDID %s to become available...\n", udid); 1251 fprintf(stderr, "Waiting for device with UDID %s to become available...\n", udid);
@@ -761,6 +1280,13 @@ int main(int argc, char *argv[])
761 } 1280 }
762 free(msg_filters); 1281 free(msg_filters);
763 } 1282 }
1283 if (num_msg_reverse_filters > 0) {
1284 int i;
1285 for (i = 0; i < num_msg_reverse_filters; i++) {
1286 free(msg_reverse_filters[i]);
1287 }
1288 free(msg_reverse_filters);
1289 }
764 if (num_trigger_filters > 0) { 1290 if (num_trigger_filters > 0) {
765 int i; 1291 int i;
766 for (i = 0; i < num_trigger_filters; i++) { 1292 for (i = 0; i < num_trigger_filters; i++) {