summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile.am12
-rw-r--r--tools/afcclient.c202
-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.c52
-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, 932 insertions, 418 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 = \
afcclient
idevicebtlogger_SOURCES = idevicebtlogger.c
-iidevicebtlogger_CFLAGS = $(AM_CFLAGS)
+idevicebtlogger_CFLAGS = $(AM_CFLAGS)
idevicebtlogger_LDFLAGS = $(top_builddir)/common/libinternalcommon.la $(AM_LDFLAGS)
idevicebtlogger_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la
@@ -51,8 +51,8 @@ idevicename_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la
idevicepair_SOURCES = idevicepair.c
idevicepair_CFLAGS = $(AM_CFLAGS)
-idevicepair_LDFLAGS = $(AM_LDFLAGS) $(libusbmuxd_LIBS) $(ssl_lib_LIBS)
-idevicepair_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la $(top_builddir)/common/libinternalcommon.la $(limd_glue_LIBS)
+idevicepair_LDFLAGS = $(AM_LDFLAGS) $(libusbmuxd_LIBS)
+idevicepair_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la $(top_builddir)/common/libinternalcommon.la $(limd_glue_LIBS) $(ssl_lib_LIBS)
idevicesyslog_SOURCES = idevicesyslog.c
idevicesyslog_CFLAGS = $(AM_CFLAGS) $(limd_glue_CFLAGS)
@@ -76,7 +76,7 @@ idevicebackup2_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la
ideviceimagemounter_SOURCES = ideviceimagemounter.c
ideviceimagemounter_CFLAGS = $(AM_CFLAGS) $(limd_glue_CFLAGS) $(libtatsu_CFLAGS)
-ideviceimagemounter_LDFLAGS = $(AM_LDFLAGS) $(limd_glue_LIBS) $(ssl_lib_LIBS) $(libtatsu_LIBS)
+ideviceimagemounter_LDFLAGS = $(AM_LDFLAGS) $(limd_glue_LIBS) $(libtatsu_LIBS)
ideviceimagemounter_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la
idevicescreenshot_SOURCES = idevicescreenshot.c
@@ -135,8 +135,8 @@ idevicesetlocation_LDFLAGS = $(AM_LDFLAGS)
idevicesetlocation_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la
afcclient_SOURCES = afcclient.c
-afcclient_CFLAGS = $(AM_CFLAGS)
-afcclient_LDFLAGS = $(AM_LDFLAGS)
+afcclient_CFLAGS = $(AM_CFLAGS) $(limd_glue_CFLAGS)
+afcclient_LDFLAGS = $(AM_LDFLAGS) $(limd_glue_LIBS)
if HAVE_READLINE
afcclient_CFLAGS += $(readline_CFLAGS)
afcclient_LDFLAGS += $(readline_LIBS)
diff --git a/tools/afcclient.c b/tools/afcclient.c
index 8f49831..a958c23 100644
--- a/tools/afcclient.c
+++ b/tools/afcclient.c
@@ -38,8 +38,9 @@
#include <unistd.h>
#include <dirent.h>
#include <time.h>
+#include <sys/stat.h>
-#ifdef WIN32
+#ifdef _WIN32
#include <windows.h>
#include <sys/time.h>
#include <conio.h>
@@ -95,7 +96,7 @@ static size_t curdir_len = 0;
static int file_exists(const char* path)
{
struct stat tst;
-#ifdef WIN32
+#ifdef _WIN32
return (stat(path, &tst) == 0);
#else
return (lstat(path, &tst) == 0);
@@ -105,7 +106,7 @@ static int file_exists(const char* path)
static int is_directory(const char* path)
{
struct stat tst;
-#ifdef WIN32
+#ifdef _WIN32
return (stat(path, &tst) == 0) && S_ISDIR(tst.st_mode);
#else
return (lstat(path, &tst) == 0) && S_ISDIR(tst.st_mode);
@@ -138,7 +139,7 @@ static void print_usage(int argc, char **argv, int is_error)
}
#ifndef HAVE_READLINE
-#ifdef WIN32
+#ifdef _WIN32
#define BS_CC '\b'
#else
#define BS_CC 0x7f
@@ -175,7 +176,7 @@ int stop_requested = 0;
static void handle_signal(int sig)
{
stop_requested++;
-#ifdef WIN32
+#ifdef _WIN32
GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
#else
kill(getpid(), SIGINT);
@@ -364,62 +365,55 @@ static char* get_realpath(const char* path)
static void handle_devinfo(afc_client_t afc, int argc, char** argv)
{
- char **info = NULL;
- afc_error_t err = afc_get_device_info(afc, &info);
+ plist_t info = NULL;
+ afc_error_t err = afc_get_device_info_plist(afc, &info);
if (err == AFC_E_SUCCESS && info) {
- int i;
- for (i = 0; info[i]; i += 2) {
- printf("%s: %s\n", info[i], info[i+1]);
+ if (argc > 0 && !strcmp(argv[0], "--plain")) {
+ plist_write_to_stream(info, stdout, PLIST_FORMAT_LIMD, PLIST_OPT_NONE);
+ } else {
+ plist_write_to_stream(info, stdout, PLIST_FORMAT_JSON, PLIST_OPT_NONE);
}
} else {
printf("Error: Failed to get device info: %s (%d)\n", afc_strerror(err), err);
}
- afc_dictionary_free(info);
+ plist_free(info);
}
static int get_file_info_stat(afc_client_t afc, const char* path, struct afc_file_stat *stbuf)
{
- char **info = NULL;
- afc_error_t ret = afc_get_file_info(afc, path, &info);
+ plist_t info = NULL;
+ afc_error_t ret = afc_get_file_info_plist(afc, path, &info);
memset(stbuf, 0, sizeof(struct afc_file_stat));
if (ret != AFC_E_SUCCESS) {
return -1;
} else if (!info) {
return -1;
- } else {
- // get file attributes from info list
- int i;
- for (i = 0; info[i]; i += 2) {
- if (!strcmp(info[i], "st_size")) {
- stbuf->st_size = atoll(info[i+1]);
- } else if (!strcmp(info[i], "st_blocks")) {
- stbuf->st_blocks = atoi(info[i+1]);
- } else if (!strcmp(info[i], "st_ifmt")) {
- if (!strcmp(info[i+1], "S_IFREG")) {
- stbuf->st_mode = S_IFREG;
- } else if (!strcmp(info[i+1], "S_IFDIR")) {
- stbuf->st_mode = S_IFDIR;
- } else if (!strcmp(info[i+1], "S_IFLNK")) {
- stbuf->st_mode = S_IFLNK;
- } else if (!strcmp(info[i+1], "S_IFBLK")) {
- stbuf->st_mode = S_IFBLK;
- } else if (!strcmp(info[i+1], "S_IFCHR")) {
- stbuf->st_mode = S_IFCHR;
- } else if (!strcmp(info[i+1], "S_IFIFO")) {
- stbuf->st_mode = S_IFIFO;
- } else if (!strcmp(info[i+1], "S_IFSOCK")) {
- stbuf->st_mode = S_IFSOCK;
- }
- } else if (!strcmp(info[i], "st_nlink")) {
- stbuf->st_nlink = atoi(info[i+1]);
- } else if (!strcmp(info[i], "st_mtime")) {
- stbuf->st_mtime = (time_t)(atoll(info[i+1]) / 1000000000);
- } else if (!strcmp(info[i], "st_birthtime")) { /* available on iOS 7+ */
- stbuf->st_birthtime = (time_t)(atoll(info[i+1]) / 1000000000);
- }
- }
- afc_dictionary_free(info);
}
+ stbuf->st_size = plist_dict_get_uint(info, "st_size");
+ stbuf->st_blocks = plist_dict_get_uint(info, "st_blocks");
+ const char* s_ifmt = plist_get_string_ptr(plist_dict_get_item(info, "st_ifmt"), NULL);
+ if (s_ifmt) {
+ if (!strcmp(s_ifmt, "S_IFREG")) {
+ stbuf->st_mode = S_IFREG;
+ } else if (!strcmp(s_ifmt, "S_IFDIR")) {
+ stbuf->st_mode = S_IFDIR;
+ } else if (!strcmp(s_ifmt, "S_IFLNK")) {
+ stbuf->st_mode = S_IFLNK;
+ } else if (!strcmp(s_ifmt, "S_IFBLK")) {
+ stbuf->st_mode = S_IFBLK;
+ } else if (!strcmp(s_ifmt, "S_IFCHR")) {
+ stbuf->st_mode = S_IFCHR;
+ } else if (!strcmp(s_ifmt, "S_IFIFO")) {
+ stbuf->st_mode = S_IFIFO;
+ } else if (!strcmp(s_ifmt, "S_IFSOCK")) {
+ stbuf->st_mode = S_IFSOCK;
+ }
+ }
+ stbuf->st_nlink = plist_dict_get_uint(info, "st_nlink");
+ stbuf->st_mtime = (time_t)(plist_dict_get_uint(info, "st_mtime") / 1000000000);
+ /* available on iOS 7+ */
+ stbuf->st_birthtime = (time_t)(plist_dict_get_uint(info, "st_birthtime") / 1000000000);
+ plist_free(info);
return 0;
}
@@ -430,22 +424,23 @@ static void handle_file_info(afc_client_t afc, int argc, char** argv)
return;
}
- char **info = NULL;
+ plist_t info = NULL;
char* abspath = get_absolute_path(argv[0]);
if (!abspath) {
printf("Error: Invalid argument\n");
return;
}
- afc_error_t err = afc_get_file_info(afc, abspath, &info);
+ afc_error_t err = afc_get_file_info_plist(afc, abspath, &info);
if (err == AFC_E_SUCCESS && info) {
- int i;
- for (i = 0; info[i]; i += 2) {
- printf("%s: %s\n", info[i], info[i+1]);
+ if (argc > 1 && !strcmp(argv[1], "--plain")) {
+ plist_write_to_stream(info, stdout, PLIST_FORMAT_LIMD, PLIST_OPT_NONE);
+ } else {
+ plist_write_to_stream(info, stdout, PLIST_FORMAT_JSON, PLIST_OPT_NONE);
}
} else {
printf("Error: Failed to get file info for %s: %s (%d)\n", argv[0], afc_strerror(err), err);
}
- afc_dictionary_free(info);
+ plist_free(info);
free(abspath);
}
@@ -483,7 +478,7 @@ static void print_file_info(afc_client_t afc, const char* path, int list_verbose
printf(" ");
printf("%10lld", (long long)st.st_size);
printf(" ");
-#ifdef WIN32
+#ifdef _WIN32
strftime(timebuf, 64, "%d %b %Y %H:%M:%S", localtime(&t));
#else
strftime(timebuf, 64, "%d %h %Y %H:%M:%S", localtime(&t));
@@ -774,7 +769,7 @@ static uint8_t get_single_file(afc_client_t afc, const char *srcpath, const char
static int __mkdir(const char* path)
{
-#ifdef WIN32
+#ifdef _WIN32
return mkdir(path);
#else
return mkdir(path, 0755);
@@ -783,28 +778,19 @@ static int __mkdir(const char* path)
static uint8_t get_file(afc_client_t afc, const char *srcpath, const char *dstpath, uint8_t force_overwrite, uint8_t recursive_get)
{
- char **info = NULL;
+ plist_t info = NULL;
uint64_t file_size = 0;
- afc_error_t err = afc_get_file_info(afc, srcpath, &info);
+ afc_error_t err = afc_get_file_info_plist(afc, srcpath, &info);
if (err == AFC_E_OBJECT_NOT_FOUND) {
printf("Error: Failed to read from file '%s': %s (%d)\n", srcpath, afc_strerror(err), err);
return 0;
}
uint8_t is_dir = 0;
if (info) {
- char **p = info;
- while (p && *p) {
- if (!strcmp(*p, "st_size")) {
- p++;
- file_size = (uint64_t) strtoull(*p, NULL, 10);
- }
- if (!strcmp(*p, "st_ifmt")) {
- p++;
- is_dir = !strcmp(*p, "S_IFDIR");
- }
- p++;
- }
- afc_dictionary_free(info);
+ file_size = plist_dict_get_uint(info, "st_size");
+ const char* ifmt = plist_get_string_ptr(plist_dict_get_item(info, "st_ifmt"), NULL);
+ is_dir = (ifmt && !strcmp(ifmt, "S_IFDIR"));
+ plist_free(info);
}
uint8_t succeed = 1;
if (is_dir) {
@@ -837,7 +823,7 @@ static uint8_t get_file(afc_client_t afc, const char *srcpath, const char *dstpa
p++;
continue;
}
- size_t len = srcpath_is_root ? strlen(*p) + 1 : srcpath_len + 1 + strlen(*p) + 1;
+ size_t len = srcpath_is_root ? (strlen(*p) + 2) : (srcpath_len + 1 + strlen(*p) + 1);
char *testpath = (char *) malloc(len);
if (srcpath_is_root) {
snprintf(testpath, len, "/%s", *p);
@@ -845,7 +831,7 @@ static uint8_t get_file(afc_client_t afc, const char *srcpath, const char *dstpa
snprintf(testpath, len, "%s/%s", srcpath, *p);
}
uint8_t dst_is_root = strcmp(srcpath, "/") == 0;
- size_t dst_len = dst_is_root ? strlen(*p) + 1 : strlen(dstpath) + 1 + strlen(*p) + 1;
+ size_t dst_len = dst_is_root ? (strlen(*p) + 2) : (strlen(dstpath) + 1 + strlen(*p) + 1);
char *newdst = (char *) malloc(dst_len);
if (dst_is_root) {
snprintf(newdst, dst_len, "/%s", *p);
@@ -921,9 +907,9 @@ static void handle_get(afc_client_t afc, int argc, char **argv)
// target is a directory, put file under this target
if (is_directory(dstpath)) {
- const char *basen = path_get_basename(argv[0]);
+ const char *basen = path_get_basename(srcpath);
uint8_t dst_is_root = strcmp(dstpath, "/") == 0;
- size_t len = dst_is_root ? (strlen(basen) + 1) : (strlen(dstpath) + 1 + strlen(basen) + 1);
+ size_t len = dst_is_root ? (strlen(basen) + 2) : (strlen(dstpath) + 1 + strlen(basen) + 1);
char *newdst = (char *) malloc(len);
if (dst_is_root) {
snprintf(newdst, len, "/%s", basen);
@@ -944,11 +930,11 @@ static void handle_get(afc_client_t afc, int argc, char **argv)
static uint8_t put_single_file(afc_client_t afc, const char *srcpath, const char *dstpath, uint8_t force_overwrite)
{
- char **info = NULL;
- afc_error_t ret = afc_get_file_info(afc, dstpath, &info);
+ plist_t info = NULL;
+ afc_error_t ret = afc_get_file_info_plist(afc, dstpath, &info);
// file exists, only overwrite with '-f' option was set
if (ret == AFC_E_SUCCESS && info) {
- afc_dictionary_free(info);
+ plist_free(info);
if (!force_overwrite) {
printf("Error: Failed to write into existing file without '-f' option: %s\n", dstpath);
return 0;
@@ -1029,10 +1015,11 @@ static uint8_t put_file(afc_client_t afc, const char *srcpath, const char *dstpa
printf("Error: Failed to put directory without '-r' option: %s\n", srcpath);
return 0;
}
- char **info = NULL;
- afc_error_t err = afc_get_file_info(afc, dstpath, &info);
+ plist_t info = NULL;
+ afc_error_t err = afc_get_file_info_plist(afc, dstpath, &info);
//create if target directory does not exist
- afc_dictionary_free(info);
+ plist_free(info);
+ info = NULL;
if (err == AFC_E_OBJECT_NOT_FOUND) {
err = afc_make_directory(afc, dstpath);
if (err != AFC_E_SUCCESS) {
@@ -1043,19 +1030,12 @@ static uint8_t put_file(afc_client_t afc, const char *srcpath, const char *dstpa
printf("Error: Failed to put existing directory without '-f' option: %s\n", dstpath);
return 0;
}
- afc_get_file_info(afc, dstpath, &info);
+ afc_get_file_info_plist(afc, dstpath, &info);
uint8_t is_dir = 0;
if (info) {
- char **p = info;
- while (p && *p) {
- if (!strcmp(*p, "st_ifmt")) {
- p++;
- is_dir = !strcmp(*p, "S_IFDIR");
- break;
- }
- p++;
- }
- afc_dictionary_free(info);
+ const char* ifmt = plist_get_string_ptr(plist_dict_get_item(info, "st_ifmt"), NULL);
+ is_dir = (ifmt && !strcmp(ifmt, "S_IFDIR"));
+ plist_free(info);
}
if (!is_dir) {
printf("Error: Failed to create or access directory: '%s'\n", dstpath);
@@ -1073,7 +1053,7 @@ static uint8_t put_file(afc_client_t afc, const char *srcpath, const char *dstpa
char *fpath = string_build_path(srcpath, ep->d_name, NULL);
if (fpath) {
uint8_t dst_is_root = strcmp(dstpath, "/") == 0;
- size_t len = dst_is_root ? strlen(ep->d_name) + 1 : strlen(dstpath) + 1 + strlen(ep->d_name) + 1;
+ size_t len = dst_is_root ? (strlen(ep->d_name) + 2) : (strlen(dstpath) + 1 + strlen(ep->d_name) + 1);
char *newdst = (char *) malloc(len);
if (dst_is_root) {
snprintf(newdst, len, "/%s", ep->d_name);
@@ -1147,8 +1127,8 @@ static void handle_put(afc_client_t afc, int argc, char **argv)
printf("Error: Invalid number of arguments\n");
return;
}
- char **info = NULL;
- afc_error_t err = afc_get_file_info(afc, dstpath, &info);
+ plist_t info = NULL;
+ afc_error_t err = afc_get_file_info_plist(afc, dstpath, &info);
// target does not exist, put directly
if (err == AFC_E_OBJECT_NOT_FOUND) {
put_file(afc, srcpath, dstpath, force_overwrite, recursive_put);
@@ -1157,22 +1137,15 @@ static void handle_put(afc_client_t afc, int argc, char **argv)
} else {
uint8_t is_dir = 0;
if (info) {
- char **p = info;
- while (p && *p) {
- if (!strcmp(*p, "st_ifmt")) {
- p++;
- is_dir = !strcmp(*p, "S_IFDIR");
- break;
- }
- p++;
- }
- afc_dictionary_free(info);
+ const char* ifmt = plist_get_string_ptr(plist_dict_get_item(info, "st_ifmt"), NULL);
+ is_dir = (ifmt && !strcmp(ifmt, "S_IFDIR"));
+ plist_free(info);
}
// target is a directory, try to put under this directory
if (is_dir) {
const char *basen = path_get_basename(srcpath);
uint8_t dst_is_root = strcmp(dstpath, "/") == 0;
- size_t len = dst_is_root ? strlen(basen) + 1 : strlen(dstpath) + 1 + strlen(basen) + 1;
+ size_t len = dst_is_root ? (strlen(basen) + 2) : (strlen(dstpath) + 1 + strlen(basen) + 1);
char *newdst = (char *) malloc(len);
if (dst_is_root) {
snprintf(newdst, len, "/%s", basen);
@@ -1227,19 +1200,12 @@ static void handle_cd(afc_client_t afc, int argc, char** argv)
char* path = get_realpath(argv[0]);
int is_dir = 0;
- char **info = NULL;
- afc_error_t err = afc_get_file_info(afc, path, &info);
+ plist_t info = NULL;
+ afc_error_t err = afc_get_file_info_plist(afc, path, &info);
if (err == AFC_E_SUCCESS && info) {
- int i;
- for (i = 0; info[i]; i += 2) {
- if (!strcmp(info[i], "st_ifmt")) {
- if (!strcmp(info[i+1], "S_IFDIR")) {
- is_dir = 1;
- }
- break;
- }
- }
- afc_dictionary_free(info);
+ const char* ifmt = plist_get_string_ptr(plist_dict_get_item(info, "st_ifmt"), NULL);
+ is_dir = (ifmt && !strcmp(ifmt, "S_IFDIR"));
+ plist_free(info);
} else {
printf("Error: Failed to get file info for %s: %s (%d)\n", path, afc_strerror(err), err);
free(path);
@@ -1483,7 +1449,7 @@ int main(int argc, char** argv)
};
signal(SIGTERM, handle_signal);
-#ifndef WIN32
+#ifndef _WIN32
signal(SIGQUIT, handle_signal);
signal(SIGPIPE, SIG_IGN);
#endif
@@ -1561,7 +1527,7 @@ int main(int argc, char** argv)
idevice_events_subscribe(&context, device_event_cb, NULL);
while (!connected && !stop_requested) {
-#ifdef WIN32
+#ifdef _WIN32
Sleep(100);
#else
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 @@
#include <unistd.h>
#include <ctype.h>
#include <time.h>
+#include <sys/stat.h>
#include <libimobiledevice/libimobiledevice.h>
#include <libimobiledevice/lockdown.h>
@@ -51,7 +52,7 @@
#define LOCK_ATTEMPTS 50
#define LOCK_WAIT 200000
-#ifdef WIN32
+#ifdef _WIN32
#include <windows.h>
#define sleep(x) Sleep(x*1000)
#endif
@@ -175,7 +176,13 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid)
if (value_node)
plist_dict_set_item(ret, "IMEI", plist_copy(value_node));
- plist_dict_set_item(ret, "Last Backup Date", plist_new_date(time(NULL) - MAC_EPOCH, 0));
+ plist_dict_set_item(ret, "Last Backup Date",
+#ifdef HAVE_PLIST_UNIX_DATE
+ plist_new_unix_date(time(NULL))
+#else
+ plist_new_date(time(NULL) - MAC_EPOCH, 0)
+#endif
+ );
value_node = plist_dict_get_item(root_node, "ProductType");
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)
return;
node = plist_dict_get_item(info_plist, "Last Backup Date");
+#ifdef HAVE_PLIST_UNIX_DATE
+ plist_set_unix_date_val(node, time(NULL));
+#else
plist_set_date_val(node, time(NULL) - MAC_EPOCH, 0);
+#endif
node = NULL;
}
@@ -642,7 +653,7 @@ int main(int argc, char *argv[])
/* we need to exit cleanly on running backups and restores or we cause havok */
signal(SIGINT, clean_exit);
signal(SIGTERM, clean_exit);
-#ifndef WIN32
+#ifndef _WIN32
signal(SIGQUIT, clean_exit);
signal(SIGPIPE, SIG_IGN);
#endif
@@ -1352,7 +1363,7 @@ files_out:
file_info_path = mobilebackup_build_path(backup_directory, hash, ".mddata");
/* determine file size */
-#ifdef WIN32
+#ifdef _WIN32
struct _stati64 fst;
if (_stati64(file_info_path, &fst) != 0)
#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 @@
#define LOCK_ATTEMPTS 50
#define LOCK_WAIT 200000
-#ifdef WIN32
+#ifdef _WIN32
#include <windows.h>
#include <conio.h>
#define sleep(x) Sleep(x*1000)
@@ -74,6 +74,7 @@
static int verbose = 1;
static int quit_flag = 0;
+static int passcode_requested = 0;
#define PRINT_VERBOSE(min_level, ...) if (verbose >= min_level) { printf(__VA_ARGS__); };
@@ -115,6 +116,10 @@ static void notify_cb(const char *notification, void *userdata)
quit_flag++;
} else if (!strcmp(notification, NP_BACKUP_DOMAIN_CHANGED)) {
backup_domain_changed = 1;
+ } else if (!strcmp(notification, "com.apple.LocalAuthentication.ui.presented")) {
+ passcode_requested = 1;
+ } else if (!strcmp(notification, "com.apple.LocalAuthentication.ui.dismissed")) {
+ passcode_requested = 0;
} else {
PRINT_VERBOSE(1, "Unhandled notification '%s' (TODO: implement)\n", notification);
}
@@ -126,21 +131,15 @@ static void mobilebackup_afc_get_file_contents(afc_client_t afc, const char *fil
return;
}
- char **fileinfo = NULL;
+ plist_t fileinfo = NULL;
uint32_t fsize = 0;
- afc_get_file_info(afc, filename, &fileinfo);
+ afc_get_file_info_plist(afc, filename, &fileinfo);
if (!fileinfo) {
return;
}
- int i;
- for (i = 0; fileinfo[i]; i+=2) {
- if (!strcmp(fileinfo[i], "st_size")) {
- fsize = atol(fileinfo[i+1]);
- break;
- }
- }
- afc_dictionary_free(fileinfo);
+ fsize = plist_dict_get_uint(fileinfo, "st_size");
+ plist_free(fileinfo);
if (fsize == 0) {
return;
@@ -173,7 +172,7 @@ static void mobilebackup_afc_get_file_contents(afc_client_t afc, const char *fil
static int __mkdir(const char* path, int mode)
{
-#ifdef WIN32
+#ifdef _WIN32
return mkdir(path);
#else
return mkdir(path, mode);
@@ -202,7 +201,7 @@ static int mkdir_with_parents(const char *dir, int mode)
return res;
}
-#ifdef WIN32
+#ifdef _WIN32
static int win32err_to_errno(int err_value)
{
switch (err_value) {
@@ -219,7 +218,7 @@ static int win32err_to_errno(int err_value)
static int remove_file(const char* path)
{
int e = 0;
-#ifdef WIN32
+#ifdef _WIN32
if (!DeleteFile(path)) {
e = win32err_to_errno(GetLastError());
}
@@ -234,7 +233,7 @@ static int remove_file(const char* path)
static int remove_directory(const char* path)
{
int e = 0;
-#ifdef WIN32
+#ifdef _WIN32
if (!RemoveDirectory(path)) {
e = win32err_to_errno(GetLastError());
}
@@ -455,7 +454,13 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid, idevice_t d
/* Installed Applications */
plist_dict_set_item(ret, "Installed Applications", installed_apps);
- plist_dict_set_item(ret, "Last Backup Date", plist_new_date(time(NULL) - MAC_EPOCH, 0));
+ plist_dict_set_item(ret, "Last Backup Date",
+#ifdef HAVE_PLIST_UNIX_DATE
+ plist_new_unix_date(time(NULL))
+#else
+ plist_new_date(time(NULL) - MAC_EPOCH, 0)
+#endif
+ );
value_node = plist_dict_get_item(root_node, "MobileEquipmentIdentifier");
if (value_node)
@@ -768,7 +773,7 @@ static int mb2_handle_send_file(mobilebackup2_client_t mobilebackup2, const char
uint32_t bytes = 0;
char *localfile = string_build_path(backup_dir, path, NULL);
char buf[32768];
-#ifdef WIN32
+#ifdef _WIN32
struct _stati64 fst;
#else
struct stat fst;
@@ -779,7 +784,7 @@ static int mb2_handle_send_file(mobilebackup2_client_t mobilebackup2, const char
int errcode = -1;
int result = -1;
uint32_t length;
-#ifdef WIN32
+#ifdef _WIN32
uint64_t total;
uint64_t sent;
#else
@@ -810,7 +815,7 @@ static int mb2_handle_send_file(mobilebackup2_client_t mobilebackup2, const char
goto leave_proto_err;
}
-#ifdef WIN32
+#ifdef _WIN32
if (_stati64(localfile, &fst) < 0)
#else
if (stat(localfile, &fst) < 0)
@@ -1218,7 +1223,12 @@ static void mb2_handle_list_directory(mobilebackup2_client_t mobilebackup2, plis
plist_dict_set_item(fdict, "DLFileType", plist_new_string(ftype));
plist_dict_set_item(fdict, "DLFileSize", plist_new_uint(st.st_size));
plist_dict_set_item(fdict, "DLFileModificationDate",
- plist_new_date(st.st_mtime - MAC_EPOCH, 0));
+#ifdef HAVE_PLIST_UNIX_DATE
+ plist_new_unix_date(st.st_mtime)
+#else
+ plist_new_date(st.st_mtime - MAC_EPOCH, 0)
+#endif
+ );
plist_dict_set_item(dirlist, ep->d_name, fdict);
free(fpath);
@@ -1343,7 +1353,7 @@ static void mb2_copy_directory_by_path(const char *src, const char *dst)
}
}
-#ifdef WIN32
+#ifdef _WIN32
#define BS_CC '\b'
#define my_getch getch
#else
@@ -1463,8 +1473,6 @@ static void print_usage(int argc, char **argv, int is_error)
);
}
-#define DEVICE_VERSION(maj, min, patch) ((((maj) & 0xFF) << 16) | (((min) & 0xFF) << 8) | ((patch) & 0xFF))
-
int main(int argc, char *argv[])
{
idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR;
@@ -1530,7 +1538,7 @@ int main(int argc, char *argv[])
/* we need to exit cleanly on running backups and restores or we cause havok */
signal(SIGINT, clean_exit);
signal(SIGTERM, clean_exit);
-#ifndef WIN32
+#ifndef _WIN32
signal(SIGQUIT, clean_exit);
signal(SIGPIPE, SIG_IGN);
#endif
@@ -1844,34 +1852,20 @@ int main(int argc, char *argv[])
}
/* get ProductVersion */
- char *product_version = NULL;
- int device_version = 0;
- node_tmp = NULL;
- lockdownd_get_value(lockdown, NULL, "ProductVersion", &node_tmp);
- if (node_tmp) {
- if (plist_get_node_type(node_tmp) == PLIST_STRING) {
- plist_get_string_val(node_tmp, &product_version);
- }
- plist_free(node_tmp);
- node_tmp = NULL;
- }
- if (product_version) {
- int vers[3] = { 0, 0, 0 };
- if (sscanf(product_version, "%d.%d.%d", &vers[0], &vers[1], &vers[2]) >= 2) {
- device_version = DEVICE_VERSION(vers[0], vers[1], vers[2]);
- }
- }
+ int device_version = idevice_get_device_version(device);
/* start notification_proxy */
ldret = lockdownd_start_service(lockdown, NP_SERVICE_NAME, &service);
if ((ldret == LOCKDOWN_E_SUCCESS) && service && service->port) {
np_client_new(device, service, &np);
np_set_notify_callback(np, notify_cb, NULL);
- const char *noties[5] = {
+ const char *noties[7] = {
NP_SYNC_CANCEL_REQUEST,
NP_SYNC_SUSPEND_REQUEST,
NP_SYNC_RESUME_REQUEST,
NP_BACKUP_DOMAIN_CHANGED,
+ "com.apple.LocalAuthentication.ui.presented",
+ "com.apple.LocalAuthentication.ui.dismissed",
NULL
};
np_observe_notifications(np, noties);
@@ -2058,6 +2052,16 @@ checkpoint:
} else {
PRINT_VERBOSE(1, "Incremental backup mode.\n");
}
+ if (device_version >= IDEVICE_DEVICE_VERSION(16,1,0)) {
+ /* let's wait 2 second to see if the device passcode is requested */
+ int retries = 20;
+ while (retries-- > 0 && !passcode_requested) {
+ usleep(100000);
+ }
+ if (passcode_requested) {
+ printf("*** Waiting for passcode to be entered on the device ***\n");
+ }
+ }
} else {
if (err == MOBILEBACKUP2_E_BAD_VERSION) {
printf("ERROR: Could not start backup process: backup protocol version mismatch!\n");
@@ -2229,7 +2233,7 @@ checkpoint:
if (newpw || backup_password) {
mobilebackup2_send_message(mobilebackup2, "ChangePassword", opts);
uint8_t passcode_hint = 0;
- if (device_version >= DEVICE_VERSION(13,0,0)) {
+ if (device_version >= IDEVICE_DEVICE_VERSION(13,0,0)) {
diagnostics_relay_client_t diag = NULL;
if (diagnostics_relay_client_start_service(device, &diag, TOOL_NAME) == DIAGNOSTICS_RELAY_E_SUCCESS) {
plist_t dict = NULL;
@@ -2307,7 +2311,7 @@ checkpoint:
/* device wants to know how much disk space is available on the computer */
uint64_t freespace = 0;
int res = -1;
-#ifdef WIN32
+#ifdef _WIN32
if (GetDiskFreeSpaceEx(backup_directory, (PULARGE_INTEGER)&freespace, NULL, NULL)) {
res = 0;
}
@@ -2316,7 +2320,7 @@ checkpoint:
memset(&fs, '\0', sizeof(fs));
res = statvfs(backup_directory, &fs);
if (res == 0) {
- freespace = (uint64_t)fs.f_bavail * (uint64_t)fs.f_bsize;
+ freespace = (uint64_t)fs.f_bavail * (uint64_t)fs.f_frsize;
}
#endif
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 @@
#include <assert.h>
#include <fcntl.h>
-#ifdef WIN32
+#ifdef _WIN32
#include <windows.h>
#define sleep(x) Sleep(x*1000)
#else
@@ -334,7 +334,7 @@ int main(int argc, char *argv[])
signal(SIGINT, clean_exit);
signal(SIGTERM, clean_exit);
-#ifndef WIN32
+#ifndef _WIN32
signal(SIGQUIT, clean_exit);
signal(SIGPIPE, SIG_IGN);
#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 @@
#include <string.h>
#include <unistd.h>
#include <getopt.h>
-#ifndef WIN32
+#include <sys/stat.h>
+#ifndef _WIN32
#include <signal.h>
#endif
#include <libimobiledevice-glue/utils.h>
@@ -42,7 +43,7 @@
#include <libimobiledevice/afc.h>
#include <plist/plist.h>
-#ifdef WIN32
+#ifdef _WIN32
#include <windows.h>
#define S_IFLNK S_IFREG
#define S_IFSOCK S_IFREG
@@ -54,11 +55,12 @@
const char* target_directory = NULL;
static int extract_raw_crash_reports = 0;
static int keep_crash_reports = 0;
+static int remove_all = 0;
static int file_exists(const char* path)
{
struct stat tst;
-#ifdef WIN32
+#ifdef _WIN32
return (stat(path, &tst) == 0);
#else
return (lstat(path, &tst) == 0);
@@ -144,7 +146,7 @@ static int afc_client_copy_and_remove_crash_reports(afc_client_t afc, const char
continue;
}
- char **fileinfo = NULL;
+ plist_t fileinfo = NULL;
struct stat stbuf;
memset(&stbuf, '\0', sizeof(struct stat));
@@ -152,7 +154,7 @@ static int afc_client_copy_and_remove_crash_reports(afc_client_t afc, const char
strcpy(((char*)source_filename) + device_directory_length, list[k]);
/* assemble absolute target filename */
-#ifdef WIN32
+#ifdef _WIN32
/* replace every ':' with '-' since ':' is an illegal character for file names in windows */
char* current_pos = strchr(list[k], ':');
while (current_pos) {
@@ -171,88 +173,93 @@ static int afc_client_copy_and_remove_crash_reports(afc_client_t afc, const char
}
/* get file information */
- afc_get_file_info(afc, source_filename, &fileinfo);
+ afc_get_file_info_plist(afc, source_filename, &fileinfo);
if (!fileinfo) {
printf("Failed to read information for '%s'. Skipping...\n", source_filename);
continue;
}
/* parse file information */
- int i;
- for (i = 0; fileinfo[i]; i+=2) {
- if (!strcmp(fileinfo[i], "st_size")) {
- stbuf.st_size = atoll(fileinfo[i+1]);
- } else if (!strcmp(fileinfo[i], "st_ifmt")) {
- if (!strcmp(fileinfo[i+1], "S_IFREG")) {
- stbuf.st_mode = S_IFREG;
- } else if (!strcmp(fileinfo[i+1], "S_IFDIR")) {
- stbuf.st_mode = S_IFDIR;
- } else if (!strcmp(fileinfo[i+1], "S_IFLNK")) {
- stbuf.st_mode = S_IFLNK;
- } else if (!strcmp(fileinfo[i+1], "S_IFBLK")) {
- stbuf.st_mode = S_IFBLK;
- } else if (!strcmp(fileinfo[i+1], "S_IFCHR")) {
- stbuf.st_mode = S_IFCHR;
- } else if (!strcmp(fileinfo[i+1], "S_IFIFO")) {
- stbuf.st_mode = S_IFIFO;
- } else if (!strcmp(fileinfo[i+1], "S_IFSOCK")) {
- stbuf.st_mode = S_IFSOCK;
- }
- } else if (!strcmp(fileinfo[i], "st_nlink")) {
- stbuf.st_nlink = atoi(fileinfo[i+1]);
- } else if (!strcmp(fileinfo[i], "st_mtime")) {
- stbuf.st_mtime = (time_t)(atoll(fileinfo[i+1]) / 1000000000);
- } else if (!strcmp(fileinfo[i], "LinkTarget")) {
- /* report latest crash report filename */
- printf("Link: %s\n", (char*)target_filename + strlen(target_directory));
-
- /* remove any previous symlink */
- if (file_exists(target_filename)) {
- remove(target_filename);
- }
+ stbuf.st_size = plist_dict_get_uint(fileinfo, "st_size");
+ const char* s_ifmt = plist_get_string_ptr(plist_dict_get_item(fileinfo, "st_ifmt"), NULL);
+ if (s_ifmt) {
+ if (!strcmp(s_ifmt, "S_IFREG")) {
+ stbuf.st_mode = S_IFREG;
+ } else if (!strcmp(s_ifmt, "S_IFDIR")) {
+ stbuf.st_mode = S_IFDIR;
+ } else if (!strcmp(s_ifmt, "S_IFLNK")) {
+ stbuf.st_mode = S_IFLNK;
+ } else if (!strcmp(s_ifmt, "S_IFBLK")) {
+ stbuf.st_mode = S_IFBLK;
+ } else if (!strcmp(s_ifmt, "S_IFCHR")) {
+ stbuf.st_mode = S_IFCHR;
+ } else if (!strcmp(s_ifmt, "S_IFIFO")) {
+ stbuf.st_mode = S_IFIFO;
+ } else if (!strcmp(s_ifmt, "S_IFSOCK")) {
+ stbuf.st_mode = S_IFSOCK;
+ }
+ }
+ stbuf.st_nlink = plist_dict_get_uint(fileinfo, "st_nlink");
+ stbuf.st_mtime = (time_t)(plist_dict_get_uint(fileinfo, "st_mtime") / 1000000000);
+ const char* linktarget = plist_get_string_ptr(plist_dict_get_item(fileinfo, "LinkTarget"), NULL);
+ if (linktarget && !remove_all) {
+ /* report latest crash report filename */
+ printf("Link: %s\n", (char*)target_filename + strlen(target_directory));
+
+ /* remove any previous symlink */
+ if (file_exists(target_filename)) {
+ remove(target_filename);
+ }
-#ifndef WIN32
- /* use relative filename */
- char* b = strrchr(fileinfo[i+1], '/');
- if (b == NULL) {
- b = fileinfo[i+1];
+#ifndef _WIN32
+ /* use relative filename */
+ const char* b = strrchr(linktarget, '/');
+ if (b == NULL) {
+ b = linktarget;
} else {
- b++;
- }
+ b++;
+ }
- /* create a symlink pointing to latest log */
- if (symlink(b, target_filename) < 0) {
- fprintf(stderr, "Can't create symlink to %s\n", b);
- }
+ /* create a symlink pointing to latest log */
+ if (symlink(b, target_filename) < 0) {
+ fprintf(stderr, "Can't create symlink to %s\n", b);
+ }
#endif
- if (!keep_crash_reports)
- afc_remove_path(afc, source_filename);
+ if (!keep_crash_reports)
+ afc_remove_path(afc, source_filename);
- res = 0;
- }
+ res = 0;
}
/* free file information */
- afc_dictionary_free(fileinfo);
+ plist_free(fileinfo);
/* recurse into child directories */
if (S_ISDIR(stbuf.st_mode)) {
-#ifdef WIN32
- mkdir(target_filename);
+ if (!remove_all) {
+#ifdef _WIN32
+ mkdir(target_filename);
#else
- mkdir(target_filename, 0755);
+ mkdir(target_filename, 0755);
#endif
+ }
res = afc_client_copy_and_remove_crash_reports(afc, source_filename, target_filename, filename_filter);
/* remove directory from device */
- if (!keep_crash_reports)
+ if (!remove_all && !keep_crash_reports)
afc_remove_path(afc, source_filename);
} else if (S_ISREG(stbuf.st_mode)) {
if (filename_filter != NULL && strstr(source_filename, filename_filter) == NULL) {
continue;
}
+ if (remove_all) {
+ printf("Remove: %s\n", source_filename);
+ afc_remove_path(afc, source_filename);
+ continue;
+ }
+
/* copy file to host */
afc_error = afc_file_open(afc, source_filename, AFC_FOPEN_RDONLY, &handle);
if(afc_error != AFC_E_SUCCESS) {
@@ -331,6 +338,7 @@ static void print_usage(int argc, char **argv, int is_error)
" -f, --filter NAME filter crash reports by NAME (case sensitive)\n"
" -h, --help prints usage information\n"
" -v, --version prints version information\n"
+ " --remove-all remove all crash logs found\n"
"\n"
"Homepage: <" PACKAGE_URL ">\n"
"Bug Reports: <" PACKAGE_BUGREPORT ">\n"
@@ -361,10 +369,11 @@ int main(int argc, char* argv[])
{ "filter", required_argument, NULL, 'f' },
{ "extract", no_argument, NULL, 'e' },
{ "keep", no_argument, NULL, 'k' },
+ { "remove-all", no_argument, NULL, 1 },
{ NULL, 0, NULL, 0}
};
-#ifndef WIN32
+#ifndef _WIN32
signal(SIGPIPE, SIG_IGN);
#endif
@@ -405,6 +414,9 @@ int main(int argc, char* argv[])
case 'k':
keep_crash_reports = 1;
break;
+ case 1:
+ remove_all = 1;
+ break;
default:
print_usage(argc, argv, 1);
return 2;
@@ -414,12 +426,16 @@ int main(int argc, char* argv[])
argv += optind;
/* ensure a target directory was supplied */
- if (!argv[0]) {
- fprintf(stderr, "ERROR: missing target directory.\n");
- print_usage(argc+optind, argv-optind, 1);
- return 2;
+ if (!remove_all) {
+ if (!argv[0]) {
+ fprintf(stderr, "ERROR: missing target directory.\n");
+ print_usage(argc+optind, argv-optind, 1);
+ return 2;
+ }
+ target_directory = argv[0];
+ } else {
+ target_directory = ".";
}
- target_directory = argv[0];
/* check if target directory exists */
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 @@
#if HAVE_LANGINFO_CODESET
#include <langinfo.h>
#endif
-#ifndef WIN32
+#ifndef _WIN32
#include <signal.h>
#endif
@@ -43,7 +43,7 @@
#ifdef _DATE_FMT
#define DATE_FMT_LANGINFO nl_langinfo (_DATE_FMT)
#else
-#ifdef WIN32
+#ifdef _WIN32
#define DATE_FMT_LANGINFO "%a %b %#d %H:%M:%S %Z %Y"
#else
#define DATE_FMT_LANGINFO "%a %b %e %H:%M:%S %Z %Y"
@@ -104,7 +104,7 @@ int main(int argc, char *argv[])
{ NULL, 0, NULL, 0}
};
-#ifndef WIN32
+#ifndef _WIN32
signal(SIGPIPE, SIG_IGN);
#endif
/* 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 @@
#include <libgen.h>
#include <getopt.h>
-#ifdef WIN32
+#ifdef _WIN32
#include <windows.h>
#define sleep(x) Sleep(x*1000)
#endif
@@ -239,7 +239,7 @@ int main(int argc, char *argv[])
/* map signals */
signal(SIGINT, on_signal);
signal(SIGTERM, on_signal);
-#ifndef WIN32
+#ifndef _WIN32
signal(SIGQUIT, on_signal);
signal(SIGPIPE, SIG_IGN);
#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 @@
#include <getopt.h>
#include <errno.h>
#include <signal.h>
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#else
@@ -219,7 +219,7 @@ int main(int argc, char *argv[])
{ NULL, 0, NULL, 0}
};
-#ifndef WIN32
+#ifndef _WIN32
struct sigaction sa;
struct sigaction si;
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 @@
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <signal.h>
#endif
-#ifdef WIN32
+#ifdef _WIN32
#include <windows.h>
#define __usleep(x) Sleep(x/1000)
#else
@@ -259,7 +259,7 @@ int main(int argc, char *argv[])
{ NULL, 0, NULL, 0}
};
-#ifndef WIN32
+#ifndef _WIN32
signal(SIGPIPE, SIG_IGN);
#endif
/* 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 @@
#include <getopt.h>
#include <errno.h>
#include <time.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <signal.h>
#endif
@@ -113,7 +113,7 @@ int main(int argc, char **argv)
{ NULL, 0, NULL, 0}
};
-#ifndef WIN32
+#ifndef _WIN32
signal(SIGPIPE, SIG_IGN);
#endif
/* 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 @@
#include <stdlib.h>
#include <getopt.h>
#include <errno.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <signal.h>
#endif
@@ -70,7 +70,7 @@ int main(int argc, char *argv[])
{ NULL, 0, NULL, 0}
};
-#ifndef WIN32
+#ifndef _WIN32
signal(SIGPIPE, SIG_IGN);
#endif
/* parse cmdline args */
diff --git a/tools/ideviceimagemounter.c b/tools/ideviceimagemounter.c
index 52b0666..b319d05 100644
--- a/tools/ideviceimagemounter.c
+++ b/tools/ideviceimagemounter.c
@@ -36,7 +36,8 @@
#include <time.h>
#include <sys/time.h>
#include <inttypes.h>
-#ifndef WIN32
+#include <sys/stat.h>
+#ifndef _WIN32
#include <signal.h>
#endif
@@ -87,7 +88,7 @@ static void print_usage(int argc, char **argv, int is_error)
" mount PATH Mount the developer disk image at PATH.\n"
" For iOS 17+, PATH is a directory containing a .dmg image,\n"
" a BuildManifest.plist, and a Firmware sub-directory;\n"
- " for older versions PATH is a .dmg filename with a"
+ " for older versions PATH is a .dmg filename with a\n"
" .dmg.signature in the same directory, or with another\n"
" parameter pointing to a file elsewhere.\n"
" list List mounted disk images.\n"
@@ -183,7 +184,7 @@ int main(int argc, char **argv)
size_t image_size = 0;
char *image_sig_path = NULL;
-#ifndef WIN32
+#ifndef _WIN32
signal(SIGPIPE, SIG_IGN);
#endif
parse_opts(argc, argv);
@@ -267,23 +268,14 @@ int main(int argc, char **argv)
goto leave;
}
- plist_t pver = NULL;
- char *product_version = NULL;
- lockdownd_get_value(lckd, NULL, "ProductVersion", &pver);
- if (pver && plist_get_node_type(pver) == PLIST_STRING) {
- plist_get_string_val(pver, &product_version);
- }
+ unsigned int device_version = idevice_get_device_version(device);
+
disk_image_upload_type_t disk_image_upload_type = DISK_IMAGE_UPLOAD_TYPE_AFC;
- int product_version_major = 0;
- int product_version_minor = 0;
- if (product_version) {
- if (sscanf(product_version, "%d.%d.%*d", &product_version_major, &product_version_minor) == 2) {
- if (product_version_major >= 7)
- disk_image_upload_type = DISK_IMAGE_UPLOAD_TYPE_UPLOAD_IMAGE;
- }
+ if (device_version >= IDEVICE_DEVICE_VERSION(7,0,0)) {
+ disk_image_upload_type = DISK_IMAGE_UPLOAD_TYPE_UPLOAD_IMAGE;
}
- if (product_version_major >= 16) {
+ if (device_version >= IDEVICE_DEVICE_VERSION(16,0,0)) {
uint8_t dev_mode_status = 0;
plist_t val = NULL;
ldret = lockdownd_get_value(lckd, "com.apple.security.mac.amfi", "DeveloperModeStatus", &val);
@@ -336,7 +328,7 @@ int main(int argc, char **argv)
goto leave;
}
image_size = fst.st_size;
- if (product_version_major < 17 && stat(image_sig_path, &fst) != 0) {
+ if (device_version < IDEVICE_DEVICE_VERSION(17,0,0) && stat(image_sig_path, &fst) != 0) {
fprintf(stderr, "ERROR: stat: %s: %s\n", image_sig_path, strerror(errno));
goto leave;
}
@@ -351,7 +343,7 @@ int main(int argc, char **argv)
if (cmd == CMD_LIST) {
/* list mounts mode */
if (!imagetype) {
- if (product_version_major < 17) {
+ if (device_version < IDEVICE_DEVICE_VERSION(17,0,0)) {
imagetype = "Developer";
} else {
imagetype = "Personalized";
@@ -371,14 +363,17 @@ int main(int argc, char **argv)
struct stat fst;
plist_t mount_options = NULL;
- if (product_version_major < 17) {
+ if (device_version < IDEVICE_DEVICE_VERSION(17,0,0)) {
f = fopen(image_sig_path, "rb");
if (!f) {
fprintf(stderr, "Error opening signature file '%s': %s\n", image_sig_path, strerror(errno));
goto leave;
}
- fstat(fileno(f), &fst);
- sig = malloc(sig_length);
+ if (fstat(fileno(f), &fst) != 0) {
+ fprintf(stderr, "Error: fstat: %s\n", strerror(errno));
+ goto leave;
+ }
+ sig = malloc(fst.st_size);
sig_length = fread(sig, 1, fst.st_size, f);
fclose(f);
if (sig_length == 0) {
@@ -603,20 +598,13 @@ int main(int argc, char **argv)
case DISK_IMAGE_UPLOAD_TYPE_AFC:
default:
printf("Uploading %s --> afc:///%s\n", image_path, targetname);
- char **strs = NULL;
- if (afc_get_file_info(afc, PKG_PATH, &strs) != AFC_E_SUCCESS) {
+ plist_t fileinfo = NULL;
+ if (afc_get_file_info_plist(afc, PKG_PATH, &fileinfo) != AFC_E_SUCCESS) {
if (afc_make_directory(afc, PKG_PATH) != AFC_E_SUCCESS) {
fprintf(stderr, "WARNING: Could not create directory '%s' on device!\n", PKG_PATH);
}
}
- if (strs) {
- int i = 0;
- while (strs[i]) {
- free(strs[i]);
- i++;
- }
- free(strs);
- }
+ plist_free(fileinfo);
uint64_t af = 0;
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 @@
#include <errno.h>
#include <stdlib.h>
#include <getopt.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <signal.h>
#endif
@@ -152,7 +152,7 @@ int main(int argc, char *argv[])
{ NULL, 0, NULL, 0}
};
-#ifndef WIN32
+#ifndef _WIN32
signal(SIGPIPE, SIG_IGN);
#endif
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 @@
#include <unistd.h>
#include <stdlib.h>
#include <getopt.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <signal.h>
#endif
@@ -72,7 +72,7 @@ int main(int argc, char** argv)
const char* udid = NULL;
int use_network = 0;
-#ifndef WIN32
+#ifndef _WIN32
signal(SIGPIPE, SIG_IGN);
#endif
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 @@
* idevicenotificationproxy.c
* Simple client for the notification_proxy service
*
- * Copyright (c) 2009-2015 Martin Szulecki All Rights Reserved.
+ * Copyright (c) 2018-2024 Nikias Bassen, All Rights Reserved.
+ * Copyright (c) 2009-2015 Martin Szulecki, All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -32,7 +33,7 @@
#include <errno.h>
#include <signal.h>
-#ifdef WIN32
+#ifdef _WIN32
#include <windows.h>
#define sleep(x) Sleep(x*1000)
#else
@@ -75,6 +76,7 @@ static void print_usage(int argc, char **argv, int is_error)
"\n"
"The following OPTIONS are accepted:\n"
" -u, --udid UDID target specific device by UDID\n"
+ " -i, --insecure use insecure notification proxy (non-paired device)\n"
" -n, --network connect to network device\n"
" -d, --debug enable communication debugging\n"
" -h, --help prints usage information\n"
@@ -102,6 +104,7 @@ int main(int argc, char *argv[])
int i = 0;
const char* udid = NULL;
int use_network = 0;
+ int insecure = 0;
int cmd = CMD_NONE;
char* cmd_arg = NULL;
@@ -114,6 +117,7 @@ int main(int argc, char *argv[])
{ "debug", no_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' },
{ "udid", required_argument, NULL, 'u' },
+ { "insecure", no_argument, NULL, 'i' },
{ "network", no_argument, NULL, 'n' },
{ "version", no_argument, NULL, 'v' },
{ NULL, 0, NULL, 0}
@@ -121,13 +125,13 @@ int main(int argc, char *argv[])
signal(SIGINT, clean_exit);
signal(SIGTERM, clean_exit);
-#ifndef WIN32
+#ifndef _WIN32
signal(SIGQUIT, clean_exit);
signal(SIGPIPE, SIG_IGN);
#endif
/* parse cmdline args */
- while ((c = getopt_long(argc, argv, "dhu:nv", longopts, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "dhu:inv", longopts, NULL)) != -1) {
switch (c) {
case 'd':
idevice_set_debug_level(1);
@@ -143,6 +147,9 @@ int main(int argc, char *argv[])
case 'n':
use_network = 1;
break;
+ case 'i':
+ insecure = 1;
+ break;
case 'h':
print_usage(argc, argv, 0);
return 0;
@@ -214,12 +221,17 @@ int main(int argc, char *argv[])
goto cleanup;
}
- if (LOCKDOWN_E_SUCCESS != (ret = lockdownd_client_new_with_handshake(device, &client, TOOL_NAME))) {
- fprintf(stderr, "ERROR: Could not connect to lockdownd, error code %d\n", ret);
+ if (insecure) {
+ ret = lockdownd_client_new(device, &client, TOOL_NAME);
+ } else {
+ ret = lockdownd_client_new_with_handshake(device, &client, TOOL_NAME);
+ }
+ if (LOCKDOWN_E_SUCCESS != ret) {
+ fprintf(stderr, "ERROR: Could not connect to lockdownd: %s (%d)\n", lockdownd_strerror(ret), ret);
goto cleanup;
}
- ret = lockdownd_start_service(client, NP_SERVICE_NAME, &service);
+ ret = lockdownd_start_service(client, (insecure) ? "com.apple.mobile.insecure_notification_proxy" : NP_SERVICE_NAME, &service);
lockdownd_client_free(client);
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 @@
#include <getopt.h>
#include <ctype.h>
#include <unistd.h>
-#ifdef WIN32
+#ifdef _WIN32
#include <windows.h>
#include <conio.h>
#else
@@ -50,7 +50,7 @@ static char *udid = NULL;
#ifdef HAVE_WIRELESS_PAIRING
-#ifdef WIN32
+#ifdef _WIN32
#define BS_CC '\b'
#define my_getch getch
#else
@@ -293,7 +293,7 @@ int main(int argc, char **argv)
}
}
-#ifndef WIN32
+#ifndef _WIN32
signal(SIGPIPE, SIG_IGN);
#endif
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 @@
#include <getopt.h>
#include <sys/stat.h>
#include <errno.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <signal.h>
#endif
-#ifdef WIN32
+#ifdef _WIN32
+#include <winsock2.h>
#include <windows.h>
#else
#include <arpa/inet.h>
@@ -314,7 +315,7 @@ int main(int argc, char *argv[])
{ NULL, 0, NULL, 0}
};
-#ifndef WIN32
+#ifndef _WIN32
signal(SIGPIPE, SIG_IGN);
#endif
/* parse cmdline args */
@@ -475,27 +476,7 @@ int main(int argc, char *argv[])
return -1;
}
- plist_t pver = NULL;
- char *pver_s = NULL;
- lockdownd_get_value(client, NULL, "ProductVersion", &pver);
- if (pver && plist_get_node_type(pver) == PLIST_STRING) {
- plist_get_string_val(pver, &pver_s);
- }
- plist_free(pver);
- int product_version_major = 0;
- int product_version_minor = 0;
- int product_version_patch = 0;
- if (pver_s) {
- sscanf(pver_s, "%d.%d.%d", &product_version_major, &product_version_minor, &product_version_patch);
- free(pver_s);
- }
- if (product_version_major == 0) {
- fprintf(stderr, "ERROR: Could not determine the device's ProductVersion\n");
- lockdownd_client_free(client);
- idevice_free(device);
- return -1;
- }
- int product_version = ((product_version_major & 0xFF) << 16) | ((product_version_minor & 0xFF) << 8) | (product_version_patch & 0xFF);
+ unsigned int device_version = idevice_get_device_version(device);
lockdownd_error_t lerr = lockdownd_start_service(client, MISAGENT_SERVICE_NAME, &service);
if (lerr != LOCKDOWN_E_SUCCESS) {
@@ -546,7 +527,7 @@ int main(int argc, char *argv[])
{
plist_t profiles = NULL;
misagent_error_t merr;
- if (product_version < 0x090300) {
+ if (device_version < IDEVICE_DEVICE_VERSION(9,3,0)) {
merr = misagent_copy(mis, &profiles);
} else {
merr = misagent_copy_all(mis, &profiles);
@@ -631,7 +612,7 @@ int main(int argc, char *argv[])
/* remove all provisioning profiles */
plist_t profiles = NULL;
misagent_error_t merr;
- if (product_version < 0x090300) {
+ if (device_version < IDEVICE_DEVICE_VERSION(9,3,0)) {
merr = misagent_copy(mis, &profiles);
} else {
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 @@
#include <errno.h>
#include <time.h>
#include <unistd.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <signal.h>
#endif
@@ -142,7 +142,7 @@ int main(int argc, char **argv)
{ NULL, 0, NULL, 0}
};
-#ifndef WIN32
+#ifndef _WIN32
signal(SIGPIPE, SIG_IGN);
#endif
/* 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)
if ((argc > 2) || (argc < 1)) {
print_usage(argc+optind, argv-optind, 1);
- return -1;
+ return 1;
}
if (argc == 2) {
@@ -123,7 +123,7 @@ int main(int argc, char **argv)
mode = RESET_LOCATION;
} else {
print_usage(argc+optind, argv-optind, 1);
- return -1;
+ return 1;
}
}
@@ -135,19 +135,30 @@ int main(int argc, char **argv)
} else {
printf("ERROR: No device found!\n");
}
- return -1;
+ return 1;
}
- lockdownd_client_t lockdown;
- lockdownd_client_new_with_handshake(device, &lockdown, TOOL_NAME);
+ lockdownd_client_t lockdown = NULL;
+ lockdownd_error_t lerr = lockdownd_client_new_with_handshake(device, &lockdown, TOOL_NAME);
+ if (lerr != LOCKDOWN_E_SUCCESS) {
+ idevice_free(device);
+ printf("ERROR: Could not connect to lockdownd: %s (%d)\n", lockdownd_strerror(lerr), lerr);
+ return 1;
+ }
lockdownd_service_descriptor_t svc = NULL;
- lockdownd_error_t lerr = lockdownd_start_service(lockdown, DT_SIMULATELOCATION_SERVICE, &svc);
+ lerr = lockdownd_start_service(lockdown, DT_SIMULATELOCATION_SERVICE, &svc);
if (lerr != LOCKDOWN_E_SUCCESS) {
+ unsigned int device_version = idevice_get_device_version(device);
lockdownd_client_free(lockdown);
idevice_free(device);
- printf("ERROR: Could not start the simulatelocation service: %s\nMake sure a developer disk image is mounted!\n", lockdownd_strerror(lerr));
- return -1;
+ printf("ERROR: Could not start the simulatelocation service: %s\n", lockdownd_strerror(lerr));
+ if (device_version >= IDEVICE_DEVICE_VERSION(17,0,0)) {
+ printf("Note: This tool is currently not supported on iOS 17+\n");
+ } else {
+ printf("Make sure a developer disk image is mounted!\n");
+ }
+ return 1;
}
lockdownd_client_free(lockdown);
@@ -158,10 +169,9 @@ int main(int argc, char **argv)
lockdownd_service_descriptor_free(svc);
if (serr != SERVICE_E_SUCCESS) {
- lockdownd_client_free(lockdown);
idevice_free(device);
printf("ERROR: Could not connect to simulatelocation service (%d)\n", serr);
- return -1;
+ return 1;
}
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 @@
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
+#include <time.h>
-#ifdef WIN32
+#ifdef _WIN32
#include <windows.h>
#define sleep(x) Sleep(x*1000)
#endif
@@ -42,10 +43,12 @@
#include <libimobiledevice/libimobiledevice.h>
#include <libimobiledevice/syslog_relay.h>
#include <libimobiledevice-glue/termcolors.h>
+#include <libimobiledevice/ostrace.h>
static int quit_flag = 0;
static int exit_on_disconnect = 0;
static int show_device_name = 0;
+static int force_syslog_relay = 0;
static char* udid = NULL;
static char** proc_filters = NULL;
@@ -58,6 +61,9 @@ static int num_pid_filters = 0;
static char** msg_filters = NULL;
static int num_msg_filters = 0;
+static char** msg_reverse_filters = NULL;
+static int num_msg_reverse_filters = 0;
+
static char** trigger_filters = NULL;
static int num_trigger_filters = 0;
static char** untrigger_filters = NULL;
@@ -66,11 +72,16 @@ static int triggered = 0;
static idevice_t device = NULL;
static syslog_relay_client_t syslog = NULL;
+static ostrace_client_t ostrace = NULL;
static 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";
static int use_network = 0;
+static long long start_time = -1;
+static long long size_limit = -1;
+static long long age_limit = -1;
+
static char *line = NULL;
static int line_buffer_size = 0;
static int lp = 0;
@@ -129,6 +140,70 @@ static int find_char(char c, char** p, const char* end)
static void stop_logging(void);
+static int message_filter_matching(const char* message)
+{
+ if (num_msg_filters > 0) {
+ int found = 0;
+ int i;
+ for (i = 0; i < num_msg_filters; i++) {
+ if (strstr(message, msg_filters[i])) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ return 0;
+ }
+ }
+ if (num_msg_reverse_filters > 0) {
+ int found = 0;
+ int i;
+ for (i = 0; i < num_msg_reverse_filters; i++) {
+ if (strstr(message, msg_reverse_filters[i])) {
+ found = 1;
+ break;
+ }
+ }
+ if (found) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int process_filter_matching(int pid, const char* process_name, int process_name_length)
+{
+ int proc_matched = 0;
+ if (num_pid_filters > 0) {
+ int found = proc_filter_excluding;
+ int i = 0;
+ for (i = 0; i < num_pid_filters; i++) {
+ if (pid == pid_filters[i]) {
+ found = !proc_filter_excluding;
+ break;
+ }
+ }
+ if (found) {
+ proc_matched = 1;
+ }
+ }
+ if (num_proc_filters > 0 && !proc_matched) {
+ int found = proc_filter_excluding;
+ int i = 0;
+ for (i = 0; i < num_proc_filters; i++) {
+ if (!proc_filters[i]) continue;
+ if (strncmp(proc_filters[i], process_name, process_name_length) == 0) {
+ found = !proc_filter_excluding;
+ break;
+ }
+ }
+ if (found) {
+ proc_matched = 1;
+ }
+ }
+ return proc_matched;
+}
+
static void syslog_callback(char c, void *user_data)
{
if (lp >= line_buffer_size-1) {
@@ -202,20 +277,9 @@ static void syslog_callback(char c, void *user_data)
}
/* check message filters */
- if (num_msg_filters > 0) {
- int found = 0;
- int i;
- for (i = 0; i < num_msg_filters; i++) {
- if (strstr(device_name_end+1, msg_filters[i])) {
- found = 1;
- break;
- }
- }
- if (!found) {
- shall_print = 0;
- break;
- }
- shall_print = 1;
+ shall_print = message_filter_matching(device_name_end+1);
+ if (!shall_print) {
+ break;
}
/* process name */
@@ -235,39 +299,10 @@ static void syslog_callback(char c, void *user_data)
proc_name_end = p;
p++;
- int proc_matched = 0;
- if (num_pid_filters > 0) {
- char* endp = NULL;
- int pid_value = (int)strtol(pid_start, &endp, 10);
- if (endp && (*endp == ']')) {
- int found = proc_filter_excluding;
- int i = 0;
- for (i = 0; i < num_pid_filters; i++) {
- if (pid_value == pid_filters[i]) {
- found = !proc_filter_excluding;
- break;
- }
- }
- if (found) {
- proc_matched = 1;
- }
- }
- }
- if (num_proc_filters > 0 && !proc_matched) {
- int found = proc_filter_excluding;
- int i = 0;
- for (i = 0; i < num_proc_filters; i++) {
- if (!proc_filters[i]) continue;
- if (strncmp(proc_filters[i], process_name_start, process_name_end-process_name_start) == 0) {
- found = !proc_filter_excluding;
- break;
- }
- }
- if (found) {
- proc_matched = 1;
- }
- }
- if (proc_matched) {
+ /* match pid / process name */
+ char* endp = NULL;
+ int pid_value = (int)strtol(pid_start, &endp, 10);
+ if (process_filter_matching(pid_value, process_name_start, process_name_end-process_name_start)) {
shall_print = 1;
} else {
if (num_pid_filters > 0 || num_proc_filters > 0) {
@@ -331,7 +366,7 @@ static void syslog_callback(char c, void *user_data)
}
} while (0);
- if ((num_msg_filters == 0 && num_proc_filters == 0 && num_pid_filters == 0 && num_trigger_filters == 0 && num_untrigger_filters == 0) || shall_print) {
+ 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) {
fwrite(linep, 1, lp, stdout);
cprintf(COLOR_RESET);
fflush(stdout);
@@ -345,12 +380,231 @@ static void syslog_callback(char c, void *user_data)
}
}
-static int start_logging(void)
+static void ostrace_syslog_callback(const void* buf, size_t len, void* user_data)
{
- idevice_error_t ret = idevice_new_with_options(&device, udid, (use_network) ? IDEVICE_LOOKUP_NETWORK : IDEVICE_LOOKUP_USBMUX);
- if (ret != IDEVICE_E_SUCCESS) {
- fprintf(stderr, "Device with udid %s not found!?\n", udid);
- return -1;
+ if (len < 0x81) {
+ fprintf(stderr, "Error: not enough data in callback function?!\n");
+ return;
+ }
+
+ struct ostrace_packet_header_t *trace_hdr = (struct ostrace_packet_header_t*)buf;
+
+ if (trace_hdr->marker != 2 || (trace_hdr->type != 8 && trace_hdr->type != 2)) {
+ fprintf(stderr, "unexpected packet data %02x %08x\n", trace_hdr->marker, trace_hdr->type);
+ }
+
+ const char* dataptr = (const char*)buf + trace_hdr->header_size;
+ const char* process_name = dataptr;
+ const char* image_name = (trace_hdr->imagepath_len > 0) ? dataptr + trace_hdr->procpath_len : NULL;
+ const char* message = (trace_hdr->message_len > 0) ? dataptr + trace_hdr->procpath_len + trace_hdr->imagepath_len : NULL;
+ //const char* subsystem = (trace_hdr->subsystem_len > 0) ? dataptr + trace_hdr->procpath_len + trace_hdr->imagepath_len + trace_hdr->message_len : NULL;
+ //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;
+
+ int shall_print = 1;
+ int trigger_off = 0;
+ const char* process_name_short = (process_name) ? strrchr(process_name, '/') : "";
+ process_name_short = (process_name_short) ? process_name_short+1 : process_name;
+ const char* image_name_short = (image_name) ? strrchr(image_name, '/') : NULL;
+ image_name_short = (image_name_short) ? image_name_short+1 : process_name;
+ if (image_name_short && !strcmp(image_name_short, process_name_short)) {
+ image_name_short = NULL;
+ }
+
+ do {
+ /* check if we have any triggers/untriggers */
+ if (num_untrigger_filters > 0 && triggered) {
+ int found = 0;
+ int i;
+ for (i = 0; i < num_untrigger_filters; i++) {
+ if (strstr(message, untrigger_filters[i])) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ shall_print = 1;
+ } else {
+ shall_print = 1;
+ trigger_off = 1;
+ }
+ } else if (num_trigger_filters > 0 && !triggered) {
+ int found = 0;
+ int i;
+ for (i = 0; i < num_trigger_filters; i++) {
+ if (strstr(message, trigger_filters[i])) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ shall_print = 0;
+ break;
+ }
+ triggered = 1;
+ shall_print = 1;
+ } else if (num_trigger_filters == 0 && num_untrigger_filters > 0 && !triggered) {
+ shall_print = 0;
+ quit_flag++;
+ break;
+ }
+
+ /* check message filters */
+ shall_print = message_filter_matching(message);
+ if (!shall_print) {
+ break;
+ }
+
+ /* check process filters */
+ if (process_filter_matching(trace_hdr->pid, process_name_short, strlen(process_name_short))) {
+ shall_print = 1;
+ } else {
+ if (num_pid_filters > 0 || num_proc_filters > 0) {
+ shall_print = 0;
+ }
+ }
+ if (!shall_print) {
+ break;
+ }
+ } while (0);
+
+ if (!shall_print) {
+ return;
+ }
+
+ const char* level_str = "Unknown";
+ const char* level_color = FG_YELLOW;
+ switch (trace_hdr->level) {
+ case 0:
+ level_str = "Notice";
+ level_color = FG_GREEN;
+ break;
+ case 0x01:
+ level_str = "Info";
+ level_color = FG_WHITE;
+ break;
+ case 0x02:
+ level_str = "Debug";
+ level_color = FG_MAGENTA;
+ break;
+ case 0x10:
+ level_str = "Error";
+ level_color = FG_RED;
+ break;
+ case 0x11:
+ level_str = "Fault";
+ level_color = FG_RED;
+ default:
+ break;
+ }
+
+ char datebuf[24];
+ struct tm *tp;
+ time_t time_sec = (time_t)trace_hdr->time_sec;
+#ifdef HAVE_LOCALTIME_R
+ struct tm tp_ = {0, };
+ tp = localtime_r(&time_sec, &tp_);
+#else
+ tp = localtime(&time_sec);
+#endif
+#ifdef _WIN32
+ strftime(datebuf, 16, "%b %#d %H:%M:%S", tp);
+#else
+ strftime(datebuf, 16, "%b %e %H:%M:%S", tp);
+#endif
+ snprintf(datebuf+15, 9, ".%06u", trace_hdr->time_usec);
+
+ /* write date and time */
+ cprintf(FG_LIGHT_GRAY "%s ", datebuf);
+
+ if (show_device_name) {
+ /* write device name TODO do we need this? */
+ //cprintf(FG_DARK_YELLOW "%s ", device_name);
+ }
+
+ /* write process name */
+ cprintf(FG_BRIGHT_CYAN "%s" FG_CYAN, process_name_short);
+ if (image_name_short) {
+ cprintf("(%s)", image_name_short);
+ }
+ cprintf("[%d]" COLOR_RESET " ", trace_hdr->pid);
+
+ /* write log level */
+ cprintf(level_color);
+ cprintf("<%s>:" COLOR_RESET " ", level_str);
+
+ /* write message */
+ cprintf(FG_WHITE);
+ cprintf("%s" COLOR_RESET "\n", message);
+ fflush(stdout);
+
+ if (trigger_off) {
+ triggered = 0;
+ }
+}
+
+static plist_t get_pid_list()
+{
+ plist_t list = NULL;
+ ostrace_client_t ostrace_tmp = NULL;
+ ostrace_client_start_service(device, &ostrace_tmp, TOOL_NAME);
+ if (ostrace_tmp) {
+ ostrace_get_pid_list(ostrace_tmp, &list);
+ ostrace_client_free(ostrace_tmp);
+ }
+ return list;
+}
+
+static int pid_valid(int pid)
+{
+ plist_t list = get_pid_list();
+ if (!list) return 0;
+ char valbuf[16];
+ snprintf(valbuf, 16, "%d", pid);
+ return (plist_dict_get_item(list, valbuf)) ? 1 : 0;
+}
+
+static int pid_for_proc(const char* procname)
+{
+ int result = -1;
+ plist_t list = get_pid_list();
+ if (!list) {
+ return result;
+ }
+ plist_dict_iter iter = NULL;
+ plist_dict_new_iter(list, &iter);
+ if (iter) {
+ plist_t node = NULL;
+ do {
+ char* key = NULL;
+ node = NULL;
+ plist_dict_next_item(list, iter, &key, &node);
+ if (!key) {
+ break;
+ }
+ if (PLIST_IS_DICT(node)) {
+ plist_t pname = plist_dict_get_item(node, "ProcessName");
+ if (PLIST_IS_STRING(pname)) {
+ if (!strcmp(plist_get_string_ptr(pname, NULL), procname)) {
+ result = (int)strtol(key, NULL, 10);
+ }
+ }
+ }
+ free(key);
+ } while (node);
+ plist_mem_free(iter);
+ }
+ plist_free(list);
+ return result;
+}
+
+static int connect_service(int ostrace_required)
+{
+ if (!device) {
+ idevice_error_t ret = idevice_new_with_options(&device, udid, (use_network) ? IDEVICE_LOOKUP_NETWORK : IDEVICE_LOOKUP_USBMUX);
+ if (ret != IDEVICE_E_SUCCESS) {
+ fprintf(stderr, "Device with udid %s not found!?\n", udid);
+ return -1;
+ }
}
lockdownd_client_t lockdown = NULL;
@@ -361,14 +615,28 @@ static int start_logging(void)
device = NULL;
return -1;
}
-
- /* start syslog_relay service */
lockdownd_service_descriptor_t svc = NULL;
- lerr = lockdownd_start_service(lockdown, SYSLOG_RELAY_SERVICE_NAME, &svc);
+
+ const char* service_name = OSTRACE_SERVICE_NAME;
+ int use_ostrace = 1;
+ if (idevice_get_device_version(device) < IDEVICE_DEVICE_VERSION(9,0,0) || force_syslog_relay) {
+ service_name = SYSLOG_RELAY_SERVICE_NAME;
+ use_ostrace = 0;
+ }
+ if (ostrace_required && !use_ostrace) {
+ fprintf(stderr, "ERROR: This operation requires iOS 9 or later.\n");
+ lockdownd_client_free(lockdown);
+ idevice_free(device);
+ device = NULL;
+ return -1;
+ }
+
+ /* start syslog_relay/os_trace_relay service */
+ lerr = lockdownd_start_service(lockdown, service_name, &svc);
if (lerr == LOCKDOWN_E_PASSWORD_PROTECTED) {
fprintf(stderr, "*** Device is passcode protected, enter passcode on the device to continue ***\n");
while (!quit_flag) {
- lerr = lockdownd_start_service(lockdown, SYSLOG_RELAY_SERVICE_NAME, &svc);
+ lerr = lockdownd_start_service(lockdown, service_name, &svc);
if (lerr != LOCKDOWN_E_PASSWORD_PROTECTED) {
break;
}
@@ -376,32 +644,84 @@ static int start_logging(void)
}
}
if (lerr != LOCKDOWN_E_SUCCESS) {
- fprintf(stderr, "ERROR: Could not connect to lockdownd: %d\n", lerr);
+ fprintf(stderr, "ERROR: Could not start %s service: %s (%d)\n", service_name, lockdownd_strerror(lerr), lerr);
idevice_free(device);
device = NULL;
return -1;
}
lockdownd_client_free(lockdown);
- /* connect to syslog_relay service */
- syslog_relay_error_t serr = SYSLOG_RELAY_E_UNKNOWN_ERROR;
- serr = syslog_relay_client_new(device, svc, &syslog);
- lockdownd_service_descriptor_free(svc);
- if (serr != SYSLOG_RELAY_E_SUCCESS) {
- fprintf(stderr, "ERROR: Could not start service com.apple.syslog_relay.\n");
- idevice_free(device);
- device = NULL;
+ if (use_ostrace) {
+ /* connect to os_trace_relay service */
+ ostrace_error_t serr = OSTRACE_E_UNKNOWN_ERROR;
+ serr = ostrace_client_new(device, svc, &ostrace);
+ lockdownd_service_descriptor_free(svc);
+ if (serr != OSTRACE_E_SUCCESS) {
+ fprintf(stderr, "ERROR: Could not connect to %s service (%d)\n", service_name, serr);
+ idevice_free(device);
+ device = NULL;
+ return -1;
+ }
+ } else {
+ /* connect to syslog_relay service */
+ syslog_relay_error_t serr = SYSLOG_RELAY_E_UNKNOWN_ERROR;
+ serr = syslog_relay_client_new(device, svc, &syslog);
+ lockdownd_service_descriptor_free(svc);
+ if (serr != SYSLOG_RELAY_E_SUCCESS) {
+ fprintf(stderr, "ERROR: Could not connect to %s service (%d)\n", service_name, serr);
+ idevice_free(device);
+ device = NULL;
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int start_logging(void)
+{
+ if (connect_service(0) < 0) {
return -1;
}
/* start capturing syslog */
- serr = syslog_relay_start_capture_raw(syslog, syslog_callback, NULL);
- if (serr != SYSLOG_RELAY_E_SUCCESS) {
- fprintf(stderr, "ERROR: Unable tot start capturing syslog.\n");
- syslog_relay_client_free(syslog);
- syslog = NULL;
- idevice_free(device);
- device = NULL;
+ if (ostrace) {
+ plist_t options = plist_new_dict();
+ if (num_proc_filters == 0 && num_pid_filters == 1 && !proc_filter_excluding) {
+ if (pid_filters[0] > 0) {
+ if (!pid_valid(pid_filters[0])) {
+ fprintf(stderr, "NOTE: A process with pid doesn't exists!\n");
+ }
+ }
+ plist_dict_set_item(options, "Pid", plist_new_int(pid_filters[0]));
+ } else if (num_proc_filters == 1 && num_pid_filters == 0 && !proc_filter_excluding) {
+ int pid = pid_for_proc(proc_filters[0]);
+ if (!strcmp(proc_filters[0], "kernel")) {
+ pid = 0;
+ }
+ if (pid >= 0) {
+ plist_dict_set_item(options, "Pid", plist_new_int(pid));
+ }
+ }
+ ostrace_error_t serr = ostrace_start_activity(ostrace, options, ostrace_syslog_callback, NULL);
+ if (serr != OSTRACE_E_SUCCESS) {
+ fprintf(stderr, "ERROR: Unable to start capturing syslog.\n");
+ ostrace_client_free(ostrace);
+ ostrace = NULL;
+ idevice_free(device);
+ device = NULL;
+ return -1;
+ }
+ } else if (syslog) {
+ syslog_relay_error_t serr = syslog_relay_start_capture_raw(syslog, syslog_callback, NULL);
+ if (serr != SYSLOG_RELAY_E_SUCCESS) {
+ fprintf(stderr, "ERROR: Unable to start capturing syslog.\n");
+ syslog_relay_client_free(syslog);
+ syslog = NULL;
+ idevice_free(device);
+ device = NULL;
+ return -1;
+ }
+ } else {
return -1;
}
@@ -419,6 +739,11 @@ static void stop_logging(void)
syslog_relay_client_free(syslog);
syslog = NULL;
}
+ if (ostrace) {
+ ostrace_stop_activity(ostrace);
+ ostrace_client_free(ostrace);
+ ostrace = NULL;
+ }
if (device) {
idevice_free(device);
@@ -426,6 +751,77 @@ static void stop_logging(void)
}
}
+static int write_callback(const void* buf, size_t len, void *user_data)
+{
+ FILE* f = (FILE*)user_data;
+ ssize_t res = fwrite(buf, 1, len, f);
+ if (res < 0) {
+ return -1;
+ }
+ if (quit_flag > 0) {
+ return -1;
+ }
+ return 0;
+}
+
+static void print_sorted_pidlist(plist_t list)
+{
+ struct listelem;
+ struct listelem {
+ int val;
+ struct listelem *next;
+ };
+ struct listelem* sortedlist = NULL;
+
+ plist_dict_iter iter = NULL;
+ plist_dict_new_iter(list, &iter);
+ if (iter) {
+ plist_t node = NULL;
+ do {
+ char* key = NULL;
+ node = NULL;
+ plist_dict_next_item(list, iter, &key, &node);
+ if (key) {
+ int pidval = (int)strtol(key, NULL, 10);
+ struct listelem* elem = (struct listelem*)malloc(sizeof(struct listelem));
+ elem->val = pidval;
+ elem->next = NULL;
+ struct listelem* prev = NULL;
+ struct listelem* curr = sortedlist;
+
+ while (curr && pidval > curr->val) {
+ prev = curr;
+ curr = curr->next;
+ }
+
+ elem->next = curr;
+ if (prev == NULL) {
+ sortedlist = elem;
+ } else {
+ prev->next = elem;
+ }
+ free(key);
+ }
+ } while (node);
+ plist_mem_free(iter);
+ }
+ struct listelem *listp = sortedlist;
+ char pidstr[16];
+ while (listp) {
+ snprintf(pidstr, 16, "%d", listp->val);
+ plist_t node = plist_dict_get_item(list, pidstr);
+ if (PLIST_IS_DICT(node)) {
+ plist_t pname = plist_dict_get_item(node, "ProcessName");
+ if (PLIST_IS_STRING(pname)) {
+ printf("%d %s\n", listp->val, plist_get_string_ptr(pname, NULL));
+ }
+ }
+ struct listelem *curr = listp;
+ listp = listp->next;
+ free(curr);
+ }
+}
+
static void device_event_cb(const idevice_event_t* event, void* userdata)
{
if (use_network && event->conn_type != CONNECTION_NETWORK) {
@@ -435,7 +831,7 @@ static void device_event_cb(const idevice_event_t* event, void* userdata)
return;
}
if (event->event == IDEVICE_DEVICE_ADD) {
- if (!syslog) {
+ if (!syslog && !ostrace) {
if (!udid) {
udid = strdup(event->udid);
}
@@ -446,7 +842,7 @@ static void device_event_cb(const idevice_event_t* event, void* userdata)
}
}
} else if (event->event == IDEVICE_DEVICE_REMOVE) {
- if (syslog && (strcmp(udid, event->udid) == 0)) {
+ if ((syslog || ostrace) && (strcmp(udid, event->udid) == 0)) {
stop_logging();
fprintf(stdout, "[disconnected:%s]\n", udid);
if (exit_on_disconnect) {
@@ -484,9 +880,20 @@ static void print_usage(int argc, char **argv, int is_error)
" -o, --output FILE write to FILE instead of stdout\n"
" (existing FILE will be overwritten)\n"
" --colors force writing colored output, e.g. for --output\n"
+ " --syslog-relay force use of syslog_relay service\n"
+ "\n"
+ "COMMANDS:\n"
+ " pidlist Print pid and name of all running processes.\n"
+ " archive PATH Request a logarchive and write it to PATH.\n"
+ " Output can be piped to another process using - as PATH.\n"
+ " The file data will be in .tar format.\n"
+ " --start-time VALUE start time of the log data as UNIX timestamp\n"
+ " --age-limit VALUE maximum age of the log data\n"
+ " --size-limit VALUE limit the size of the archive\n"
"\n"
"FILTER OPTIONS:\n"
" -m, --match STRING only print messages that contain STRING\n"
+ " -M, --unmatch STRING print messages that not contain STRING\n"
" -t, --trigger STRING start logging when matching STRING\n"
" -T, --untrigger STRING stop logging when matching STRING\n"
" -p, --process PROCESS only print messages from matching process(es)\n"
@@ -530,6 +937,12 @@ int main(int argc, char *argv[])
{ "quiet-list", no_argument, NULL, 1 },
{ "no-colors", no_argument, NULL, 2 },
{ "colors", no_argument, NULL, 3 },
+ { "syslog_relay", no_argument, NULL, 4 },
+ { "syslog-relay", no_argument, NULL, 4 },
+ { "legacy", no_argument, NULL, 4 },
+ { "start-time", required_argument, NULL, 5 },
+ { "size-limit", required_argument, NULL, 6 },
+ { "age-limit", required_argument, NULL, 7 },
{ "output", required_argument, NULL, 'o' },
{ "version", no_argument, NULL, 'v' },
{ NULL, 0, NULL, 0}
@@ -537,12 +950,12 @@ int main(int argc, char *argv[])
signal(SIGINT, clean_exit);
signal(SIGTERM, clean_exit);
-#ifndef WIN32
+#ifndef _WIN32
signal(SIGQUIT, clean_exit);
signal(SIGPIPE, SIG_IGN);
#endif
- while ((c = getopt_long(argc, argv, "dhu:nxt:T:m:e:p:qkKo:v", longopts, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "dhu:nxt:T:m:M:e:p:qkKo:v", longopts, NULL)) != -1) {
switch (c) {
case 'd':
idevice_set_debug_level(1);
@@ -593,6 +1006,22 @@ int main(int argc, char *argv[])
num_msg_filters++;
}
break;
+ case 'M':
+ if (!*optarg) {
+ fprintf(stderr, "ERROR: reverse message filter string must not be empty!\n");
+ print_usage(argc, argv, 1);
+ return 2;
+ } else {
+ char **new_msg_filters = realloc(msg_reverse_filters, sizeof(char*) * (num_msg_reverse_filters+1));
+ if (!new_msg_filters) {
+ fprintf(stderr, "ERROR: realloc() failed\n");
+ exit(EXIT_FAILURE);
+ }
+ msg_reverse_filters = new_msg_filters;
+ msg_reverse_filters[num_msg_reverse_filters] = strdup(optarg);
+ num_msg_reverse_filters++;
+ }
+ break;
case 't':
if (!*optarg) {
fprintf(stderr, "ERROR: trigger filter string must not be empty!\n");
@@ -647,6 +1076,18 @@ int main(int argc, char *argv[])
case 3:
force_colors = 1;
break;
+ case 4:
+ force_syslog_relay = 1;
+ break;
+ case 5:
+ start_time = strtoll(optarg, NULL, 10);
+ break;
+ case 6:
+ size_limit = strtoll(optarg, NULL, 10);
+ break;
+ case 7:
+ age_limit = strtoll(optarg, NULL, 10);
+ break;
case 'o':
if (!*optarg) {
fprintf(stderr, "ERROR: --output option requires an argument!\n");
@@ -719,14 +1160,92 @@ int main(int argc, char *argv[])
argc -= optind;
argv += optind;
+ if (argc > 0) {
+ if (!strcmp(argv[0], "pidlist")) {
+ if (connect_service(1) < 0) {
+ return 1;
+ }
+ plist_t list = NULL;
+ ostrace_get_pid_list(ostrace, &list);
+ ostrace_client_free(ostrace);
+ ostrace = NULL;
+ idevice_free(device);
+ device = NULL;
+ if (!list) {
+ return 1;
+ }
+ print_sorted_pidlist(list);
+ plist_free(list);
+ return 0;
+ } else if (!strcmp(argv[0], "archive")) {
+ if (force_syslog_relay) {
+ force_syslog_relay = 0;
+ }
+ if (argc < 2) {
+ fprintf(stderr, "Please specify an output filename.\n");
+ return 1;
+ }
+ FILE* outf = NULL;
+ if (!strcmp(argv[1], "-")) {
+ if (isatty(1)) {
+ fprintf(stderr, "Refusing to directly write to stdout. Pipe the output to another process.\n");
+ return 1;
+ }
+ outf = stdout;
+ } else {
+ outf = fopen(argv[1], "w");
+ }
+ if (!outf) {
+ fprintf(stderr, "Failed to open %s: %s\n", argv[1], strerror(errno));
+ return 1;
+ }
+ if (connect_service(1) < 0) {
+ if (outf != stdout) {
+ fclose(outf);
+ }
+ return 1;
+ }
+ plist_t options = plist_new_dict();
+ if (start_time > 0) {
+ plist_dict_set_item(options, "StartTime", plist_new_int(start_time));
+ }
+ if (size_limit > 0) {
+ plist_dict_set_item(options, "SizeLimit", plist_new_int(size_limit));
+ }
+ if (age_limit > 0) {
+ plist_dict_set_item(options, "AgeLimit", plist_new_int(age_limit));
+ }
+ ostrace_create_archive(ostrace, options, write_callback, outf);
+ ostrace_client_free(ostrace);
+ ostrace = NULL;
+ idevice_free(device);
+ device = NULL;
+ if (outf != stdout) {
+ fclose(outf);
+ }
+ return 0;
+ } else {
+ fprintf(stderr, "Unknown command '%s'. See --help for valid commands.\n", argv[0]);
+ return 1;
+ }
+ }
+
int num = 0;
idevice_info_t *devices = NULL;
idevice_get_device_list_extended(&devices, &num);
+ int count = 0;
+ for (int i = 0; i < num; i++) {
+ if (devices[i]->conn_type == CONNECTION_NETWORK && use_network) {
+ count++;
+ } else if (devices[i]->conn_type == CONNECTION_USBMUXD) {
+ count++;
+ }
+ }
idevice_device_list_extended_free(devices);
- if (num == 0) {
+ if (count == 0) {
if (!udid) {
- fprintf(stderr, "No device found. Plug in a device or pass UDID with -u to wait for device to be available.\n");
- return -1;
+ fprintf(stderr, "No device found. Plug in a device or pass UDID with -u to wait for device to become available.\n");
+ return 1;
}
fprintf(stderr, "Waiting for device with UDID %s to become available...\n", udid);
@@ -761,6 +1280,13 @@ int main(int argc, char *argv[])
}
free(msg_filters);
}
+ if (num_msg_reverse_filters > 0) {
+ int i;
+ for (i = 0; i < num_msg_reverse_filters; i++) {
+ free(msg_reverse_filters[i]);
+ }
+ free(msg_reverse_filters);
+ }
if (num_trigger_filters > 0) {
int i;
for (i = 0; i < num_trigger_filters; i++) {