diff options
Diffstat (limited to 'tools/ideviceimagemounter.c')
-rw-r--r-- | tools/ideviceimagemounter.c | 168 |
1 files changed, 92 insertions, 76 deletions
diff --git a/tools/ideviceimagemounter.c b/tools/ideviceimagemounter.c index 7101c7e..f551b6c 100644 --- a/tools/ideviceimagemounter.c +++ b/tools/ideviceimagemounter.c @@ -23,6 +23,8 @@ #include <config.h> #endif +#define TOOL_NAME "ideviceimagemounter" + #include <stdlib.h> #define _GNU_SOURCE 1 #define __USE_GNU 1 @@ -34,6 +36,9 @@ #include <time.h> #include <sys/time.h> #include <inttypes.h> +#ifndef WIN32 +#include <signal.h> +#endif #include <libimobiledevice/libimobiledevice.h> #include <libimobiledevice/lockdown.h> @@ -41,12 +46,13 @@ #include <libimobiledevice/notification_proxy.h> #include <libimobiledevice/mobile_image_mounter.h> #include <asprintf.h> -#include "common/utils.h" +#include <plist/plist.h> static int list_mode = 0; +static int use_network = 0; static int xml_mode = 0; -static char *udid = NULL; -static char *imagetype = NULL; +static const char *udid = NULL; +static const char *imagetype = NULL; static const char PKG_PATH[] = "PublicStaging"; static const char PATH_PREFIX[] = "/private/var/mobile/Media"; @@ -56,62 +62,70 @@ typedef enum { DISK_IMAGE_UPLOAD_TYPE_UPLOAD_IMAGE } disk_image_upload_type_t; -static void print_usage(int argc, char **argv) +static void print_usage(int argc, char **argv, int is_error) { - char *name = NULL; - - name = strrchr(argv[0], '/'); - printf("Usage: %s [OPTIONS] IMAGE_FILE IMAGE_SIGNATURE_FILE\n\n", (name ? name + 1: argv[0])); - printf("Mounts the specified disk image on the device.\n\n"); - printf(" -u, --udid UDID\ttarget specific device by UDID\n"); - printf(" -l, --list\t\tList mount information\n"); - printf(" -t, --imagetype\tImage type to use, default is 'Developer'\n"); - printf(" -x, --xml\t\tUse XML output\n"); - printf(" -d, --debug\t\tenable communication debugging\n"); - printf(" -h, --help\t\tprints usage information\n"); - printf("\n"); - printf("Homepage: <" PACKAGE_URL ">\n"); + char *name = strrchr(argv[0], '/'); + fprintf(is_error ? stderr : stdout, "Usage: %s [OPTIONS] IMAGE_FILE IMAGE_SIGNATURE_FILE\n", (name ? name + 1: argv[0])); + fprintf(is_error ? stderr : stdout, + "\n" + "Mounts the specified disk image on the device.\n" + "\n" + "OPTIONS:\n" + " -u, --udid UDID target specific device by UDID\n" + " -n, --network connect to network device\n" + " -l, --list List mount information\n" + " -t, --imagetype TYPE Image type to use, default is 'Developer'\n" + " -x, --xml Use XML output\n" + " -d, --debug enable communication debugging\n" + " -h, --help prints usage information\n" + " -v, --version prints version information\n" + "\n" + "Homepage: <" PACKAGE_URL ">\n" + "Bug Reports: <" PACKAGE_BUGREPORT ">\n" + ); } static void parse_opts(int argc, char **argv) { static struct option longopts[] = { - {"help", no_argument, NULL, 'h'}, - {"udid", required_argument, NULL, 'u'}, - {"list", no_argument, NULL, 'l'}, - {"imagetype", required_argument, NULL, 't'}, - {"xml", no_argument, NULL, 'x'}, - {"debug", no_argument, NULL, 'd'}, - {NULL, 0, NULL, 0} + { "help", no_argument, NULL, 'h' }, + { "udid", required_argument, NULL, 'u' }, + { "network", no_argument, NULL, 'n' }, + { "list", no_argument, NULL, 'l' }, + { "imagetype", required_argument, NULL, 't' }, + { "xml", no_argument, NULL, 'x' }, + { "debug", no_argument, NULL, 'd' }, + { "version", no_argument, NULL, 'v' }, + { NULL, 0, NULL, 0 } }; int c; while (1) { - c = getopt_long(argc, argv, "hu:lt:xd", longopts, NULL); + c = getopt_long(argc, argv, "hu:lt:xdnv", longopts, NULL); if (c == -1) { break; } switch (c) { case 'h': - print_usage(argc, argv); + print_usage(argc, argv, 0); exit(0); case 'u': if (!*optarg) { fprintf(stderr, "ERROR: UDID must not be empty!\n"); - print_usage(argc, argv); + print_usage(argc, argv, 1); exit(2); } - free(udid); - udid = strdup(optarg); + udid = optarg; + break; + case 'n': + use_network = 1; break; case 'l': list_mode = 1; break; case 't': - if (imagetype) - free(imagetype); - imagetype = strdup(optarg); + imagetype = optarg; break; case 'x': xml_mode = 1; @@ -119,22 +133,16 @@ static void parse_opts(int argc, char **argv) case 'd': idevice_set_debug_level(1); break; + case 'v': + printf("%s %s\n", TOOL_NAME, PACKAGE_VERSION); + exit(0); default: - print_usage(argc, argv); + print_usage(argc, argv, 1); exit(2); } } } -static void print_xml(plist_t node) -{ - char *xml = NULL; - uint32_t len = 0; - plist_to_xml(node, &xml, &len); - if (xml) - puts(xml); -} - static ssize_t mim_upload_cb(void* buf, size_t size, void* userdata) { return fread(buf, 1, size, (FILE*)userdata); @@ -153,6 +161,9 @@ int main(int argc, char **argv) size_t image_size = 0; char *image_sig_path = NULL; +#ifndef WIN32 + signal(SIGPIPE, SIG_IGN); +#endif parse_opts(argc, argv); argc -= optind; @@ -174,12 +185,16 @@ int main(int argc, char **argv) } } - if (IDEVICE_E_SUCCESS != idevice_new(&device, udid)) { - printf("No device found, is it plugged in?\n"); + if (IDEVICE_E_SUCCESS != idevice_new_with_options(&device, udid, (use_network) ? IDEVICE_LOOKUP_NETWORK : IDEVICE_LOOKUP_USBMUX)) { + if (udid) { + printf("No device found with udid %s.\n", udid); + } else { + printf("No device found.\n"); + } return -1; } - if (LOCKDOWN_E_SUCCESS != (ldret = lockdownd_client_new_with_handshake(device, &lckd, "ideviceimagemounter"))) { + if (LOCKDOWN_E_SUCCESS != (ldret = lockdownd_client_new_with_handshake(device, &lckd, TOOL_NAME))) { printf("ERROR: Could not connect to lockdown, error code %d.\n", ldret); goto leave; } @@ -200,6 +215,20 @@ int main(int argc, char **argv) } } + if (product_version_major == 16) { + uint8_t dev_mode_status = 0; + plist_t val = NULL; + ldret = lockdownd_get_value(lckd, "com.apple.security.mac.amfi", "DeveloperModeStatus", &val); + if (ldret == LOCKDOWN_E_SUCCESS) { + plist_get_bool_val(val, &dev_mode_status); + plist_free(val); + } + if (!dev_mode_status) { + printf("ERROR: You have to enable Developer Mode on the given device in order to allowing mounting a developer disk image.\n"); + goto leave; + } + } + lockdownd_start_service(lckd, "com.apple.mobile.mobile_image_mounter", &service); if (!service || service->port == 0) { @@ -248,23 +277,18 @@ int main(int argc, char **argv) lockdownd_client_free(lckd); lckd = NULL; - mobile_image_mounter_error_t err; + mobile_image_mounter_error_t err = MOBILE_IMAGE_MOUNTER_E_UNKNOWN_ERROR; plist_t result = NULL; if (list_mode) { /* list mounts mode */ if (!imagetype) { - imagetype = strdup("Developer"); + imagetype = "Developer"; } err = mobile_image_mounter_lookup_image(mim, imagetype, &result); - free(imagetype); if (err == MOBILE_IMAGE_MOUNTER_E_SUCCESS) { res = 0; - if (xml_mode) { - print_xml(result); - } else { - plist_print_to_stream(result, stdout); - } + plist_write_to_stream(result, stdout, (xml_mode) ? PLIST_FORMAT_XML : PLIST_FORMAT_LIMD, 0); } else { printf("Error: lookup_image returned %d\n", err); } @@ -302,7 +326,7 @@ int main(int argc, char **argv) if (!imagetype) { - imagetype = strdup("Developer"); + imagetype = "Developer"; } switch(disk_image_upload_type) { @@ -344,7 +368,7 @@ int main(int argc, char **argv) uint32_t written, total = 0; while (total < amount) { written = 0; - if (afc_file_write(afc, af, buf, amount, &written) != + if (afc_file_write(afc, af, buf + total, amount - total, &written) != AFC_E_SUCCESS) { fprintf(stderr, "AFC Write error!\n"); break; @@ -368,11 +392,18 @@ int main(int argc, char **argv) fclose(f); + if (err != MOBILE_IMAGE_MOUNTER_E_SUCCESS) { + if (err == MOBILE_IMAGE_MOUNTER_E_DEVICE_LOCKED) { + printf("ERROR: Device is locked, can't mount. Unlock device and try again.\n"); + } else { + printf("ERROR: Unknown error occurred, can't mount.\n"); + } + goto error_out; + } printf("done.\n"); printf("Mounting...\n"); err = mobile_image_mounter_mount_image(mim, mountname, sig, sig_length, imagetype, &result); - free(imagetype); if (err == MOBILE_IMAGE_MOUNTER_E_SUCCESS) { if (result) { plist_t node = plist_dict_get_item(result, "Status"); @@ -385,20 +416,12 @@ int main(int argc, char **argv) res = 0; } else { printf("unexpected status value:\n"); - if (xml_mode) { - print_xml(result); - } else { - plist_print_to_stream(result, stdout); - } + plist_write_to_stream(result, stdout, (xml_mode) ? PLIST_FORMAT_XML : PLIST_FORMAT_LIMD, 0); } free(status); } else { printf("unexpected result:\n"); - if (xml_mode) { - print_xml(result); - } else { - plist_print_to_stream(result, stdout); - } + plist_write_to_stream(result, stdout, (xml_mode) ? PLIST_FORMAT_XML : PLIST_FORMAT_LIMD, 0); } } node = plist_dict_get_item(result, "Error"); @@ -410,19 +433,11 @@ int main(int argc, char **argv) free(error); } else { printf("unexpected result:\n"); - if (xml_mode) { - print_xml(result); - } else { - plist_print_to_stream(result, stdout); - } + plist_write_to_stream(result, stdout, (xml_mode) ? PLIST_FORMAT_XML : PLIST_FORMAT_LIMD, 0); } } else { - if (xml_mode) { - print_xml(result); - } else { - plist_print_to_stream(result, stdout); - } + plist_write_to_stream(result, stdout, (xml_mode) ? PLIST_FORMAT_XML : PLIST_FORMAT_LIMD, 0); } } } else { @@ -435,6 +450,7 @@ int main(int argc, char **argv) plist_free(result); } +error_out: /* perform hangup command */ mobile_image_mounter_hangup(mim); /* free client */ |