diff options
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/Makefile.am | 12 | ||||
| -rw-r--r-- | tools/afcclient.c | 202 | ||||
| -rw-r--r-- | tools/idevicebackup.c | 19 | ||||
| -rw-r--r-- | tools/idevicebackup2.c | 94 | ||||
| -rw-r--r-- | tools/idevicebtlogger.c | 4 | ||||
| -rw-r--r-- | tools/idevicecrashreport.c | 144 | ||||
| -rw-r--r-- | tools/idevicedate.c | 6 | ||||
| -rw-r--r-- | tools/idevicedebug.c | 4 | ||||
| -rw-r--r-- | tools/idevicedebugserverproxy.c | 4 | ||||
| -rw-r--r-- | tools/idevicedevmodectl.c | 6 | ||||
| -rw-r--r-- | tools/idevicediagnostics.c | 4 | ||||
| -rw-r--r-- | tools/ideviceenterrecovery.c | 4 | ||||
| -rw-r--r-- | tools/ideviceimagemounter.c | 52 | ||||
| -rw-r--r-- | tools/ideviceinfo.c | 4 | ||||
| -rw-r--r-- | tools/idevicename.c | 4 | ||||
| -rw-r--r-- | tools/idevicenotificationproxy.c | 26 | ||||
| -rw-r--r-- | tools/idevicepair.c | 6 | ||||
| -rw-r--r-- | tools/ideviceprovision.c | 33 | ||||
| -rw-r--r-- | tools/idevicescreenshot.c | 4 | ||||
| -rw-r--r-- | tools/idevicesetlocation.c | 30 | ||||
| -rw-r--r-- | tools/idevicesyslog.c | 688 |
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++) { |
