From a13cc14bef4397850fa03e57cfbe93b12f78e076 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 30 Apr 2013 11:45:23 -0700 Subject: [PATCH 001/219] Update README.md --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index f087557c..1c7bc8f5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,4 @@ -## This project is no longer maintained. - -fruitstrap +ios-deploy ========== Install and debug iPhone apps without using Xcode. Designed to work on unjailbroken devices. From 5cfa9161e08fec3957e40989b2ce2725bd8b7b07 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 30 Apr 2013 12:01:03 -0700 Subject: [PATCH 002/219] Updated Makefile (renaming of binary, iOS 6.1 SDK, using clang instead of gcc) --- .DS_Store | Bin 0 -> 6148 bytes .gitignore | 2 +- Makefile | 17 +++++++++-------- fruitstrap.c => ios-deploy.c | 0 4 files changed, 10 insertions(+), 9 deletions(-) create mode 100644 .DS_Store rename fruitstrap.c => ios-deploy.c (100%) diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..573436a88bd24231684bcae05ca3553b55854235 GIT binary patch literal 6148 zcmeHKOHRWu5PdEIO8E%EhGmv)sKgBdv`9$6qU;g$CklmB{3Lcc28ZGR9DsY2H)Dg6 zw1^Et2+c_LbL@GZ@pBW`0Nn0FcN)l{a!EzbNqLamWn!sLnA?&@4uoxfJhQ zW>p+<%~#Z~&v?|a=nvV^=bZlv{Zq8PFB;@MvfUxpaZ%#R?&i4*XfdlDvW|##{(ibe zhVF5mu}(&hx~1HsTaD6UOLqIaUCz(KG|YZP0iM}n)kTk1n*yeQDe$R)d>>*K!6abj zQ9m85^a? Date: Tue, 30 Apr 2013 12:07:52 -0700 Subject: [PATCH 003/219] Updated Makefile for install and debug targets. --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 7b247948..8d307ee4 100644 --- a/Makefile +++ b/Makefile @@ -16,10 +16,10 @@ ios-deploy: ios-deploy.c gcc -o ios-deploy -framework CoreFoundation -framework MobileDevice -F/System/Library/PrivateFrameworks ios-deploy.c install: all - ./ios-deploy demo.app + ./ios-deploy --bundle demo.app debug: all - ./ios-deploy -d demo.app + ./ios-deploy --debug --bundle demo.app clean: rm -rf *.app demo ios-deploy \ No newline at end of file From d99423c6bde9a85daad04e45d3260db537df76c1 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 30 Apr 2013 12:19:01 -0700 Subject: [PATCH 004/219] Added note about listing device ids. --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 1c7bc8f5..04e98030 100644 --- a/README.md +++ b/README.md @@ -24,3 +24,10 @@ Install and debug iPhone apps without using Xcode. Designed to work on unjailbro ## Notes * With some modifications, it may be possible to use this without Xcode installed; however, you would need a copy of the relevant DeveloperDiskImage.dmg (included with Xcode). GDB would also run slower as symbols would be downloaded from the device on-the-fly. + + +## Listing Device Ids + +Device Ids are the UDIDs of the iOS devices. From the command line, you can list device ids [this way](http://javierhz.blogspot.com/2012/06/how-to-get-udid-of-iphone-using-shell.html): + + system_profiler SPUSBDataType | sed -n -e '/iPad/,/Serial/p' -e '/iPhone/,/Serial/p' | grep "Serial Number:" | awk -F ": " '{print $2}' From ab28039aa58b339725dec8b97c7fa63f4a83d866 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 30 Apr 2013 12:20:02 -0700 Subject: [PATCH 005/219] Executable rename in docs. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 04e98030..6db3b531 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Install and debug iPhone apps without using Xcode. Designed to work on unjailbro ## Usage -* `fruitstrap [-d] -b [device_id]` +* `ios-deploy [-d] -b [device_id]` * Optional `-d` flag launches a remote GDB session after the app has been installed. * `` must be an iPhone application bundle, *not* an IPA. * Optional `device_id`; useful when you have more than one iPhone/iPad connected. From ba7d916e7bddf2a7e792703f93526e8095b0cc93 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 30 Apr 2013 12:34:33 -0700 Subject: [PATCH 006/219] Update LICENSE --- LICENSE | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE b/LICENSE index e03ea70f..e8010a30 100644 --- a/LICENSE +++ b/LICENSE @@ -1,2 +1,2 @@ -fruitstrap is available under the provisions of the GNU General Public License, -version 3 (or later), available here: http://www.gnu.org/licenses/gpl-3.0.html \ No newline at end of file +ios-deploy is available under the provisions of the GNU General Public License, +version 3 (or later), available here: http://www.gnu.org/licenses/gpl-3.0.html From 7d0ba9249319d9e40e061c40810954ed6448b236 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Fri, 10 May 2013 16:44:54 -0700 Subject: [PATCH 007/219] Added -V/--version flag to output the app version. --- ios-deploy.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 6693f515..840505ee 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -9,6 +9,7 @@ #include #include "MobileDevice.h" +#define APP_VERSION "1.0" #define FDVENDOR_PATH "/tmp/fruitstrap-remote-debugserver" #define PREP_CMDS_PATH "/tmp/fruitstrap-gdb-prep-cmds" #define GDB_SHELL "/Developer/Platforms/iPhoneOS.platform/Developer/usr/libexec/gdb/gdb-arm-apple-darwin --arch armv7 -q -x " PREP_CMDS_PATH @@ -496,7 +497,11 @@ void timeout_callback(CFRunLoopTimerRef timer, void *info) { } void usage(const char* app) { - printf("usage: %s [-d/--debug] [-i/--id device_id] -b/--bundle bundle.app [-a/--args arguments] [-t/--timeout timeout(seconds)]\n", app); + printf("usage: %s [-V/--version] [-v/--verbose] [-d/--debug] [-i/--id device_id] -b/--bundle bundle.app [-a/--args arguments] [-t/--timeout timeout(seconds)]\n", app); +} + +void version() { + printf("%s\n", APP_VERSION); } int main(int argc, char *argv[]) { @@ -507,11 +512,12 @@ int main(int argc, char *argv[]) { { "args", required_argument, NULL, 'a' }, { "verbose", no_argument, NULL, 'v' }, { "timeout", required_argument, NULL, 't' }, + { "version", no_argument, NULL, 'V' }, { NULL, 0, NULL, 0 }, }; char ch; - while ((ch = getopt_long(argc, argv, "dvi:b:a:t:", longopts, NULL)) != -1) + while ((ch = getopt_long(argc, argv, "Vdvi:b:a:t:", longopts, NULL)) != -1) { switch (ch) { case 'd': @@ -529,6 +535,9 @@ int main(int argc, char *argv[]) { case 'v': verbose = 1; break; + case 'V': + version(); + return 1; case 't': timeout = atoi(optarg); break; From c599684b96305626201bcd6e4a283c1728c00cfb Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Fri, 10 May 2013 16:50:29 -0700 Subject: [PATCH 008/219] Removing last remnants of old project name. --- ios-deploy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 840505ee..c4dc6476 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -10,8 +10,8 @@ #include "MobileDevice.h" #define APP_VERSION "1.0" -#define FDVENDOR_PATH "/tmp/fruitstrap-remote-debugserver" -#define PREP_CMDS_PATH "/tmp/fruitstrap-gdb-prep-cmds" +#define FDVENDOR_PATH "/tmp/ios-deploy-remote-debugserver" +#define PREP_CMDS_PATH "/tmp/ios-deploy-gdb-prep-cmds" #define GDB_SHELL "/Developer/Platforms/iPhoneOS.platform/Developer/usr/libexec/gdb/gdb-arm-apple-darwin --arch armv7 -q -x " PREP_CMDS_PATH // approximation of what Xcode does: From bab114a250a77448593666e7132ad29ee15d8e0d Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Fri, 10 May 2013 16:51:14 -0700 Subject: [PATCH 009/219] Ignore .DS_Store --- .DS_Store | Bin 6148 -> 0 bytes .gitignore | 2 ++ 2 files changed, 2 insertions(+) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 573436a88bd24231684bcae05ca3553b55854235..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKOHRWu5PdEIO8E%EhGmv)sKgBdv`9$6qU;g$CklmB{3Lcc28ZGR9DsY2H)Dg6 zw1^Et2+c_LbL@GZ@pBW`0Nn0FcN)l{a!EzbNqLamWn!sLnA?&@4uoxfJhQ zW>p+<%~#Z~&v?|a=nvV^=bZlv{Zq8PFB;@MvfUxpaZ%#R?&i4*XfdlDvW|##{(ibe zhVF5mu}(&hx~1HsTaD6UOLqIaUCz(KG|YZP0iM}n)kTk1n*yeQDe$R)d>>*K!6abj zQ9m85^a? Date: Fri, 10 May 2013 17:34:19 -0700 Subject: [PATCH 010/219] Updated Makefile for homebrew --- Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 8d307ee4..9c14d7d6 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ IOS_CC = clang IOS_SDK = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk -all: demo.app ios-deploy +all: ios-deploy demo.app: demo Info.plist mkdir -p demo.app @@ -16,7 +16,8 @@ ios-deploy: ios-deploy.c gcc -o ios-deploy -framework CoreFoundation -framework MobileDevice -F/System/Library/PrivateFrameworks ios-deploy.c install: all - ./ios-deploy --bundle demo.app + mkdir -p $(prefix)/bin + cp ios-deploy $(prefix)/bin debug: all ./ios-deploy --debug --bundle demo.app From cca4ef14d29438ec5ecbb1d86d7166ab575ce7c5 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Fri, 10 May 2013 18:02:27 -0700 Subject: [PATCH 011/219] Updated ios-deploy to compile using clang --- Makefile | 4 ++-- ios-deploy.c | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 9c14d7d6..f2e7b303 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ IOS_CC = clang IOS_SDK = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk -all: ios-deploy +all: clean ios-deploy demo.app: demo Info.plist mkdir -p demo.app @@ -13,7 +13,7 @@ demo: demo.c $(IOS_CC) -arch armv7 -isysroot $(IOS_SDK) -framework CoreFoundation -o demo demo.c ios-deploy: ios-deploy.c - gcc -o ios-deploy -framework CoreFoundation -framework MobileDevice -F/System/Library/PrivateFrameworks ios-deploy.c + $(IOS_CC) -o ios-deploy -framework CoreFoundation -framework MobileDevice -F/System/Library/PrivateFrameworks ios-deploy.c install: all mkdir -p $(prefix)/bin diff --git a/ios-deploy.c b/ios-deploy.c index c4dc6476..7c50da7f 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -44,6 +44,8 @@ int AMDeviceSecureTransferPath(int zero, AMDeviceRef device, CFURLRef url, CFDic int AMDeviceSecureInstallApplication(int zero, AMDeviceRef device, CFURLRef url, CFDictionaryRef options, void *callback, int cbarg); int AMDeviceMountImage(AMDeviceRef device, CFStringRef image, CFDictionaryRef options, void *callback, int cbarg); int AMDeviceLookupApplications(AMDeviceRef device, int zero, CFDictionaryRef* result); +int AMDeviceTransferApplication(unsigned int fd, CFStringRef path, void* ptr, void *transfer_callback, void* ptr2); +int AMDeviceInstallApplication(unsigned int fd, CFStringRef path, CFDictionaryRef options, void *install_callback, void* ptr); bool found_device = false, debug = false, verbose = false; char *app_path = NULL; @@ -125,11 +127,11 @@ CFStringRef copy_developer_disk_image_path(AMDeviceRef device) { found = path_exists(path); } if (!found) { - path = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s/Library/Developer/Xcode/iOS DeviceSupport/@%/DeveloperDiskImage.dmg"), home, version); + path = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s/Library/Developer/Xcode/iOS DeviceSupport/%@/DeveloperDiskImage.dmg"), home, version); found = path_exists(path); } if (!found) { - path = CFStringCreateWithFormat(NULL, NULL, CFSTR("/Developer/Platforms/iPhoneOS.platform/DeviceSupport/@%/DeveloperDiskImage.dmg"), version); + path = CFStringCreateWithFormat(NULL, NULL, CFSTR("/Developer/Platforms/iPhoneOS.platform/DeviceSupport/%@/DeveloperDiskImage.dmg"), version); found = path_exists(path); } if (!found) { @@ -414,7 +416,7 @@ void handle_device(AMDeviceRef device) { CFRelease(relative_url); - int afcFd; + unsigned int afcFd; assert(AMDeviceStartService(device, CFSTR("com.apple.afc"), &afcFd, NULL) == 0); assert(AMDeviceStopSession(device) == 0); assert(AMDeviceDisconnect(device) == 0); @@ -431,7 +433,7 @@ void handle_device(AMDeviceRef device) { assert(AMDeviceValidatePairing(device) == 0); assert(AMDeviceStartSession(device) == 0); - int installFd; + unsigned int installFd; assert(AMDeviceStartService(device, CFSTR("com.apple.mobile.installation_proxy"), &installFd, NULL) == 0); assert(AMDeviceStopSession(device) == 0); From 87e5f9ee06b748679a1c61147387ad5f2ed349b6 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 13 May 2013 12:10:48 -0700 Subject: [PATCH 012/219] Removed clean target that might have returned error that aborted homebrew install --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f2e7b303..c2829c18 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ demo: demo.c ios-deploy: ios-deploy.c $(IOS_CC) -o ios-deploy -framework CoreFoundation -framework MobileDevice -F/System/Library/PrivateFrameworks ios-deploy.c -install: all +install: ios-deploy mkdir -p $(prefix)/bin cp ios-deploy $(prefix)/bin From 7cdecd6f12df4afe1c787f9a2ad6abf3795b20da Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 28 May 2013 15:40:03 -0700 Subject: [PATCH 013/219] Changed default compiler to gcc (since on Snow Leopard 10.6 gcc is the default) On a clean Snow Leopard system, and installing Xcode 4.2 (the last Xcode for SL), the default compiler is gcc (i686-apple-darwin10-llvm-gcc-4.2) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c2829c18..31760528 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -IOS_CC = clang +IOS_CC = gcc IOS_SDK = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk all: clean ios-deploy From 41165f433ad900190b30dbdf2142a65c0080490a Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Sun, 21 Jul 2013 12:58:34 -0700 Subject: [PATCH 014/219] Added package.json for npm install --- package.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 package.json diff --git a/package.json b/package.json new file mode 100644 index 00000000..e3436c29 --- /dev/null +++ b/package.json @@ -0,0 +1,19 @@ +{ + "name": "ios-deploy", + "version": "1.0.1", + "description": "launch iOS apps iOS devices from the command line (Xcode 4)", + "main": "ios-deploy", + "scripts": { + "install": "make install prefix=/usr/local" + }, + "repository": { + "type": "git", + "url": "https://github.com/phonegap/ios-deploy" + }, + "keywords": [ + "ios-deploy", + "deploy to iOS device" + ], + "author": "Greg Hughes", + "license": "GPLv3" +} From 8990de95666fa8b82d1e2b37921f64be4ee67d3e Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Sat, 27 Jul 2013 00:27:11 -0700 Subject: [PATCH 015/219] Updated Makefile to install 'Latest' symlink (#2) --- Makefile | 8 ++++++-- ios-deploy.c | 9 +++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 31760528..33c42bfc 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ IOS_CC = gcc -IOS_SDK = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk +IOS_SDK = $(shell xcode-select --print-path)/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk +DEVICE_SUPPORT = $(shell xcode-select --print-path)/Platforms/iPhoneOS.platform/DeviceSupport all: clean ios-deploy @@ -15,7 +16,10 @@ demo: demo.c ios-deploy: ios-deploy.c $(IOS_CC) -o ios-deploy -framework CoreFoundation -framework MobileDevice -F/System/Library/PrivateFrameworks ios-deploy.c -install: ios-deploy +symlink: + cd $(DEVICE_SUPPORT); ln -sfn "`find . -type d -maxdepth 1 -exec basename {} \; | tail -1`" Latest + +install: symlink ios-deploy mkdir -p $(prefix)/bin cp ios-deploy $(prefix)/bin diff --git a/ios-deploy.c b/ios-deploy.c index 7c50da7f..c82dde03 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -95,7 +95,7 @@ CFStringRef copy_device_support_path(AMDeviceRef device) { } if (!found) { - path = CFStringCreateWithFormat(NULL, NULL, CFSTR("/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/%@"), version); + path = CFStringCreateWithFormat(NULL, NULL, CFSTR("/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/Latest")); found = path_exists(path); } @@ -123,7 +123,7 @@ CFStringRef copy_developer_disk_image_path(AMDeviceRef device) { found = path_exists(path); if (!found) { - path = CFStringCreateWithFormat(NULL, NULL, CFSTR("/Developer/Platforms/iPhoneOS.platform/DeviceSupport/%@ (%@/DeveloperDiskImage.dmg)"), version, build); + path = CFStringCreateWithFormat(NULL, NULL, CFSTR("/Developer/Platforms/iPhoneOS.platform/DeviceSupport/%@ (%@)/DeveloperDiskImage.dmg)"), version, build); found = path_exists(path); } if (!found) { @@ -142,6 +142,11 @@ CFStringRef copy_developer_disk_image_path(AMDeviceRef device) { path = CFStringCreateWithFormat(NULL, NULL, CFSTR("/Developer/Platforms/iPhoneOS.platform/DeviceSupport/Latest/DeveloperDiskImage.dmg")); found = path_exists(path); } + if (!found) + { + path = CFStringCreateWithFormat(NULL, NULL, CFSTR("/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/Latest/DeveloperDiskImage.dmg")); + found = path_exists(path); + } CFRelease(version); CFRelease(build); From 512e741f8b1f2b5bd074e8cf8e2a7a1fb75c04f7 Mon Sep 17 00:00:00 2001 From: Henrik Nilsson Date: Sat, 1 Jun 2013 00:27:31 +0200 Subject: [PATCH 016/219] Use xcode-select to locate gdb binary. Gdb command change from finish to continue and quit (from @HenrikNilsson) --- ios-deploy.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index c82dde03..5095736c 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -12,7 +12,7 @@ #define APP_VERSION "1.0" #define FDVENDOR_PATH "/tmp/ios-deploy-remote-debugserver" #define PREP_CMDS_PATH "/tmp/ios-deploy-gdb-prep-cmds" -#define GDB_SHELL "/Developer/Platforms/iPhoneOS.platform/Developer/usr/libexec/gdb/gdb-arm-apple-darwin --arch armv7 -q -x " PREP_CMDS_PATH +#define GDB_SHELL "`xcode-select -print-path`/Platforms/iPhoneOS.platform/Developer/usr/libexec/gdb/gdb-arm-apple-darwin --arch armv7 -q -x " PREP_CMDS_PATH // approximation of what Xcode does: #define GDB_PREP_CMDS CFSTR("set mi-show-protections off\n\ @@ -37,7 +37,9 @@ set inferior-auto-start-cfm off\n\ set sharedLibrary load-rules dyld \".*libobjc.*\" all dyld \".*CoreFoundation.*\" all dyld \".*Foundation.*\" all dyld \".*libSystem.*\" all dyld \".*AppKit.*\" all dyld \".*PBGDBIntrospectionSupport.*\" all dyld \".*/usr/lib/dyld.*\" all dyld \".*CarbonDataFormatters.*\" all dyld \".*libauto.*\" all dyld \".*CFDataFormatters.*\" all dyld \"/System/Library/Frameworks\\\\\\\\|/System/Library/PrivateFrameworks\\\\\\\\|/usr/lib\" extern dyld \".*\" all exec \".*\" all\n\ sharedlibrary apply-load-rules all\n\ - set inferior-auto-start-dyld 1") + set inferior-auto-start-dyld 1\n\ + continue\n\ + quit\n") typedef struct am_device * AMDeviceRef; int AMDeviceSecureTransferPath(int zero, AMDeviceRef device, CFURLRef url, CFDictionaryRef options, void *callback, int cbarg); From ea8e9dd53b1c291c5690c30cfe8d77bd4b6837a9 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Sat, 27 Jul 2013 00:37:26 -0700 Subject: [PATCH 017/219] Updated version to 1.0.2 --- ios-deploy.c | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 5095736c..4b21718f 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -9,7 +9,7 @@ #include #include "MobileDevice.h" -#define APP_VERSION "1.0" +#define APP_VERSION "1.0.2" #define FDVENDOR_PATH "/tmp/ios-deploy-remote-debugserver" #define PREP_CMDS_PATH "/tmp/ios-deploy-gdb-prep-cmds" #define GDB_SHELL "`xcode-select -print-path`/Platforms/iPhoneOS.platform/Developer/usr/libexec/gdb/gdb-arm-apple-darwin --arch armv7 -q -x " PREP_CMDS_PATH diff --git a/package.json b/package.json index e3436c29..24811568 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ios-deploy", - "version": "1.0.1", + "version": "1.0.2", "description": "launch iOS apps iOS devices from the command line (Xcode 4)", "main": "ios-deploy", "scripts": { From 88db2f05554bc160d1b2ea30afdac850a67fd9ce Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 29 Jul 2013 15:52:34 -0700 Subject: [PATCH 018/219] v1.0.3 - support npm uninstall --- Makefile | 5 ++++- package.json | 5 +++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 33c42bfc..c9d75e32 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ demo.app: demo Info.plist demo: demo.c $(IOS_CC) -arch armv7 -isysroot $(IOS_SDK) -framework CoreFoundation -o demo demo.c -ios-deploy: ios-deploy.c +ios-deploy: clean ios-deploy.c $(IOS_CC) -o ios-deploy -framework CoreFoundation -framework MobileDevice -F/System/Library/PrivateFrameworks ios-deploy.c symlink: @@ -23,6 +23,9 @@ install: symlink ios-deploy mkdir -p $(prefix)/bin cp ios-deploy $(prefix)/bin +uninstall: + rm $(prefix)/bin/ios-deploy + debug: all ./ios-deploy --debug --bundle demo.app diff --git a/package.json b/package.json index 24811568..ba640ec2 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,12 @@ { "name": "ios-deploy", - "version": "1.0.2", + "version": "1.0.3", "description": "launch iOS apps iOS devices from the command line (Xcode 4)", "main": "ios-deploy", "scripts": { - "install": "make install prefix=/usr/local" + "preinstall": "make ios-deploy" }, + "bin" : "./ios-deploy" , "repository": { "type": "git", "url": "https://github.com/phonegap/ios-deploy" From 79aff2586afbc6639e2a1fbb043ce81f9c7d9aaa Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Thu, 19 Sep 2013 14:31:56 -0700 Subject: [PATCH 019/219] Interim checkin for issue #5 to make it compile (still has runtime errors IndexError: list index out of range) --- MobileDevice.h | 5 + ios-deploy.c | 419 +++++++++++++++++++++++++++++++------------------ 2 files changed, 270 insertions(+), 154 deletions(-) diff --git a/MobileDevice.h b/MobileDevice.h index 1a39b098..837cfd4d 100644 --- a/MobileDevice.h +++ b/MobileDevice.h @@ -448,6 +448,11 @@ void AMDAddLogFileDescriptor(int fd); //kern_return_t AMDeviceSendMessage(service_conn_t socket, void *unused, CFPropertyListRef plist); //kern_return_t AMDeviceReceiveMessage(service_conn_t socket, CFDictionaryRef options, CFPropertyListRef * result); +typedef int (*am_device_install_application_callback)(CFDictionaryRef, int); + +mach_error_t AMDeviceInstallApplication(service_conn_t socket, CFStringRef path, CFDictionaryRef options, am_device_install_application_callback callback, void *user); +mach_error_t AMDeviceTransferApplication(service_conn_t socket, CFStringRef path, CFDictionaryRef options, am_device_install_application_callback callbackj, void *user); + /* ---------------------------------------------------------------------------- * Semi-private routines * ------------------------------------------------------------------------- */ diff --git a/ios-deploy.c b/ios-deploy.c index 4b21718f..b08f351a 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -3,59 +3,74 @@ #import #include #include +#include +#include #include #include #include #include +#include +#include +#include #include "MobileDevice.h" -#define APP_VERSION "1.0.2" -#define FDVENDOR_PATH "/tmp/ios-deploy-remote-debugserver" -#define PREP_CMDS_PATH "/tmp/ios-deploy-gdb-prep-cmds" -#define GDB_SHELL "`xcode-select -print-path`/Platforms/iPhoneOS.platform/Developer/usr/libexec/gdb/gdb-arm-apple-darwin --arch armv7 -q -x " PREP_CMDS_PATH - -// approximation of what Xcode does: -#define GDB_PREP_CMDS CFSTR("set mi-show-protections off\n\ - set auto-raise-load-levels 1\n\ - set shlib-path-substitutions /usr \"{ds_path}/Symbols/usr\" /System \"{ds_path}/Symbols/System\" \"{device_container}\" \"{disk_container}\" \"/private{device_container}\" \"{disk_container}\" /Developer \"{ds_path}/Symbols/Developer\"\n\ - set remote max-packet-size 1024\n\ - set sharedlibrary check-uuids on\n\ - set env NSUnbufferedIO YES\n\ - set minimal-signal-handling 1\n\ - set sharedlibrary load-rules \\\".*\\\" \\\".*\\\" container\n\ - set inferior-auto-start-dyld 0\n\ - file \"{disk_app}\"\n\ - set remote executable-directory {device_app}\n\ - set remote noack-mode 1\n\ - set trust-readonly-sections 1\n\ - target remote-mobile " FDVENDOR_PATH "\n\ - mem 0x1000 0x3fffffff cache\n\ - mem 0x40000000 0xffffffff none\n\ - mem 0x00000000 0x0fff none\n\ - run {args}\n\ - set minimal-signal-handling 0\n\ - set inferior-auto-start-cfm off\n\ - set sharedLibrary load-rules dyld \".*libobjc.*\" all dyld \".*CoreFoundation.*\" all dyld \".*Foundation.*\" all dyld \".*libSystem.*\" all dyld \".*AppKit.*\" all dyld \".*PBGDBIntrospectionSupport.*\" all dyld \".*/usr/lib/dyld.*\" all dyld \".*CarbonDataFormatters.*\" all dyld \".*libauto.*\" all dyld \".*CFDataFormatters.*\" all dyld \"/System/Library/Frameworks\\\\\\\\|/System/Library/PrivateFrameworks\\\\\\\\|/usr/lib\" extern dyld \".*\" all exec \".*\" all\n\ - sharedlibrary apply-load-rules all\n\ - set inferior-auto-start-dyld 1\n\ - continue\n\ - quit\n") +#define FDVENDOR_PATH "/tmp/fruitstrap-remote-debugserver" +#define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds" +#define PYTHON_MODULE_PATH "/tmp/fruitstrap.py" +#define LLDB_SHELL "python -u -c \"import time; time.sleep(0.5); print 'run'; time.sleep(2000000)\" | lldb -s " PREP_CMDS_PATH + +/* + * Startup script passed to lldb. + * To see how xcode interacts with lldb, put this into .lldbinit: + * log enable -v -f /Users/vargaz/lldb.log lldb all + * log enable -v -f /Users/vargaz/gdb-remote.log gdb-remote all + */ +#define LLDB_PREP_CMDS CFSTR("\ + script fruitstrap_device_app=\"{device_app}\"\n\ + script fruitstrap_connect_url=\"connect://127.0.0.1:12345\"\n\ + platform select remote-ios\n\ + target create \"{disk_app}\"\n\ + #settings set target.process.extra-startup-command \"QSetLogging:bitmask=LOG_ALL;\"\n \ + command script import \"" PYTHON_MODULE_PATH "\"\n\ +") + +/* + * Some things do not seem to work when using the normal commands like process connect/launch, so we invoke them + * through the python interface. Also, Launch () doesn't seem to work when ran from init_module (), so we add + * a command which can be used by the user to run it. + */ +#define LLDB_FRUITSTRAP_MODULE CFSTR("\ +import lldb\n\ +\n\ +def __lldb_init_module(debugger, internal_dict):\n\ + # These two are passed in by the script which loads us\n\ + device_app=internal_dict['fruitstrap_device_app']\n\ + connect_url=internal_dict['fruitstrap_connect_url']\n\ + lldb.target.modules[0].SetPlatformFileSpec(lldb.SBFileSpec(device_app))\n\ + lldb.debugger.HandleCommand (\"command script add -s asynchronous -f fruitstrap.fsrun_command run\")\n\ + error=lldb.SBError()\n\ + lldb.target.ConnectRemote(lldb.target.GetDebugger().GetListener(),connect_url,None,error)\n\ +\n\ +def fsrun_command(debugger, command, result, internal_dict):\n\ + error=lldb.SBError()\n\ + lldb.target.Launch(lldb.SBLaunchInfo(None),error)\n\ +") + typedef struct am_device * AMDeviceRef; int AMDeviceSecureTransferPath(int zero, AMDeviceRef device, CFURLRef url, CFDictionaryRef options, void *callback, int cbarg); int AMDeviceSecureInstallApplication(int zero, AMDeviceRef device, CFURLRef url, CFDictionaryRef options, void *callback, int cbarg); int AMDeviceMountImage(AMDeviceRef device, CFStringRef image, CFDictionaryRef options, void *callback, int cbarg); int AMDeviceLookupApplications(AMDeviceRef device, int zero, CFDictionaryRef* result); -int AMDeviceTransferApplication(unsigned int fd, CFStringRef path, void* ptr, void *transfer_callback, void* ptr2); -int AMDeviceInstallApplication(unsigned int fd, CFStringRef path, CFDictionaryRef options, void *install_callback, void* ptr); -bool found_device = false, debug = false, verbose = false; +bool found_device = false, debug = false, verbose = false, unbuffered = false; char *app_path = NULL; char *device_id = NULL; char *args = NULL; int timeout = 0; CFStringRef last_path = NULL; service_conn_t gdbfd; +int child_pid = 0; Boolean path_exists(CFTypeRef path) { if (CFGetTypeID(path) == CFStringGetTypeID()) { @@ -70,44 +85,110 @@ Boolean path_exists(CFTypeRef path) { } } -CFStringRef copy_device_support_path(AMDeviceRef device) { - CFStringRef version = AMDeviceCopyValue(device, 0, CFSTR("ProductVersion")); - CFStringRef build = AMDeviceCopyValue(device, 0, CFSTR("BuildVersion")); +CFStringRef copy_long_shot_disk_image_path() { + FILE *fpipe = NULL; + char *command = "find `xcode-select --print-path` -name DeveloperDiskImage.dmg | tail -n 1"; + + if (!(fpipe = (FILE *)popen(command, "r"))) + { + perror("Error encountered while opening pipe"); + exit(EXIT_FAILURE); + } + + char buffer[256] = { '\0' }; + + fgets(buffer, sizeof(buffer), fpipe); + pclose(fpipe); + + strtok(buffer, "\n"); + return CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8); +} + +CFStringRef copy_xcode_dev_path() { + FILE *fpipe = NULL; + char *command = "xcode-select -print-path"; + + if (!(fpipe = (FILE *)popen(command, "r"))) + { + perror("Error encountered while opening pipe"); + exit(EXIT_FAILURE); + } + + char buffer[256] = { '\0' }; + + fgets(buffer, sizeof(buffer), fpipe); + pclose(fpipe); + + strtok(buffer, "\n"); + return CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8); +} + +const char *get_home() { const char* home = getenv("HOME"); + if (!home) { + struct passwd *pwd = getpwuid(getuid()); + home = pwd->pw_dir; + } + return home; +} + +CFStringRef copy_xcode_path_for(CFStringRef search) { + CFStringRef xcodeDevPath = copy_xcode_dev_path(); CFStringRef path; bool found = false; + const char* home = get_home(); - path = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s/Library/Developer/Xcode/iOS DeviceSupport/%@ (%@)"), home, version, build); - found = path_exists(path); - - if (!found) - { - path = CFStringCreateWithFormat(NULL, NULL, CFSTR("/Developer/Platforms/iPhoneOS.platform/DeviceSupport/%@ (%@)"), version, build); + + // Try using xcode-select --print-path + if (!found) { + path = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@/%@"), xcodeDevPath, search); found = path_exists(path); } - if (!found) - { - path = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s/Library/Developer/Xcode/iOS DeviceSupport/%@"), home, version); + // If not look in the default xcode location (xcode-select is sometimes wrong) + if (!found) { + path = CFStringCreateWithFormat(NULL, NULL, CFSTR("/Applications/Xcode.app/Contents/Developer/%@"), search); found = path_exists(path); } - if (!found) - { - path = CFStringCreateWithFormat(NULL, NULL, CFSTR("/Developer/Platforms/iPhoneOS.platform/DeviceSupport/%@"), version); + // If not look in the users home directory, Xcode can store device support stuff there + if (!found) { + path = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s/Library/Developer/Xcode/%@"), home, search); found = path_exists(path); } - if (!found) - { - path = CFStringCreateWithFormat(NULL, NULL, CFSTR("/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/Latest")); - found = path_exists(path); + + CFRelease(xcodeDevPath); + + if (found) { + return path; + } else { + CFRelease(path); + return NULL; } +} +CFStringRef copy_device_support_path(AMDeviceRef device) { + CFStringRef version = AMDeviceCopyValue(device, 0, CFSTR("ProductVersion")); + CFStringRef build = AMDeviceCopyValue(device, 0, CFSTR("BuildVersion")); + CFStringRef path = NULL; + + if (path == NULL) { + path = copy_xcode_path_for(CFStringCreateWithFormat(NULL, NULL, CFSTR("iOS DeviceSupport/%@ (%@)"), version, build)); + } + if (path == NULL) { + path = copy_xcode_path_for(CFStringCreateWithFormat(NULL, NULL, CFSTR("Platforms/iPhoneOS.platform/DeviceSupport/%@ (%@)"), version, build)); + } + if (path == NULL) { + path = copy_xcode_path_for(CFStringCreateWithFormat(NULL, NULL, CFSTR("Platforms/iPhoneOS.platform/DeviceSupport/%@"), version)); + } + if (path == NULL) { + path = copy_xcode_path_for(CFSTR("Platforms/iPhoneOS.platform/DeviceSupport/Latest")); + } + CFRelease(version); CFRelease(build); - if (!found) + if (path == NULL) { - CFRelease(path); - printf("[ !! ] Unable to locate DeviceSupport directory.\n"); + printf("[ !! ] Unable to locate DeviceSupport directory.\n[ !! ] This probably means you don't have Xcode installed, you will need to launch the app manually and logging output will not be shown!\n"); exit(1); } @@ -117,45 +198,32 @@ CFStringRef copy_device_support_path(AMDeviceRef device) { CFStringRef copy_developer_disk_image_path(AMDeviceRef device) { CFStringRef version = AMDeviceCopyValue(device, 0, CFSTR("ProductVersion")); CFStringRef build = AMDeviceCopyValue(device, 0, CFSTR("BuildVersion")); - const char *home = getenv("HOME"); - CFStringRef path; - bool found = false; + CFStringRef path = NULL; - path = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s/Library/Developer/Xcode/iOS DeviceSupport/%@ (%@)/DeveloperDiskImage.dmg"), home, version, build); - found = path_exists(path); - - if (!found) { - path = CFStringCreateWithFormat(NULL, NULL, CFSTR("/Developer/Platforms/iPhoneOS.platform/DeviceSupport/%@ (%@)/DeveloperDiskImage.dmg)"), version, build); - found = path_exists(path); - } - if (!found) { - path = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s/Library/Developer/Xcode/iOS DeviceSupport/%@/DeveloperDiskImage.dmg"), home, version); - found = path_exists(path); - } - if (!found) { - path = CFStringCreateWithFormat(NULL, NULL, CFSTR("/Developer/Platforms/iPhoneOS.platform/DeviceSupport/%@/DeveloperDiskImage.dmg"), version); - found = path_exists(path); - } - if (!found) { - path = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s/Library/Developer/Xcode/iOS DeviceSupport/Latest/DeveloperDiskImage.dmg"), home); - found = path_exists(path); + if (path == NULL) { + path = copy_xcode_path_for(CFStringCreateWithFormat(NULL, NULL, CFSTR("Platforms/iPhoneOS.platform/DeviceSupport/%@ (%@)/DeveloperDiskImage.dmg"), version, build)); } - if (!found) { - path = CFStringCreateWithFormat(NULL, NULL, CFSTR("/Developer/Platforms/iPhoneOS.platform/DeviceSupport/Latest/DeveloperDiskImage.dmg")); - found = path_exists(path); + if (path == NULL) { + path = copy_xcode_path_for(CFStringCreateWithFormat(NULL, NULL, CFSTR("Platforms/iPhoneOS.platform/DeviceSupport/%@/DeveloperDiskImage.dmg"), version)); } - if (!found) - { - path = CFStringCreateWithFormat(NULL, NULL, CFSTR("/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/Latest/DeveloperDiskImage.dmg")); - found = path_exists(path); + if (path == NULL) { + path = copy_xcode_path_for(CFSTR("Platforms/iPhoneOS.platform/DeviceSupport/Latest/DeveloperDiskImage.dmg")); } - + CFRelease(version); CFRelease(build); + + if (path == NULL) { + // Sometimes Latest seems to be missing in Xcode, in that case use find and hope for the best + path = copy_long_shot_disk_image_path(); + if (CFStringGetLength(path) < 5) { + path = NULL; + } + } - if (!found) { - CFRelease(path); - printf("[ !! ] Unable to locate DeviceSupport directory containing DeveloperDiskImage.dmg.\n"); + if (path == NULL) + { + printf("[ !! ] Unable to locate DeveloperDiskImage.dmg.\n[ !! ] This probably means you don't have Xcode installed, you will need to launch the app manually and logging output will not be shown!\n"); exit(1); } @@ -215,7 +283,7 @@ void mount_developer_image(AMDeviceRef device) { CFRelease(options); } -void transfer_callback(CFDictionaryRef dict, int arg) { +mach_error_t transfer_callback(CFDictionaryRef dict, int arg) { int percent; CFStringRef status = CFDictionaryGetValue(dict, CFSTR("Status")); CFNumberGetValue(CFDictionaryGetValue(dict, CFSTR("PercentComplete")), kCFNumberSInt32Type, &percent); @@ -232,49 +300,17 @@ void transfer_callback(CFDictionaryRef dict, int arg) { } last_path = CFStringCreateCopy(NULL, path); } + + return 0; } -void install_callback(CFDictionaryRef dict, int arg) { +mach_error_t install_callback(CFDictionaryRef dict, int arg) { int percent; CFStringRef status = CFDictionaryGetValue(dict, CFSTR("Status")); CFNumberGetValue(CFDictionaryGetValue(dict, CFSTR("PercentComplete")), kCFNumberSInt32Type, &percent); printf("[%3d%%] %s\n", (percent / 2) + 50, CFStringGetCStringPtr(status, kCFStringEncodingMacRoman)); -} - -void fdvendor_callback(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, const void *data, void *info) { - CFSocketNativeHandle socket = (CFSocketNativeHandle)(*((CFSocketNativeHandle *)data)); - - struct msghdr message; - struct iovec iov[1]; - struct cmsghdr *control_message = NULL; - char ctrl_buf[CMSG_SPACE(sizeof(int))]; - char dummy_data[1]; - - memset(&message, 0, sizeof(struct msghdr)); - memset(ctrl_buf, 0, CMSG_SPACE(sizeof(int))); - - dummy_data[0] = ' '; - iov[0].iov_base = dummy_data; - iov[0].iov_len = sizeof(dummy_data); - - message.msg_name = NULL; - message.msg_namelen = 0; - message.msg_iov = iov; - message.msg_iovlen = 1; - message.msg_controllen = CMSG_SPACE(sizeof(int)); - message.msg_control = ctrl_buf; - - control_message = CMSG_FIRSTHDR(&message); - control_message->cmsg_level = SOL_SOCKET; - control_message->cmsg_type = SCM_RIGHTS; - control_message->cmsg_len = CMSG_LEN(sizeof(int)); - - *((int *) CMSG_DATA(control_message)) = gdbfd; - - sendmsg(socket, &message, 0); - CFSocketInvalidate(s); - CFRelease(s); + return 0; } CFURLRef copy_device_app_url(AMDeviceRef device, CFStringRef identifier) { @@ -307,8 +343,8 @@ CFStringRef copy_disk_app_identifier(CFURLRef disk_app_url) { return bundle_identifier; } -void write_gdb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { - CFMutableStringRef cmds = CFStringCreateMutableCopy(NULL, 0, GDB_PREP_CMDS); +void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { + CFMutableStringRef cmds = CFStringCreateMutableCopy(NULL, 0, LLDB_PREP_CMDS); CFRange range = { 0, CFStringGetLength(cmds) }; CFStringRef ds_path = copy_device_support_path(device); @@ -352,6 +388,12 @@ void write_gdb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { fwrite(CFDataGetBytePtr(cmds_data), CFDataGetLength(cmds_data), 1, out); fclose(out); + CFMutableStringRef pmodule = CFStringCreateMutableCopy(NULL, 0, LLDB_FRUITSTRAP_MODULE); + CFDataRef pmodule_data = CFStringCreateExternalRepresentation(NULL, pmodule, kCFStringEncodingASCII, 0); + out = fopen(PYTHON_MODULE_PATH, "w"); + fwrite(CFDataGetBytePtr(pmodule_data), CFDataGetLength(pmodule_data), 1, out); + fclose(out); + CFRelease(cmds); if (ds_path != NULL) CFRelease(ds_path); CFRelease(bundle_identifier); @@ -366,31 +408,97 @@ void write_gdb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { CFRelease(cmds_data); } +CFSocketRef server_socket; +CFSocketRef lldb_socket; +CFWriteStreamRef serverWriteStream = NULL; +CFWriteStreamRef lldbWriteStream = NULL; + +void +server_callback (CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, const void *data, void *info) +{ + int res; + + //PRINT ("server: %s\n", CFDataGetBytePtr (data)); + + if (CFDataGetLength (data) == 0) { + // FIXME: Close the socket + //shutdown (CFSocketGetNative (lldb_socket), SHUT_RDWR); + //close (CFSocketGetNative (lldb_socket)); + return; + } + res = write (CFSocketGetNative (lldb_socket), CFDataGetBytePtr (data), CFDataGetLength (data)); +} + +void lldb_callback(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, const void *data, void *info) +{ + //PRINT ("lldb: %s\n", CFDataGetBytePtr (data)); + + if (CFDataGetLength (data) == 0) + return; + write (gdbfd, CFDataGetBytePtr (data), CFDataGetLength (data)); +} + +void fdvendor_callback(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, const void *data, void *info) { + CFSocketNativeHandle socket = (CFSocketNativeHandle)(*((CFSocketNativeHandle *)data)); + + assert (callbackType == kCFSocketAcceptCallBack); + //PRINT ("callback!\n"); + + lldb_socket = CFSocketCreateWithNative(NULL, socket, kCFSocketDataCallBack, &lldb_callback, NULL); + CFRunLoopAddSource(CFRunLoopGetMain(), CFSocketCreateRunLoopSource(NULL, lldb_socket, 0), kCFRunLoopCommonModes); +} + void start_remote_debug_server(AMDeviceRef device) { + char buf [256]; + int res, err, i; + char msg [256]; + int chsum, len; + struct stat s; + socklen_t buflen; + struct sockaddr name; + int namelen; + assert(AMDeviceStartService(device, CFSTR("com.apple.debugserver"), &gdbfd, NULL) == 0); + assert (gdbfd); + + /* + * The debugserver connection is through a fd handle, while lldb requires a host/port to connect, so create an intermediate + * socket to transfer data. + */ + server_socket = CFSocketCreateWithNative (NULL, gdbfd, kCFSocketDataCallBack, &server_callback, NULL); + CFRunLoopAddSource(CFRunLoopGetMain(), CFSocketCreateRunLoopSource(NULL, server_socket, 0), kCFRunLoopCommonModes); - CFSocketRef fdvendor = CFSocketCreate(NULL, AF_UNIX, 0, 0, kCFSocketAcceptCallBack, &fdvendor_callback, NULL); + struct sockaddr_in addr4; + memset(&addr4, 0, sizeof(addr4)); + addr4.sin_len = sizeof(addr4); + addr4.sin_family = AF_INET; + addr4.sin_port = htons(12345); + addr4.sin_addr.s_addr = htonl(INADDR_ANY); + + CFSocketRef fdvendor = CFSocketCreate(NULL, PF_INET, 0, 0, kCFSocketAcceptCallBack, &fdvendor_callback, NULL); int yes = 1; setsockopt(CFSocketGetNative(fdvendor), SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); + int flag = 1; + res = setsockopt(CFSocketGetNative(fdvendor), IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)); + assert (res == 0); - struct sockaddr_un address; - memset(&address, 0, sizeof(address)); - address.sun_family = AF_UNIX; - strcpy(address.sun_path, FDVENDOR_PATH); - address.sun_len = SUN_LEN(&address); - CFDataRef address_data = CFDataCreate(NULL, (const UInt8 *)&address, sizeof(address)); - - unlink(FDVENDOR_PATH); + CFDataRef address_data = CFDataCreate(NULL, (const UInt8 *)&addr4, sizeof(addr4)); CFSocketSetAddress(fdvendor, address_data); CFRelease(address_data); CFRunLoopAddSource(CFRunLoopGetMain(), CFSocketCreateRunLoopSource(NULL, fdvendor, 0), kCFRunLoopCommonModes); } -void gdb_ready_handler(int signum) +void killed(int signum) { + // SIGKILL needed to kill lldb, probably a better way to do this. + kill(0, SIGKILL); + _exit(0); +} + +void lldb_finished_handler(int signum) { - _exit(0); + _exit(0); } void handle_device(AMDeviceRef device) { @@ -423,7 +531,7 @@ void handle_device(AMDeviceRef device) { CFRelease(relative_url); - unsigned int afcFd; + service_conn_t afcFd; assert(AMDeviceStartService(device, CFSTR("com.apple.afc"), &afcFd, NULL) == 0); assert(AMDeviceStopSession(device) == 0); assert(AMDeviceDisconnect(device) == 0); @@ -440,7 +548,7 @@ void handle_device(AMDeviceRef device) { assert(AMDeviceValidatePairing(device) == 0); assert(AMDeviceStartSession(device) == 0); - unsigned int installFd; + service_conn_t installFd; assert(AMDeviceStartService(device, CFSTR("com.apple.mobile.installation_proxy"), &installFd, NULL) == 0); assert(AMDeviceStopSession(device) == 0); @@ -471,22 +579,27 @@ void handle_device(AMDeviceRef device) { mount_developer_image(device); // put debugserver on the device start_remote_debug_server(device); // start debugserver - write_gdb_prep_cmds(device, url); // dump the necessary gdb commands into a file + write_lldb_prep_cmds(device, url); // dump the necessary lldb commands into a file CFRelease(url); printf("[100%%] Connecting to remote debug server\n"); printf("-------------------------\n"); - signal(SIGHUP, gdb_ready_handler); + signal(SIGHUP, lldb_finished_handler); + + setpgid(getpid(), 0); pid_t parent = getpid(); int pid = fork(); if (pid == 0) { - system(GDB_SHELL); // launch gdb + system(LLDB_SHELL); // launch lldb kill(parent, SIGHUP); // "No. I am your father." _exit(0); } + + signal(SIGINT, killed); + signal(SIGTERM, killed); } void device_callback(struct am_device_notification_callback_info *info, void *arg) { @@ -506,11 +619,7 @@ void timeout_callback(CFRunLoopTimerRef timer, void *info) { } void usage(const char* app) { - printf("usage: %s [-V/--version] [-v/--verbose] [-d/--debug] [-i/--id device_id] -b/--bundle bundle.app [-a/--args arguments] [-t/--timeout timeout(seconds)]\n", app); -} - -void version() { - printf("%s\n", APP_VERSION); + printf("usage: %s [-d/--debug] [-i/--id device_id] -b/--bundle bundle.app [-a/--args arguments] [-t/--timeout timeout(seconds)] [-u/--unbuffered] [-g/--gdbargs gdbarguments]\n", app); } int main(int argc, char *argv[]) { @@ -521,12 +630,12 @@ int main(int argc, char *argv[]) { { "args", required_argument, NULL, 'a' }, { "verbose", no_argument, NULL, 'v' }, { "timeout", required_argument, NULL, 't' }, - { "version", no_argument, NULL, 'V' }, + { "unbuffered", no_argument, NULL, 'u' }, { NULL, 0, NULL, 0 }, }; char ch; - while ((ch = getopt_long(argc, argv, "Vdvi:b:a:t:", longopts, NULL)) != -1) + while ((ch = getopt_long(argc, argv, "dvi:b:a:t:u:g:", longopts, NULL)) != -1) { switch (ch) { case 'd': @@ -544,12 +653,12 @@ int main(int argc, char *argv[]) { case 'v': verbose = 1; break; - case 'V': - version(); - return 1; case 't': timeout = atoi(optarg); break; + case 'u': + unbuffered = 1; + break; default: usage(argv[0]); return 1; @@ -561,6 +670,8 @@ int main(int argc, char *argv[]) { exit(0); } + if (unbuffered) setbuf(stdout, NULL); + printf("------ Install phase ------\n"); assert(access(app_path, F_OK) == 0); @@ -580,4 +691,4 @@ int main(int argc, char *argv[]) { struct am_device_notification *notify; AMDeviceNotificationSubscribe(&device_callback, 0, 0, NULL, ¬ify); CFRunLoopRun(); -} +} \ No newline at end of file From 017b85e4e8f6b09ee442692eedfac8db4e63c31c Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 22 Oct 2013 13:54:23 -0700 Subject: [PATCH 020/219] Use lldv instead of gdb debugger from https://github.com/markusjura/fruitstrap/commit/621f67bd2d63ad355adeb104b68af58ad5a209eb --- ios-deploy.c | 447 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 300 insertions(+), 147 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index b08f351a..188e2a92 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -14,9 +15,7 @@ #include #include "MobileDevice.h" -#define FDVENDOR_PATH "/tmp/fruitstrap-remote-debugserver" -#define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds" -#define PYTHON_MODULE_PATH "/tmp/fruitstrap.py" +#define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "python -u -c \"import time; time.sleep(0.5); print 'run'; time.sleep(2000000)\" | lldb -s " PREP_CMDS_PATH /* @@ -26,16 +25,16 @@ * log enable -v -f /Users/vargaz/gdb-remote.log gdb-remote all */ #define LLDB_PREP_CMDS CFSTR("\ + platform select remote-ios --sysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/*\n\ + target create \"{disk_app}\"\n\ script fruitstrap_device_app=\"{device_app}\"\n\ script fruitstrap_connect_url=\"connect://127.0.0.1:12345\"\n\ - platform select remote-ios\n\ - target create \"{disk_app}\"\n\ - #settings set target.process.extra-startup-command \"QSetLogging:bitmask=LOG_ALL;\"\n \ - command script import \"" PYTHON_MODULE_PATH "\"\n\ + script fruitstrap_handle_command=\"command script add -s asynchronous -f {python_command}.fsrun_command run\"\n\ + command script import \"{python_file_path}\"\n\ ") /* - * Some things do not seem to work when using the normal commands like process connect/launch, so we invoke them + * Some things do not seem to work when using the normal commands like process connect/launch, so we invoke them * through the python interface. Also, Launch () doesn't seem to work when ran from init_module (), so we add * a command which can be used by the user to run it. */ @@ -46,31 +45,32 @@ def __lldb_init_module(debugger, internal_dict):\n\ # These two are passed in by the script which loads us\n\ device_app=internal_dict['fruitstrap_device_app']\n\ connect_url=internal_dict['fruitstrap_connect_url']\n\ + handle_command = internal_dict['fruitstrap_handle_command']\n\ lldb.target.modules[0].SetPlatformFileSpec(lldb.SBFileSpec(device_app))\n\ - lldb.debugger.HandleCommand (\"command script add -s asynchronous -f fruitstrap.fsrun_command run\")\n\ + lldb.debugger.HandleCommand(handle_command)\n\ error=lldb.SBError()\n\ lldb.target.ConnectRemote(lldb.target.GetDebugger().GetListener(),connect_url,None,error)\n\ \n\ def fsrun_command(debugger, command, result, internal_dict):\n\ error=lldb.SBError()\n\ - lldb.target.Launch(lldb.SBLaunchInfo(None),error)\n\ + lldb.target.Launch(lldb.SBLaunchInfo(['{args}']),error)\n\ + print str(error)\n\ ") - typedef struct am_device * AMDeviceRef; int AMDeviceSecureTransferPath(int zero, AMDeviceRef device, CFURLRef url, CFDictionaryRef options, void *callback, int cbarg); int AMDeviceSecureInstallApplication(int zero, AMDeviceRef device, CFURLRef url, CFDictionaryRef options, void *callback, int cbarg); int AMDeviceMountImage(AMDeviceRef device, CFStringRef image, CFDictionaryRef options, void *callback, int cbarg); int AMDeviceLookupApplications(AMDeviceRef device, int zero, CFDictionaryRef* result); -bool found_device = false, debug = false, verbose = false, unbuffered = false; +bool found_device = false, debug = false, verbose = false, unbuffered = false, nostart = false, detect_only = false, install = true; char *app_path = NULL; char *device_id = NULL; char *args = NULL; int timeout = 0; CFStringRef last_path = NULL; service_conn_t gdbfd; -int child_pid = 0; +pid_t parent = 0; Boolean path_exists(CFTypeRef path) { if (CFGetTypeID(path) == CFStringGetTypeID()) { @@ -85,9 +85,20 @@ Boolean path_exists(CFTypeRef path) { } } -CFStringRef copy_long_shot_disk_image_path() { +CFStringRef find_path(CFStringRef rootPath, CFStringRef namePattern, CFStringRef expression) { FILE *fpipe = NULL; - char *command = "find `xcode-select --print-path` -name DeveloperDiskImage.dmg | tail -n 1"; + CFStringRef quotedRootPath = rootPath; + if (CFStringGetCharacterAtIndex(rootPath, 0) != '`') { + quotedRootPath = CFStringCreateWithFormat(NULL, NULL, CFSTR("'%@'"), rootPath); + } + CFStringRef cf_command = CFStringCreateWithFormat(NULL, NULL, CFSTR("find %@ -name '%@' %@ 2>/dev/null | sort | tail -n 1"), quotedRootPath, namePattern, expression); + if (quotedRootPath != rootPath) { + CFRelease(quotedRootPath); + } + + char command[1024] = { '\0' }; + CFStringGetCString(cf_command, command, sizeof(command), kCFStringEncodingUTF8); + CFRelease(cf_command); if (!(fpipe = (FILE *)popen(command, "r"))) { @@ -104,23 +115,31 @@ CFStringRef copy_long_shot_disk_image_path() { return CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8); } -CFStringRef copy_xcode_dev_path() { - FILE *fpipe = NULL; - char *command = "xcode-select -print-path"; +CFStringRef copy_long_shot_disk_image_path() { + return find_path(CFSTR("`xcode-select --print-path`"), CFSTR("DeveloperDiskImage.dmg"), CFSTR("")); +} - if (!(fpipe = (FILE *)popen(command, "r"))) - { - perror("Error encountered while opening pipe"); - exit(EXIT_FAILURE); - } +CFStringRef copy_xcode_dev_path() { + static char xcode_dev_path[256] = { '\0' }; + if (strlen(xcode_dev_path) == 0) { + FILE *fpipe = NULL; + char *command = "xcode-select -print-path"; + + if (!(fpipe = (FILE *)popen(command, "r"))) + { + perror("Error encountered while opening pipe"); + exit(EXIT_FAILURE); + } - char buffer[256] = { '\0' }; + char buffer[256] = { '\0' }; - fgets(buffer, sizeof(buffer), fpipe); - pclose(fpipe); + fgets(buffer, sizeof(buffer), fpipe); + pclose(fpipe); - strtok(buffer, "\n"); - return CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8); + strtok(buffer, "\n"); + strcpy(xcode_dev_path, buffer); + } + return CFStringCreateWithCString(NULL, xcode_dev_path, kCFStringEncodingUTF8); } const char *get_home() { @@ -132,29 +151,34 @@ const char *get_home() { return home; } -CFStringRef copy_xcode_path_for(CFStringRef search) { +CFStringRef copy_xcode_path_for(CFStringRef subPath, CFStringRef search) { CFStringRef xcodeDevPath = copy_xcode_dev_path(); CFStringRef path; bool found = false; const char* home = get_home(); - + // Try using xcode-select --print-path if (!found) { - path = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@/%@"), xcodeDevPath, search); + path = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@/%@/%@"), xcodeDevPath, subPath, search); found = path_exists(path); } + // Try find `xcode-select --print-path` with search as a name pattern + if (!found) { + path = find_path(CFStringCreateWithFormat(NULL, NULL, CFSTR("%@/%@"), xcodeDevPath, subPath), search, CFSTR("-maxdepth 1")); + found = CFStringGetLength(path) > 0 && path_exists(path); + } // If not look in the default xcode location (xcode-select is sometimes wrong) if (!found) { - path = CFStringCreateWithFormat(NULL, NULL, CFSTR("/Applications/Xcode.app/Contents/Developer/%@"), search); + path = CFStringCreateWithFormat(NULL, NULL, CFSTR("/Applications/Xcode.app/Contents/Developer/%@&%@"), subPath, search); found = path_exists(path); } // If not look in the users home directory, Xcode can store device support stuff there if (!found) { - path = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s/Library/Developer/Xcode/%@"), home, search); + path = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s/Library/Developer/Xcode/%@/%@"), home, subPath, search); found = path_exists(path); } - + CFRelease(xcodeDevPath); if (found) { @@ -165,25 +189,46 @@ CFStringRef copy_xcode_path_for(CFStringRef search) { } } -CFStringRef copy_device_support_path(AMDeviceRef device) { +CFMutableArrayRef get_device_product_version_parts(AMDeviceRef device) { CFStringRef version = AMDeviceCopyValue(device, 0, CFSTR("ProductVersion")); + CFArrayRef parts = CFStringCreateArrayBySeparatingStrings(NULL, version, CFSTR(".")); + CFMutableArrayRef result = CFArrayCreateMutableCopy(NULL, CFArrayGetCount(parts), parts); + CFRelease(version); + CFRelease(parts); + return result; +} + +CFStringRef copy_device_support_path(AMDeviceRef device) { + CFStringRef version = NULL; CFStringRef build = AMDeviceCopyValue(device, 0, CFSTR("BuildVersion")); CFStringRef path = NULL; + CFMutableArrayRef version_parts = get_device_product_version_parts(device); - if (path == NULL) { - path = copy_xcode_path_for(CFStringCreateWithFormat(NULL, NULL, CFSTR("iOS DeviceSupport/%@ (%@)"), version, build)); - } - if (path == NULL) { - path = copy_xcode_path_for(CFStringCreateWithFormat(NULL, NULL, CFSTR("Platforms/iPhoneOS.platform/DeviceSupport/%@ (%@)"), version, build)); - } - if (path == NULL) { - path = copy_xcode_path_for(CFStringCreateWithFormat(NULL, NULL, CFSTR("Platforms/iPhoneOS.platform/DeviceSupport/%@"), version)); - } - if (path == NULL) { - path = copy_xcode_path_for(CFSTR("Platforms/iPhoneOS.platform/DeviceSupport/Latest")); + while (CFArrayGetCount(version_parts) > 0) { + version = CFStringCreateByCombiningStrings(NULL, version_parts, CFSTR(".")); + if (path == NULL) { + path = copy_xcode_path_for(CFSTR("iOS DeviceSupport"), CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ (%@)"), version, build)); + } + if (path == NULL) { + path = copy_xcode_path_for(CFSTR("Platforms/iPhoneOS.platform/DeviceSupport"), CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ (%@)"), version, build)); + } + if (path == NULL) { + path = copy_xcode_path_for(CFSTR("Platforms/iPhoneOS.platform/DeviceSupport"), CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ (*)"), version)); + } + if (path == NULL) { + path = copy_xcode_path_for(CFSTR("Platforms/iPhoneOS.platform/DeviceSupport"), version); + } + if (path == NULL) { + path = copy_xcode_path_for(CFSTR("Platforms/iPhoneOS.platform/DeviceSupport/Latest"), CFSTR("")); + } + CFRelease(version); + if (path != NULL) { + break; + } + CFArrayRemoveValueAtIndex(version_parts, CFArrayGetCount(version_parts) - 1); } - - CFRelease(version); + + CFRelease(version_parts); CFRelease(build); if (path == NULL) @@ -195,28 +240,18 @@ CFStringRef copy_device_support_path(AMDeviceRef device) { return path; } -CFStringRef copy_developer_disk_image_path(AMDeviceRef device) { - CFStringRef version = AMDeviceCopyValue(device, 0, CFSTR("ProductVersion")); - CFStringRef build = AMDeviceCopyValue(device, 0, CFSTR("BuildVersion")); - CFStringRef path = NULL; - - if (path == NULL) { - path = copy_xcode_path_for(CFStringCreateWithFormat(NULL, NULL, CFSTR("Platforms/iPhoneOS.platform/DeviceSupport/%@ (%@)/DeveloperDiskImage.dmg"), version, build)); - } - if (path == NULL) { - path = copy_xcode_path_for(CFStringCreateWithFormat(NULL, NULL, CFSTR("Platforms/iPhoneOS.platform/DeviceSupport/%@/DeveloperDiskImage.dmg"), version)); - } - if (path == NULL) { - path = copy_xcode_path_for(CFSTR("Platforms/iPhoneOS.platform/DeviceSupport/Latest/DeveloperDiskImage.dmg")); +CFStringRef copy_developer_disk_image_path(CFStringRef deviceSupportPath) { + CFStringRef path = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@/%@"), deviceSupportPath, CFSTR("DeveloperDiskImage.dmg")); + if (!path_exists(path)) { + CFRelease(path); + path = NULL; } - - CFRelease(version); - CFRelease(build); - + if (path == NULL) { // Sometimes Latest seems to be missing in Xcode, in that case use find and hope for the best path = copy_long_shot_disk_image_path(); if (CFStringGetLength(path) < 5) { + CFRelease(path); path = NULL; } } @@ -244,18 +279,14 @@ void mount_callback(CFDictionaryRef dict, int arg) { void mount_developer_image(AMDeviceRef device) { CFStringRef ds_path = copy_device_support_path(device); - CFStringRef image_path = copy_developer_disk_image_path(device); + CFStringRef image_path = copy_developer_disk_image_path(ds_path); CFStringRef sig_path = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@.signature"), image_path); - CFRelease(ds_path); if (verbose) { - printf("Device support path: "); - fflush(stdout); - CFShow(ds_path); - printf("Developer disk image: "); - fflush(stdout); - CFShow(image_path); + printf("Device support path: %s\n", CFStringGetCStringPtr(ds_path, CFStringGetSystemEncoding())); + printf("Developer disk image: %s\n", CFStringGetCStringPtr(image_path, CFStringGetSystemEncoding())); } + CFRelease(ds_path); FILE* sig = fopen(CFStringGetCStringPtr(sig_path, kCFStringEncodingMacRoman), "rb"); void *sig_buf = malloc(128); @@ -351,9 +382,20 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { CFStringFindAndReplace(cmds, CFSTR("{ds_path}"), ds_path, range, 0); range.length = CFStringGetLength(cmds); + CFMutableStringRef pmodule = CFStringCreateMutableCopy(NULL, 0, LLDB_FRUITSTRAP_MODULE); if (args) { CFStringRef cf_args = CFStringCreateWithCString(NULL, args, kCFStringEncodingASCII); CFStringFindAndReplace(cmds, CFSTR("{args}"), cf_args, range, 0); + + //format the arguments 'arg1 arg2 ....' to an argument list ['arg1', 'arg2', ...] + CFMutableStringRef argsListLLDB = CFStringCreateMutableCopy(NULL, 0, cf_args); + CFRange rangeLLDB = { 0, CFStringGetLength(argsListLLDB) }; + CFStringFindAndReplace(argsListLLDB, CFSTR(" "), CFSTR(" "), rangeLLDB, 0);//remove multiple spaces + rangeLLDB.length = CFStringGetLength(argsListLLDB); + CFStringFindAndReplace(argsListLLDB, CFSTR(" "), CFSTR("', '"), rangeLLDB, 0); + rangeLLDB.length = CFStringGetLength(pmodule); + CFStringFindAndReplace(pmodule, CFSTR("{args}"), argsListLLDB, rangeLLDB, 0); + CFRelease(cf_args); } else { CFStringFindAndReplace(cmds, CFSTR(" {args}"), CFSTR(""), range, 0); @@ -383,14 +425,32 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { CFStringRef disk_container_path = CFURLCopyFileSystemPath(disk_container_url, kCFURLPOSIXPathStyle); CFStringFindAndReplace(cmds, CFSTR("{disk_container}"), disk_container_path, range, 0); + char python_file_path[300] = "/tmp/fruitstrap_"; + char python_command[300] = "fruitstrap_"; + if(device_id != NULL) { + strcat(python_file_path, device_id); + strcat(python_command, device_id); + } + strcat(python_file_path, ".py"); + + CFStringRef cf_python_command = CFStringCreateWithCString(NULL, python_command, kCFStringEncodingASCII); + CFStringFindAndReplace(cmds, CFSTR("{python_command}"), cf_python_command, range, 0); + range.length = CFStringGetLength(cmds); + CFStringRef cf_python_file_path = CFStringCreateWithCString(NULL, python_file_path, kCFStringEncodingASCII); + CFStringFindAndReplace(cmds, CFSTR("{python_file_path}"), cf_python_file_path, range, 0); + range.length = CFStringGetLength(cmds); + CFDataRef cmds_data = CFStringCreateExternalRepresentation(NULL, cmds, kCFStringEncodingASCII, 0); - FILE *out = fopen(PREP_CMDS_PATH, "w"); + char prep_cmds_path[300] = PREP_CMDS_PATH; + if(device_id != NULL) + strcat(prep_cmds_path, device_id); + FILE *out = fopen(prep_cmds_path, "w"); fwrite(CFDataGetBytePtr(cmds_data), CFDataGetLength(cmds_data), 1, out); fclose(out); - CFMutableStringRef pmodule = CFStringCreateMutableCopy(NULL, 0, LLDB_FRUITSTRAP_MODULE); CFDataRef pmodule_data = CFStringCreateExternalRepresentation(NULL, pmodule, kCFStringEncodingASCII, 0); - out = fopen(PYTHON_MODULE_PATH, "w"); + + out = fopen(python_file_path, "w"); fwrite(CFDataGetBytePtr(pmodule_data), CFDataGetLength(pmodule_data), 1, out); fclose(out); @@ -406,6 +466,8 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { CFRelease(disk_container_url); CFRelease(disk_container_path); CFRelease(cmds_data); + CFRelease(cf_python_command); + CFRelease(cf_python_file_path); } CFSocketRef server_socket; @@ -426,7 +488,7 @@ server_callback (CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef add //close (CFSocketGetNative (lldb_socket)); return; } - res = write (CFSocketGetNative (lldb_socket), CFDataGetBytePtr (data), CFDataGetLength (data)); + res = write (CFSocketGetNative (lldb_socket), CFDataGetBytePtr (data), CFDataGetLength (data)); } void lldb_callback(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, const void *data, void *info) @@ -479,7 +541,7 @@ void start_remote_debug_server(AMDeviceRef device) { int yes = 1; setsockopt(CFSocketGetNative(fdvendor), SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); - int flag = 1; + int flag = 1; res = setsockopt(CFSocketGetNative(fdvendor), IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)); assert (res == 0); @@ -490,6 +552,44 @@ void start_remote_debug_server(AMDeviceRef device) { CFRunLoopAddSource(CFRunLoopGetMain(), CFSocketCreateRunLoopSource(NULL, fdvendor, 0), kCFRunLoopCommonModes); } +void kill_ptree_inner(pid_t root, int signum, struct kinfo_proc *kp, int kp_len) { + int i; + for (i = 0; i < kp_len; i++) { + if (kp[i].kp_eproc.e_ppid == root) { + kill_ptree_inner(kp[i].kp_proc.p_pid, signum, kp, kp_len); + } + } + if (root != getpid()) { + kill(root, signum); + } +} + +int kill_ptree(pid_t root, int signum) { + int mib[3]; + size_t len; + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_ALL; + if (sysctl(mib, 3, NULL, &len, NULL, 0) == -1) { + return -1; + } + + struct kinfo_proc *kp = calloc(1, len); + if (!kp) { + return -1; + } + + if (sysctl(mib, 3, kp, &len, NULL, 0) == -1) { + free(kp); + return -1; + } + + kill_ptree_inner(root, signum, kp, len / sizeof(struct kinfo_proc)); + + free(kp); + return 0; +} + void killed(int signum) { // SIGKILL needed to kill lldb, probably a better way to do this. kill(0, SIGKILL); @@ -501,9 +601,43 @@ void lldb_finished_handler(int signum) _exit(0); } +void launch_debugger(AMDeviceRef device, CFURLRef url) { + AMDeviceConnect(device); + assert(AMDeviceIsPaired(device)); + assert(AMDeviceValidatePairing(device) == 0); + assert(AMDeviceStartSession(device) == 0); + + printf("------ Debug phase ------\n"); + + mount_developer_image(device); // put debugserver on the device + start_remote_debug_server(device); // start debugserver + write_lldb_prep_cmds(device, url); // dump the necessary lldb commands into a file + + CFRelease(url); + + printf("[100%%] Connecting to remote debug server\n"); + printf("-------------------------\n"); + + signal(SIGHUP, lldb_finished_handler); + setpgid(getpid(), 0); + signal(SIGINT, killed); + signal(SIGTERM, killed); + + parent = getpid(); + int pid = fork(); + if (pid == 0) { + char lldb_shell[300] = LLDB_SHELL; + if(device_id != NULL) + strcat(lldb_shell, device_id); + system(lldb_shell); // launch lldb + kill(parent, SIGHUP); // "No. I am your father." + _exit(0); + } + +} + void handle_device(AMDeviceRef device) { if (found_device) return; // handle one device only - CFStringRef found_device_id = AMDeviceCopyDeviceIdentifier(device); if (device_id != NULL) { @@ -516,14 +650,13 @@ void handle_device(AMDeviceRef device) { found_device = true; } - CFRetain(device); // don't know if this is necessary? + if (detect_only) { + printf("[....] Found device (%s).\n", CFStringGetCStringPtr(found_device_id, CFStringGetSystemEncoding())); + exit(0); + } - printf("[ 0%%] Found device (%s), beginning install\n", CFStringGetCStringPtr(found_device_id, CFStringGetSystemEncoding())); - AMDeviceConnect(device); - assert(AMDeviceIsPaired(device)); - assert(AMDeviceValidatePairing(device) == 0); - assert(AMDeviceStartSession(device) == 0); + CFRetain(device); // don't know if this is necessary? CFStringRef path = CFStringCreateWithCString(NULL, app_path, kCFStringEncodingASCII); CFURLRef relative_url = CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, false); @@ -531,75 +664,56 @@ void handle_device(AMDeviceRef device) { CFRelease(relative_url); - service_conn_t afcFd; - assert(AMDeviceStartService(device, CFSTR("com.apple.afc"), &afcFd, NULL) == 0); - assert(AMDeviceStopSession(device) == 0); - assert(AMDeviceDisconnect(device) == 0); - assert(AMDeviceTransferApplication(afcFd, path, NULL, transfer_callback, NULL) == 0); - - close(afcFd); - - CFStringRef keys[] = { CFSTR("PackageType") }; - CFStringRef values[] = { CFSTR("Developer") }; - CFDictionaryRef options = CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&values, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - - AMDeviceConnect(device); - assert(AMDeviceIsPaired(device)); - assert(AMDeviceValidatePairing(device) == 0); - assert(AMDeviceStartSession(device) == 0); + if(install) { + printf("[ 0%%] Found device (%s), beginning install\n", CFStringGetCStringPtr(found_device_id, CFStringGetSystemEncoding())); - service_conn_t installFd; - assert(AMDeviceStartService(device, CFSTR("com.apple.mobile.installation_proxy"), &installFd, NULL) == 0); + AMDeviceConnect(device); + assert(AMDeviceIsPaired(device)); + assert(AMDeviceValidatePairing(device) == 0); + assert(AMDeviceStartSession(device) == 0); - assert(AMDeviceStopSession(device) == 0); - assert(AMDeviceDisconnect(device) == 0); - mach_error_t result = AMDeviceInstallApplication(installFd, path, options, install_callback, NULL); - if (result != 0) - { - printf("AMDeviceInstallApplication failed: %d\n", result); - exit(1); - } - - close(installFd); - CFRelease(path); - CFRelease(options); + service_conn_t afcFd; + assert(AMDeviceStartService(device, CFSTR("com.apple.afc"), &afcFd, NULL) == 0); + assert(AMDeviceStopSession(device) == 0); + assert(AMDeviceDisconnect(device) == 0); + assert(AMDeviceTransferApplication(afcFd, path, NULL, transfer_callback, NULL) == 0); - printf("[100%%] Installed package %s\n", app_path); - - if (!debug) exit(0); // no debug phase + close(afcFd); - AMDeviceConnect(device); - assert(AMDeviceIsPaired(device)); - assert(AMDeviceValidatePairing(device) == 0); - assert(AMDeviceStartSession(device) == 0); + CFStringRef keys[] = { CFSTR("PackageType") }; + CFStringRef values[] = { CFSTR("Developer") }; + CFDictionaryRef options = CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&values, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - printf("------ Debug phase ------\n"); + AMDeviceConnect(device); + assert(AMDeviceIsPaired(device)); + assert(AMDeviceValidatePairing(device) == 0); + assert(AMDeviceStartSession(device) == 0); - mount_developer_image(device); // put debugserver on the device - start_remote_debug_server(device); // start debugserver - write_lldb_prep_cmds(device, url); // dump the necessary lldb commands into a file + service_conn_t installFd; + assert(AMDeviceStartService(device, CFSTR("com.apple.mobile.installation_proxy"), &installFd, NULL) == 0); - CFRelease(url); + assert(AMDeviceStopSession(device) == 0); + assert(AMDeviceDisconnect(device) == 0); - printf("[100%%] Connecting to remote debug server\n"); - printf("-------------------------\n"); + mach_error_t result = AMDeviceInstallApplication(installFd, path, options, install_callback, NULL); + if (result != 0) + { + printf("AMDeviceInstallApplication failed: %d\n", result); + exit(1); + } - signal(SIGHUP, lldb_finished_handler); + close(installFd); - setpgid(getpid(), 0); + CFRelease(path); + CFRelease(options); - pid_t parent = getpid(); - int pid = fork(); - if (pid == 0) { - system(LLDB_SHELL); // launch lldb - kill(parent, SIGHUP); // "No. I am your father." - _exit(0); + printf("[100%%] Installed package %s\n", app_path); } - signal(SIGINT, killed); - signal(SIGTERM, killed); + if (!debug) exit(0); // no debug phase + launch_debugger(device, url); } void device_callback(struct am_device_notification_callback_info *info, void *arg) { @@ -613,13 +727,27 @@ void device_callback(struct am_device_notification_callback_info *info, void *ar void timeout_callback(CFRunLoopTimerRef timer, void *info) { if (!found_device) { - printf("Timed out waiting for device.\n"); + printf("[....] Timed out waiting for device.\n"); exit(1); } } void usage(const char* app) { - printf("usage: %s [-d/--debug] [-i/--id device_id] -b/--bundle bundle.app [-a/--args arguments] [-t/--timeout timeout(seconds)] [-u/--unbuffered] [-g/--gdbargs gdbarguments]\n", app); + printf( + "Usage: %s [OPTION]...\n" + " -d, --debug launch the app in GDB after installation\n" + " -i, --id the id of the device to connect to\n" + " -c, --detect only detect if the device is connected\n" + " -b, --bundle the path to the app bundle to be installed\n" + " -a, --args command line arguments to pass to the app when launching it\n" + " -t, --timeout number of seconds to wait for a device to be connected\n" + " -u, --unbuffered don't buffer stdout\n" + " -g, --gdbargs extra arguments to pass to GDB when starting the debugger\n" + " -x, --gdbexec GDB commands script file\n" + " -n, --nostart do not start the app when debugging\n" + " -v, --verbose enable verbose output\n" + " -m, --noinstall directly start debugging without app install (-d not required) \n", + app); } int main(int argc, char *argv[]) { @@ -630,14 +758,22 @@ int main(int argc, char *argv[]) { { "args", required_argument, NULL, 'a' }, { "verbose", no_argument, NULL, 'v' }, { "timeout", required_argument, NULL, 't' }, + { "gdbexec", no_argument, NULL, 'x' }, { "unbuffered", no_argument, NULL, 'u' }, + { "nostart", no_argument, NULL, 'n' }, + { "detect", no_argument, NULL, 'c' }, + { "noinstall", no_argument, NULL, 'm' }, { NULL, 0, NULL, 0 }, }; char ch; - while ((ch = getopt_long(argc, argv, "dvi:b:a:t:u:g:", longopts, NULL)) != -1) + while ((ch = getopt_long(argc, argv, "mcdvuni:b:a:t:g:x:", longopts, NULL)) != -1) { switch (ch) { + case 'm': + install = 0; + debug = 1; + break; case 'd': debug = 1; break; @@ -659,22 +795,39 @@ int main(int argc, char *argv[]) { case 'u': unbuffered = 1; break; + case 'n': + nostart = 1; + break; + case 'c': + detect_only = true; + break; default: usage(argv[0]); return 1; } } - if (!app_path) { + if (!app_path && !detect_only) { usage(argv[0]); exit(0); } - if (unbuffered) setbuf(stdout, NULL); + if (unbuffered) { + setbuf(stdout, NULL); + setbuf(stderr, NULL); + } + + if (detect_only && timeout == 0) { + timeout = 5; + } - printf("------ Install phase ------\n"); + if (!detect_only) { + printf("------ Install phase ------\n"); + } - assert(access(app_path, F_OK) == 0); + if (app_path) { + assert(access(app_path, F_OK) == 0); + } AMDSetLogLevel(5); // otherwise syslog gets flooded with crap if (timeout > 0) @@ -691,4 +844,4 @@ int main(int argc, char *argv[]) { struct am_device_notification *notify; AMDeviceNotificationSubscribe(&device_callback, 0, 0, NULL, ¬ify); CFRunLoopRun(); -} \ No newline at end of file +} From 1fe3ce5244203c3dff691fe7a508f1f572e1a3ea Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 22 Oct 2013 14:01:00 -0700 Subject: [PATCH 021/219] Updated README --- README.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6db3b531..892bacee 100644 --- a/README.md +++ b/README.md @@ -10,10 +10,20 @@ Install and debug iPhone apps without using Xcode. Designed to work on unjailbro ## Usage -* `ios-deploy [-d] -b [device_id]` -* Optional `-d` flag launches a remote GDB session after the app has been installed. -* `` must be an iPhone application bundle, *not* an IPA. -* Optional `device_id`; useful when you have more than one iPhone/iPad connected. +./ios-deploy [OPTION]... + -d, --debug launch the app in GDB after installation + -i, --id the id of the device to connect to + -c, --detect only detect if the device is connected + -b, --bundle the path to the app bundle to be installed + -a, --args command line arguments to pass to the app when launching it + -t, --timeout number of seconds to wait for a device to be connected + -u, --unbuffered don't buffer stdout + -g, --gdbargs extra arguments to pass to GDB when starting the debugger + -x, --gdbexec GDB commands script file + -n, --nostart do not start the app when debugging + -v, --verbose enable verbose output + -m, --noinstall directly start debugging without app install (-d not required) + -V, --version print the executable version ## Demo From 2c99d25d53a13987043a4dd48f79a1d06f89b9d9 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 22 Oct 2013 14:10:52 -0700 Subject: [PATCH 022/219] Added -V, --version option --- ios-deploy.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 188e2a92..2bf282d0 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -15,6 +15,7 @@ #include #include "MobileDevice.h" +#define APP_VERSION "1.0.2" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "python -u -c \"import time; time.sleep(0.5); print 'run'; time.sleep(2000000)\" | lldb -s " PREP_CMDS_PATH @@ -746,10 +747,15 @@ void usage(const char* app) { " -x, --gdbexec GDB commands script file\n" " -n, --nostart do not start the app when debugging\n" " -v, --verbose enable verbose output\n" - " -m, --noinstall directly start debugging without app install (-d not required) \n", + " -m, --noinstall directly start debugging without app install (-d not required) \n" + " -V, --version print the executable version \n", app); } +void show_version() { + printf("%s\n", APP_VERSION); +} + int main(int argc, char *argv[]) { static struct option longopts[] = { { "debug", no_argument, NULL, 'd' }, @@ -762,12 +768,13 @@ int main(int argc, char *argv[]) { { "unbuffered", no_argument, NULL, 'u' }, { "nostart", no_argument, NULL, 'n' }, { "detect", no_argument, NULL, 'c' }, + { "version", no_argument, NULL, 'V' }, { "noinstall", no_argument, NULL, 'm' }, { NULL, 0, NULL, 0 }, }; char ch; - while ((ch = getopt_long(argc, argv, "mcdvuni:b:a:t:g:x:", longopts, NULL)) != -1) + while ((ch = getopt_long(argc, argv, "Vmcdvuni:b:a:t:g:x:", longopts, NULL)) != -1) { switch (ch) { case 'm': @@ -801,6 +808,9 @@ int main(int argc, char *argv[]) { case 'c': detect_only = true; break; + case 'V': + show_version(); + return 1; default: usage(argv[0]); return 1; From 3854bc429a000fe44c4b8ec3f0196cf23690714f Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 22 Oct 2013 14:12:30 -0700 Subject: [PATCH 023/219] Updated version to 1.0.4 --- ios-deploy.c | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 2bf282d0..bf34a253 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -15,7 +15,7 @@ #include #include "MobileDevice.h" -#define APP_VERSION "1.0.2" +#define APP_VERSION "1.0.4" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "python -u -c \"import time; time.sleep(0.5); print 'run'; time.sleep(2000000)\" | lldb -s " PREP_CMDS_PATH diff --git a/package.json b/package.json index ba640ec2..a37ad194 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ios-deploy", - "version": "1.0.3", + "version": "1.0.4", "description": "launch iOS apps iOS devices from the command line (Xcode 4)", "main": "ios-deploy", "scripts": { From 6f78fbc5f3b08f5c19e84bb20fb0e7d1ef1bfc14 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Fri, 25 Oct 2013 15:43:59 -0700 Subject: [PATCH 024/219] Update README.md --- README.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 892bacee..7f3ab70c 100644 --- a/README.md +++ b/README.md @@ -10,20 +10,20 @@ Install and debug iPhone apps without using Xcode. Designed to work on unjailbro ## Usage -./ios-deploy [OPTION]... - -d, --debug launch the app in GDB after installation - -i, --id the id of the device to connect to - -c, --detect only detect if the device is connected - -b, --bundle the path to the app bundle to be installed - -a, --args command line arguments to pass to the app when launching it - -t, --timeout number of seconds to wait for a device to be connected - -u, --unbuffered don't buffer stdout - -g, --gdbargs extra arguments to pass to GDB when starting the debugger - -x, --gdbexec GDB commands script file - -n, --nostart do not start the app when debugging - -v, --verbose enable verbose output - -m, --noinstall directly start debugging without app install (-d not required) - -V, --version print the executable version + ./ios-deploy [OPTION]... + -d, --debug launch the app in GDB after installation + -i, --id the id of the device to connect to + -c, --detect only detect if the device is connected + -b, --bundle the path to the app bundle to be installed + -a, --args command line arguments to pass to the app when launching it + -t, --timeout number of seconds to wait for a device to be connected + -u, --unbuffered don't buffer stdout + -g, --gdbargs extra arguments to pass to GDB when starting the debugger + -x, --gdbexec GDB commands script file + -n, --nostart do not start the app when debugging + -v, --verbose enable verbose output + -m, --noinstall directly start debugging without app install (-d not required) + -V, --version print the executable version ## Demo From d7c38e9e9fd62e2179b58e578c45aed9ca0bae97 Mon Sep 17 00:00:00 2001 From: Zachary Gramana Date: Mon, 9 Dec 2013 17:59:19 -0800 Subject: [PATCH 025/219] Enabled LLDB interactive session. Perf improvement. --- Makefile | 8 ++++---- ios-deploy.c | 39 +++++++++++++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index c9d75e32..3bfddacf 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -IOS_CC = gcc +IOS_CC = gcc -ObjC IOS_SDK = $(shell xcode-select --print-path)/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk DEVICE_SUPPORT = $(shell xcode-select --print-path)/Platforms/iPhoneOS.platform/DeviceSupport @@ -11,10 +11,10 @@ demo.app: demo Info.plist codesign -f -s "iPhone Developer" --entitlements Entitlements.plist demo.app demo: demo.c - $(IOS_CC) -arch armv7 -isysroot $(IOS_SDK) -framework CoreFoundation -o demo demo.c + $(IOS_CC) -g -arch armv7 -isysroot $(IOS_SDK) -framework CoreFoundation -o demo demo.c ios-deploy: clean ios-deploy.c - $(IOS_CC) -o ios-deploy -framework CoreFoundation -framework MobileDevice -F/System/Library/PrivateFrameworks ios-deploy.c + $(IOS_CC) -g -o ios-deploy -framework Foundation -framework CoreFoundation -framework MobileDevice -F/System/Library/PrivateFrameworks ios-deploy.c symlink: cd $(DEVICE_SUPPORT); ln -sfn "`find . -type d -maxdepth 1 -exec basename {} \; | tail -1`" Latest @@ -30,4 +30,4 @@ debug: all ./ios-deploy --debug --bundle demo.app clean: - rm -rf *.app demo ios-deploy \ No newline at end of file + rm -rf *.app demo ios-deploy diff --git a/ios-deploy.c b/ios-deploy.c index bf34a253..1ff84b66 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1,6 +1,7 @@ //TODO: don't copy/mount DeveloperDiskImage.dmg if it's already done - Xcode checks this somehow #import +#import #include #include #include @@ -17,7 +18,7 @@ #define APP_VERSION "1.0.4" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" -#define LLDB_SHELL "python -u -c \"import time; time.sleep(0.5); print 'run'; time.sleep(2000000)\" | lldb -s " PREP_CMDS_PATH +#define LLDB_SHELL "python -u -c $'import time\ntime.sleep(0.5)\nwhile True: time.sleep(0.1); cmd = raw_input(); print (cmd)' | lldb -s " PREP_CMDS_PATH /* * Startup script passed to lldb. @@ -62,7 +63,7 @@ typedef struct am_device * AMDeviceRef; int AMDeviceSecureTransferPath(int zero, AMDeviceRef device, CFURLRef url, CFDictionaryRef options, void *callback, int cbarg); int AMDeviceSecureInstallApplication(int zero, AMDeviceRef device, CFURLRef url, CFDictionaryRef options, void *callback, int cbarg); int AMDeviceMountImage(AMDeviceRef device, CFStringRef image, CFDictionaryRef options, void *callback, int cbarg); -int AMDeviceLookupApplications(AMDeviceRef device, int zero, CFDictionaryRef* result); +mach_error_t AMDeviceLookupApplications(AMDeviceRef device, CFDictionaryRef options, CFDictionaryRef *result); bool found_device = false, debug = false, verbose = false, unbuffered = false, nostart = false, detect_only = false, install = true; char *app_path = NULL; @@ -346,8 +347,38 @@ mach_error_t install_callback(CFDictionaryRef dict, int arg) { } CFURLRef copy_device_app_url(AMDeviceRef device, CFStringRef identifier) { - CFDictionaryRef result; - assert(AMDeviceLookupApplications(device, 0, &result) == 0); + CFDictionaryRef result = nil; + + NSArray *a = [NSArray arrayWithObjects: + @"CFBundleIdentifier", // absolute must + @"ApplicationDSID", + @"ApplicationType", + @"CFBundleExecutable", + @"CFBundleDisplayName", + @"CFBundleIconFile", + @"CFBundleName", + @"CFBundleShortVersionString", + @"CFBundleSupportedPlatforms", + @"CFBundleURLTypes", + @"CodeInfoIdentifier", + @"Container", + @"Entitlements", + @"HasSettingsBundle", + @"IsUpgradeable", + @"MinimumOSVersion", + @"Path", + @"SignerIdentity", + @"UIDeviceFamily", + @"UIFileSharingEnabled", + @"UIStatusBarHidden", + @"UISupportedInterfaceOrientations", + nil]; + + NSDictionary *optionsDict = [NSDictionary dictionaryWithObject:a forKey:@"ReturnAttributes"]; + CFDictionaryRef options = (CFDictionaryRef)optionsDict; + + afc_error_t resultStatus = AMDeviceLookupApplications(device, options, &result); + assert(resultStatus == 0); CFDictionaryRef app_dict = CFDictionaryGetValue(result, identifier); assert(app_dict != NULL); From c97735aaee96204e3d2d806bda5bb2b3879c9894 Mon Sep 17 00:00:00 2001 From: Zachary Gramana Date: Tue, 10 Dec 2013 11:18:13 -0800 Subject: [PATCH 026/219] Added back support for -n/--nostart option. --- ios-deploy.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 1ff84b66..dbd3c479 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -18,7 +18,7 @@ #define APP_VERSION "1.0.4" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" -#define LLDB_SHELL "python -u -c $'import time\ntime.sleep(0.5)\nwhile True: time.sleep(0.1); cmd = raw_input(); print (cmd)' | lldb -s " PREP_CMDS_PATH +#define LLDB_SHELL "python -u -c $'import time\ntime.sleep(1.0)\n%swhile True: time.sleep(0.1); cmd = raw_input(); print (cmd)' | lldb -s " PREP_CMDS_PATH /* * Startup script passed to lldb. @@ -658,7 +658,10 @@ void launch_debugger(AMDeviceRef device, CFURLRef url) { parent = getpid(); int pid = fork(); if (pid == 0) { - char lldb_shell[300] = LLDB_SHELL; + char *runOption = nostart ? "" : "print \\\'run\\\'\n"; + char lldb_shell[400]; + sprintf(lldb_shell, LLDB_SHELL, runOption); + if(device_id != NULL) strcat(lldb_shell, device_id); system(lldb_shell); // launch lldb From 42f41798a6ecef4a94777d4fe77fe628d9731b15 Mon Sep 17 00:00:00 2001 From: Zachary Gramana Date: Fri, 13 Dec 2013 16:02:14 -0800 Subject: [PATCH 027/219] Fixes phonegap/ios-deploy#8. --- ios-deploy.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index dbd3c479..325782fe 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -27,7 +27,7 @@ * log enable -v -f /Users/vargaz/gdb-remote.log gdb-remote all */ #define LLDB_PREP_CMDS CFSTR("\ - platform select remote-ios --sysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/*\n\ + platform select remote-ios --sysroot {home}/Library/Developer/Xcode/iOS\\ DeviceSupport/7.0.4\\ (11B554a)/Symbols/\n\ target create \"{disk_app}\"\n\ script fruitstrap_device_app=\"{device_app}\"\n\ script fruitstrap_connect_url=\"connect://127.0.0.1:12345\"\n\ @@ -410,6 +410,10 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { CFMutableStringRef cmds = CFStringCreateMutableCopy(NULL, 0, LLDB_PREP_CMDS); CFRange range = { 0, CFStringGetLength(cmds) }; + CFStringRef user_home_path = CFStringCreateWithCString(NULL, getenv("HOME"), kCFStringEncodingASCII); + CFStringFindAndReplace(cmds, CFSTR("{home}"), user_home_path, range, 0); + range.length = CFStringGetLength(cmds); + CFStringRef ds_path = copy_device_support_path(device); CFStringFindAndReplace(cmds, CFSTR("{ds_path}"), ds_path, range, 0); range.length = CFStringGetLength(cmds); @@ -488,6 +492,7 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { CFRelease(cmds); if (ds_path != NULL) CFRelease(ds_path); + CFRelease(user_home_path); CFRelease(bundle_identifier); CFRelease(device_app_url); CFRelease(device_app_path); From fa88a73a9a788c4dd2fb4b681d5858b96f2d7200 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Thu, 20 Mar 2014 17:00:32 -0700 Subject: [PATCH 028/219] Fixes #20 - lldb startup super-slow unless ios-deploy.c is edited to match exact xcode version --- ios-deploy.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 325782fe..447a198d 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -27,7 +27,7 @@ * log enable -v -f /Users/vargaz/gdb-remote.log gdb-remote all */ #define LLDB_PREP_CMDS CFSTR("\ - platform select remote-ios --sysroot {home}/Library/Developer/Xcode/iOS\\ DeviceSupport/7.0.4\\ (11B554a)/Symbols/\n\ + platform select remote-ios --sysroot {symbols_path}\n\ target create \"{disk_app}\"\n\ script fruitstrap_device_app=\"{device_app}\"\n\ script fruitstrap_connect_url=\"connect://127.0.0.1:12345\"\n\ @@ -407,14 +407,15 @@ CFStringRef copy_disk_app_identifier(CFURLRef disk_app_url) { } void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { + CFStringRef ds_path = copy_device_support_path(device); + CFStringRef symbols_path = CFStringCreateWithFormat(NULL, NULL, CFSTR("'%@/Symbols'"), ds_path); + CFMutableStringRef cmds = CFStringCreateMutableCopy(NULL, 0, LLDB_PREP_CMDS); CFRange range = { 0, CFStringGetLength(cmds) }; - CFStringRef user_home_path = CFStringCreateWithCString(NULL, getenv("HOME"), kCFStringEncodingASCII); - CFStringFindAndReplace(cmds, CFSTR("{home}"), user_home_path, range, 0); + CFStringFindAndReplace(cmds, CFSTR("{symbols_path}"), symbols_path, range, 0); range.length = CFStringGetLength(cmds); - CFStringRef ds_path = copy_device_support_path(device); CFStringFindAndReplace(cmds, CFSTR("{ds_path}"), ds_path, range, 0); range.length = CFStringGetLength(cmds); @@ -492,7 +493,6 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { CFRelease(cmds); if (ds_path != NULL) CFRelease(ds_path); - CFRelease(user_home_path); CFRelease(bundle_identifier); CFRelease(device_app_url); CFRelease(device_app_path); From ad7c97d01f0e16468e7f0bd7b3487e3af7ed2cc7 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Thu, 20 Mar 2014 17:03:52 -0700 Subject: [PATCH 029/219] Updated version to 1.0.5 --- ios-deploy.c | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 447a198d..34da441f 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -16,7 +16,7 @@ #include #include "MobileDevice.h" -#define APP_VERSION "1.0.4" +#define APP_VERSION "1.0.5" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "python -u -c $'import time\ntime.sleep(1.0)\n%swhile True: time.sleep(0.1); cmd = raw_input(); print (cmd)' | lldb -s " PREP_CMDS_PATH diff --git a/package.json b/package.json index a37ad194..7009d28e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ios-deploy", - "version": "1.0.4", + "version": "1.0.5", "description": "launch iOS apps iOS devices from the command line (Xcode 4)", "main": "ios-deploy", "scripts": { From 7f2231bd391a0ae320ce196e8a8bcb07069b059f Mon Sep 17 00:00:00 2001 From: wjywbs Date: Fri, 20 Dec 2013 17:38:58 -0500 Subject: [PATCH 030/219] Read port number in command line to debug app in multiple devices. --- ios-deploy.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 34da441f..7604a096 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -30,7 +30,7 @@ platform select remote-ios --sysroot {symbols_path}\n\ target create \"{disk_app}\"\n\ script fruitstrap_device_app=\"{device_app}\"\n\ - script fruitstrap_connect_url=\"connect://127.0.0.1:12345\"\n\ + script fruitstrap_connect_url=\"connect://127.0.0.1:{device_port}\"\n\ script fruitstrap_handle_command=\"command script add -s asynchronous -f {python_command}.fsrun_command run\"\n\ command script import \"{python_file_path}\"\n\ ") @@ -70,6 +70,7 @@ char *app_path = NULL; char *device_id = NULL; char *args = NULL; int timeout = 0; +int port = 12345; CFStringRef last_path = NULL; service_conn_t gdbfd; pid_t parent = 0; @@ -449,6 +450,10 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { CFStringFindAndReplace(cmds, CFSTR("{disk_app}"), disk_app_path, range, 0); range.length = CFStringGetLength(cmds); + CFStringRef device_port = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), port); + CFStringFindAndReplace(cmds, CFSTR("{device_port}"), device_port, range, 0); + range.length = CFStringGetLength(cmds); + CFURLRef device_container_url = CFURLCreateCopyDeletingLastPathComponent(NULL, device_app_url); CFStringRef device_container_path = CFURLCopyFileSystemPath(device_container_url, kCFURLPOSIXPathStyle); CFMutableStringRef dcp_noprivate = CFStringCreateMutableCopy(NULL, 0, device_container_path); @@ -571,7 +576,7 @@ void start_remote_debug_server(AMDeviceRef device) { memset(&addr4, 0, sizeof(addr4)); addr4.sin_len = sizeof(addr4); addr4.sin_family = AF_INET; - addr4.sin_port = htons(12345); + addr4.sin_port = htons(port); addr4.sin_addr.s_addr = htonl(INADDR_ANY); CFSocketRef fdvendor = CFSocketCreate(NULL, PF_INET, 0, 0, kCFSocketAcceptCallBack, &fdvendor_callback, NULL); @@ -787,6 +792,7 @@ void usage(const char* app) { " -n, --nostart do not start the app when debugging\n" " -v, --verbose enable verbose output\n" " -m, --noinstall directly start debugging without app install (-d not required) \n" + " -p, --port port used for device, default: 12345 \n" " -V, --version print the executable version \n", app); } @@ -809,11 +815,12 @@ int main(int argc, char *argv[]) { { "detect", no_argument, NULL, 'c' }, { "version", no_argument, NULL, 'V' }, { "noinstall", no_argument, NULL, 'm' }, + { "port", required_argument, NULL, 'p' }, { NULL, 0, NULL, 0 }, }; char ch; - while ((ch = getopt_long(argc, argv, "Vmcdvuni:b:a:t:g:x:", longopts, NULL)) != -1) + while ((ch = getopt_long(argc, argv, "Vmcdvuni:b:a:t:g:x:p:", longopts, NULL)) != -1) { switch (ch) { case 'm': @@ -850,6 +857,9 @@ int main(int argc, char *argv[]) { case 'V': show_version(); return 1; + case 'p': + port = atoi(optarg); + break; default: usage(argv[0]); return 1; From a3a99e6553fda5608cd92cd904c073c64bce11c7 Mon Sep 17 00:00:00 2001 From: Julius Trinkunas Date: Wed, 26 Mar 2014 18:59:01 +0200 Subject: [PATCH 031/219] Remove python wrapper shell. --- ios-deploy.c | 60 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 7604a096..8341ac5a 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -18,7 +18,7 @@ #define APP_VERSION "1.0.5" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" -#define LLDB_SHELL "python -u -c $'import time\ntime.sleep(1.0)\n%swhile True: time.sleep(0.1); cmd = raw_input(); print (cmd)' | lldb -s " PREP_CMDS_PATH +#define LLDB_SHELL "lldb -s " PREP_CMDS_PATH /* * Startup script passed to lldb. @@ -31,10 +31,18 @@ target create \"{disk_app}\"\n\ script fruitstrap_device_app=\"{device_app}\"\n\ script fruitstrap_connect_url=\"connect://127.0.0.1:{device_port}\"\n\ - script fruitstrap_handle_command=\"command script add -s asynchronous -f {python_command}.fsrun_command run\"\n\ command script import \"{python_file_path}\"\n\ + command script add -f {python_command}.connect_command connect\n\ + command script add -s asynchronous -f {python_command}.run_command run\n\ + connect\n\ ") +const char* lldb_prep_no_cmds = ""; + +const char* lldb_prep_interactive_cmds = "\ + run\n\ +"; + /* * Some things do not seem to work when using the normal commands like process connect/launch, so we invoke them * through the python interface. Also, Launch () doesn't seem to work when ran from init_module (), so we add @@ -43,19 +51,35 @@ #define LLDB_FRUITSTRAP_MODULE CFSTR("\ import lldb\n\ \n\ -def __lldb_init_module(debugger, internal_dict):\n\ +def connect_command(debugger, command, result, internal_dict):\n\ # These two are passed in by the script which loads us\n\ - device_app=internal_dict['fruitstrap_device_app']\n\ - connect_url=internal_dict['fruitstrap_connect_url']\n\ - handle_command = internal_dict['fruitstrap_handle_command']\n\ - lldb.target.modules[0].SetPlatformFileSpec(lldb.SBFileSpec(device_app))\n\ - lldb.debugger.HandleCommand(handle_command)\n\ - error=lldb.SBError()\n\ - lldb.target.ConnectRemote(lldb.target.GetDebugger().GetListener(),connect_url,None,error)\n\ + connect_url = internal_dict['fruitstrap_connect_url']\n\ + error = lldb.SBError()\n\ +\n\ + process = lldb.target.ConnectRemote(lldb.target.GetDebugger().GetListener(), connect_url, None, error)\n\ \n\ -def fsrun_command(debugger, command, result, internal_dict):\n\ - error=lldb.SBError()\n\ - lldb.target.Launch(lldb.SBLaunchInfo(['{args}']),error)\n\ + # Wait for connection to succeed\n\ + listener = lldb.target.GetDebugger().GetListener()\n\ + listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged)\n\ + events = []\n\ + state = lldb.eStateInvalid\n\ + while state != lldb.eStateConnected:\n\ + event = lldb.SBEvent()\n\ + if listener.WaitForEvent(1, event):\n\ + state = process.GetStateFromEvent(event)\n\ + events.append(event)\n\ + else:\n\ + state = lldb.eStateInvalid\n\ +\n\ + # Add events back to queue, otherwise lldb freezes\n\ + for event in events:\n\ + listener.AddEvent(event)\n\ +\n\ +def run_command(debugger, command, result, internal_dict):\n\ + device_app = internal_dict['fruitstrap_device_app']\n\ + error = lldb.SBError()\n\ + lldb.target.modules[0].SetPlatformFileSpec(lldb.SBFileSpec(device_app))\n\ + lldb.target.Launch(lldb.SBLaunchInfo(['{args}']), error)\n\ print str(error)\n\ ") @@ -488,6 +512,13 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { strcat(prep_cmds_path, device_id); FILE *out = fopen(prep_cmds_path, "w"); fwrite(CFDataGetBytePtr(cmds_data), CFDataGetLength(cmds_data), 1, out); + // Write additional commands based on mode we're running in + const char* extra_cmds; + if (nostart) + extra_cmds = lldb_prep_no_cmds; + else + extra_cmds = lldb_prep_interactive_cmds; + fwrite(extra_cmds, strlen(extra_cmds), 1, out); fclose(out); CFDataRef pmodule_data = CFStringCreateExternalRepresentation(NULL, pmodule, kCFStringEncodingASCII, 0); @@ -668,9 +699,8 @@ void launch_debugger(AMDeviceRef device, CFURLRef url) { parent = getpid(); int pid = fork(); if (pid == 0) { - char *runOption = nostart ? "" : "print \\\'run\\\'\n"; char lldb_shell[400]; - sprintf(lldb_shell, LLDB_SHELL, runOption); + sprintf(lldb_shell, LLDB_SHELL); if(device_id != NULL) strcat(lldb_shell, device_id); From a4f3c2c84be6c573fb1bbbc515de53d3e9b6d5f5 Mon Sep 17 00:00:00 2001 From: Julius Trinkunas Date: Wed, 26 Mar 2014 19:13:48 +0200 Subject: [PATCH 032/219] Add non interactive mode. --- ios-deploy.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 8341ac5a..791c2f66 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -43,6 +43,13 @@ const char* lldb_prep_interactive_cmds = "\ run\n\ "; +const char* lldb_prep_noninteractive_cmds = "\ + settings set -- auto-confirm true\n\ + target stop-hook add --one-liner \"bt\"\n\ + target stop-hook add --one-liner \"quit\"\n\ + run\n\ +"; + /* * Some things do not seem to work when using the normal commands like process connect/launch, so we invoke them * through the python interface. Also, Launch () doesn't seem to work when ran from init_module (), so we add @@ -90,6 +97,7 @@ int AMDeviceMountImage(AMDeviceRef device, CFStringRef image, CFDictionaryRef op mach_error_t AMDeviceLookupApplications(AMDeviceRef device, CFDictionaryRef options, CFDictionaryRef *result); bool found_device = false, debug = false, verbose = false, unbuffered = false, nostart = false, detect_only = false, install = true; +bool interactive = true; char *app_path = NULL; char *device_id = NULL; char *args = NULL; @@ -514,7 +522,9 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { fwrite(CFDataGetBytePtr(cmds_data), CFDataGetLength(cmds_data), 1, out); // Write additional commands based on mode we're running in const char* extra_cmds; - if (nostart) + if (!interactive) + extra_cmds = lldb_prep_noninteractive_cmds; + else if (nostart) extra_cmds = lldb_prep_no_cmds; else extra_cmds = lldb_prep_interactive_cmds; @@ -820,8 +830,9 @@ void usage(const char* app) { " -g, --gdbargs extra arguments to pass to GDB when starting the debugger\n" " -x, --gdbexec GDB commands script file\n" " -n, --nostart do not start the app when debugging\n" + " -I, --noninteractive start in non interactive mode (quit when app crashes or exits)\n" " -v, --verbose enable verbose output\n" - " -m, --noinstall directly start debugging without app install (-d not required) \n" + " -m, --noinstall directly start debugging without app install (-d not required)\n" " -p, --port port used for device, default: 12345 \n" " -V, --version print the executable version \n", app); @@ -842,6 +853,7 @@ int main(int argc, char *argv[]) { { "gdbexec", no_argument, NULL, 'x' }, { "unbuffered", no_argument, NULL, 'u' }, { "nostart", no_argument, NULL, 'n' }, + { "noninteractive", no_argument, NULL, 'I' }, { "detect", no_argument, NULL, 'c' }, { "version", no_argument, NULL, 'V' }, { "noinstall", no_argument, NULL, 'm' }, @@ -850,7 +862,7 @@ int main(int argc, char *argv[]) { }; char ch; - while ((ch = getopt_long(argc, argv, "Vmcdvuni:b:a:t:g:x:p:", longopts, NULL)) != -1) + while ((ch = getopt_long(argc, argv, "VmcdvunIi:b:a:t:g:x:p:", longopts, NULL)) != -1) { switch (ch) { case 'm': @@ -881,6 +893,9 @@ int main(int argc, char *argv[]) { case 'n': nostart = 1; break; + case 'I': + interactive = false; + break; case 'c': detect_only = true; break; From 08f3b92306bdb11cc5cb104c6f9bc9885efd35c6 Mon Sep 17 00:00:00 2001 From: Julius Trinkunas Date: Thu, 27 Mar 2014 16:14:14 +0200 Subject: [PATCH 033/219] Fix hangup when launching from scripts. --- ios-deploy.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ios-deploy.c b/ios-deploy.c index 791c2f66..239c265c 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -684,6 +684,16 @@ void lldb_finished_handler(int signum) _exit(0); } +void bring_process_to_foreground() { + if (setpgid(0, 0) == -1) + perror("setpgid failed"); + + signal(SIGTTOU, SIG_IGN); + if (tcsetpgrp(STDIN_FILENO, getpid()) == -1) + perror("tcsetpgrp failed"); + signal(SIGTTOU, SIG_DFL); +} + void launch_debugger(AMDeviceRef device, CFURLRef url) { AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); @@ -709,6 +719,8 @@ void launch_debugger(AMDeviceRef device, CFURLRef url) { parent = getpid(); int pid = fork(); if (pid == 0) { + bring_process_to_foreground(); + char lldb_shell[400]; sprintf(lldb_shell, LLDB_SHELL); From f1a2c40566c8c284ddd11fa9bc64737020712f4a Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Thu, 27 Mar 2014 15:11:35 -0700 Subject: [PATCH 034/219] Increment version to 1.0.6 --- ios-deploy.c | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 239c265c..c9ede030 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -16,7 +16,7 @@ #include #include "MobileDevice.h" -#define APP_VERSION "1.0.5" +#define APP_VERSION "1.0.6" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH diff --git a/package.json b/package.json index 7009d28e..9e5cf9af 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ios-deploy", - "version": "1.0.5", + "version": "1.0.6", "description": "launch iOS apps iOS devices from the command line (Xcode 4)", "main": "ios-deploy", "scripts": { From f54f67c41834e888f26b501c3ace6218de466a55 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Thu, 27 Mar 2014 15:32:19 -0700 Subject: [PATCH 035/219] Added the two new flags from 1.0.6 to the README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 7f3ab70c..ba9a4f26 100644 --- a/README.md +++ b/README.md @@ -21,8 +21,10 @@ Install and debug iPhone apps without using Xcode. Designed to work on unjailbro -g, --gdbargs extra arguments to pass to GDB when starting the debugger -x, --gdbexec GDB commands script file -n, --nostart do not start the app when debugging + -I, --noninteractive start in non interactive mode (quit when app crashes or exits) -v, --verbose enable verbose output -m, --noinstall directly start debugging without app install (-d not required) + -p, --port port used for device, default: 12345 -V, --version print the executable version ## Demo From 79c4cc5c6a838fa53f09579894b33df21b2db954 Mon Sep 17 00:00:00 2001 From: Julius Trinkunas Date: Tue, 1 Apr 2014 15:37:49 +0300 Subject: [PATCH 036/219] Fix exiting and propagate app exit code in non interactive mode. --- ios-deploy.c | 105 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 83 insertions(+), 22 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index c9ede030..53bae3a4 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -34,6 +34,7 @@ command script import \"{python_file_path}\"\n\ command script add -f {python_command}.connect_command connect\n\ command script add -s asynchronous -f {python_command}.run_command run\n\ + command script add -s asynchronous -f {python_command}.autoexit_command autoexit\n\ connect\n\ ") @@ -44,10 +45,8 @@ const char* lldb_prep_interactive_cmds = "\ "; const char* lldb_prep_noninteractive_cmds = "\ - settings set -- auto-confirm true\n\ - target stop-hook add --one-liner \"bt\"\n\ - target stop-hook add --one-liner \"quit\"\n\ run\n\ + autoexit\n\ "; /* @@ -57,6 +56,7 @@ const char* lldb_prep_noninteractive_cmds = "\ */ #define LLDB_FRUITSTRAP_MODULE CFSTR("\ import lldb\n\ +import sys\n\ \n\ def connect_command(debugger, command, result, internal_dict):\n\ # These two are passed in by the script which loads us\n\ @@ -88,6 +88,35 @@ def run_command(debugger, command, result, internal_dict):\n\ lldb.target.modules[0].SetPlatformFileSpec(lldb.SBFileSpec(device_app))\n\ lldb.target.Launch(lldb.SBLaunchInfo(['{args}']), error)\n\ print str(error)\n\ +\n\ +def autoexit_command(debugger, command, result, internal_dict):\n\ + process = lldb.target.process\n\ + listener = debugger.GetListener()\n\ + listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR)\n\ + event = lldb.SBEvent()\n\ + while True:\n\ + if listener.WaitForEvent(1, event):\n\ + state = process.GetStateFromEvent(event)\n\ + else:\n\ + state = lldb.eStateInvalid\n\ +\n\ + stdout = process.GetSTDOUT(1024)\n\ + while stdout:\n\ + sys.stdout.write(stdout)\n\ + stdout = process.GetSTDOUT(1024)\n\ +\n\ + stderr = process.GetSTDERR(1024)\n\ + while stderr:\n\ + sys.stdout.write(stderr)\n\ + stderr = process.GetSTDERR(1024)\n\ +\n\ + if lldb.SBProcess.EventIsProcessEvent(event):\n\ + if state == lldb.eStateExited:\n\ + sys.exit(process.GetExitStatus())\n\ + if state == lldb.eStateStopped:\n\ + debugger.HandleCommand('frame select')\n\ + debugger.HandleCommand('bt')\n\ + sys.exit({exitcode_app_crash})\n\ ") typedef struct am_device * AMDeviceRef; @@ -106,6 +135,15 @@ int port = 12345; CFStringRef last_path = NULL; service_conn_t gdbfd; pid_t parent = 0; +// PID of child process running lldb +pid_t child = 0; +// Signal sent from child to parent process when LLDB finishes. +const int SIGLLDB = SIGUSR1; + +// Error codes we report on different failures, so scripts can distinguish between user app exit +// codes and our exit codes. For non app errors we use codes in reserved 128-255 range. +const int exitcode_error = 253; +const int exitcode_app_crash = 254; Boolean path_exists(CFTypeRef path) { if (CFGetTypeID(path) == CFStringGetTypeID()) { @@ -138,7 +176,7 @@ CFStringRef find_path(CFStringRef rootPath, CFStringRef namePattern, CFStringRef if (!(fpipe = (FILE *)popen(command, "r"))) { perror("Error encountered while opening pipe"); - exit(EXIT_FAILURE); + exit(exitcode_error); } char buffer[256] = { '\0' }; @@ -163,7 +201,7 @@ CFStringRef copy_xcode_dev_path() { if (!(fpipe = (FILE *)popen(command, "r"))) { perror("Error encountered while opening pipe"); - exit(EXIT_FAILURE); + exit(exitcode_error); } char buffer[256] = { '\0' }; @@ -269,7 +307,7 @@ CFStringRef copy_device_support_path(AMDeviceRef device) { if (path == NULL) { printf("[ !! ] Unable to locate DeviceSupport directory.\n[ !! ] This probably means you don't have Xcode installed, you will need to launch the app manually and logging output will not be shown!\n"); - exit(1); + exit(exitcode_error); } return path; @@ -294,7 +332,7 @@ CFStringRef copy_developer_disk_image_path(CFStringRef deviceSupportPath) { if (path == NULL) { printf("[ !! ] Unable to locate DeveloperDiskImage.dmg.\n[ !! ] This probably means you don't have Xcode installed, you will need to launch the app manually and logging output will not be shown!\n"); - exit(1); + exit(exitcode_error); } return path; @@ -342,7 +380,7 @@ void mount_developer_image(AMDeviceRef device) { printf("[ 95%%] Developer disk image already mounted\n"); } else { printf("[ !! ] Unable to mount developer disk image. (%x)\n", result); - exit(1); + exit(exitcode_error); } CFRelease(image_path); @@ -453,13 +491,19 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { range.length = CFStringGetLength(cmds); CFMutableStringRef pmodule = CFStringCreateMutableCopy(NULL, 0, LLDB_FRUITSTRAP_MODULE); + + CFRange rangeLLDB = { 0, CFStringGetLength(pmodule) }; + CFStringRef exitcode_app_crash_str = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), exitcode_app_crash); + CFStringFindAndReplace(pmodule, CFSTR("{exitcode_app_crash}"), exitcode_app_crash_str, rangeLLDB, 0); + rangeLLDB.length = CFStringGetLength(pmodule); + if (args) { CFStringRef cf_args = CFStringCreateWithCString(NULL, args, kCFStringEncodingASCII); CFStringFindAndReplace(cmds, CFSTR("{args}"), cf_args, range, 0); //format the arguments 'arg1 arg2 ....' to an argument list ['arg1', 'arg2', ...] CFMutableStringRef argsListLLDB = CFStringCreateMutableCopy(NULL, 0, cf_args); - CFRange rangeLLDB = { 0, CFStringGetLength(argsListLLDB) }; + rangeLLDB.length = CFStringGetLength(argsListLLDB); CFStringFindAndReplace(argsListLLDB, CFSTR(" "), CFSTR(" "), rangeLLDB, 0);//remove multiple spaces rangeLLDB.length = CFStringGetLength(argsListLLDB); CFStringFindAndReplace(argsListLLDB, CFSTR(" "), CFSTR("', '"), rangeLLDB, 0); @@ -681,7 +725,10 @@ void killed(int signum) { void lldb_finished_handler(int signum) { - _exit(0); + int status = 0; + if (waitpid(child, &status, 0) == -1) + perror("waitpid failed"); + _exit(WEXITSTATUS(status)); } void bring_process_to_foreground() { @@ -711,26 +758,40 @@ void launch_debugger(AMDeviceRef device, CFURLRef url) { printf("[100%%] Connecting to remote debug server\n"); printf("-------------------------\n"); - signal(SIGHUP, lldb_finished_handler); setpgid(getpid(), 0); + signal(SIGHUP, killed); signal(SIGINT, killed); signal(SIGTERM, killed); + // Need this before fork to avoid race conditions. For child process we remove this right after fork. + signal(SIGLLDB, lldb_finished_handler); parent = getpid(); int pid = fork(); if (pid == 0) { + signal(SIGHUP, SIG_DFL); + signal(SIGLLDB, SIG_DFL); + child = getpid(); bring_process_to_foreground(); char lldb_shell[400]; sprintf(lldb_shell, LLDB_SHELL); - if(device_id != NULL) strcat(lldb_shell, device_id); - system(lldb_shell); // launch lldb - kill(parent, SIGHUP); // "No. I am your father." - _exit(0); - } + int status = system(lldb_shell); // launch lldb + if (status == -1) + perror("failed launching lldb"); + + // Notify parent we're exiting + kill(parent, SIGLLDB); + // Pass lldb exit code + _exit(WEXITSTATUS(status)); + } else if (pid > 0) { + child = pid; + } else { + perror("fork failed"); + exit(exitcode_error); + } } void handle_device(AMDeviceRef device) { @@ -797,8 +858,8 @@ void handle_device(AMDeviceRef device) { mach_error_t result = AMDeviceInstallApplication(installFd, path, options, install_callback, NULL); if (result != 0) { - printf("AMDeviceInstallApplication failed: %d\n", result); - exit(1); + printf("AMDeviceInstallApplication failed: %d\n", result); + exit(exitcode_error); } close(installFd); @@ -825,7 +886,7 @@ void device_callback(struct am_device_notification_callback_info *info, void *ar void timeout_callback(CFRunLoopTimerRef timer, void *info) { if (!found_device) { printf("[....] Timed out waiting for device.\n"); - exit(1); + exit(exitcode_error); } } @@ -913,19 +974,19 @@ int main(int argc, char *argv[]) { break; case 'V': show_version(); - return 1; + return exitcode_error; case 'p': port = atoi(optarg); break; default: usage(argv[0]); - return 1; + return exitcode_error; } } if (!app_path && !detect_only) { usage(argv[0]); - exit(0); + exit(exitcode_error); } if (unbuffered) { From 8fc098a877677aced14056a75ab874d2a48dc460 Mon Sep 17 00:00:00 2001 From: Jose Pereira Date: Thu, 3 Apr 2014 11:42:57 -0700 Subject: [PATCH 037/219] Added version to Info.plist file, fixes -402653028 error --- Info.plist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Info.plist b/Info.plist index 13168c43..c2ade143 100644 --- a/Info.plist +++ b/Info.plist @@ -10,6 +10,8 @@ CFBundleExecutable demo + CFBundleVersion + 1.0 CFBundleIdentifier demo CFBundleResourceSpecification From f0d5d58a8b3fc5f6f7705579dea64af14813c00b Mon Sep 17 00:00:00 2001 From: Jose Pereira Date: Thu, 3 Apr 2014 11:45:57 -0700 Subject: [PATCH 038/219] Separated sdk version from full path, easier to set after updates --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3bfddacf..bef1d321 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,8 @@ +IOS_SDK_VERSION = 7.1 + IOS_CC = gcc -ObjC -IOS_SDK = $(shell xcode-select --print-path)/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk DEVICE_SUPPORT = $(shell xcode-select --print-path)/Platforms/iPhoneOS.platform/DeviceSupport +IOS_SDK = $(shell xcode-select --print-path)/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS$(IOS_SDK_VERSION).sdk all: clean ios-deploy From 0a9418a5645bda44fe09d62c906449fe6bbfc350 Mon Sep 17 00:00:00 2001 From: Julius Trinkunas Date: Mon, 28 Apr 2014 18:31:59 +0300 Subject: [PATCH 039/219] Add friendly message for code-signing check fails. --- ios-deploy.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index 53bae3a4..20ef95a0 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -858,7 +858,10 @@ void handle_device(AMDeviceRef device) { mach_error_t result = AMDeviceInstallApplication(installFd, path, options, install_callback, NULL); if (result != 0) { - printf("AMDeviceInstallApplication failed: %d\n", result); + char* error = "Unknown error."; + if (result == 0xe8008015) + error = "Your application failed code-signing checks. Check your certificates, provisioning profiles, and bundle ids."; + printf("AMDeviceInstallApplication failed: 0x%X: %s\n", result, error); exit(exitcode_error); } From 3ee1bca51353cf21aaf940ad3582a6cc2363d484 Mon Sep 17 00:00:00 2001 From: Julius Trinkunas Date: Tue, 29 Apr 2014 14:24:53 +0300 Subject: [PATCH 040/219] Stop lldb's "^D" and "quit" spam in a non terminal environment. --- ios-deploy.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index 20ef95a0..cadaaed1 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -741,6 +741,13 @@ void bring_process_to_foreground() { signal(SIGTTOU, SIG_DFL); } +void setup_dummy_pipe_on_stdin(int pfd[2]) { + if (pipe(pfd) == -1) + perror("pipe failed"); + if (dup2(pfd[0], STDIN_FILENO) == -1) + perror("dup2 failed"); +} + void launch_debugger(AMDeviceRef device, CFURLRef url) { AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); @@ -771,7 +778,17 @@ void launch_debugger(AMDeviceRef device, CFURLRef url) { signal(SIGHUP, SIG_DFL); signal(SIGLLDB, SIG_DFL); child = getpid(); - bring_process_to_foreground(); + + int pfd[2] = {-1, -1}; + if (isatty(STDIN_FILENO)) + // If we are running on a terminal, then we need to bring process to foreground for input + // to work correctly on lldb's end. + bring_process_to_foreground(); + else + // If lldb is running in a non terminal environment, then it freaks out spamming "^D" and + // "quit". It seems this is caused by read() on stdin returning EOF in lldb. To hack around + // this we setup a dummy pipe on stdin, so read() would block expecting "user's" input. + setup_dummy_pipe_on_stdin(pfd); char lldb_shell[400]; sprintf(lldb_shell, LLDB_SHELL); @@ -782,6 +799,8 @@ void launch_debugger(AMDeviceRef device, CFURLRef url) { if (status == -1) perror("failed launching lldb"); + close(pfd[0]); + close(pfd[1]); // Notify parent we're exiting kill(parent, SIGLLDB); // Pass lldb exit code From 9e52fd16d7a409a5edd0d24c588c2ac2f26e295d Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Thu, 1 May 2014 23:11:25 -0700 Subject: [PATCH 041/219] Added CONTRIBUTING file --- CONTRIBUTING.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..2b87cddc --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,31 @@ +## Contributing to ios-deploy + +Github url: + + https://github.com/phonegap/ios-deploy + +Git clone url: + + https://github.com/phonegap/ios-deploy.git + +## Filing an issue + +Please run the commands below in your Terminal.app and include it in the issue: + +``` +1. sw_vers -productVersion +2. ios-deploy -V +3. xcodebuild -version +4. xcode-select --print-path +5. gcc --version +6. lldb --version + +``` +Also include **command line arguments** you used for ios-deploy. + + +## Sending a Pull Request + +Please **create a topic branch** for your issue before submitting your pull request. You will be asked to re-submit if your pull request contains unrelated commits. + +Please elaborate regarding the problem the pull request is supposed to solve, and perhaps also link to any relevant issues the pull request is trying to fix. \ No newline at end of file From cfb086ee44642a361993a0025157f7f2f3a2e1f8 Mon Sep 17 00:00:00 2001 From: wjywbs Date: Fri, 27 Dec 2013 11:59:39 -0500 Subject: [PATCH 042/219] Add uninstall feature. --- MobileDevice.h | 2 ++ ios-deploy.c | 71 +++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 67 insertions(+), 6 deletions(-) diff --git a/MobileDevice.h b/MobileDevice.h index 837cfd4d..e078a44c 100644 --- a/MobileDevice.h +++ b/MobileDevice.h @@ -453,6 +453,8 @@ typedef int (*am_device_install_application_callback)(CFDictionaryRef, int); mach_error_t AMDeviceInstallApplication(service_conn_t socket, CFStringRef path, CFDictionaryRef options, am_device_install_application_callback callback, void *user); mach_error_t AMDeviceTransferApplication(service_conn_t socket, CFStringRef path, CFDictionaryRef options, am_device_install_application_callback callbackj, void *user); +int AMDeviceSecureUninstallApplication(int unknown0, struct am_device *device, CFStringRef bundle_id, int unknown1, void *callback, int callback_arg); + /* ---------------------------------------------------------------------------- * Semi-private routines * ------------------------------------------------------------------------- */ diff --git a/ios-deploy.c b/ios-deploy.c index cadaaed1..ebf80fc1 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -125,7 +125,7 @@ int AMDeviceSecureInstallApplication(int zero, AMDeviceRef device, CFURLRef url, int AMDeviceMountImage(AMDeviceRef device, CFStringRef image, CFDictionaryRef options, void *callback, int cbarg); mach_error_t AMDeviceLookupApplications(AMDeviceRef device, CFDictionaryRef options, CFDictionaryRef *result); -bool found_device = false, debug = false, verbose = false, unbuffered = false, nostart = false, detect_only = false, install = true; +bool found_device = false, debug = false, verbose = false, unbuffered = false, nostart = false, detect_only = false, install = true, uninstall = false; bool interactive = true; char *app_path = NULL; char *device_id = NULL; @@ -813,6 +813,42 @@ void launch_debugger(AMDeviceRef device, CFURLRef url) { } } +CFStringRef get_bundle_id(CFURLRef app_url) +{ + if (app_url == NULL) + return NULL; + + CFURLRef url = CFURLCreateCopyAppendingPathComponent(NULL, app_url, CFSTR("Info.plist"), false); + + if (url == NULL) + return NULL; + + CFReadStreamRef stream = CFReadStreamCreateWithFile(NULL, url); + CFRelease(url); + + if (stream == NULL) + return NULL; + + CFPropertyListRef plist = NULL; + if (CFReadStreamOpen(stream) == TRUE) { + plist = CFPropertyListCreateWithStream(NULL, stream, 0, + kCFPropertyListImmutable, NULL, NULL); + } + CFReadStreamClose(stream); + CFRelease(stream); + + if (plist == NULL) + return NULL; + + const void *value = CFDictionaryGetValue(plist, CFSTR("CFBundleIdentifier")); + CFStringRef bundle_id = NULL; + if (value != NULL) + bundle_id = CFRetain(value); + + CFRelease(plist); + return bundle_id; +} + void handle_device(AMDeviceRef device) { if (found_device) return; // handle one device only CFStringRef found_device_id = AMDeviceCopyDeviceIdentifier(device); @@ -841,7 +877,29 @@ void handle_device(AMDeviceRef device) { CFRelease(relative_url); + if (uninstall) { + printf("------ Uninstall phase ------\n"); + + CFStringRef bundle_id = get_bundle_id(url); + if (bundle_id == NULL) { + printf("Error: Unable to get bundle id from package %s\n Uninstall failed\n", app_path); + } else { + AMDeviceConnect(device); + assert(AMDeviceIsPaired(device)); + assert(AMDeviceValidatePairing(device) == 0); + assert(AMDeviceStartSession(device) == 0); + + assert(AMDeviceSecureUninstallApplication(0, device, bundle_id, 0, NULL, 0) == 0); + + assert(AMDeviceStopSession(device) == 0); + assert(AMDeviceDisconnect(device) == 0); + + printf("[ OK ] Uninstalled package with bundle id %s\n", CFStringGetCStringPtr(bundle_id, CFStringGetSystemEncoding())); + } + } + if(install) { + printf("------ Install phase ------\n"); printf("[ 0%%] Found device (%s), beginning install\n", CFStringGetCStringPtr(found_device_id, CFStringGetSystemEncoding())); AMDeviceConnect(device); @@ -929,6 +987,7 @@ void usage(const char* app) { " -v, --verbose enable verbose output\n" " -m, --noinstall directly start debugging without app install (-d not required)\n" " -p, --port port used for device, default: 12345 \n" + " -r, --uninstall uninstall the app before install (do not use with -m; app cache and data are cleared) \n" " -V, --version print the executable version \n", app); } @@ -953,11 +1012,12 @@ int main(int argc, char *argv[]) { { "version", no_argument, NULL, 'V' }, { "noinstall", no_argument, NULL, 'm' }, { "port", required_argument, NULL, 'p' }, + { "uninstall", no_argument, NULL, 'r' }, { NULL, 0, NULL, 0 }, }; char ch; - while ((ch = getopt_long(argc, argv, "VmcdvunIi:b:a:t:g:x:p:", longopts, NULL)) != -1) + while ((ch = getopt_long(argc, argv, "VmcdvunrIi:b:a:t:g:x:p:", longopts, NULL)) != -1) { switch (ch) { case 'm': @@ -1000,6 +1060,9 @@ int main(int argc, char *argv[]) { case 'p': port = atoi(optarg); break; + case 'r': + uninstall = 1; + break; default: usage(argv[0]); return exitcode_error; @@ -1020,10 +1083,6 @@ int main(int argc, char *argv[]) { timeout = 5; } - if (!detect_only) { - printf("------ Install phase ------\n"); - } - if (app_path) { assert(access(app_path, F_OK) == 0); } From 4f9afb74996cbcf4dbcab5bb2bfc72eb8cc6a768 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Fri, 9 May 2014 16:53:22 -0700 Subject: [PATCH 043/219] Update version to 1.0.7 --- ios-deploy.c | 2 +- package.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index ebf80fc1..ca4d3582 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -16,7 +16,7 @@ #include #include "MobileDevice.h" -#define APP_VERSION "1.0.6" +#define APP_VERSION "1.0.7" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH diff --git a/package.json b/package.json index 9e5cf9af..87fc2acd 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "ios-deploy", - "version": "1.0.6", - "description": "launch iOS apps iOS devices from the command line (Xcode 4)", + "version": "1.0.7", + "description": "launch iOS apps iOS devices from the command line (Xcode 5)", "main": "ios-deploy", "scripts": { "preinstall": "make ios-deploy" From 42a7dbcc1fc217f2452668ca2cf9b0664c79c346 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Fri, 9 May 2014 16:57:46 -0700 Subject: [PATCH 044/219] Updated README for --uninstall option. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ba9a4f26..10a82971 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ Install and debug iPhone apps without using Xcode. Designed to work on unjailbro -v, --verbose enable verbose output -m, --noinstall directly start debugging without app install (-d not required) -p, --port port used for device, default: 12345 + -r, --uninstall uninstall the app before install (do not use with -m; app cache and data are cleared) -V, --version print the executable version ## Demo From 443abe4d38aea9c0fc074a42940629d2a2a66c66 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 12 May 2014 18:05:45 -0700 Subject: [PATCH 045/219] Updated version to 1.0.8 --- ios-deploy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index ca4d3582..c2f74935 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -16,7 +16,7 @@ #include #include "MobileDevice.h" -#define APP_VERSION "1.0.7" +#define APP_VERSION "1.0.8" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH From 6fc2ee5e3876a71c501ae0d56c8f526bc39f8723 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 12 May 2014 18:09:05 -0700 Subject: [PATCH 046/219] Updated npm version to 1.0.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 87fc2acd..56ccbefc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ios-deploy", - "version": "1.0.7", + "version": "1.0.8", "description": "launch iOS apps iOS devices from the command line (Xcode 5)", "main": "ios-deploy", "scripts": { From c5d206b72c61261709ed648ba0197b71f2fd4dd4 Mon Sep 17 00:00:00 2001 From: Dmitriy Shesterkin Date: Fri, 27 Jun 2014 14:53:57 -0300 Subject: [PATCH 047/219] Added an ability to pass arguments with space character to the application by using the command "--args": ./ios-deploy ... --args "\"TEST_FILTER=some text here\" arg2 arg3" --- ios-deploy.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index c2f74935..8729c697 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -57,6 +57,7 @@ const char* lldb_prep_noninteractive_cmds = "\ #define LLDB_FRUITSTRAP_MODULE CFSTR("\ import lldb\n\ import sys\n\ +import shlex\n\ \n\ def connect_command(debugger, command, result, internal_dict):\n\ # These two are passed in by the script which loads us\n\ @@ -86,7 +87,7 @@ def run_command(debugger, command, result, internal_dict):\n\ device_app = internal_dict['fruitstrap_device_app']\n\ error = lldb.SBError()\n\ lldb.target.modules[0].SetPlatformFileSpec(lldb.SBFileSpec(device_app))\n\ - lldb.target.Launch(lldb.SBLaunchInfo(['{args}']), error)\n\ + lldb.target.Launch(lldb.SBLaunchInfo(shlex.split('{args}')), error)\n\ print str(error)\n\ \n\ def autoexit_command(debugger, command, result, internal_dict):\n\ @@ -500,15 +501,8 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { if (args) { CFStringRef cf_args = CFStringCreateWithCString(NULL, args, kCFStringEncodingASCII); CFStringFindAndReplace(cmds, CFSTR("{args}"), cf_args, range, 0); - - //format the arguments 'arg1 arg2 ....' to an argument list ['arg1', 'arg2', ...] - CFMutableStringRef argsListLLDB = CFStringCreateMutableCopy(NULL, 0, cf_args); - rangeLLDB.length = CFStringGetLength(argsListLLDB); - CFStringFindAndReplace(argsListLLDB, CFSTR(" "), CFSTR(" "), rangeLLDB, 0);//remove multiple spaces - rangeLLDB.length = CFStringGetLength(argsListLLDB); - CFStringFindAndReplace(argsListLLDB, CFSTR(" "), CFSTR("', '"), rangeLLDB, 0); rangeLLDB.length = CFStringGetLength(pmodule); - CFStringFindAndReplace(pmodule, CFSTR("{args}"), argsListLLDB, rangeLLDB, 0); + CFStringFindAndReplace(pmodule, CFSTR("{args}"), cf_args, rangeLLDB, 0); CFRelease(cf_args); } else { From e466aeac66b46a5b9185054a3a2b97c7f8a4765a Mon Sep 17 00:00:00 2001 From: Neo Alienson Date: Wed, 25 Jun 2014 17:33:54 +0800 Subject: [PATCH 048/219] Implements #42 - Merge file listing feature from phildrip/fruitstrap. Signed-off-by: Shazron Abdullah --- .gitignore | 5 +- README.md | 1 + ios-deploy.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 226 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 0d45b1d7..d3423eed 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ demo demo.app ios-deploy - -/.DS_Store \ No newline at end of file +ios-deploy.dSYM +/.DS_Store +*~ diff --git a/README.md b/README.md index 10a82971..3716a1fb 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ Install and debug iPhone apps without using Xcode. Designed to work on unjailbro -m, --noinstall directly start debugging without app install (-d not required) -p, --port port used for device, default: 12345 -r, --uninstall uninstall the app before install (do not use with -m; app cache and data are cleared) + -l, --list list files -V, --version print the executable version ## Demo diff --git a/ios-deploy.c b/ios-deploy.c index 8729c697..fc338cf8 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -127,6 +127,11 @@ int AMDeviceMountImage(AMDeviceRef device, CFStringRef image, CFDictionaryRef op mach_error_t AMDeviceLookupApplications(AMDeviceRef device, CFDictionaryRef options, CFDictionaryRef *result); bool found_device = false, debug = false, verbose = false, unbuffered = false, nostart = false, detect_only = false, install = true, uninstall = false; +bool command_only = false; +char *command = NULL; +char *target_filename = NULL; +char *upload_pathname = NULL; +char *bundle_id = NULL; bool interactive = true; char *app_path = NULL; char *device_id = NULL; @@ -794,7 +799,7 @@ void launch_debugger(AMDeviceRef device, CFURLRef url) { perror("failed launching lldb"); close(pfd[0]); - close(pfd[1]); + close(pfd[1]); // Notify parent we're exiting kill(parent, SIGLLDB); // Pass lldb exit code @@ -843,6 +848,187 @@ CFStringRef get_bundle_id(CFURLRef app_url) return bundle_id; } +void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir) +{ + char *dir_ent; + + afc_connection afc_conn; + if (!afc_conn_p) { + afc_conn_p = &afc_conn; + AFCConnectionOpen(afcFd, 0, &afc_conn_p); + } + + printf("%s\n", dir); + + afc_dictionary afc_dict; + afc_dictionary* afc_dict_p = &afc_dict; + AFCFileInfoOpen(afc_conn_p, dir, &afc_dict_p); + + afc_directory afc_dir; + afc_directory* afc_dir_p = &afc_dir; + afc_error_t err = AFCDirectoryOpen(afc_conn_p, dir, &afc_dir_p); + + if (err != 0) + { + // Couldn't open dir - was probably a file + return; + } + + while(true) { + err = AFCDirectoryRead(afc_conn_p, afc_dir_p, &dir_ent); + + if (!dir_ent) + break; + + if (strcmp(dir_ent, ".") == 0 || strcmp(dir_ent, "..") == 0) + continue; + + char* dir_joined = malloc(strlen(dir) + strlen(dir_ent) + 2); + strcpy(dir_joined, dir); + if (dir_joined[strlen(dir)-1] != '/') + strcat(dir_joined, "/"); + strcat(dir_joined, dir_ent); + read_dir(afcFd, afc_conn_p, dir_joined); + free(dir_joined); + } + + AFCDirectoryClose(afc_conn_p, afc_dir_p); +} + + +// Used to send files to app-specific sandbox (Documents dir) +service_conn_t start_house_arrest_service(AMDeviceRef device) { + AMDeviceConnect(device); + assert(AMDeviceIsPaired(device)); + assert(AMDeviceValidatePairing(device) == 0); + assert(AMDeviceStartSession(device) == 0); + + service_conn_t houseFd; + + if (bundle_id == NULL) { + printf("Bundle id is not specified\n"); + exit(1); + } + + CFStringRef cf_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingASCII); + if (AMDeviceStartHouseArrestService(device, cf_bundle_id, 0, &houseFd, 0) != 0) + { + printf("Unable to find bundle with id: %s\n", bundle_id); + exit(1); + } + + assert(AMDeviceStopSession(device) == 0); + assert(AMDeviceDisconnect(device) == 0); + CFRelease(cf_bundle_id); + + return houseFd; +} + +char* get_filename_from_path(char* path) +{ + char *ptr = path + strlen(path); + while (ptr > path) + { + if (*ptr == '/') + break; + --ptr; + } + if (ptr+1 >= path+strlen(path)) + return NULL; + if (ptr == path) + return ptr; + return ptr+1; +} + +void* read_file_to_memory(char * path, size_t* file_size) +{ + struct stat buf; + int err = stat(path, &buf); + if (err < 0) + { + return NULL; + } + + *file_size = buf.st_size; + FILE* fd = fopen(path, "r"); + char* content = malloc(*file_size); + if (fread(content, *file_size, 1, fd) != 1) + { + fclose(fd); + return NULL; + } + fclose(fd); + return content; +} + +void list_files(AMDeviceRef device) +{ + service_conn_t houseFd = start_house_arrest_service(device); + + afc_connection afc_conn; + afc_connection* afc_conn_p = &afc_conn; + AFCConnectionOpen(houseFd, 0, &afc_conn_p); + + read_dir(houseFd, afc_conn_p, "/"); +} + +void upload_file(AMDeviceRef device) { + service_conn_t houseFd = start_house_arrest_service(device); + + afc_file_ref file_ref; + + afc_connection afc_conn; + afc_connection* afc_conn_p = &afc_conn; + AFCConnectionOpen(houseFd, 0, &afc_conn_p); + + // read_dir(houseFd, NULL, "/"); + + if (!target_filename) + { + target_filename = get_filename_from_path(upload_pathname); + } + + size_t file_size; + void* file_content = read_file_to_memory(upload_pathname, &file_size); + + if (!file_content) + { + printf("Could not open file: %s\n", upload_pathname); + exit(-1); + } + + // Make sure the directory was created + { + char *dirpath = strdup(target_filename); + char *c = dirpath, *lastSlash = dirpath; + while(*c) { + if(*c == '/') { + lastSlash = c; + } + c++; + } + *lastSlash = '\0'; + assert(AFCDirectoryCreate(afc_conn_p, dirpath) == 0); + } + + + int ret = AFCFileRefOpen(afc_conn_p, target_filename, 3, &file_ref); + if (ret == 0x000a) { + printf("Cannot write to %s. Permission error.\n", target_filename); + exit(1); + } + if (ret == 0x0009) { + printf("Target %s is a directory.\n", target_filename); + exit(1); + } + assert(ret == 0); + assert(AFCFileRefWrite(afc_conn_p, file_ref, file_content, file_size) == 0); + assert(AFCFileRefClose(afc_conn_p, file_ref) == 0); + assert(AFCConnectionClose(afc_conn_p) == 0); + + free(file_content); +} + void handle_device(AMDeviceRef device) { if (found_device) return; // handle one device only CFStringRef found_device_id = AMDeviceCopyDeviceIdentifier(device); @@ -861,6 +1047,15 @@ void handle_device(AMDeviceRef device) { printf("[....] Found device (%s).\n", CFStringGetCStringPtr(found_device_id, CFStringGetSystemEncoding())); exit(0); } + + if (command_only) { + if (strcmp("list", command) == 0) { + list_files(device); + } else if (strcmp("upload", command) == 0) { + upload_file(device); + } + exit(0); + } CFRetain(device); // don't know if this is necessary? @@ -982,6 +1177,10 @@ void usage(const char* app) { " -m, --noinstall directly start debugging without app install (-d not required)\n" " -p, --port port used for device, default: 12345 \n" " -r, --uninstall uninstall the app before install (do not use with -m; app cache and data are cleared) \n" + " -1, --bundle_id specify bundle id for list and upload\n" + " -l, --list list files\n" + " -o, --upload upload file\n" + " -2, --to use together with upload file. specify target for upload\n" " -V, --version print the executable version \n", app); } @@ -1007,11 +1206,15 @@ int main(int argc, char *argv[]) { { "noinstall", no_argument, NULL, 'm' }, { "port", required_argument, NULL, 'p' }, { "uninstall", no_argument, NULL, 'r' }, + { "list", no_argument, NULL, 'l' }, + { "bundle_id", required_argument, NULL, '1'}, + { "upload", required_argument, NULL, 'o'}, + { "to", required_argument, NULL, '2'}, { NULL, 0, NULL, 0 }, }; char ch; - while ((ch = getopt_long(argc, argv, "VmcdvunrIi:b:a:t:g:x:p:", longopts, NULL)) != -1) + while ((ch = getopt_long(argc, argv, "VmcdvunlrIi:b:a:t:g:x:p:1:2:o:", longopts, NULL)) != -1) { switch (ch) { case 'm': @@ -1057,13 +1260,28 @@ int main(int argc, char *argv[]) { case 'r': uninstall = 1; break; + case '1': + bundle_id = optarg; + break; + case '2': + target_filename = optarg; + break; + case 'o': + command_only = true; + upload_pathname = optarg; + command = "upload"; + break; + case 'l': + command_only = true; + command = "list"; + break; default: usage(argv[0]); return exitcode_error; } } - if (!app_path && !detect_only) { + if (!app_path && !detect_only && !command_only) { usage(argv[0]); exit(exitcode_error); } @@ -1097,3 +1315,4 @@ int main(int argc, char *argv[]) { AMDeviceNotificationSubscribe(&device_callback, 0, 0, NULL, ¬ify); CFRunLoopRun(); } + From 3799a8a535d83797f07e099a2948286b3621bdd9 Mon Sep 17 00:00:00 2001 From: Alexandre Gomes Date: Thu, 31 Jul 2014 14:44:24 +0100 Subject: [PATCH 049/219] Implements #48 - Wifi Support & Checks Signed-off-by: Shazron Abdullah --- ios-deploy.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 181 insertions(+), 19 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index fc338cf8..a38b982f 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -121,10 +121,12 @@ def autoexit_command(debugger, command, result, internal_dict):\n\ ") typedef struct am_device * AMDeviceRef; +mach_error_t AMDeviceSecureStartService(struct am_device *device, CFStringRef service_name, unsigned int *unknown, service_conn_t *handle); int AMDeviceSecureTransferPath(int zero, AMDeviceRef device, CFURLRef url, CFDictionaryRef options, void *callback, int cbarg); int AMDeviceSecureInstallApplication(int zero, AMDeviceRef device, CFURLRef url, CFDictionaryRef options, void *callback, int cbarg); int AMDeviceMountImage(AMDeviceRef device, CFStringRef image, CFDictionaryRef options, void *callback, int cbarg); mach_error_t AMDeviceLookupApplications(AMDeviceRef device, CFDictionaryRef options, CFDictionaryRef *result); +int AMDeviceGetInterfaceType(struct am_device *device); bool found_device = false, debug = false, verbose = false, unbuffered = false, nostart = false, detect_only = false, install = true, uninstall = false; bool command_only = false; @@ -145,6 +147,7 @@ pid_t parent = 0; pid_t child = 0; // Signal sent from child to parent process when LLDB finishes. const int SIGLLDB = SIGUSR1; +AMDeviceRef best_device_match = NULL; // Error codes we report on different failures, so scripts can distinguish between user app exit // codes and our exit codes. For non app errors we use codes in reserved 128-255 range. @@ -268,6 +271,125 @@ CFStringRef copy_xcode_path_for(CFStringRef subPath, CFStringRef search) { } } +// Please ensure that device is connected or the name will be unknown +const CFStringRef get_device_hardware_name(const AMDeviceRef device) { + CFStringRef model = AMDeviceCopyValue(device, 0, CFSTR("HardwareModel")); + const char *hwmodel = CFStringGetCStringPtr(model, CFStringGetSystemEncoding()); + + if (hwmodel && !strcmp("M68AP", hwmodel)) + return CFSTR("iPhone"); + if (hwmodel && !strcmp("N45AP", hwmodel)) + return CFSTR("iPod touch"); + if (hwmodel && !strcmp("N82AP", hwmodel)) + return CFSTR("iPhone 3G"); + if (hwmodel && !strcmp("N72AP", hwmodel)) + return CFSTR("iPod touch 2G"); + if (hwmodel && !strcmp("N88AP", hwmodel)) + return CFSTR("iPhone 3GS"); + if (hwmodel && !strcmp("N18AP", hwmodel)) + return CFSTR("iPod touch 3G"); + if (hwmodel && !strcmp("K48AP", hwmodel)) + return CFSTR("iPad"); + if (hwmodel && !strcmp("N90AP", hwmodel)) + return CFSTR("iPhone 4 (GSM)"); + if (hwmodel && !strcmp("N81AP", hwmodel)) + return CFSTR("iPod touch 4G"); + if (hwmodel && !strcmp("K66AP", hwmodel)) + return CFSTR("Apple TV 2G"); + if (hwmodel && !strcmp("N92AP", hwmodel)) + return CFSTR("iPhone 4 (CDMA)"); + if (hwmodel && !strcmp("N90BAP", hwmodel)) + return CFSTR("iPhone 4 (GSM, revision A)"); + if (hwmodel && !strcmp("K93AP", hwmodel)) + return CFSTR("iPad 2"); + if (hwmodel && !strcmp("K94AP", hwmodel)) + return CFSTR("iPad 2 (GSM)"); + if (hwmodel && !strcmp("K95AP", hwmodel)) + return CFSTR("iPad 2 (CDMA)"); + if (hwmodel && !strcmp("K93AAP", hwmodel)) + return CFSTR("iPad 2 (Wi-Fi, revision A)"); + if (hwmodel && !strcmp("P105AP", hwmodel)) + return CFSTR("iPad mini"); + if (hwmodel && !strcmp("P106AP", hwmodel)) + return CFSTR("iPad mini (GSM)"); + if (hwmodel && !strcmp("P107AP", hwmodel)) + return CFSTR("iPad mini (CDMA)"); + if (hwmodel && !strcmp("N94AP", hwmodel)) + return CFSTR("iPhone 4S"); + if (hwmodel && !strcmp("N41AP", hwmodel)) + return CFSTR("iPhone 5 (GSM)"); + if (hwmodel && !strcmp("N42AP", hwmodel)) + return CFSTR("iPhone 5 (Global/CDMA)"); + if (hwmodel && !strcmp("N48AP", hwmodel)) + return CFSTR("iPhone 5c (GSM)"); + if (hwmodel && !strcmp("N49AP", hwmodel)) + return CFSTR("iPhone 5c (Global/CDMA)"); + if (hwmodel && !strcmp("N51AP", hwmodel)) + return CFSTR("iPhone 5s (GSM)"); + if (hwmodel && !strcmp("N53AP", hwmodel)) + return CFSTR("iPhone 5s (Global/CDMA)"); + if (hwmodel && !strcmp("J1AP", hwmodel)) + return CFSTR("iPad 3"); + if (hwmodel && !strcmp("J2AP", hwmodel)) + return CFSTR("iPad 3 (GSM)"); + if (hwmodel && !strcmp("J2AAP", hwmodel)) + return CFSTR("iPad 3 (CDMA)"); + if (hwmodel && !strcmp("P101AP", hwmodel)) + return CFSTR("iPad 4"); + if (hwmodel && !strcmp("P102AP", hwmodel)) + return CFSTR("iPad 4 (GSM)"); + if (hwmodel && !strcmp("P103AP", hwmodel)) + return CFSTR("iPad 4 (CDMA)"); + if (hwmodel && !strcmp("N78AP", hwmodel)) + return CFSTR("iPod touch 5G"); + if (hwmodel && !strcmp("J33AP", hwmodel)) + return CFSTR("Apple TV 3G"); + if (hwmodel && !strcmp("J33IAP", hwmodel)) + return CFSTR("Apple TV 3.1G"); + + return CFSTR("Unknown Device"); +} + +CFStringRef get_device_full_name(const AMDeviceRef device) { + CFStringRef full_name = NULL, + device_udid = AMDeviceCopyDeviceIdentifier(device), + device_name = NULL, + model_name = NULL; + + AMDeviceConnect(device); + + device_name = AMDeviceCopyValue(device, 0, CFSTR("DeviceName")), + model_name = get_device_hardware_name(device); + + if(device_name != NULL && model_name != NULL) + full_name = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ '%@' (%@)"), model_name, device_name, device_udid); + else + full_name = CFStringCreateWithFormat(NULL, NULL, CFSTR("(%@)"), device_udid); + + AMDeviceDisconnect(device); + + if(device_udid != NULL) + CFRelease(device_udid); + if(device_name != NULL) + CFRelease(device_name); + if(model_name != NULL) + CFRelease(model_name); + + return full_name; +} + +CFStringRef get_device_interface_name(const AMDeviceRef device) { + // AMDeviceGetInterfaceType(device) 0=Unknown, 1 = Direct/USB, 2 = Indirect/WIFI + switch(AMDeviceGetInterfaceType(device)) { + case 1: + return CFSTR("USB"); + case 2: + return CFSTR("WIFI"); + default: + return CFSTR("Unknown Connection"); + } +} + CFMutableArrayRef get_device_product_version_parts(AMDeviceRef device) { CFStringRef version = AMDeviceCopyValue(device, 0, CFSTR("ProductVersion")); CFArrayRef parts = CFStringCreateArrayBySeparatingStrings(NULL, version, CFSTR(".")); @@ -748,6 +870,9 @@ void setup_dummy_pipe_on_stdin(int pfd[2]) { } void launch_debugger(AMDeviceRef device, CFURLRef url) { + CFStringRef device_full_name = get_device_full_name(device), + device_interface_name = get_device_interface_name(device); + AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); assert(AMDeviceValidatePairing(device) == 0); @@ -755,6 +880,14 @@ void launch_debugger(AMDeviceRef device, CFURLRef url) { printf("------ Debug phase ------\n"); + if(AMDeviceGetInterfaceType(device) == 2) + { + printf("Cannot debug %s over %s.\n", CFStringGetCStringPtr(device_full_name, CFStringGetSystemEncoding()), CFStringGetCStringPtr(device_interface_name, CFStringGetSystemEncoding())); + exit(0); + } + + printf("Starting debug of %s connected through %s...\n", CFStringGetCStringPtr(device_full_name, CFStringGetSystemEncoding()), CFStringGetCStringPtr(device_interface_name, CFStringGetSystemEncoding())); + mount_developer_image(device); // put debugserver on the device start_remote_debug_server(device); // start debugserver write_lldb_prep_cmds(device, url); // dump the necessary lldb commands into a file @@ -1030,8 +1163,12 @@ void upload_file(AMDeviceRef device) { } void handle_device(AMDeviceRef device) { - if (found_device) return; // handle one device only - CFStringRef found_device_id = AMDeviceCopyDeviceIdentifier(device); + if (found_device) + return; // handle one device only + + CFStringRef found_device_id = AMDeviceCopyDeviceIdentifier(device), + device_full_name = get_device_full_name(device), + device_interface_name = get_device_interface_name(device); if (device_id != NULL) { if(strcmp(device_id, CFStringGetCStringPtr(found_device_id, CFStringGetSystemEncoding())) == 0) { @@ -1044,7 +1181,7 @@ void handle_device(AMDeviceRef device) { } if (detect_only) { - printf("[....] Found device (%s).\n", CFStringGetCStringPtr(found_device_id, CFStringGetSystemEncoding())); + printf("[....] Found %s connected through %s.\n", CFStringGetCStringPtr(device_full_name, CFStringGetSystemEncoding()), CFStringGetCStringPtr(device_interface_name, CFStringGetSystemEncoding())); exit(0); } @@ -1089,7 +1226,7 @@ void handle_device(AMDeviceRef device) { if(install) { printf("------ Install phase ------\n"); - printf("[ 0%%] Found device (%s), beginning install\n", CFStringGetCStringPtr(found_device_id, CFStringGetSystemEncoding())); + printf("[ 0%%] Found %s connected through %s, beginning install\n", CFStringGetCStringPtr(device_full_name, CFStringGetSystemEncoding()), CFStringGetCStringPtr(device_interface_name, CFStringGetSystemEncoding())); AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); @@ -1097,31 +1234,37 @@ void handle_device(AMDeviceRef device) { assert(AMDeviceStartSession(device) == 0); - + // NOTE: the secure version doesn't seem to require us to start the AFC service service_conn_t afcFd; - assert(AMDeviceStartService(device, CFSTR("com.apple.afc"), &afcFd, NULL) == 0); + assert(AMDeviceSecureStartService(device, CFSTR("com.apple.afc"), NULL, &afcFd) == 0); assert(AMDeviceStopSession(device) == 0); assert(AMDeviceDisconnect(device) == 0); - assert(AMDeviceTransferApplication(afcFd, path, NULL, transfer_callback, NULL) == 0); - - close(afcFd); CFStringRef keys[] = { CFSTR("PackageType") }; CFStringRef values[] = { CFSTR("Developer") }; CFDictionaryRef options = CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&values, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + //assert(AMDeviceTransferApplication(afcFd, path, NULL, transfer_callback, NULL) == 0); + assert(AMDeviceSecureTransferPath(0, device, url, options, transfer_callback, 0)==0); + + close(afcFd); + + + AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); assert(AMDeviceValidatePairing(device) == 0); assert(AMDeviceStartSession(device) == 0); - service_conn_t installFd; - assert(AMDeviceStartService(device, CFSTR("com.apple.mobile.installation_proxy"), &installFd, NULL) == 0); + // // NOTE: the secure version doesn't seem to require us to start the installation_proxy service + // // Although I can't find it right now, I in some code that the first param of AMDeviceSecureInstallApplication was a "dontStartInstallProxy" + // // implying this is done for us by iOS already - assert(AMDeviceStopSession(device) == 0); - assert(AMDeviceDisconnect(device) == 0); + //service_conn_t installFd; + //assert(AMDeviceSecureStartService(device, CFSTR("com.apple.mobile.installation_proxy"), NULL, &installFd) == 0); - mach_error_t result = AMDeviceInstallApplication(installFd, path, options, install_callback, NULL); + //mach_error_t result = AMDeviceInstallApplication(installFd, path, options, install_callback, NULL); + mach_error_t result = AMDeviceSecureInstallApplication(0, device, url, options, install_callback, 0); if (result != 0) { char* error = "Unknown error."; @@ -1131,7 +1274,10 @@ void handle_device(AMDeviceRef device) { exit(exitcode_error); } - close(installFd); + // close(installFd); + + assert(AMDeviceStopSession(device) == 0); + assert(AMDeviceDisconnect(device) == 0); CFRelease(path); CFRelease(options); @@ -1139,14 +1285,21 @@ void handle_device(AMDeviceRef device) { printf("[100%%] Installed package %s\n", app_path); } - if (!debug) exit(0); // no debug phase + if (!debug) + exit(0); // no debug phase + launch_debugger(device, url); } void device_callback(struct am_device_notification_callback_info *info, void *arg) { switch (info->msg) { case ADNCI_MSG_CONNECTED: - handle_device(info->dev); + if(device_id != NULL || !debug || AMDeviceGetInterfaceType(info->dev) != 2) { + handle_device(info->dev); + } else if(best_device_match == NULL) { + best_device_match = info->dev; + CFRetain(best_device_match); + } default: break; } @@ -1154,8 +1307,17 @@ void device_callback(struct am_device_notification_callback_info *info, void *ar void timeout_callback(CFRunLoopTimerRef timer, void *info) { if (!found_device) { - printf("[....] Timed out waiting for device.\n"); - exit(exitcode_error); + if(best_device_match != NULL) { + handle_device(best_device_match); + + CFRelease(best_device_match); + best_device_match = NULL; + } + + if(!found_device) { + printf("[....] Timed out waiting for device.\n"); + exit(exitcode_error); + } } } From 54a62bfdd01751b520a0acaa37f9599ddd77d8e2 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Thu, 31 Jul 2014 17:49:44 -0700 Subject: [PATCH 050/219] Fixes #49 - Update README with new help text #49 --- README.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 3716a1fb..3eabf955 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Install and debug iPhone apps without using Xcode. Designed to work on unjailbro ## Usage - ./ios-deploy [OPTION]... + Usage: ./ios-deploy [OPTION]... -d, --debug launch the app in GDB after installation -i, --id the id of the device to connect to -c, --detect only detect if the device is connected @@ -23,11 +23,14 @@ Install and debug iPhone apps without using Xcode. Designed to work on unjailbro -n, --nostart do not start the app when debugging -I, --noninteractive start in non interactive mode (quit when app crashes or exits) -v, --verbose enable verbose output - -m, --noinstall directly start debugging without app install (-d not required) - -p, --port port used for device, default: 12345 - -r, --uninstall uninstall the app before install (do not use with -m; app cache and data are cleared) - -l, --list list files - -V, --version print the executable version + -m, --noinstall directly start debugging without app install (-d not required) + -p, --port port used for device, default: 12345 + -r, --uninstall uninstall the app before install (do not use with -m; app cache and data are cleared) + -1, --bundle_id specify bundle id for list and upload + -l, --list list files + -o, --upload upload file + -2, --to use together with upload file. specify target for upload + -V, --version print the executable version ## Demo From 5f90ebb32bc567874aa7410331ce56c141562f02 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Fri, 1 Aug 2014 15:20:24 -0700 Subject: [PATCH 051/219] Fixes #50 - Publish 1.0.9 version --- ios-deploy.c | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index a38b982f..bbf89bf6 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -16,7 +16,7 @@ #include #include "MobileDevice.h" -#define APP_VERSION "1.0.8" +#define APP_VERSION "1.0.9" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH diff --git a/package.json b/package.json index 56ccbefc..1d581b4d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ios-deploy", - "version": "1.0.8", + "version": "1.0.9", "description": "launch iOS apps iOS devices from the command line (Xcode 5)", "main": "ios-deploy", "scripts": { From 55a12cb02e7ea6552bdb5c47e2a19da1a9e942b2 Mon Sep 17 00:00:00 2001 From: senthil Date: Sun, 3 Aug 2014 12:56:17 -0400 Subject: [PATCH 052/219] Fix for issues 51 and 52 51: Updated the python:run_command to look for : Locked. 52: Added option -L that is a variation of non-interactive Added the constant with safequit and implemented the equivalent python --- ios-deploy.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index bbf89bf6..230d3163 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -35,6 +35,7 @@ command script add -f {python_command}.connect_command connect\n\ command script add -s asynchronous -f {python_command}.run_command run\n\ command script add -s asynchronous -f {python_command}.autoexit_command autoexit\n\ + command script add -s asynchronous -f {python_command}.safequit_command safequit\n\ connect\n\ ") @@ -44,6 +45,12 @@ const char* lldb_prep_interactive_cmds = "\ run\n\ "; +const char* lldb_prep_noninteractive_justlaunch_cmds = "\ + run\n\ + detach\n\ + safequit\n\ +"; + const char* lldb_prep_noninteractive_cmds = "\ run\n\ autoexit\n\ @@ -88,7 +95,15 @@ def run_command(debugger, command, result, internal_dict):\n\ error = lldb.SBError()\n\ lldb.target.modules[0].SetPlatformFileSpec(lldb.SBFileSpec(device_app))\n\ lldb.target.Launch(lldb.SBLaunchInfo(shlex.split('{args}')), error)\n\ - print str(error)\n\ + lockedstr = ': Locked'\n\ + if lockedstr in str(error):\n\ + print('\\nDevice Locked\\n')\n\ + sys.exit(254)\n\ + else:\n\ + print(str(error))\n\ +\n\ +def safequit_command(debugger, command, result, internal_dict):\n\ + sys.exit(0);\n\ \n\ def autoexit_command(debugger, command, result, internal_dict):\n\ process = lldb.target.process\n\ @@ -135,6 +150,7 @@ char *target_filename = NULL; char *upload_pathname = NULL; char *bundle_id = NULL; bool interactive = true; +bool justlaunch = false; char *app_path = NULL; char *device_id = NULL; char *args = NULL; @@ -688,7 +704,12 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { // Write additional commands based on mode we're running in const char* extra_cmds; if (!interactive) - extra_cmds = lldb_prep_noninteractive_cmds; + { + if (justlaunch) + extra_cmds = lldb_prep_noninteractive_justlaunch_cmds; + else + extra_cmds = lldb_prep_noninteractive_cmds; + } else if (nostart) extra_cmds = lldb_prep_no_cmds; else @@ -1335,6 +1356,7 @@ void usage(const char* app) { " -x, --gdbexec GDB commands script file\n" " -n, --nostart do not start the app when debugging\n" " -I, --noninteractive start in non interactive mode (quit when app crashes or exits)\n" + " -L, --justlaunch just launch the app and exit lldb\n" " -v, --verbose enable verbose output\n" " -m, --noinstall directly start debugging without app install (-d not required)\n" " -p, --port port used for device, default: 12345 \n" @@ -1363,6 +1385,7 @@ int main(int argc, char *argv[]) { { "unbuffered", no_argument, NULL, 'u' }, { "nostart", no_argument, NULL, 'n' }, { "noninteractive", no_argument, NULL, 'I' }, + { "justlaunch", no_argument, NULL, 'L' }, { "detect", no_argument, NULL, 'c' }, { "version", no_argument, NULL, 'V' }, { "noinstall", no_argument, NULL, 'm' }, @@ -1376,7 +1399,7 @@ int main(int argc, char *argv[]) { }; char ch; - while ((ch = getopt_long(argc, argv, "VmcdvunlrIi:b:a:t:g:x:p:1:2:o:", longopts, NULL)) != -1) + while ((ch = getopt_long(argc, argv, "VmcdvunlrILi:b:a:t:g:x:p:1:2:o:", longopts, NULL)) != -1) { switch (ch) { case 'm': @@ -1410,6 +1433,10 @@ int main(int argc, char *argv[]) { case 'I': interactive = false; break; + case 'L': + interactive = false; + justlaunch = true; + break; case 'c': detect_only = true; break; From 616b6ab1ff416e152e4842a05d02b88323cf2065 Mon Sep 17 00:00:00 2001 From: senthil Date: Sun, 3 Aug 2014 13:43:38 -0400 Subject: [PATCH 053/219] updated to version 1.0.10 --- ios-deploy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index 230d3163..78b5b310 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -16,7 +16,7 @@ #include #include "MobileDevice.h" -#define APP_VERSION "1.0.9" +#define APP_VERSION "1.0.10" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH From 0f1ef6f4eff88dd91e2c5c16244a91020b01a0f5 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 4 Aug 2014 19:07:31 -0700 Subject: [PATCH 054/219] Fixes #54 - Publish 1.1.0 version --- README.md | 45 +++++++++++++++++++++++---------------------- ios-deploy.c | 2 +- package.json | 2 +- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 3eabf955..a8db9d13 100644 --- a/README.md +++ b/README.md @@ -10,28 +10,29 @@ Install and debug iPhone apps without using Xcode. Designed to work on unjailbro ## Usage - Usage: ./ios-deploy [OPTION]... - -d, --debug launch the app in GDB after installation - -i, --id the id of the device to connect to - -c, --detect only detect if the device is connected - -b, --bundle the path to the app bundle to be installed - -a, --args command line arguments to pass to the app when launching it - -t, --timeout number of seconds to wait for a device to be connected - -u, --unbuffered don't buffer stdout - -g, --gdbargs extra arguments to pass to GDB when starting the debugger - -x, --gdbexec GDB commands script file - -n, --nostart do not start the app when debugging - -I, --noninteractive start in non interactive mode (quit when app crashes or exits) - -v, --verbose enable verbose output - -m, --noinstall directly start debugging without app install (-d not required) - -p, --port port used for device, default: 12345 - -r, --uninstall uninstall the app before install (do not use with -m; app cache and data are cleared) - -1, --bundle_id specify bundle id for list and upload - -l, --list list files - -o, --upload upload file - -2, --to use together with upload file. specify target for upload - -V, --version print the executable version - + Usage: ./ios-deploy [OPTION]... + -d, --debug launch the app in GDB after installation + -i, --id the id of the device to connect to + -c, --detect only detect if the device is connected + -b, --bundle the path to the app bundle to be installed + -a, --args command line arguments to pass to the app when launching it + -t, --timeout number of seconds to wait for a device to be connected + -u, --unbuffered don't buffer stdout + -g, --gdbargs extra arguments to pass to GDB when starting the debugger + -x, --gdbexec GDB commands script file + -n, --nostart do not start the app when debugging + -I, --noninteractive start in non interactive mode (quit when app crashes or exits) + -L, --justlaunch just launch the app and exit lldb + -v, --verbose enable verbose output + -m, --noinstall directly start debugging without app install (-d not required) + -p, --port port used for device, default: 12345 + -r, --uninstall uninstall the app before install (do not use with -m; app cache and data are cleared) + -1, --bundle_id specify bundle id for list and upload + -l, --list list files + -o, --upload upload file + -2, --to use together with upload file. specify target for upload + -V, --version print the executable version + ## Demo * The included demo.app represents the minimum required to get code running on iOS. diff --git a/ios-deploy.c b/ios-deploy.c index 78b5b310..75b083a6 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -16,7 +16,7 @@ #include #include "MobileDevice.h" -#define APP_VERSION "1.0.10" +#define APP_VERSION "1.1.0" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH diff --git a/package.json b/package.json index 1d581b4d..d81493af 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ios-deploy", - "version": "1.0.9", + "version": "1.1.0", "description": "launch iOS apps iOS devices from the command line (Xcode 5)", "main": "ios-deploy", "scripts": { From 35097bd5a01d0305f6c519196a9938a61786ebe3 Mon Sep 17 00:00:00 2001 From: "Michael R. Hines" Date: Tue, 19 Aug 2014 19:51:20 +0800 Subject: [PATCH 055/219] Don't forget about iPods too =) Update the readme to include iPods in the device identifier search. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a8db9d13..bd44b492 100644 --- a/README.md +++ b/README.md @@ -48,4 +48,4 @@ Install and debug iPhone apps without using Xcode. Designed to work on unjailbro Device Ids are the UDIDs of the iOS devices. From the command line, you can list device ids [this way](http://javierhz.blogspot.com/2012/06/how-to-get-udid-of-iphone-using-shell.html): - system_profiler SPUSBDataType | sed -n -e '/iPad/,/Serial/p' -e '/iPhone/,/Serial/p' | grep "Serial Number:" | awk -F ": " '{print $2}' + system_profiler SPUSBDataType | sed -n -e '/iPod/,/Serial/p' | sed -n -e '/iPad/,/Serial/p' -e '/iPhone/,/Serial/p' | grep "Serial Number:" | awk -F ": " '{print $2}' From 6bd90a5133431c8e65cf9d9c02e382a2bc076bfb Mon Sep 17 00:00:00 2001 From: senthil Date: Tue, 2 Sep 2014 16:18:33 -0400 Subject: [PATCH 056/219] a minor debugging version --- ios-deploy.c | 45 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 75b083a6..f1a52c99 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -292,6 +292,8 @@ const CFStringRef get_device_hardware_name(const AMDeviceRef device) { CFStringRef model = AMDeviceCopyValue(device, 0, CFSTR("HardwareModel")); const char *hwmodel = CFStringGetCStringPtr(model, CFStringGetSystemEncoding()); + printf("-->Hardware model: %s\n", hwmodel); + if (hwmodel && !strcmp("M68AP", hwmodel)) return CFSTR("iPhone"); if (hwmodel && !strcmp("N45AP", hwmodel)) @@ -358,6 +360,8 @@ const CFStringRef get_device_hardware_name(const AMDeviceRef device) { return CFSTR("iPad 4 (CDMA)"); if (hwmodel && !strcmp("N78AP", hwmodel)) return CFSTR("iPod touch 5G"); + if (hwmodel && !strcmp("A1509", hwmodel)) + return CFSTR("iPod touch 5G"); if (hwmodel && !strcmp("J33AP", hwmodel)) return CFSTR("Apple TV 3G"); if (hwmodel && !strcmp("J33IAP", hwmodel)) @@ -366,21 +370,53 @@ const CFStringRef get_device_hardware_name(const AMDeviceRef device) { return CFSTR("Unknown Device"); } +char * MYCFStringCopyUTF8String(CFStringRef aString) { + if (aString == NULL) { + return NULL; + } + + CFIndex length = CFStringGetLength(aString); + CFIndex maxSize = + CFStringGetMaximumSizeForEncoding(length, + kCFStringEncodingUTF8); + char *buffer = (char *)malloc(maxSize); + if (CFStringGetCString(aString, buffer, maxSize, + kCFStringEncodingUTF8)) { + return buffer; + } + return NULL; +} + CFStringRef get_device_full_name(const AMDeviceRef device) { CFStringRef full_name = NULL, device_udid = AMDeviceCopyDeviceIdentifier(device), device_name = NULL, model_name = NULL; - AMDeviceConnect(device); - + kern_return_t ret = AMDeviceConnect(device); + printf("-->AMDeviceConnect: %08x\n",ret); + device_name = AMDeviceCopyValue(device, 0, CFSTR("DeviceName")), model_name = get_device_hardware_name(device); - if(device_name != NULL && model_name != NULL) + printf("-->[%s] %ld\n",CFStringGetCStringPtr(device_name, CFStringGetSystemEncoding()), CFStringGetLength(device_name)); + printf("-->[%s] %ld\n",CFStringGetCStringPtr(device_name, kCFStringEncodingUTF8), CFStringGetLength(device_name)); + printf("-->[%s] %ld\n",CFStringGetCStringPtr(model_name, CFStringGetSystemEncoding()), CFStringGetLength(model_name)); + printf("-->[%s] %ld\n",CFStringGetCStringPtr(device_udid, CFStringGetSystemEncoding()), CFStringGetLength(device_udid)); + + CFShowStr(device_name); + printf("-->[%s] bytes\n",MYCFStringCopyUTF8String(device_name)); + + if((device_name != NULL) && CFStringGetLength(device_name) > 0 && (model_name != NULL) && CFStringGetLength(model_name)>0) + { + printf("In if\n"); full_name = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ '%@' (%@)"), model_name, device_name, device_udid); + } else - full_name = CFStringCreateWithFormat(NULL, NULL, CFSTR("(%@)"), device_udid); + { + printf("In else: %s\n",CFStringGetCStringPtr(device_udid, CFStringGetSystemEncoding())); + full_name = CFStringCreateWithFormat(NULL, NULL, CFSTR("(%@ss)"), device_udid); + } AMDeviceDisconnect(device); @@ -391,6 +427,7 @@ CFStringRef get_device_full_name(const AMDeviceRef device) { if(model_name != NULL) CFRelease(model_name); + printf("-->[%s]\n",CFStringGetCStringPtr(full_name, CFStringGetSystemEncoding())); return full_name; } From bf5a1e065ee4ed6468503fc49d1686b4ac71663c Mon Sep 17 00:00:00 2001 From: Alexandre Gomes Date: Mon, 6 Oct 2014 13:36:31 +0100 Subject: [PATCH 057/219] fix lldb status checking --- ios-deploy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index 75b083a6..efdca286 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -77,7 +77,7 @@ def connect_command(debugger, command, result, internal_dict):\n\ listener = lldb.target.GetDebugger().GetListener()\n\ listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged)\n\ events = []\n\ - state = lldb.eStateInvalid\n\ + state = (process.GetState() or lldb.eStateInvalid)\n\ while state != lldb.eStateConnected:\n\ event = lldb.SBEvent()\n\ if listener.WaitForEvent(1, event):\n\ From 4869a343e884c41fae5ac5c84e0af72e920f850e Mon Sep 17 00:00:00 2001 From: Andy Polyakov Date: Mon, 6 Oct 2014 22:32:36 +0200 Subject: [PATCH 058/219] fix AFCFileRef[Read|Write] prototypes Incorrect AFCFileRefRead prototype was causing crashes in 64-bit build when reading large files. --- MobileDevice.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MobileDevice.h b/MobileDevice.h index e078a44c..d97eafb5 100644 --- a/MobileDevice.h +++ b/MobileDevice.h @@ -396,11 +396,11 @@ afc_error_t AFCFileRefOpen(afc_connection *conn, const char *path, afc_error_t AFCFileRefSeek(afc_connection *conn, afc_file_ref ref, unsigned long long offset1, unsigned long long offset2); afc_error_t AFCFileRefRead(afc_connection *conn, afc_file_ref ref, - void *buf, unsigned int *len); + void *buf, size_t *len); afc_error_t AFCFileRefSetFileSize(afc_connection *conn, afc_file_ref ref, unsigned long long offset); afc_error_t AFCFileRefWrite(afc_connection *conn, afc_file_ref ref, - const void *buf, unsigned int len); + const void *buf, size_t len); afc_error_t AFCFileRefClose(afc_connection *conn, afc_file_ref ref); afc_error_t AFCFileInfoOpen(afc_connection *conn, const char *path, struct @@ -493,4 +493,4 @@ typedef unsigned int (*t_performOperation)(struct am_restore_device *rdev, } #endif -#endif \ No newline at end of file +#endif From 23afce0d3714e5599462cb2ed5326343973a148e Mon Sep 17 00:00:00 2001 From: Andy Polyakov Date: Mon, 6 Oct 2014 22:40:43 +0200 Subject: [PATCH 059/219] handle no --args When no --args are passed application was started with {args} as argument instead of no argument. --- ios-deploy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 75b083a6..fb1f1810 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -644,12 +644,12 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { if (args) { CFStringRef cf_args = CFStringCreateWithCString(NULL, args, kCFStringEncodingASCII); CFStringFindAndReplace(cmds, CFSTR("{args}"), cf_args, range, 0); - rangeLLDB.length = CFStringGetLength(pmodule); CFStringFindAndReplace(pmodule, CFSTR("{args}"), cf_args, rangeLLDB, 0); CFRelease(cf_args); } else { - CFStringFindAndReplace(cmds, CFSTR(" {args}"), CFSTR(""), range, 0); + CFStringFindAndReplace(cmds, CFSTR("{args}"), CFSTR(""), range, 0); + CFStringFindAndReplace(pmodule, CFSTR("{args}"), CFSTR(""), rangeLLDB, 0); } range.length = CFStringGetLength(cmds); From 9a2da6f6427e740eec83d9136569968309798183 Mon Sep 17 00:00:00 2001 From: Andy Polyakov Date: Mon, 6 Oct 2014 23:02:06 +0200 Subject: [PATCH 060/219] Fix usage semantic and pair of resource leaks AFCConnectionOpen and AFCFIleInfoOpen don't require initialized pointer to pointer to result, but do require corresponding Close calls. --- ios-deploy.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index fb1f1810..1c636bfc 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1014,12 +1014,24 @@ void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir) printf("%s\n", dir); - afc_dictionary afc_dict; - afc_dictionary* afc_dict_p = &afc_dict; + afc_dictionary* afc_dict_p; + char *key, *val; + int not_dir; + AFCFileInfoOpen(afc_conn_p, dir, &afc_dict_p); - - afc_directory afc_dir; - afc_directory* afc_dir_p = &afc_dir; + while((AFCKeyValueRead(afc_dict_p,&key,&val) == 0) && key && val) { + if (strcmp(key,"st_ifmt")==0) { + not_dir = strcmp(val,"S_IFDIR"); + break; + } + } + AFCKeyValueClose(afc_dict_p); + + if (not_dir) { + return; + } + + afc_directory* afc_dir_p; afc_error_t err = AFCDirectoryOpen(afc_conn_p, dir, &afc_dir_p); if (err != 0) @@ -1031,7 +1043,7 @@ void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir) while(true) { err = AFCDirectoryRead(afc_conn_p, afc_dir_p, &dir_ent); - if (!dir_ent) + if (err != 0 || !dir_ent) break; if (strcmp(dir_ent, ".") == 0 || strcmp(dir_ent, "..") == 0) @@ -1119,11 +1131,11 @@ void list_files(AMDeviceRef device) { service_conn_t houseFd = start_house_arrest_service(device); - afc_connection afc_conn; - afc_connection* afc_conn_p = &afc_conn; - AFCConnectionOpen(houseFd, 0, &afc_conn_p); - - read_dir(houseFd, afc_conn_p, "/"); + afc_connection* afc_conn_p; + if (AFCConnectionOpen(houseFd, 0, &afc_conn_p) == 0) { + read_dir(houseFd, afc_conn_p, "/"); + AFCConnectionClose(afc_conn_p); + } } void upload_file(AMDeviceRef device) { From 4589cd5d05016ed89fc73bbb5c2519b6654a3708 Mon Sep 17 00:00:00 2001 From: Andy Polyakov Date: Mon, 6 Oct 2014 23:16:40 +0200 Subject: [PATCH 061/219] arrange callback in read_dir for future use Custom callback is called for every file or directory listed on device. This will be used for file download. --- ios-deploy.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 1c636bfc..6082c007 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1002,7 +1002,8 @@ CFStringRef get_bundle_id(CFURLRef app_url) return bundle_id; } -void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir) +void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir, + void(*callback)(afc_connection *conn,const char *dir,int file)) { char *dir_ent; @@ -1028,16 +1029,18 @@ void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir) AFCKeyValueClose(afc_dict_p); if (not_dir) { + if (callback) (*callback)(afc_conn_p, dir, not_dir); return; } afc_directory* afc_dir_p; afc_error_t err = AFCDirectoryOpen(afc_conn_p, dir, &afc_dir_p); - if (err != 0) - { + if (err != 0) { // Couldn't open dir - was probably a file return; + } else { + if (callback) (*callback)(afc_conn_p, dir, not_dir); } while(true) { @@ -1054,7 +1057,7 @@ void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir) if (dir_joined[strlen(dir)-1] != '/') strcat(dir_joined, "/"); strcat(dir_joined, dir_ent); - read_dir(afcFd, afc_conn_p, dir_joined); + read_dir(afcFd, afc_conn_p, dir_joined, callback); free(dir_joined); } @@ -1133,7 +1136,7 @@ void list_files(AMDeviceRef device) afc_connection* afc_conn_p; if (AFCConnectionOpen(houseFd, 0, &afc_conn_p) == 0) { - read_dir(houseFd, afc_conn_p, "/"); + read_dir(houseFd, afc_conn_p, "/", NULL); AFCConnectionClose(afc_conn_p); } } @@ -1147,7 +1150,7 @@ void upload_file(AMDeviceRef device) { afc_connection* afc_conn_p = &afc_conn; AFCConnectionOpen(houseFd, 0, &afc_conn_p); - // read_dir(houseFd, NULL, "/"); + // read_dir(houseFd, NULL, "/", NULL); if (!target_filename) { From c57f208422e5ae248b3d410ce5f869b42173fd7f Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 6 Oct 2014 22:09:39 -0700 Subject: [PATCH 062/219] Update version to 1.2.0 --- ios-deploy.c | 2 +- package.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index f120544c..c32f027c 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -16,7 +16,7 @@ #include #include "MobileDevice.h" -#define APP_VERSION "1.1.0" +#define APP_VERSION "1.2.0" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH diff --git a/package.json b/package.json index d81493af..6eb080fe 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "ios-deploy", - "version": "1.1.0", - "description": "launch iOS apps iOS devices from the command line (Xcode 5)", + "version": "1.2.0", + "description": "launch iOS apps iOS devices from the command line (Xcode 6)", "main": "ios-deploy", "scripts": { "preinstall": "make ios-deploy" From 9f0c8a85c65d3aab7afd4d3e69e3490e24e7d801 Mon Sep 17 00:00:00 2001 From: Andy Polyakov Date: Tue, 7 Oct 2014 09:23:34 +0200 Subject: [PATCH 063/219] Add download option. Unlike upload option, download pulls down whole tree. For this reason --to is expected to be directory path. --- ios-deploy.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 102 insertions(+), 3 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index c32f027c..e56606e9 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1017,7 +1017,7 @@ void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir, afc_dictionary* afc_dict_p; char *key, *val; - int not_dir; + int not_dir = 0; AFCFileInfoOpen(afc_conn_p, dir, &afc_dict_p); while((AFCKeyValueRead(afc_dict_p,&key,&val) == 0) && key && val) { @@ -1141,6 +1141,97 @@ void list_files(AMDeviceRef device) } } +void copy_file_callback(afc_connection* afc_conn_p, const char *name,int file) +{ + const char *local_name=name; + + if (*local_name=='/') local_name++; + + if (*local_name=='\0') return; + + if (file) { + afc_file_ref fref; + int err = AFCFileRefOpen(afc_conn_p,name,1,&fref); + + if (err) { + fprintf(stderr,"AFCFileRefOpen(\"%s\") failed: %d\n",name,err); + return; + } + + FILE *fp = fopen(local_name,"w"); + + if (fp==NULL) { + fprintf(stderr,"fopen(\"%s\",\"w\") failer: %s\n",local_name,strerror(errno)); + AFCFileRefClose(afc_conn_p,fref); + return; + } + + char buf[4096]; + size_t sz=sizeof(buf); + + while (AFCFileRefRead(afc_conn_p,fref,buf,&sz)==0 && sz) { + fwrite(buf,sz,1,fp); + sz = sizeof(buf); + } + + AFCFileRefClose(afc_conn_p,fref); + fclose(fp); + } else { + if (mkdir(local_name,0777) && errno!=EEXIST) + fprintf(stderr,"mkdir(\"%s\") failed: %s\n",local_name,strerror(errno)); + } +} + +void mkdirhier(char *path) +{ + char *slash; + struct stat buf; + + if (path[0]=='.' && path[1]=='/') path+=2; + + if ((slash = strrchr(path,'/'))) { + *slash = '\0'; + if (stat(path,&buf)==0) { + *slash = '/'; + return; + } + mkdirhier(path); + mkdir (path,0777); + *slash = '/'; + } + + return; +} + +void download_tree(AMDeviceRef device) +{ + service_conn_t houseFd = start_house_arrest_service(device); + afc_connection* afc_conn_p = NULL; + char *dirname = NULL; + + if (AFCConnectionOpen(houseFd, 0, &afc_conn_p) == 0) do { + + if (target_filename) { + dirname = strdup(target_filename); + mkdirhier(dirname); + if (mkdir(dirname,0777) && errno!=EEXIST) { + fprintf(stderr,"mkdir(\"%s\") failed: %s\n",dirname,strerror(errno)); + break; + } + if (chdir(dirname)) { + fprintf(stderr,"chdir(\"%s\") failed: %s\n",dirname,strerror(errno)); + break; + } + } + + read_dir(houseFd, afc_conn_p, "/", copy_file_callback); + + } while(0); + + if (dirname) free(dirname); + if (afc_conn_p) AFCConnectionClose(afc_conn_p); +} + void upload_file(AMDeviceRef device) { service_conn_t houseFd = start_house_arrest_service(device); @@ -1226,6 +1317,8 @@ void handle_device(AMDeviceRef device) { list_files(device); } else if (strcmp("upload", command) == 0) { upload_file(device); + } else if (strcmp("download", command) == 0) { + download_tree(device); } exit(0); } @@ -1379,7 +1472,8 @@ void usage(const char* app) { " -1, --bundle_id specify bundle id for list and upload\n" " -l, --list list files\n" " -o, --upload upload file\n" - " -2, --to use together with upload file. specify target for upload\n" + " -w, --download download app tree\n" + " -2, --to use together with up/download file/tree. specify target\n" " -V, --version print the executable version \n", app); } @@ -1409,12 +1503,13 @@ int main(int argc, char *argv[]) { { "list", no_argument, NULL, 'l' }, { "bundle_id", required_argument, NULL, '1'}, { "upload", required_argument, NULL, 'o'}, + { "download", no_argument, NULL, 'w'}, { "to", required_argument, NULL, '2'}, { NULL, 0, NULL, 0 }, }; char ch; - while ((ch = getopt_long(argc, argv, "VmcdvunlrILi:b:a:t:g:x:p:1:2:o:", longopts, NULL)) != -1) + while ((ch = getopt_long(argc, argv, "VmcdvunlrILiw:b:a:t:g:x:p:1:2:o:", longopts, NULL)) != -1) { switch (ch) { case 'm': @@ -1479,6 +1574,10 @@ int main(int argc, char *argv[]) { command_only = true; command = "list"; break; + case 'w': + command_only = true; + command = "download"; + break; default: usage(argv[0]); return exitcode_error; From 7742c5d532a3583fa51ff7bc03ff40196e3a2bc1 Mon Sep 17 00:00:00 2001 From: Andy Polyakov Date: Tue, 7 Oct 2014 11:23:33 +0200 Subject: [PATCH 064/219] Allow --list and --download to pick specific subdirectories. Note that in a way it introduces inconsistency with help message. This is because arguments to --list and --download are optional and has to be passed with '=', e.g. --list=/Documents. --- ios-deploy.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index e56606e9..1189753a 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -154,6 +154,7 @@ bool justlaunch = false; char *app_path = NULL; char *device_id = NULL; char *args = NULL; +char *list_root = NULL; int timeout = 0; int port = 12345; CFStringRef last_path = NULL; @@ -1136,7 +1137,7 @@ void list_files(AMDeviceRef device) afc_connection* afc_conn_p; if (AFCConnectionOpen(houseFd, 0, &afc_conn_p) == 0) { - read_dir(houseFd, afc_conn_p, "/", NULL); + read_dir(houseFd, afc_conn_p, list_root?list_root:"/", NULL); AFCConnectionClose(afc_conn_p); } } @@ -1224,7 +1225,7 @@ void download_tree(AMDeviceRef device) } } - read_dir(houseFd, afc_conn_p, "/", copy_file_callback); + read_dir(houseFd, afc_conn_p, list_root?list_root:"/", copy_file_callback); } while(0); @@ -1500,16 +1501,16 @@ int main(int argc, char *argv[]) { { "noinstall", no_argument, NULL, 'm' }, { "port", required_argument, NULL, 'p' }, { "uninstall", no_argument, NULL, 'r' }, - { "list", no_argument, NULL, 'l' }, + { "list", optional_argument, NULL, 'l' }, { "bundle_id", required_argument, NULL, '1'}, { "upload", required_argument, NULL, 'o'}, - { "download", no_argument, NULL, 'w'}, + { "download", optional_argument, NULL, 'w'}, { "to", required_argument, NULL, '2'}, { NULL, 0, NULL, 0 }, }; char ch; - while ((ch = getopt_long(argc, argv, "VmcdvunlrILiw:b:a:t:g:x:p:1:2:o:", longopts, NULL)) != -1) + while ((ch = getopt_long(argc, argv, "VmcdvunrILib:a:t:g:x:p:1:2:o:l::w::", longopts, NULL)) != -1) { switch (ch) { case 'm': @@ -1573,10 +1574,12 @@ int main(int argc, char *argv[]) { case 'l': command_only = true; command = "list"; + list_root = optarg; break; case 'w': command_only = true; command = "download"; + list_root = optarg; break; default: usage(argv[0]); From 63917d796b0d66c9145d3e82b33a094f0b17d736 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 7 Oct 2014 14:34:54 -0700 Subject: [PATCH 065/219] Added scripts for buildbox. --- resources/buildbox/build.sh | 3 +++ 1 file changed, 3 insertions(+) create mode 100755 resources/buildbox/build.sh diff --git a/resources/buildbox/build.sh b/resources/buildbox/build.sh new file mode 100755 index 00000000..aea6cbfa --- /dev/null +++ b/resources/buildbox/build.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +echo "$ make" +make \ No newline at end of file From 029d22ecef846c5da73b9bd9cc8a1cf4c2d52e75 Mon Sep 17 00:00:00 2001 From: senthil Date: Thu, 9 Oct 2014 14:29:15 -0400 Subject: [PATCH 066/219] added iPhone 6 --- ios-deploy.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index f1a52c99..4ff2c1d0 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -292,8 +292,6 @@ const CFStringRef get_device_hardware_name(const AMDeviceRef device) { CFStringRef model = AMDeviceCopyValue(device, 0, CFSTR("HardwareModel")); const char *hwmodel = CFStringGetCStringPtr(model, CFStringGetSystemEncoding()); - printf("-->Hardware model: %s\n", hwmodel); - if (hwmodel && !strcmp("M68AP", hwmodel)) return CFSTR("iPhone"); if (hwmodel && !strcmp("N45AP", hwmodel)) @@ -346,6 +344,8 @@ const CFStringRef get_device_hardware_name(const AMDeviceRef device) { return CFSTR("iPhone 5s (GSM)"); if (hwmodel && !strcmp("N53AP", hwmodel)) return CFSTR("iPhone 5s (Global/CDMA)"); + if (hwmodel && !strcmp("N61AP", hwmodel)) + return CFSTR("iPhone 6 (GSM)"); if (hwmodel && !strcmp("J1AP", hwmodel)) return CFSTR("iPad 3"); if (hwmodel && !strcmp("J2AP", hwmodel)) @@ -367,7 +367,8 @@ const CFStringRef get_device_hardware_name(const AMDeviceRef device) { if (hwmodel && !strcmp("J33IAP", hwmodel)) return CFSTR("Apple TV 3.1G"); - return CFSTR("Unknown Device"); + return CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), hwmodel); + //return CFSTR("Unknown Device"); } char * MYCFStringCopyUTF8String(CFStringRef aString) { @@ -393,28 +394,26 @@ CFStringRef get_device_full_name(const AMDeviceRef device) { device_name = NULL, model_name = NULL; - kern_return_t ret = AMDeviceConnect(device); - printf("-->AMDeviceConnect: %08x\n",ret); + AMDeviceConnect(device); device_name = AMDeviceCopyValue(device, 0, CFSTR("DeviceName")), model_name = get_device_hardware_name(device); - printf("-->[%s] %ld\n",CFStringGetCStringPtr(device_name, CFStringGetSystemEncoding()), CFStringGetLength(device_name)); - printf("-->[%s] %ld\n",CFStringGetCStringPtr(device_name, kCFStringEncodingUTF8), CFStringGetLength(device_name)); - printf("-->[%s] %ld\n",CFStringGetCStringPtr(model_name, CFStringGetSystemEncoding()), CFStringGetLength(model_name)); - printf("-->[%s] %ld\n",CFStringGetCStringPtr(device_udid, CFStringGetSystemEncoding()), CFStringGetLength(device_udid)); - - CFShowStr(device_name); - printf("-->[%s] bytes\n",MYCFStringCopyUTF8String(device_name)); + if (verbose) + { + char *devName = MYCFStringCopyUTF8String(device_name); + printf("Device Name:[%s]\n",devName); + CFShow(device_name); + printf("\n"); + free(devName); + } - if((device_name != NULL) && CFStringGetLength(device_name) > 0 && (model_name != NULL) && CFStringGetLength(model_name)>0) + if(device_name != NULL && model_name != NULL) { - printf("In if\n"); full_name = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ '%@' (%@)"), model_name, device_name, device_udid); } else { - printf("In else: %s\n",CFStringGetCStringPtr(device_udid, CFStringGetSystemEncoding())); full_name = CFStringCreateWithFormat(NULL, NULL, CFSTR("(%@ss)"), device_udid); } @@ -427,7 +426,6 @@ CFStringRef get_device_full_name(const AMDeviceRef device) { if(model_name != NULL) CFRelease(model_name); - printf("-->[%s]\n",CFStringGetCStringPtr(full_name, CFStringGetSystemEncoding())); return full_name; } From d86b0cad0de79c6a7debe0d6cd0b02f7a05ac053 Mon Sep 17 00:00:00 2001 From: senthil Date: Mon, 13 Oct 2014 16:59:19 -0400 Subject: [PATCH 067/219] Merged with phone-gap and fixed the hang --- MobileDevice.h | 6 +- README.md | 2 +- ios-deploy.c | 170 +++++++++++++++++++++++++++++++++++++++++-------- package.json | 4 +- 4 files changed, 149 insertions(+), 33 deletions(-) diff --git a/MobileDevice.h b/MobileDevice.h index e078a44c..d97eafb5 100644 --- a/MobileDevice.h +++ b/MobileDevice.h @@ -396,11 +396,11 @@ afc_error_t AFCFileRefOpen(afc_connection *conn, const char *path, afc_error_t AFCFileRefSeek(afc_connection *conn, afc_file_ref ref, unsigned long long offset1, unsigned long long offset2); afc_error_t AFCFileRefRead(afc_connection *conn, afc_file_ref ref, - void *buf, unsigned int *len); + void *buf, size_t *len); afc_error_t AFCFileRefSetFileSize(afc_connection *conn, afc_file_ref ref, unsigned long long offset); afc_error_t AFCFileRefWrite(afc_connection *conn, afc_file_ref ref, - const void *buf, unsigned int len); + const void *buf, size_t len); afc_error_t AFCFileRefClose(afc_connection *conn, afc_file_ref ref); afc_error_t AFCFileInfoOpen(afc_connection *conn, const char *path, struct @@ -493,4 +493,4 @@ typedef unsigned int (*t_performOperation)(struct am_restore_device *rdev, } #endif -#endif \ No newline at end of file +#endif diff --git a/README.md b/README.md index a8db9d13..bd44b492 100644 --- a/README.md +++ b/README.md @@ -48,4 +48,4 @@ Install and debug iPhone apps without using Xcode. Designed to work on unjailbro Device Ids are the UDIDs of the iOS devices. From the command line, you can list device ids [this way](http://javierhz.blogspot.com/2012/06/how-to-get-udid-of-iphone-using-shell.html): - system_profiler SPUSBDataType | sed -n -e '/iPad/,/Serial/p' -e '/iPhone/,/Serial/p' | grep "Serial Number:" | awk -F ": " '{print $2}' + system_profiler SPUSBDataType | sed -n -e '/iPod/,/Serial/p' | sed -n -e '/iPad/,/Serial/p' -e '/iPhone/,/Serial/p' | grep "Serial Number:" | awk -F ": " '{print $2}' diff --git a/ios-deploy.c b/ios-deploy.c index 4ff2c1d0..531a548d 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -16,7 +16,7 @@ #include #include "MobileDevice.h" -#define APP_VERSION "1.1.0" +#define APP_VERSION "1.2.0" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH @@ -47,7 +47,6 @@ const char* lldb_prep_interactive_cmds = "\ const char* lldb_prep_noninteractive_justlaunch_cmds = "\ run\n\ - detach\n\ safequit\n\ "; @@ -77,7 +76,7 @@ def connect_command(debugger, command, result, internal_dict):\n\ listener = lldb.target.GetDebugger().GetListener()\n\ listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged)\n\ events = []\n\ - state = lldb.eStateInvalid\n\ + state = (process.GetState() or lldb.eStateInvalid)\n\ while state != lldb.eStateConnected:\n\ event = lldb.SBEvent()\n\ if listener.WaitForEvent(1, event):\n\ @@ -154,6 +153,7 @@ bool justlaunch = false; char *app_path = NULL; char *device_id = NULL; char *args = NULL; +char *list_root = NULL; int timeout = 0; int port = 12345; CFStringRef last_path = NULL; @@ -395,7 +395,7 @@ CFStringRef get_device_full_name(const AMDeviceRef device) { model_name = NULL; AMDeviceConnect(device); - + device_name = AMDeviceCopyValue(device, 0, CFSTR("DeviceName")), model_name = get_device_hardware_name(device); @@ -684,7 +684,7 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { CFRelease(cf_args); } else { - CFStringFindAndReplace(cmds, CFSTR(" {args}"), CFSTR(""), range, 0); + CFStringFindAndReplace(cmds, CFSTR("{args}"), CFSTR(""), range, 0); } range.length = CFStringGetLength(cmds); @@ -784,12 +784,12 @@ server_callback (CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef add { int res; - //PRINT ("server: %s\n", CFDataGetBytePtr (data)); - + //printf("server: %s\n", CFDataGetBytePtr (data)); if (CFDataGetLength (data) == 0) { // FIXME: Close the socket //shutdown (CFSocketGetNative (lldb_socket), SHUT_RDWR); //close (CFSocketGetNative (lldb_socket)); + exit(exitcode_error); return; } res = write (CFSocketGetNative (lldb_socket), CFDataGetBytePtr (data), CFDataGetLength (data)); @@ -797,7 +797,7 @@ server_callback (CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef add void lldb_callback(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, const void *data, void *info) { - //PRINT ("lldb: %s\n", CFDataGetBytePtr (data)); + //printf ("lldb: %s\n", CFDataGetBytePtr (data)); if (CFDataGetLength (data) == 0) return; @@ -1037,7 +1037,8 @@ CFStringRef get_bundle_id(CFURLRef app_url) return bundle_id; } -void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir) +void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir, + void(*callback)(afc_connection *conn,const char *dir,int file)) { char *dir_ent; @@ -1049,24 +1050,38 @@ void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir) printf("%s\n", dir); - afc_dictionary afc_dict; - afc_dictionary* afc_dict_p = &afc_dict; + afc_dictionary* afc_dict_p; + char *key, *val; + int not_dir = 0; + AFCFileInfoOpen(afc_conn_p, dir, &afc_dict_p); - - afc_directory afc_dir; - afc_directory* afc_dir_p = &afc_dir; + while((AFCKeyValueRead(afc_dict_p,&key,&val) == 0) && key && val) { + if (strcmp(key,"st_ifmt")==0) { + not_dir = strcmp(val,"S_IFDIR"); + break; + } + } + AFCKeyValueClose(afc_dict_p); + + if (not_dir) { + if (callback) (*callback)(afc_conn_p, dir, not_dir); + return; + } + + afc_directory* afc_dir_p; afc_error_t err = AFCDirectoryOpen(afc_conn_p, dir, &afc_dir_p); - if (err != 0) - { + if (err != 0) { // Couldn't open dir - was probably a file return; + } else { + if (callback) (*callback)(afc_conn_p, dir, not_dir); } while(true) { err = AFCDirectoryRead(afc_conn_p, afc_dir_p, &dir_ent); - if (!dir_ent) + if (err != 0 || !dir_ent) break; if (strcmp(dir_ent, ".") == 0 || strcmp(dir_ent, "..") == 0) @@ -1077,7 +1092,7 @@ void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir) if (dir_joined[strlen(dir)-1] != '/') strcat(dir_joined, "/"); strcat(dir_joined, dir_ent); - read_dir(afcFd, afc_conn_p, dir_joined); + read_dir(afcFd, afc_conn_p, dir_joined, callback); free(dir_joined); } @@ -1154,11 +1169,102 @@ void list_files(AMDeviceRef device) { service_conn_t houseFd = start_house_arrest_service(device); - afc_connection afc_conn; - afc_connection* afc_conn_p = &afc_conn; - AFCConnectionOpen(houseFd, 0, &afc_conn_p); - - read_dir(houseFd, afc_conn_p, "/"); + afc_connection* afc_conn_p; + if (AFCConnectionOpen(houseFd, 0, &afc_conn_p) == 0) { + read_dir(houseFd, afc_conn_p, list_root?list_root:"/", NULL); + AFCConnectionClose(afc_conn_p); + } +} + +void copy_file_callback(afc_connection* afc_conn_p, const char *name,int file) +{ + const char *local_name=name; + + if (*local_name=='/') local_name++; + + if (*local_name=='\0') return; + + if (file) { + afc_file_ref fref; + int err = AFCFileRefOpen(afc_conn_p,name,1,&fref); + + if (err) { + fprintf(stderr,"AFCFileRefOpen(\"%s\") failed: %d\n",name,err); + return; + } + + FILE *fp = fopen(local_name,"w"); + + if (fp==NULL) { + fprintf(stderr,"fopen(\"%s\",\"w\") failer: %s\n",local_name,strerror(errno)); + AFCFileRefClose(afc_conn_p,fref); + return; + } + + char buf[4096]; + size_t sz=sizeof(buf); + + while (AFCFileRefRead(afc_conn_p,fref,buf,&sz)==0 && sz) { + fwrite(buf,sz,1,fp); + sz = sizeof(buf); + } + + AFCFileRefClose(afc_conn_p,fref); + fclose(fp); + } else { + if (mkdir(local_name,0777) && errno!=EEXIST) + fprintf(stderr,"mkdir(\"%s\") failed: %s\n",local_name,strerror(errno)); + } +} + +void mkdirhier(char *path) +{ + char *slash; + struct stat buf; + + if (path[0]=='.' && path[1]=='/') path+=2; + + if ((slash = strrchr(path,'/'))) { + *slash = '\0'; + if (stat(path,&buf)==0) { + *slash = '/'; + return; + } + mkdirhier(path); + mkdir (path,0777); + *slash = '/'; + } + + return; +} + +void download_tree(AMDeviceRef device) +{ + service_conn_t houseFd = start_house_arrest_service(device); + afc_connection* afc_conn_p = NULL; + char *dirname = NULL; + + if (AFCConnectionOpen(houseFd, 0, &afc_conn_p) == 0) do { + + if (target_filename) { + dirname = strdup(target_filename); + mkdirhier(dirname); + if (mkdir(dirname,0777) && errno!=EEXIST) { + fprintf(stderr,"mkdir(\"%s\") failed: %s\n",dirname,strerror(errno)); + break; + } + if (chdir(dirname)) { + fprintf(stderr,"chdir(\"%s\") failed: %s\n",dirname,strerror(errno)); + break; + } + } + + read_dir(houseFd, afc_conn_p, list_root?list_root:"/", copy_file_callback); + + } while(0); + + if (dirname) free(dirname); + if (afc_conn_p) AFCConnectionClose(afc_conn_p); } void upload_file(AMDeviceRef device) { @@ -1170,7 +1276,7 @@ void upload_file(AMDeviceRef device) { afc_connection* afc_conn_p = &afc_conn; AFCConnectionOpen(houseFd, 0, &afc_conn_p); - // read_dir(houseFd, NULL, "/"); + // read_dir(houseFd, NULL, "/", NULL); if (!target_filename) { @@ -1246,6 +1352,8 @@ void handle_device(AMDeviceRef device) { list_files(device); } else if (strcmp("upload", command) == 0) { upload_file(device); + } else if (strcmp("download", command) == 0) { + download_tree(device); } exit(0); } @@ -1399,7 +1507,8 @@ void usage(const char* app) { " -1, --bundle_id specify bundle id for list and upload\n" " -l, --list list files\n" " -o, --upload upload file\n" - " -2, --to use together with upload file. specify target for upload\n" + " -w, --download download app tree\n" + " -2, --to use together with up/download file/tree. specify target\n" " -V, --version print the executable version \n", app); } @@ -1426,15 +1535,16 @@ int main(int argc, char *argv[]) { { "noinstall", no_argument, NULL, 'm' }, { "port", required_argument, NULL, 'p' }, { "uninstall", no_argument, NULL, 'r' }, - { "list", no_argument, NULL, 'l' }, + { "list", optional_argument, NULL, 'l' }, { "bundle_id", required_argument, NULL, '1'}, { "upload", required_argument, NULL, 'o'}, + { "download", optional_argument, NULL, 'w'}, { "to", required_argument, NULL, '2'}, { NULL, 0, NULL, 0 }, }; char ch; - while ((ch = getopt_long(argc, argv, "VmcdvunlrILi:b:a:t:g:x:p:1:2:o:", longopts, NULL)) != -1) + while ((ch = getopt_long(argc, argv, "VmcdvunrILib:a:t:g:x:p:1:2:o:l::w::", longopts, NULL)) != -1) { switch (ch) { case 'm': @@ -1498,6 +1608,12 @@ int main(int argc, char *argv[]) { case 'l': command_only = true; command = "list"; + list_root = optarg; + break; + case 'w': + command_only = true; + command = "download"; + list_root = optarg; break; default: usage(argv[0]); diff --git a/package.json b/package.json index d81493af..6eb080fe 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "ios-deploy", - "version": "1.1.0", - "description": "launch iOS apps iOS devices from the command line (Xcode 5)", + "version": "1.2.0", + "description": "launch iOS apps iOS devices from the command line (Xcode 6)", "main": "ios-deploy", "scripts": { "preinstall": "make ios-deploy" From 54600a9eafda6e1b244dbdac05aa68678bff3fb5 Mon Sep 17 00:00:00 2001 From: senthil Date: Mon, 13 Oct 2014 17:20:52 -0400 Subject: [PATCH 068/219] Fixed two issues: 1. When the device is locked, the python source prints and exists. The server sees this as an empty packet. We are using this to exit out of the connection 2. When we use just launch, we need to do safequit and detach. Otherwise we hang for ever --- ios-deploy.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ios-deploy.c b/ios-deploy.c index 531a548d..5e99dee4 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -48,6 +48,7 @@ const char* lldb_prep_interactive_cmds = "\ const char* lldb_prep_noninteractive_justlaunch_cmds = "\ run\n\ safequit\n\ + detach\n\ "; const char* lldb_prep_noninteractive_cmds = "\ @@ -789,6 +790,8 @@ server_callback (CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef add // FIXME: Close the socket //shutdown (CFSocketGetNative (lldb_socket), SHUT_RDWR); //close (CFSocketGetNative (lldb_socket)); + CFSocketInvalidate(lldb_socket); + CFSocketInvalidate(server_socket); exit(exitcode_error); return; } From d51bb22f23f2d78ca5116d48e0726ea3ee9fed07 Mon Sep 17 00:00:00 2001 From: CSOscarTanner Date: Tue, 21 Oct 2014 14:33:33 -0200 Subject: [PATCH 069/219] Fixed problem with the parser of the value of the parameter -i. --- ios-deploy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index 1189753a..cbd43424 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1510,7 +1510,7 @@ int main(int argc, char *argv[]) { }; char ch; - while ((ch = getopt_long(argc, argv, "VmcdvunrILib:a:t:g:x:p:1:2:o:l::w::", longopts, NULL)) != -1) + while ((ch = getopt_long(argc, argv, "VmcdvunrILi:b:a:t:g:x:p:1:2:o:l::w::", longopts, NULL)) != -1) { switch (ch) { case 'm': From 4aa233d14704d8b16845e3fc2711b193b082ce23 Mon Sep 17 00:00:00 2001 From: Eddie Hillenbrand Date: Mon, 3 Nov 2014 16:09:36 -0800 Subject: [PATCH 070/219] Allow the symbols and the disk images to be in different DeviceSupport directories. --- ios-deploy.c | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 1189753a..121c36a4 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -458,22 +458,38 @@ CFStringRef copy_device_support_path(AMDeviceRef device) { return path; } -CFStringRef copy_developer_disk_image_path(CFStringRef deviceSupportPath) { - CFStringRef path = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@/%@"), deviceSupportPath, CFSTR("DeveloperDiskImage.dmg")); - if (!path_exists(path)) { - CFRelease(path); - path = NULL; - } +CFStringRef copy_developer_disk_image_path(AMDeviceRef device) { + CFStringRef version = NULL; + CFStringRef build = AMDeviceCopyValue(device, 0, CFSTR("BuildVersion")); + CFStringRef path = NULL; + CFMutableArrayRef version_parts = get_device_product_version_parts(device); - if (path == NULL) { - // Sometimes Latest seems to be missing in Xcode, in that case use find and hope for the best - path = copy_long_shot_disk_image_path(); - if (CFStringGetLength(path) < 5) { - CFRelease(path); - path = NULL; + while (CFArrayGetCount(version_parts) > 0) { + version = CFStringCreateByCombiningStrings(NULL, version_parts, CFSTR(".")); + if (path == NULL) { + path = copy_xcode_path_for(CFSTR("iOS DeviceSupport"), CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ (%@)/DeveloperDiskImage.dmg"), version, build)); + } + if (path == NULL) { + path = copy_xcode_path_for(CFSTR("Platforms/iPhoneOS.platform/DeviceSupport"), CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ (%@)/DeveloperDiskImage.dmg"), version, build)); + } + if (path == NULL) { + path = copy_xcode_path_for(CFSTR("Platforms/iPhoneOS.platform/DeviceSupport"), CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ (*)/DeveloperDiskImage.dmg"), version)); + } + if (path == NULL) { + path = copy_xcode_path_for(CFSTR("Platforms/iPhoneOS.platform/DeviceSupport"), CFStringCreateWithFormat(NULL, NULL, CFSTR("%@/DeveloperDiskImage.dmg"), version)); + } + if (path == NULL) { + path = copy_xcode_path_for(CFSTR("Platforms/iPhoneOS.platform/DeviceSupport/Latest"), CFSTR("DeveloperDiskImage.dmg")); + } + CFRelease(version); + if (path != NULL) { + break; } + CFArrayRemoveValueAtIndex(version_parts, CFArrayGetCount(version_parts) - 1); } + CFRelease(version_parts); + CFRelease(build); if (path == NULL) { printf("[ !! ] Unable to locate DeveloperDiskImage.dmg.\n[ !! ] This probably means you don't have Xcode installed, you will need to launch the app manually and logging output will not be shown!\n"); @@ -497,7 +513,7 @@ void mount_callback(CFDictionaryRef dict, int arg) { void mount_developer_image(AMDeviceRef device) { CFStringRef ds_path = copy_device_support_path(device); - CFStringRef image_path = copy_developer_disk_image_path(ds_path); + CFStringRef image_path = copy_developer_disk_image_path(device); CFStringRef sig_path = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@.signature"), image_path); if (verbose) { From 049a89e87308fba3664b129eaf85ba02f1ebef22 Mon Sep 17 00:00:00 2001 From: Eddie Hillenbrand Date: Tue, 4 Nov 2014 12:31:39 -0800 Subject: [PATCH 071/219] Fix for mismatched build numbers. --- ios-deploy.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 121c36a4..efa0b4bd 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -187,10 +187,20 @@ Boolean path_exists(CFTypeRef path) { CFStringRef find_path(CFStringRef rootPath, CFStringRef namePattern, CFStringRef expression) { FILE *fpipe = NULL; CFStringRef quotedRootPath = rootPath; + CFStringRef cf_command; + CFRange slashLocation; + if (CFStringGetCharacterAtIndex(rootPath, 0) != '`') { quotedRootPath = CFStringCreateWithFormat(NULL, NULL, CFSTR("'%@'"), rootPath); } - CFStringRef cf_command = CFStringCreateWithFormat(NULL, NULL, CFSTR("find %@ -name '%@' %@ 2>/dev/null | sort | tail -n 1"), quotedRootPath, namePattern, expression); + + slashLocation = CFStringFind(namePattern, CFSTR("/"), 0); + if (slashLocation.location == kCFNotFound) { + cf_command = CFStringCreateWithFormat(NULL, NULL, CFSTR("find %@ -name '%@' %@ 2>/dev/null | sort | tail -n 1"), quotedRootPath, namePattern, expression); + } else { + cf_command = CFStringCreateWithFormat(NULL, NULL, CFSTR("find %@ -path '%@' %@ 2>/dev/null | sort | tail -n 1"), quotedRootPath, namePattern, expression); + } + if (quotedRootPath != rootPath) { CFRelease(quotedRootPath); } @@ -255,6 +265,7 @@ CFStringRef copy_xcode_path_for(CFStringRef subPath, CFStringRef search) { CFStringRef path; bool found = false; const char* home = get_home(); + CFRange slashLocation; // Try using xcode-select --print-path @@ -264,7 +275,12 @@ CFStringRef copy_xcode_path_for(CFStringRef subPath, CFStringRef search) { } // Try find `xcode-select --print-path` with search as a name pattern if (!found) { - path = find_path(CFStringCreateWithFormat(NULL, NULL, CFSTR("%@/%@"), xcodeDevPath, subPath), search, CFSTR("-maxdepth 1")); + slashLocation = CFStringFind(search, CFSTR("/"), 0); + if (slashLocation.location == kCFNotFound) { + path = find_path(CFStringCreateWithFormat(NULL, NULL, CFSTR("%@/%@"), xcodeDevPath, subPath), search, CFSTR("-maxdepth 1")); + } else { + path = find_path(CFStringCreateWithFormat(NULL, NULL, CFSTR("%@/%@"), xcodeDevPath, subPath), search, CFSTR("")); + } found = CFStringGetLength(path) > 0 && path_exists(path); } // If not look in the default xcode location (xcode-select is sometimes wrong) @@ -473,7 +489,7 @@ CFStringRef copy_developer_disk_image_path(AMDeviceRef device) { path = copy_xcode_path_for(CFSTR("Platforms/iPhoneOS.platform/DeviceSupport"), CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ (%@)/DeveloperDiskImage.dmg"), version, build)); } if (path == NULL) { - path = copy_xcode_path_for(CFSTR("Platforms/iPhoneOS.platform/DeviceSupport"), CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ (*)/DeveloperDiskImage.dmg"), version)); + path = copy_xcode_path_for(CFSTR("Platforms/iPhoneOS.platform/DeviceSupport"), CFStringCreateWithFormat(NULL, NULL, CFSTR("*/%@ (*)/DeveloperDiskImage.dmg"), version)); } if (path == NULL) { path = copy_xcode_path_for(CFSTR("Platforms/iPhoneOS.platform/DeviceSupport"), CFStringCreateWithFormat(NULL, NULL, CFSTR("%@/DeveloperDiskImage.dmg"), version)); From b796b70e29510f2f6172e6bbe7a417f6d6236685 Mon Sep 17 00:00:00 2001 From: senthil Date: Fri, 7 Nov 2014 18:43:02 -0500 Subject: [PATCH 072/219] updated the version --- ios-deploy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index e1e34c44..768621f0 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -16,7 +16,7 @@ #include #include "MobileDevice.h" -#define APP_VERSION "1.2.0" +#define APP_VERSION "1.2.2" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH From b4f91912ee8d01e2544f5846a4f46eae23351e51 Mon Sep 17 00:00:00 2001 From: senthil Date: Tue, 11 Nov 2014 20:15:39 -0500 Subject: [PATCH 073/219] fixed the lauch using python --- ios-deploy.c | 242 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 211 insertions(+), 31 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 768621f0..a1c25944 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -19,7 +19,6 @@ #define APP_VERSION "1.2.2" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH - /* * Startup script passed to lldb. * To see how xcode interacts with lldb, put this into .lldbinit: @@ -102,7 +101,19 @@ def run_command(debugger, command, result, internal_dict):\n\ print(str(error))\n\ \n\ def safequit_command(debugger, command, result, internal_dict):\n\ - sys.exit(0);\n\ + process = lldb.target.process\n\ + listener = debugger.GetListener()\n\ + listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR)\n\ + event = lldb.SBEvent()\n\ + while True:\n\ + if listener.WaitForEvent(1, event):\n\ + state = process.GetStateFromEvent(event)\n\ + else:\n\ + state = lldb.eStateInvalid\n\ + print('\\nin process\\n')\n\ + print(state)\n\ + process.Detach()\n\ + sys.exit(0)\n\ \n\ def autoexit_command(debugger, command, result, internal_dict):\n\ process = lldb.target.process\n\ @@ -972,42 +983,46 @@ void setup_dummy_pipe_on_stdin(int pfd[2]) { perror("dup2 failed"); } -void launch_debugger(AMDeviceRef device, CFURLRef url) { +void setup_lldb(AMDeviceRef device, CFURLRef url) { CFStringRef device_full_name = get_device_full_name(device), - device_interface_name = get_device_interface_name(device); - + device_interface_name = get_device_interface_name(device); + AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); assert(AMDeviceValidatePairing(device) == 0); assert(AMDeviceStartSession(device) == 0); - + printf("------ Debug phase ------\n"); - + if(AMDeviceGetInterfaceType(device) == 2) { printf("Cannot debug %s over %s.\n", CFStringGetCStringPtr(device_full_name, CFStringGetSystemEncoding()), CFStringGetCStringPtr(device_interface_name, CFStringGetSystemEncoding())); exit(0); } - + printf("Starting debug of %s connected through %s...\n", CFStringGetCStringPtr(device_full_name, CFStringGetSystemEncoding()), CFStringGetCStringPtr(device_interface_name, CFStringGetSystemEncoding())); - + mount_developer_image(device); // put debugserver on the device start_remote_debug_server(device); // start debugserver write_lldb_prep_cmds(device, url); // dump the necessary lldb commands into a file - + CFRelease(url); - + printf("[100%%] Connecting to remote debug server\n"); printf("-------------------------\n"); - + setpgid(getpid(), 0); signal(SIGHUP, killed); signal(SIGINT, killed); signal(SIGTERM, killed); // Need this before fork to avoid race conditions. For child process we remove this right after fork. signal(SIGLLDB, lldb_finished_handler); - + parent = getpid(); +} + +void launch_debugger(AMDeviceRef device, CFURLRef url) { + setup_lldb(device, url); int pid = fork(); if (pid == 0) { signal(SIGHUP, SIG_DFL); @@ -1015,19 +1030,16 @@ void launch_debugger(AMDeviceRef device, CFURLRef url) { child = getpid(); int pfd[2] = {-1, -1}; - - if (!justlaunch) - { - if (isatty(STDIN_FILENO) && !justlaunch) - // If we are running on a terminal, then we need to bring process to foreground for input - // to work correctly on lldb's end. - bring_process_to_foreground(); - else - // If lldb is running in a non terminal environment, then it freaks out spamming "^D" and - // "quit". It seems this is caused by read() on stdin returning EOF in lldb. To hack around - // this we setup a dummy pipe on stdin, so read() would block expecting "user's" input. - setup_dummy_pipe_on_stdin(pfd); - } + if (isatty(STDIN_FILENO)) + // If we are running on a terminal, then we need to bring process to foreground for input + // to work correctly on lldb's end. + bring_process_to_foreground(); + else + // If lldb is running in a non terminal environment, then it freaks out spamming "^D" and + // "quit". It seems this is caused by read() on stdin returning EOF in lldb. To hack around + // this we setup a dummy pipe on stdin, so read() would block expecting "user's" input. + setup_dummy_pipe_on_stdin(pfd); + char lldb_shell[400]; sprintf(lldb_shell, LLDB_SHELL); if(device_id != NULL) @@ -1039,22 +1051,186 @@ void launch_debugger(AMDeviceRef device, CFURLRef url) { close(pfd[0]); close(pfd[1]); + // Notify parent we're exiting - printf("LLDB: Notifying parent\n"); kill(parent, SIGLLDB); // Pass lldb exit code _exit(WEXITSTATUS(status)); } else if (pid > 0) { child = pid; - if (justlaunch) + } else { + perror("fork failed"); + exit(exitcode_error); + } +} + +#define USE_SYSTEM 1 +void launch_debugger_and_exit(AMDeviceRef device, CFURLRef url) { + setup_lldb(device,url); +#ifdef USE_SYSTEM +#define PARENT_READ pfd[0] +#define CHILD_WRITE pfd[1] +#define CHILD_READ pfd[0] +#define PARENT_WRITE pfd[1] + + int pfd[2] = {-1, -1}; + if (pipe(pfd) == -1) + perror("Pipe failed"); + int pid = fork(); + if (pid == 0) { + signal(SIGHUP, SIG_DFL); + signal(SIGLLDB, SIG_DFL); + child = getpid(); + + //close(pfd[1]); + if (dup2(pfd[0],STDIN_FILENO) == -1) + perror("dup2 failed"); + + char lldb_shell[400]; + sprintf(lldb_shell, LLDB_SHELL); + if(device_id != NULL) + strcat(lldb_shell, device_id); + + int status = system(lldb_shell); // launch lldb + if (status == -1) + perror("failed launching lldb"); + printf("Done launching\n"); + + close(pfd[0]); + + // Notify parent we're exiting + kill(parent, SIGLLDB); + // Pass lldb exit code + _exit(WEXITSTATUS(status)); + } else if (pid > 0) { + child = pid; + //char ch; + //while(read(pfd[1],&ch,1)) + // printf("[%c]",ch); + } else { + perror("fork failed"); + exit(exitcode_error); + } +#endif +#ifdef USE_EXEC +#define PARENT_READ pfd[0] +#define CHILD_WRITE pfd[1] +#define CHILD_READ pfd[0] +#define PARENT_WRITE pfd[1] + + int pfd[2] = {-1, -1}; + if (pipe(pfd) == -1) + perror("Pipe failed"); + int pid = fork(); + if (pid == 0) { + signal(SIGHUP, SIG_DFL); + signal(SIGLLDB, SIG_DFL); + child = getpid(); + + if (dup2(pfd[0],STDIN_FILENO) == -1) + perror("dup2 failed"); + if (dup2(pfd[1],STDOUT_FILENO) == -1) + perror("dup2 failed for out"); + + char lldb_shell[400]; + sprintf(lldb_shell, PREP_CMDS_PATH); + if(device_id != NULL) + strcat(lldb_shell, device_id); + + char *path[4]; + path[0] = "lldb"; + path[1] = "-s"; + path[2] = lldb_shell; + path[3] = NULL; + +/* path[0] = "echo"; + path[1] = "hello"; + path[2] = NULL;*/ + int status = execvp(path[0],path); + if (status == -1) + perror("failed launching lldb"); + + close(pfd[0]); + close(pfd[1]); + + // Notify parent we're exiting + kill(parent, SIGLLDB); + // Pass lldb exit code + _exit(WEXITSTATUS(status)); + } else if (pid > 0) { + child = pid; + char ch; + bool eof = false; + while (!eof) { - printf("writing detach\n"); - write(0,"detach\n",7); + int ret = read(pfd[0],&ch,1); + printf("%c",ch); } + printf("Done"); + } else { + perror("fork failed"); + exit(exitcode_error); + } +#endif +#ifdef USE_PIPE + printf("--------USING PIPE------\n"); + char lldb_shell[400]; + sprintf(lldb_shell, LLDB_SHELL); + if(device_id != NULL) + strcat(lldb_shell, device_id); + FILE *lldb = popen(lldb_shell, "rw"); + if (lldb == NULL) + perror("failed popen"); + while (!feof(lldb)) + { + char buffer[128]; + char *ret = fgets(buffer, 128, lldb); + if (!ret) + break; + printf("%s",ret); + } +#endif +#ifdef SAMEASOTHER + int pid = fork(); + if (pid == 0) { + signal(SIGHUP, SIG_DFL); + signal(SIGLLDB, SIG_DFL); + child = getpid(); + + int pfd[2] = {-1, -1}; + if (isatty(STDIN_FILENO)) + // If we are running on a terminal, then we need to bring process to foreground for input + // to work correctly on lldb's end. + bring_process_to_foreground(); + else + // If lldb is running in a non terminal environment, then it freaks out spamming "^D" and + // "quit". It seems this is caused by read() on stdin returning EOF in lldb. To hack around + // this we setup a dummy pipe on stdin, so read() would block expecting "user's" input. + setup_dummy_pipe_on_stdin(pfd); + + char lldb_shell[400]; + sprintf(lldb_shell, LLDB_SHELL); + if(device_id != NULL) + strcat(lldb_shell, device_id); + + int status = system(lldb_shell); // launch lldb + if (status == -1) + perror("failed launching lldb"); + + close(pfd[0]); + close(pfd[1]); + + // Notify parent we're exiting + kill(parent, SIGLLDB); + // Pass lldb exit code + _exit(WEXITSTATUS(status)); + } else if (pid > 0) { + child = pid; } else { perror("fork failed"); exit(exitcode_error); } +#endif } CFStringRef get_bundle_id(CFURLRef app_url) @@ -1093,6 +1269,7 @@ CFStringRef get_bundle_id(CFURLRef app_url) return bundle_id; } + void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir, void(*callback)(afc_connection *conn,const char *dir,int file)) { @@ -1511,7 +1688,10 @@ void handle_device(AMDeviceRef device) { if (!debug) exit(0); // no debug phase - launch_debugger(device, url); + if (justlaunch) + launch_debugger_and_exit(device, url); + else + launch_debugger(device, url); } void device_callback(struct am_device_notification_callback_info *info, void *arg) { From 06187e348a3b85b4122c62afe8c08c1f00f174d1 Mon Sep 17 00:00:00 2001 From: senthil Date: Wed, 12 Nov 2014 12:04:47 -0500 Subject: [PATCH 074/219] updated the version to 1.3.0 --- ios-deploy.c | 154 ++++++--------------------------------------------- 1 file changed, 16 insertions(+), 138 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index a1c25944..eaba69ee 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -16,7 +16,7 @@ #include #include "MobileDevice.h" -#define APP_VERSION "1.2.2" +#define APP_VERSION "1.3.0" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH /* @@ -110,8 +110,6 @@ def safequit_command(debugger, command, result, internal_dict):\n\ state = process.GetStateFromEvent(event)\n\ else:\n\ state = lldb.eStateInvalid\n\ - print('\\nin process\\n')\n\ - print(state)\n\ process.Detach()\n\ sys.exit(0)\n\ \n\ @@ -833,18 +831,30 @@ CFSocketRef lldb_socket; CFWriteStreamRef serverWriteStream = NULL; CFWriteStreamRef lldbWriteStream = NULL; +int kill_ptree(pid_t root, int signum); void server_callback (CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, const void *data, void *info) { int res; - //printf("server: %s\n", CFDataGetBytePtr (data)); if (CFDataGetLength (data) == 0) { // FIXME: Close the socket //shutdown (CFSocketGetNative (lldb_socket), SHUT_RDWR); //close (CFSocketGetNative (lldb_socket)); CFSocketInvalidate(lldb_socket); CFSocketInvalidate(server_socket); + int mypid = getpid(); + assert((child != 0) && (child != mypid)); //child should not be here + if ((parent != 0) && (parent == mypid) && (child != 0)) + { + //we shouldn't be here because it is the parent + //just in case. + if (verbose) + { + printf("Got an empty packet hence killing child (%d) tree\n", child); + } + kill_ptree(child, SIGHUP); + } exit(exitcode_error); return; } @@ -965,7 +975,6 @@ void lldb_finished_handler(int signum) } void bring_process_to_foreground() { - printf("Bringing process to foreground\n"); if (setpgid(0, 0) == -1) perror("setpgid failed"); @@ -976,7 +985,6 @@ void bring_process_to_foreground() { } void setup_dummy_pipe_on_stdin(int pfd[2]) { - printf("Setting up dummy pipe\n"); if (pipe(pfd) == -1) perror("pipe failed"); if (dup2(pfd[0], STDIN_FILENO) == -1) @@ -1064,15 +1072,8 @@ void launch_debugger(AMDeviceRef device, CFURLRef url) { } } -#define USE_SYSTEM 1 void launch_debugger_and_exit(AMDeviceRef device, CFURLRef url) { setup_lldb(device,url); -#ifdef USE_SYSTEM -#define PARENT_READ pfd[0] -#define CHILD_WRITE pfd[1] -#define CHILD_READ pfd[0] -#define PARENT_WRITE pfd[1] - int pfd[2] = {-1, -1}; if (pipe(pfd) == -1) perror("Pipe failed"); @@ -1082,7 +1083,6 @@ void launch_debugger_and_exit(AMDeviceRef device, CFURLRef url) { signal(SIGLLDB, SIG_DFL); child = getpid(); - //close(pfd[1]); if (dup2(pfd[0],STDIN_FILENO) == -1) perror("dup2 failed"); @@ -1091,134 +1091,11 @@ void launch_debugger_and_exit(AMDeviceRef device, CFURLRef url) { if(device_id != NULL) strcat(lldb_shell, device_id); - int status = system(lldb_shell); // launch lldb - if (status == -1) - perror("failed launching lldb"); - printf("Done launching\n"); - - close(pfd[0]); - - // Notify parent we're exiting - kill(parent, SIGLLDB); - // Pass lldb exit code - _exit(WEXITSTATUS(status)); - } else if (pid > 0) { - child = pid; - //char ch; - //while(read(pfd[1],&ch,1)) - // printf("[%c]",ch); - } else { - perror("fork failed"); - exit(exitcode_error); - } -#endif -#ifdef USE_EXEC -#define PARENT_READ pfd[0] -#define CHILD_WRITE pfd[1] -#define CHILD_READ pfd[0] -#define PARENT_WRITE pfd[1] - - int pfd[2] = {-1, -1}; - if (pipe(pfd) == -1) - perror("Pipe failed"); - int pid = fork(); - if (pid == 0) { - signal(SIGHUP, SIG_DFL); - signal(SIGLLDB, SIG_DFL); - child = getpid(); - - if (dup2(pfd[0],STDIN_FILENO) == -1) - perror("dup2 failed"); - if (dup2(pfd[1],STDOUT_FILENO) == -1) - perror("dup2 failed for out"); - - char lldb_shell[400]; - sprintf(lldb_shell, PREP_CMDS_PATH); - if(device_id != NULL) - strcat(lldb_shell, device_id); - - char *path[4]; - path[0] = "lldb"; - path[1] = "-s"; - path[2] = lldb_shell; - path[3] = NULL; - -/* path[0] = "echo"; - path[1] = "hello"; - path[2] = NULL;*/ - int status = execvp(path[0],path); - if (status == -1) - perror("failed launching lldb"); - - close(pfd[0]); - close(pfd[1]); - - // Notify parent we're exiting - kill(parent, SIGLLDB); - // Pass lldb exit code - _exit(WEXITSTATUS(status)); - } else if (pid > 0) { - child = pid; - char ch; - bool eof = false; - while (!eof) - { - int ret = read(pfd[0],&ch,1); - printf("%c",ch); - } - printf("Done"); - } else { - perror("fork failed"); - exit(exitcode_error); - } -#endif -#ifdef USE_PIPE - printf("--------USING PIPE------\n"); - char lldb_shell[400]; - sprintf(lldb_shell, LLDB_SHELL); - if(device_id != NULL) - strcat(lldb_shell, device_id); - FILE *lldb = popen(lldb_shell, "rw"); - if (lldb == NULL) - perror("failed popen"); - while (!feof(lldb)) - { - char buffer[128]; - char *ret = fgets(buffer, 128, lldb); - if (!ret) - break; - printf("%s",ret); - } -#endif -#ifdef SAMEASOTHER - int pid = fork(); - if (pid == 0) { - signal(SIGHUP, SIG_DFL); - signal(SIGLLDB, SIG_DFL); - child = getpid(); - - int pfd[2] = {-1, -1}; - if (isatty(STDIN_FILENO)) - // If we are running on a terminal, then we need to bring process to foreground for input - // to work correctly on lldb's end. - bring_process_to_foreground(); - else - // If lldb is running in a non terminal environment, then it freaks out spamming "^D" and - // "quit". It seems this is caused by read() on stdin returning EOF in lldb. To hack around - // this we setup a dummy pipe on stdin, so read() would block expecting "user's" input. - setup_dummy_pipe_on_stdin(pfd); - - char lldb_shell[400]; - sprintf(lldb_shell, LLDB_SHELL); - if(device_id != NULL) - strcat(lldb_shell, device_id); - int status = system(lldb_shell); // launch lldb if (status == -1) perror("failed launching lldb"); close(pfd[0]); - close(pfd[1]); // Notify parent we're exiting kill(parent, SIGLLDB); @@ -1226,11 +1103,12 @@ void launch_debugger_and_exit(AMDeviceRef device, CFURLRef url) { _exit(WEXITSTATUS(status)); } else if (pid > 0) { child = pid; + if (verbose) + printf("Waiting for child [Child: %d][Parent: %d]\n", child, parent); } else { perror("fork failed"); exit(exitcode_error); } -#endif } CFStringRef get_bundle_id(CFURLRef app_url) From 72caad4526addb756c9d1f57787d6a144b940f78 Mon Sep 17 00:00:00 2001 From: senthil Date: Wed, 12 Nov 2014 16:15:53 -0500 Subject: [PATCH 075/219] Allow timeout for download and run --- ios-deploy.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index eaba69ee..f5252bb4 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1602,7 +1602,22 @@ void timeout_callback(CFRunLoopTimerRef timer, void *info) { } else { - printf("[....] No more devices found.\n"); + if (!debug) + printf("[....] No more devices found.\n"); + else + { + int mypid = getpid(); + if ((parent != 0) && (parent == mypid) && (child != 0)) + { + //we shouldn't be here because it is the parent + //just in case. + if (verbose) + { + printf("Timeout. Killing child (%d) tree\n", child); + } + kill_ptree(child, SIGHUP); + } + } exit(0); } } From dbe381112a505b32f0731614c4fd5fb87af1d4e3 Mon Sep 17 00:00:00 2001 From: senthil Date: Wed, 12 Nov 2014 16:23:20 -0500 Subject: [PATCH 076/219] Removed the wrong comment --- ios-deploy.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index f5252bb4..4540c033 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -847,8 +847,6 @@ server_callback (CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef add assert((child != 0) && (child != mypid)); //child should not be here if ((parent != 0) && (parent == mypid) && (child != 0)) { - //we shouldn't be here because it is the parent - //just in case. if (verbose) { printf("Got an empty packet hence killing child (%d) tree\n", child); @@ -1609,8 +1607,6 @@ void timeout_callback(CFRunLoopTimerRef timer, void *info) { int mypid = getpid(); if ((parent != 0) && (parent == mypid) && (child != 0)) { - //we shouldn't be here because it is the parent - //just in case. if (verbose) { printf("Timeout. Killing child (%d) tree\n", child); From 6f662ae450ed85784643ac1f1d31e114cde949ef Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Thu, 13 Nov 2014 17:33:44 -0800 Subject: [PATCH 077/219] Fixes phonegap/ios-deploy#37 - AMDeviceValidatePairing fails when uninstalling --- ios-deploy.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 4540c033..e78d674e 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1490,13 +1490,15 @@ void handle_device(AMDeviceRef device) { assert(AMDeviceIsPaired(device)); assert(AMDeviceValidatePairing(device) == 0); assert(AMDeviceStartSession(device) == 0); - - assert(AMDeviceSecureUninstallApplication(0, device, bundle_id, 0, NULL, 0) == 0); - + + int code = AMDeviceSecureUninstallApplication(0, device, bundle_id, 0, NULL, 0); + if (code == 0) { + printf("[ OK ] Uninstalled package with bundle id %s\n", CFStringGetCStringPtr(bundle_id, CFStringGetSystemEncoding())); + } else { + printf("[ ERROR ] Could not uninstall package with bundle id %s\n", CFStringGetCStringPtr(bundle_id, CFStringGetSystemEncoding())); + } assert(AMDeviceStopSession(device) == 0); assert(AMDeviceDisconnect(device) == 0); - - printf("[ OK ] Uninstalled package with bundle id %s\n", CFStringGetCStringPtr(bundle_id, CFStringGetSystemEncoding())); } } From 707565701559d301b9336c45b555dcb481089f21 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Thu, 13 Nov 2014 22:57:58 -0800 Subject: [PATCH 078/219] Fixes phonegap/ios-deploy#74 - SIGSEGV-ed while listing the sandbox of an application on iOS8 --- ios-deploy.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index e78d674e..342fb151 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1163,7 +1163,12 @@ void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir, char *key, *val; int not_dir = 0; - AFCFileInfoOpen(afc_conn_p, dir, &afc_dict_p); + unsigned int code = AFCFileInfoOpen(afc_conn_p, dir, &afc_dict_p); + if (code != 0) { + // there was a problem reading or opening the file to get info on it, abort + return; + } + while((AFCKeyValueRead(afc_dict_p,&key,&val) == 0) && key && val) { if (strcmp(key,"st_ifmt")==0) { not_dir = strcmp(val,"S_IFDIR"); From 5bfc25376a0e0dac22cd0640434d7c52615cdb2b Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Thu, 13 Nov 2014 22:58:18 -0800 Subject: [PATCH 079/219] Update package.json version to 1.3.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6eb080fe..7db68e31 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ios-deploy", - "version": "1.2.0", + "version": "1.3.0", "description": "launch iOS apps iOS devices from the command line (Xcode 6)", "main": "ios-deploy", "scripts": { From 63303ea4b0004379288c80a288f824d84ec45362 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Thu, 13 Nov 2014 23:24:27 -0800 Subject: [PATCH 080/219] Removed unused gdbargs and gdbexec options. --- README.md | 43 ++++++++++++++++++++++--------------------- ios-deploy.c | 3 --- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index bd44b492..f936c644 100644 --- a/README.md +++ b/README.md @@ -11,27 +11,28 @@ Install and debug iPhone apps without using Xcode. Designed to work on unjailbro ## Usage Usage: ./ios-deploy [OPTION]... - -d, --debug launch the app in GDB after installation - -i, --id the id of the device to connect to - -c, --detect only detect if the device is connected - -b, --bundle the path to the app bundle to be installed - -a, --args command line arguments to pass to the app when launching it - -t, --timeout number of seconds to wait for a device to be connected - -u, --unbuffered don't buffer stdout - -g, --gdbargs extra arguments to pass to GDB when starting the debugger - -x, --gdbexec GDB commands script file - -n, --nostart do not start the app when debugging - -I, --noninteractive start in non interactive mode (quit when app crashes or exits) - -L, --justlaunch just launch the app and exit lldb - -v, --verbose enable verbose output - -m, --noinstall directly start debugging without app install (-d not required) - -p, --port port used for device, default: 12345 - -r, --uninstall uninstall the app before install (do not use with -m; app cache and data are cleared) - -1, --bundle_id specify bundle id for list and upload - -l, --list list files - -o, --upload upload file - -2, --to use together with upload file. specify target for upload - -V, --version print the executable version + -d, --debug launch the app in GDB after installation\n" + -i, --id the id of the device to connect to\n" + -c, --detect only detect if the device is connected\n" + -b, --bundle the path to the app bundle to be installed\n" + -a, --args command line arguments to pass to the app when launching it\n" + -t, --timeout number of seconds to wait for a device to be connected\n" + -u, --unbuffered don't buffer stdout\n" + -g, --gdbargs extra arguments to pass to GDB when starting the debugger\n" + -x, --gdbexec GDB commands script file\n" + -n, --nostart do not start the app when debugging\n" + -I, --noninteractive start in non interactive mode (quit when app crashes or exits)\n" + -L, --justlaunch just launch the app and exit lldb\n" + -v, --verbose enable verbose output\n" + -m, --noinstall directly start debugging without app install (-d not required)\n" + -p, --port port used for device, default: 12345 \n" + -r, --uninstall uninstall the app before install (do not use with -m; app cache and data are cleared) \n" + -1, --bundle_id specify bundle id for list and upload\n" + -l, --list list files\n" + -o, --upload upload file\n" + -w, --download download app tree\n" + -2, --to use together with up/download file/tree. specify target\n" + -V, --version print the executable version \n", ## Demo diff --git a/ios-deploy.c b/ios-deploy.c index 342fb151..c8d22cb9 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1635,8 +1635,6 @@ void usage(const char* app) { " -a, --args command line arguments to pass to the app when launching it\n" " -t, --timeout number of seconds to wait for a device to be connected\n" " -u, --unbuffered don't buffer stdout\n" - " -g, --gdbargs extra arguments to pass to GDB when starting the debugger\n" - " -x, --gdbexec GDB commands script file\n" " -n, --nostart do not start the app when debugging\n" " -I, --noninteractive start in non interactive mode (quit when app crashes or exits)\n" " -L, --justlaunch just launch the app and exit lldb\n" @@ -1665,7 +1663,6 @@ int main(int argc, char *argv[]) { { "args", required_argument, NULL, 'a' }, { "verbose", no_argument, NULL, 'v' }, { "timeout", required_argument, NULL, 't' }, - { "gdbexec", no_argument, NULL, 'x' }, { "unbuffered", no_argument, NULL, 'u' }, { "nostart", no_argument, NULL, 'n' }, { "noninteractive", no_argument, NULL, 'I' }, From 021c222a552fcb110e18adc966bfad8979b44294 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Thu, 13 Nov 2014 23:24:51 -0800 Subject: [PATCH 081/219] Update README. Removed gdbargs, gdbexec. Added download. --- README.md | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index f936c644..0d50d327 100644 --- a/README.md +++ b/README.md @@ -10,29 +10,27 @@ Install and debug iPhone apps without using Xcode. Designed to work on unjailbro ## Usage - Usage: ./ios-deploy [OPTION]... - -d, --debug launch the app in GDB after installation\n" - -i, --id the id of the device to connect to\n" - -c, --detect only detect if the device is connected\n" - -b, --bundle the path to the app bundle to be installed\n" - -a, --args command line arguments to pass to the app when launching it\n" - -t, --timeout number of seconds to wait for a device to be connected\n" - -u, --unbuffered don't buffer stdout\n" - -g, --gdbargs extra arguments to pass to GDB when starting the debugger\n" - -x, --gdbexec GDB commands script file\n" - -n, --nostart do not start the app when debugging\n" - -I, --noninteractive start in non interactive mode (quit when app crashes or exits)\n" - -L, --justlaunch just launch the app and exit lldb\n" - -v, --verbose enable verbose output\n" - -m, --noinstall directly start debugging without app install (-d not required)\n" - -p, --port port used for device, default: 12345 \n" - -r, --uninstall uninstall the app before install (do not use with -m; app cache and data are cleared) \n" - -1, --bundle_id specify bundle id for list and upload\n" - -l, --list list files\n" - -o, --upload upload file\n" - -w, --download download app tree\n" - -2, --to use together with up/download file/tree. specify target\n" - -V, --version print the executable version \n", + Usage: ios-deploy [OPTION]... + -d, --debug launch the app in GDB after installation + -i, --id the id of the device to connect to + -c, --detect only detect if the device is connected + -b, --bundle the path to the app bundle to be installed + -a, --args command line arguments to pass to the app when launching it + -t, --timeout number of seconds to wait for a device to be connected + -u, --unbuffered don't buffer stdout + -n, --nostart do not start the app when debugging + -I, --noninteractive start in non interactive mode (quit when app crashes or exits) + -L, --justlaunch just launch the app and exit lldb + -v, --verbose enable verbose output + -m, --noinstall directly start debugging without app install (-d not required) + -p, --port port used for device, default: 12345 + -r, --uninstall uninstall the app before install (do not use with -m; app cache and data are cleared) + -1, --bundle_id specify bundle id for list and upload + -l, --list list files + -o, --upload upload file + -w, --download download app tree + -2, --to use together with up/download file/tree. specify target + -V, --version print the executable version ## Demo From 7a447b480f4476c3ee383b031b9f0ef73826ba66 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Thu, 13 Nov 2014 23:47:50 -0800 Subject: [PATCH 082/219] Fixes phonegap/ios-deploy#79 - Update README.md for sample usage of ios-deploy flags and options --- README.md | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 0d50d327..2472d9f3 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ ios-deploy ========== -Install and debug iPhone apps without using Xcode. Designed to work on unjailbroken devices. +Install and debug iOS apps without using Xcode. Designed to work on un-jailbroken devices. ## Requirements -* Mac OS X. Tested on Snow Leopard only. -* You need to have a valid iPhone development certificate installed. -* Xcode must be installed, along with the SDK for your iOS version. +* Mac OS X. Tested on 10.10 Yosemite and iOS 8.1 +* You need to have a valid iOS development certificate installed. +* Xcode 6.1 should be installed ## Usage @@ -31,7 +31,32 @@ Install and debug iPhone apps without using Xcode. Designed to work on unjailbro -w, --download download app tree -2, --to use together with up/download file/tree. specify target -V, --version print the executable version - + +## Examples + +The commands below assume that you have an app called `my.app` with bundle id `bundle.id`. Substitute where necessary. + + // deploy and debug your app to a connected device + ios-deploy --debug --bundle my.app + + // deploy and launch your app to a connected device, but quit the debugger after + ios-deploy --justlaunch --debug --bundle my.app + + // deploy and launch your app to a connected device, quit when app crashes or exits + ios-deploy --noninteractive --debug --bundle my.app + + // Upload a file to your app's Documents folder + ios-deploy --bundle_id 'bundle.id' --upload test.txt --to Documents/test.txt + + // Download your app's Documents, Library and tmp folders + ios-deploy --bundle_id 'bundle.id' --download --to MyDestinationFolder + + // List the contents of your app's Documents, Library and tmp folders + ios-deploy --bundle_id 'bundle.id' --list + + // deploy and debug your app to a connected device, uninstall the app first + ios-deploy --uninstall --debug --bundle my.app + ## Demo * The included demo.app represents the minimum required to get code running on iOS. @@ -40,7 +65,7 @@ Install and debug iPhone apps without using Xcode. Designed to work on unjailbro ## Notes -* With some modifications, it may be possible to use this without Xcode installed; however, you would need a copy of the relevant DeveloperDiskImage.dmg (included with Xcode). GDB would also run slower as symbols would be downloaded from the device on-the-fly. +* With some modifications, it may be possible to use this without Xcode installed; however, you would need a copy of the relevant DeveloperDiskImage.dmg (included with Xcode). lldb would also run slower as symbols would be downloaded from the device on-the-fly. ## Listing Device Ids From 767c386ba9e966cb8fb68879b30b55c0ae23fa8c Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Fri, 14 Nov 2014 13:07:19 -0800 Subject: [PATCH 083/219] Fixes phonegap/ios-deploy#80 --detect not showing non-zero exit code when no devices are detected. --- ios-deploy.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index c8d22cb9..36a3eeb9 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1607,8 +1607,10 @@ void timeout_callback(CFRunLoopTimerRef timer, void *info) { } else { - if (!debug) + if (!debug) { printf("[....] No more devices found.\n"); + exit(exitcode_error); + } else { int mypid = getpid(); From 7c9af71d86098c41322176cc7aa4662bc8eeaaf3 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Fri, 14 Nov 2014 13:09:11 -0800 Subject: [PATCH 084/219] Updated version to 1.3.1 --- ios-deploy.c | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 36a3eeb9..6fc20f55 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -16,7 +16,7 @@ #include #include "MobileDevice.h" -#define APP_VERSION "1.3.0" +#define APP_VERSION "1.3.1" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH /* diff --git a/package.json b/package.json index 7db68e31..d872fef6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ios-deploy", - "version": "1.3.0", + "version": "1.3.1", "description": "launch iOS apps iOS devices from the command line (Xcode 6)", "main": "ios-deploy", "scripts": { From 33f6a83e1d94df5cf5041e9e16394409c4f63656 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Sun, 16 Nov 2014 20:49:33 -0800 Subject: [PATCH 085/219] Fixes phonegap/ios-deploy#80 (re-fix) --detect not showing non-zero exit code when no devices are detected. When --detect is turned on, --debug is turned on implicitly so you won't get a segmentation fault. --- ios-deploy.c | 14 +++++++++----- package.json | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 6fc20f55..156d1bf4 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -16,7 +16,7 @@ #include #include "MobileDevice.h" -#define APP_VERSION "1.3.1" +#define APP_VERSION "1.3.2" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH /* @@ -1448,6 +1448,7 @@ void handle_device(AMDeviceRef device) { if (detect_only) { printf("[....] Found %s connected through %s.\n", CFStringGetCStringPtr(device_full_name, CFStringGetSystemEncoding()), CFStringGetCStringPtr(device_interface_name, CFStringGetSystemEncoding())); + found_device = true; return; } if (device_id != NULL) { @@ -1609,10 +1610,12 @@ void timeout_callback(CFRunLoopTimerRef timer, void *info) { { if (!debug) { printf("[....] No more devices found.\n"); - exit(exitcode_error); } - else - { + + if (detect_only && !found_device) { + exit(exitcode_error); + return; + } else { int mypid = getpid(); if ((parent != 0) && (parent == mypid) && (child != 0)) { @@ -1630,7 +1633,7 @@ void timeout_callback(CFRunLoopTimerRef timer, void *info) { void usage(const char* app) { printf( "Usage: %s [OPTION]...\n" - " -d, --debug launch the app in GDB after installation\n" + " -d, --debug launch the app in lldb after installation\n" " -i, --id the id of the device to connect to\n" " -c, --detect only detect if the device is connected\n" " -b, --bundle the path to the app bundle to be installed\n" @@ -1723,6 +1726,7 @@ int main(int argc, char *argv[]) { break; case 'c': detect_only = true; + debug = 1; break; case 'V': show_version(); diff --git a/package.json b/package.json index d872fef6..53b15d9e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ios-deploy", - "version": "1.3.1", + "version": "1.3.2", "description": "launch iOS apps iOS devices from the command line (Xcode 6)", "main": "ios-deploy", "scripts": { From 3dcd64f7c06d0b80892516d3c12d9a5f0374d0cc Mon Sep 17 00:00:00 2001 From: senthil Date: Mon, 17 Nov 2014 10:06:48 -0500 Subject: [PATCH 086/219] Merge with phonegap Fixed the issue with implictly turning on debug for -c instead of -L --- ios-deploy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index 156d1bf4..a021c660 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1723,10 +1723,10 @@ int main(int argc, char *argv[]) { case 'L': interactive = false; justlaunch = true; + debug = 1; break; case 'c': detect_only = true; - debug = 1; break; case 'V': show_version(); From 6ac084844ed703802449d596075f8b80a81eeeba Mon Sep 17 00:00:00 2001 From: senthil Date: Mon, 17 Nov 2014 10:08:42 -0500 Subject: [PATCH 087/219] updated the version to 1.3.3 --- ios-deploy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index a021c660..a119bcb6 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -16,7 +16,7 @@ #include #include "MobileDevice.h" -#define APP_VERSION "1.3.2" +#define APP_VERSION "1.3.3" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH /* From 99f401018df3e5036ba377bee4d43d460e16f91e Mon Sep 17 00:00:00 2001 From: senthil Date: Sat, 6 Dec 2014 20:24:48 -0500 Subject: [PATCH 088/219] Using debug for -c as well --- ios-deploy.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ios-deploy.c b/ios-deploy.c index a119bcb6..bbb2295c 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1727,6 +1727,7 @@ int main(int argc, char *argv[]) { break; case 'c': detect_only = true; + debug = 1; break; case 'V': show_version(); From e4c4660f2ae0f393386965358307e784096c1396 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Fri, 12 Dec 2014 17:43:50 -0800 Subject: [PATCH 089/219] Cleaned up get_device_hardware_name by using a macro (related to issue #88). This prepares it for adding models that are missing, see: https://theiphonewiki.com/wiki/Models --- ios-deploy.c | 132 ++++++++++++++++++++++----------------------------- 1 file changed, 56 insertions(+), 76 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 156d1bf4..852917b3 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -312,87 +312,67 @@ CFStringRef copy_xcode_path_for(CFStringRef subPath, CFStringRef search) { } } +#define GET_FRIENDLY_MODEL_NAME(VALUE, INTERNAL_NAME, FRIENDLY_NAME) if (kCFCompareEqualTo == CFStringCompare(VALUE, CFSTR(INTERNAL_NAME), kCFCompareNonliteral)) { return CFSTR( FRIENDLY_NAME); }; + + // Please ensure that device is connected or the name will be unknown const CFStringRef get_device_hardware_name(const AMDeviceRef device) { CFStringRef model = AMDeviceCopyValue(device, 0, CFSTR("HardwareModel")); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("M68AP"), kCFCompareNonliteral)) - return CFSTR("iPhone"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N45AP"), kCFCompareNonliteral)) - return CFSTR("iPod touch"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N82AP"), kCFCompareNonliteral)) - return CFSTR("iPhone 3G"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N72AP"), kCFCompareNonliteral)) - return CFSTR("iPod touch 2G"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N88AP"), kCFCompareNonliteral)) - return CFSTR("iPhone 3GS"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N18AP"), kCFCompareNonliteral)) - return CFSTR("iPod touch 3G"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("K48AP"), kCFCompareNonliteral)) - return CFSTR("iPad"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N90AP"), kCFCompareNonliteral)) - return CFSTR("iPhone 4 (GSM)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N81AP"), kCFCompareNonliteral)) - return CFSTR("iPod touch 4G"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("K66AP"), kCFCompareNonliteral)) - return CFSTR("Apple TV 2G"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N92AP"), kCFCompareNonliteral)) - return CFSTR("iPhone 4 (CDMA)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N90BAP"), kCFCompareNonliteral)) - return CFSTR("iPhone 4 (GSM, revision A)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("K93AP"), kCFCompareNonliteral)) - return CFSTR("iPad 2"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("K94AP"), kCFCompareNonliteral)) - return CFSTR("iPad 2 (GSM)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("K95AP"), kCFCompareNonliteral)) - return CFSTR("iPad 2 (CDMA)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("K93AAP"), kCFCompareNonliteral)) - return CFSTR("iPad 2 (Wi-Fi, revision A)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("P105AP"), kCFCompareNonliteral)) - return CFSTR("iPad mini"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("P106AP"), kCFCompareNonliteral)) - return CFSTR("iPad mini (GSM)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("P107AP"), kCFCompareNonliteral)) - return CFSTR("iPad mini (CDMA)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N94AP"), kCFCompareNonliteral)) - return CFSTR("iPhone 4S"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N41AP"), kCFCompareNonliteral)) - return CFSTR("iPhone 5 (GSM)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N42AP"), kCFCompareNonliteral)) - return CFSTR("iPhone 5 (Global/CDMA)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N48AP"), kCFCompareNonliteral)) - return CFSTR("iPhone 5c (GSM)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N49AP"), kCFCompareNonliteral)) - return CFSTR("iPhone 5c (Global/CDMA)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N51AP"), kCFCompareNonliteral)) - return CFSTR("iPhone 5s (GSM)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N53AP"), kCFCompareNonliteral)) - return CFSTR("iPhone 5s (Global/CDMA)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N61AP"), kCFCompareNonliteral)) - return CFSTR("iPhone 6 (GSM)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("J1AP"), kCFCompareNonliteral)) - return CFSTR("iPad 3"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("J2AP"), kCFCompareNonliteral)) - return CFSTR("iPad 3 (GSM)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("J2AAP"), kCFCompareNonliteral)) - return CFSTR("iPad 3 (CDMA)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("P101AP"), kCFCompareNonliteral)) - return CFSTR("iPad 4"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("P102AP"), kCFCompareNonliteral)) - return CFSTR("iPad 4 (GSM)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("P103AP"), kCFCompareNonliteral)) - return CFSTR("iPad 4 (CDMA)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N78AP"), kCFCompareNonliteral)) - return CFSTR("iPod touch 5G"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("A1509"), kCFCompareNonliteral)) - return CFSTR("iPod touch 5G"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("J33AP"), kCFCompareNonliteral)) - return CFSTR("Apple TV 3G"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("J33IAP"), kCFCompareNonliteral)) - return CFSTR("Apple TV 3.1G"); + + // iPod Touch + + GET_FRIENDLY_MODEL_NAME(model, "N45AP", "iPod Touch") + GET_FRIENDLY_MODEL_NAME(model, "N72AP", "iPod Touch 2G") + GET_FRIENDLY_MODEL_NAME(model, "N18AP", "iPod Touch 3G") + GET_FRIENDLY_MODEL_NAME(model, "N81AP", "iPod Touch 4G") + GET_FRIENDLY_MODEL_NAME(model, "N78AP", "iPod Touch 5G") + GET_FRIENDLY_MODEL_NAME(model, "N78AAP", "iPod Touch 5G") + + // iPad + + GET_FRIENDLY_MODEL_NAME(model, "K48AP", "iPad") + GET_FRIENDLY_MODEL_NAME(model, "K93AP", "iPad 2") + GET_FRIENDLY_MODEL_NAME(model, "K94AP", "iPad 2 (GSM)") + GET_FRIENDLY_MODEL_NAME(model, "K95AP", "iPad 2 (CDMA)") + GET_FRIENDLY_MODEL_NAME(model, "K93AAP", "iPad 2 (Wi-Fi, revision A)") + GET_FRIENDLY_MODEL_NAME(model, "J1AP", "iPad 3") + GET_FRIENDLY_MODEL_NAME(model, "J2AP", "iPad 3 (GSM)") + GET_FRIENDLY_MODEL_NAME(model, "J2AAP", "iPad 3 (CDMA)") + GET_FRIENDLY_MODEL_NAME(model, "P101AP", "iPad 4") + GET_FRIENDLY_MODEL_NAME(model, "P102AP", "iPad 4 (GSM)") + GET_FRIENDLY_MODEL_NAME(model, "P103AP", "iPad 4 (CDMA)") + + // iPad Mini + + GET_FRIENDLY_MODEL_NAME(model, "P105AP", "iPad mini") + GET_FRIENDLY_MODEL_NAME(model, "P106AP", "iPad mini (GSM)") + GET_FRIENDLY_MODEL_NAME(model, "P107AP", "iPad mini (CDMA)") + + // Apple TV + + GET_FRIENDLY_MODEL_NAME(model, "K66AP", "Apple TV 2G") + GET_FRIENDLY_MODEL_NAME(model, "J33AP", "Apple TV 3G") + GET_FRIENDLY_MODEL_NAME(model, "J33IAP", "Apple TV 3.1G") + + // iPhone + + GET_FRIENDLY_MODEL_NAME(model, "M68AP", "iPhone") + GET_FRIENDLY_MODEL_NAME(model, "N82AP", "iPhone 3G") + GET_FRIENDLY_MODEL_NAME(model, "N88AP", "iPhone 3GS") + GET_FRIENDLY_MODEL_NAME(model, "N90AP", "iPhone 4 (GSM)") + GET_FRIENDLY_MODEL_NAME(model, "N92AP", "iPhone 4 (CDMA)") + GET_FRIENDLY_MODEL_NAME(model, "N90BAP", "iPhone 4 (GSM, revision A)") + GET_FRIENDLY_MODEL_NAME(model, "N94AP", "iPhone 4S") + GET_FRIENDLY_MODEL_NAME(model, "N41AP", "iPhone 5 (GSM)") + GET_FRIENDLY_MODEL_NAME(model, "N88AP", "iPhone 5 (Global/CDMA)") + GET_FRIENDLY_MODEL_NAME(model, "N88AP", "iPhone 5c (GSM)") + GET_FRIENDLY_MODEL_NAME(model, "N88AP", "iPhone 5c (Global/CDMA)") + GET_FRIENDLY_MODEL_NAME(model, "N88AP", "iPhone 5s (GSM)") + GET_FRIENDLY_MODEL_NAME(model, "N88AP", "iPhone 5s (Global/CDMA)") + GET_FRIENDLY_MODEL_NAME(model, "N61AP", "iPhone 6 (GSM)") + GET_FRIENDLY_MODEL_NAME(model, "N56AP", "iPhone 6 Plus") return model; - //return CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), hwmodel); - //return CFSTR("Unknown Device"); } char * MYCFStringCopyUTF8String(CFStringRef aString) { From e1aacc0ba1aaab2b3acc988baf9130173d2ea16a Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Fri, 12 Dec 2014 17:46:56 -0800 Subject: [PATCH 090/219] Model table typo (copy paste error) for iPhone 5 models. --- ios-deploy.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 852917b3..561aeee8 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -364,11 +364,11 @@ const CFStringRef get_device_hardware_name(const AMDeviceRef device) { GET_FRIENDLY_MODEL_NAME(model, "N90BAP", "iPhone 4 (GSM, revision A)") GET_FRIENDLY_MODEL_NAME(model, "N94AP", "iPhone 4S") GET_FRIENDLY_MODEL_NAME(model, "N41AP", "iPhone 5 (GSM)") - GET_FRIENDLY_MODEL_NAME(model, "N88AP", "iPhone 5 (Global/CDMA)") - GET_FRIENDLY_MODEL_NAME(model, "N88AP", "iPhone 5c (GSM)") - GET_FRIENDLY_MODEL_NAME(model, "N88AP", "iPhone 5c (Global/CDMA)") - GET_FRIENDLY_MODEL_NAME(model, "N88AP", "iPhone 5s (GSM)") - GET_FRIENDLY_MODEL_NAME(model, "N88AP", "iPhone 5s (Global/CDMA)") + GET_FRIENDLY_MODEL_NAME(model, "N42AP", "iPhone 5 (Global/CDMA)") + GET_FRIENDLY_MODEL_NAME(model, "N48AP", "iPhone 5c (GSM)") + GET_FRIENDLY_MODEL_NAME(model, "N49AP", "iPhone 5c (Global/CDMA)") + GET_FRIENDLY_MODEL_NAME(model, "N51AP", "iPhone 5s (GSM)") + GET_FRIENDLY_MODEL_NAME(model, "N53AP", "iPhone 5s (Global/CDMA)") GET_FRIENDLY_MODEL_NAME(model, "N61AP", "iPhone 6 (GSM)") GET_FRIENDLY_MODEL_NAME(model, "N56AP", "iPhone 6 Plus") From 0dece5157e6db8bff689496c4103fe9f5c0fa877 Mon Sep 17 00:00:00 2001 From: William Dias Date: Mon, 15 Dec 2014 09:28:13 -0200 Subject: [PATCH 091/219] Add installation instructions in README. --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 2472d9f3..b6f5d4ba 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,12 @@ Install and debug iOS apps without using Xcode. Designed to work on un-jailbroke * You need to have a valid iOS development certificate installed. * Xcode 6.1 should be installed +## Installation + +```bash +$ npm install -g ios-deploy +``` + ## Usage Usage: ios-deploy [OPTION]... From e5e2a6349d9d37ad0f5a380768ac52bca598c759 Mon Sep 17 00:00:00 2001 From: Alex Dunn Date: Tue, 23 Dec 2014 04:53:35 -0800 Subject: [PATCH 092/219] Clarify what npm is and how to get it --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index b6f5d4ba..07b4d007 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,12 @@ Install and debug iOS apps without using Xcode. Designed to work on un-jailbroke * Xcode 6.1 should be installed ## Installation +ios-deploy installation is made simple using the node.js package manager. If you use [Homebrew](http://brew.sh/), install node.js: +```bash +brew install node +``` +Now install ios-deploy with the node.js package manager: ```bash $ npm install -g ios-deploy ``` From 8577ef34110e925910879840692a9ae16232b525 Mon Sep 17 00:00:00 2001 From: senthil Date: Sat, 17 Jan 2015 17:29:54 -0500 Subject: [PATCH 093/219] sometimes the model is null in get_device_hardware_name; updated to v1.3.4 --- ios-deploy.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index bbb2295c..0c0dd51d 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -16,7 +16,7 @@ #include #include "MobileDevice.h" -#define APP_VERSION "1.3.3" +#define APP_VERSION "1.3.4" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH /* @@ -315,6 +315,13 @@ CFStringRef copy_xcode_path_for(CFStringRef subPath, CFStringRef search) { // Please ensure that device is connected or the name will be unknown const CFStringRef get_device_hardware_name(const AMDeviceRef device) { CFStringRef model = AMDeviceCopyValue(device, 0, CFSTR("HardwareModel")); + + if (model == NULL) + { + return CFSTR("Unknown Device"); + } + //printf("Device model: %s\n", CFStringGetCStringPtr(model, CFStringGetSystemEncoding())); + if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("M68AP"), kCFCompareNonliteral)) return CFSTR("iPhone"); if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N45AP"), kCFCompareNonliteral)) From 96e91eb2695e44315dafcd09479d8e1d37464999 Mon Sep 17 00:00:00 2001 From: senthil Date: Tue, 20 Jan 2015 17:36:45 -0500 Subject: [PATCH 094/219] merged with phonegap/ios-deploy --- README.md | 11 +++++ ios-deploy.c | 133 ++++++++++++++++++++++----------------------------- 2 files changed, 67 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index 2472d9f3..07b4d007 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,17 @@ Install and debug iOS apps without using Xcode. Designed to work on un-jailbroke * You need to have a valid iOS development certificate installed. * Xcode 6.1 should be installed +## Installation +ios-deploy installation is made simple using the node.js package manager. If you use [Homebrew](http://brew.sh/), install node.js: +```bash +brew install node +``` + +Now install ios-deploy with the node.js package manager: +```bash +$ npm install -g ios-deploy +``` + ## Usage Usage: ios-deploy [OPTION]... diff --git a/ios-deploy.c b/ios-deploy.c index 0c0dd51d..b485bfe9 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -16,7 +16,7 @@ #include #include "MobileDevice.h" -#define APP_VERSION "1.3.4" +#define APP_VERSION "1.3.5" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH /* @@ -312,6 +312,9 @@ CFStringRef copy_xcode_path_for(CFStringRef subPath, CFStringRef search) { } } +#define GET_FRIENDLY_MODEL_NAME(VALUE, INTERNAL_NAME, FRIENDLY_NAME) if (kCFCompareEqualTo == CFStringCompare(VALUE, CFSTR(INTERNAL_NAME), kCFCompareNonliteral)) { return CFSTR( FRIENDLY_NAME); }; + + // Please ensure that device is connected or the name will be unknown const CFStringRef get_device_hardware_name(const AMDeviceRef device) { CFStringRef model = AMDeviceCopyValue(device, 0, CFSTR("HardwareModel")); @@ -322,84 +325,60 @@ const CFStringRef get_device_hardware_name(const AMDeviceRef device) { } //printf("Device model: %s\n", CFStringGetCStringPtr(model, CFStringGetSystemEncoding())); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("M68AP"), kCFCompareNonliteral)) - return CFSTR("iPhone"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N45AP"), kCFCompareNonliteral)) - return CFSTR("iPod touch"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N82AP"), kCFCompareNonliteral)) - return CFSTR("iPhone 3G"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N72AP"), kCFCompareNonliteral)) - return CFSTR("iPod touch 2G"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N88AP"), kCFCompareNonliteral)) - return CFSTR("iPhone 3GS"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N18AP"), kCFCompareNonliteral)) - return CFSTR("iPod touch 3G"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("K48AP"), kCFCompareNonliteral)) - return CFSTR("iPad"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N90AP"), kCFCompareNonliteral)) - return CFSTR("iPhone 4 (GSM)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N81AP"), kCFCompareNonliteral)) - return CFSTR("iPod touch 4G"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("K66AP"), kCFCompareNonliteral)) - return CFSTR("Apple TV 2G"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N92AP"), kCFCompareNonliteral)) - return CFSTR("iPhone 4 (CDMA)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N90BAP"), kCFCompareNonliteral)) - return CFSTR("iPhone 4 (GSM, revision A)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("K93AP"), kCFCompareNonliteral)) - return CFSTR("iPad 2"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("K94AP"), kCFCompareNonliteral)) - return CFSTR("iPad 2 (GSM)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("K95AP"), kCFCompareNonliteral)) - return CFSTR("iPad 2 (CDMA)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("K93AAP"), kCFCompareNonliteral)) - return CFSTR("iPad 2 (Wi-Fi, revision A)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("P105AP"), kCFCompareNonliteral)) - return CFSTR("iPad mini"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("P106AP"), kCFCompareNonliteral)) - return CFSTR("iPad mini (GSM)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("P107AP"), kCFCompareNonliteral)) - return CFSTR("iPad mini (CDMA)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N94AP"), kCFCompareNonliteral)) - return CFSTR("iPhone 4S"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N41AP"), kCFCompareNonliteral)) - return CFSTR("iPhone 5 (GSM)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N42AP"), kCFCompareNonliteral)) - return CFSTR("iPhone 5 (Global/CDMA)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N48AP"), kCFCompareNonliteral)) - return CFSTR("iPhone 5c (GSM)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N49AP"), kCFCompareNonliteral)) - return CFSTR("iPhone 5c (Global/CDMA)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N51AP"), kCFCompareNonliteral)) - return CFSTR("iPhone 5s (GSM)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N53AP"), kCFCompareNonliteral)) - return CFSTR("iPhone 5s (Global/CDMA)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N61AP"), kCFCompareNonliteral)) - return CFSTR("iPhone 6 (GSM)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("J1AP"), kCFCompareNonliteral)) - return CFSTR("iPad 3"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("J2AP"), kCFCompareNonliteral)) - return CFSTR("iPad 3 (GSM)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("J2AAP"), kCFCompareNonliteral)) - return CFSTR("iPad 3 (CDMA)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("P101AP"), kCFCompareNonliteral)) - return CFSTR("iPad 4"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("P102AP"), kCFCompareNonliteral)) - return CFSTR("iPad 4 (GSM)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("P103AP"), kCFCompareNonliteral)) - return CFSTR("iPad 4 (CDMA)"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("N78AP"), kCFCompareNonliteral)) - return CFSTR("iPod touch 5G"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("A1509"), kCFCompareNonliteral)) - return CFSTR("iPod touch 5G"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("J33AP"), kCFCompareNonliteral)) - return CFSTR("Apple TV 3G"); - if (kCFCompareEqualTo == CFStringCompare(model,CFSTR("J33IAP"), kCFCompareNonliteral)) - return CFSTR("Apple TV 3.1G"); + //iPod Touch + + GET_FRIENDLY_MODEL_NAME(model, "N45AP", "iPod Touch") + GET_FRIENDLY_MODEL_NAME(model, "N72AP", "iPod Touch 2G") + GET_FRIENDLY_MODEL_NAME(model, "N18AP", "iPod Touch 3G") + GET_FRIENDLY_MODEL_NAME(model, "N81AP", "iPod Touch 4G") + GET_FRIENDLY_MODEL_NAME(model, "N78AP", "iPod Touch 5G") + GET_FRIENDLY_MODEL_NAME(model, "N78AAP", "iPod Touch 5G") + + // iPad + + GET_FRIENDLY_MODEL_NAME(model, "K48AP", "iPad") + GET_FRIENDLY_MODEL_NAME(model, "K93AP", "iPad 2") + GET_FRIENDLY_MODEL_NAME(model, "K94AP", "iPad 2 (GSM)") + GET_FRIENDLY_MODEL_NAME(model, "K95AP", "iPad 2 (CDMA)") + GET_FRIENDLY_MODEL_NAME(model, "K93AAP", "iPad 2 (Wi-Fi, revision A)") + GET_FRIENDLY_MODEL_NAME(model, "J1AP", "iPad 3") + GET_FRIENDLY_MODEL_NAME(model, "J2AP", "iPad 3 (GSM)") + GET_FRIENDLY_MODEL_NAME(model, "J2AAP", "iPad 3 (CDMA)") + GET_FRIENDLY_MODEL_NAME(model, "P101AP", "iPad 4") + GET_FRIENDLY_MODEL_NAME(model, "P102AP", "iPad 4 (GSM)") + GET_FRIENDLY_MODEL_NAME(model, "P103AP", "iPad 4 (CDMA)") + + // iPad Mini + + GET_FRIENDLY_MODEL_NAME(model, "P105AP", "iPad mini") + GET_FRIENDLY_MODEL_NAME(model, "P106AP", "iPad mini (GSM)") + GET_FRIENDLY_MODEL_NAME(model, "P107AP", "iPad mini (CDMA)") + + // Apple TV + + GET_FRIENDLY_MODEL_NAME(model, "K66AP", "Apple TV 2G") + GET_FRIENDLY_MODEL_NAME(model, "J33AP", "Apple TV 3G") + GET_FRIENDLY_MODEL_NAME(model, "J33IAP", "Apple TV 3.1G") + + // iPhone + + GET_FRIENDLY_MODEL_NAME(model, "M68AP", "iPhone") + GET_FRIENDLY_MODEL_NAME(model, "N82AP", "iPhone 3G") + GET_FRIENDLY_MODEL_NAME(model, "N88AP", "iPhone 3GS") + GET_FRIENDLY_MODEL_NAME(model, "N90AP", "iPhone 4 (GSM)") + GET_FRIENDLY_MODEL_NAME(model, "N92AP", "iPhone 4 (CDMA)") + GET_FRIENDLY_MODEL_NAME(model, "N90BAP", "iPhone 4 (GSM, revision A)") + GET_FRIENDLY_MODEL_NAME(model, "N94AP", "iPhone 4S") + GET_FRIENDLY_MODEL_NAME(model, "N41AP", "iPhone 5 (GSM)") + GET_FRIENDLY_MODEL_NAME(model, "N42AP", "iPhone 5 (Global/CDMA)") + GET_FRIENDLY_MODEL_NAME(model, "N48AP", "iPhone 5c (GSM)") + GET_FRIENDLY_MODEL_NAME(model, "N49AP", "iPhone 5c (Global/CDMA)") + GET_FRIENDLY_MODEL_NAME(model, "N51AP", "iPhone 5s (GSM)") + GET_FRIENDLY_MODEL_NAME(model, "N53AP", "iPhone 5s (Global/CDMA)") + GET_FRIENDLY_MODEL_NAME(model, "N61AP", "iPhone 6 (GSM)") + GET_FRIENDLY_MODEL_NAME(model, "N56AP", "iPhone 6 Plus") return model; - //return CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), hwmodel); - //return CFSTR("Unknown Device"); } char * MYCFStringCopyUTF8String(CFStringRef aString) { From 134a0a5fd04366887fd1bfe16c0a1cba8d5e1dc9 Mon Sep 17 00:00:00 2001 From: senthil Date: Tue, 27 Jan 2015 15:07:44 -0500 Subject: [PATCH 095/219] The return code must be < 128 otherwise treated as a signal --- ios-deploy.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index b485bfe9..6fcbd1b4 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -96,7 +96,7 @@ def run_command(debugger, command, result, internal_dict):\n\ lockedstr = ': Locked'\n\ if lockedstr in str(error):\n\ print('\\nDevice Locked\\n')\n\ - sys.exit(254)\n\ + sys.exit({exitcode_error})\n\ else:\n\ print(str(error))\n\ \n\ @@ -176,8 +176,8 @@ AMDeviceRef best_device_match = NULL; // Error codes we report on different failures, so scripts can distinguish between user app exit // codes and our exit codes. For non app errors we use codes in reserved 128-255 range. -const int exitcode_error = 253; -const int exitcode_app_crash = 254; +const int exitcode_error = SIGTERM; +const int exitcode_app_crash = SIGABRT; Boolean path_exists(CFTypeRef path) { if (CFGetTypeID(path) == CFStringGetTypeID()) { @@ -705,6 +705,8 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { CFMutableStringRef pmodule = CFStringCreateMutableCopy(NULL, 0, LLDB_FRUITSTRAP_MODULE); CFRange rangeLLDB = { 0, CFStringGetLength(pmodule) }; + CFStringRef exitcode_error_str = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), exitcode_error); + CFStringFindAndReplace(pmodule, CFSTR("{exitcode_error}"), exitcode_error_str, rangeLLDB, 0); CFStringRef exitcode_app_crash_str = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), exitcode_app_crash); CFStringFindAndReplace(pmodule, CFSTR("{exitcode_app_crash}"), exitcode_app_crash_str, rangeLLDB, 0); rangeLLDB.length = CFStringGetLength(pmodule); From ba60ff6351bdbdb305ffeb3a3aa8eb777e53297e Mon Sep 17 00:00:00 2001 From: senthil Date: Tue, 27 Jan 2015 15:09:26 -0500 Subject: [PATCH 096/219] updated to version 1.3.6 --- ios-deploy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index 6fcbd1b4..247a4454 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -16,7 +16,7 @@ #include #include "MobileDevice.h" -#define APP_VERSION "1.3.5" +#define APP_VERSION "1.3.6" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH /* From 3e8a897fbc15a961cdd972154cb06cec2efde963 Mon Sep 17 00:00:00 2001 From: senthil Date: Thu, 29 Jan 2015 18:06:07 -0500 Subject: [PATCH 097/219] when just launch, if we get an empty packet, exit without an error --- ios-deploy.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 247a4454..ea722d6b 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -16,7 +16,7 @@ #include #include "MobileDevice.h" -#define APP_VERSION "1.3.6" +#define APP_VERSION "1.3.7" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH /* @@ -841,7 +841,12 @@ server_callback (CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef add } kill_ptree(child, SIGHUP); } - exit(exitcode_error); + if (justlaunch) + //when in justlaunch at times, we get an empty packet at the end. + //Assume everything is ok + exit(0); + else + exit(exitcode_error); return; } res = write (CFSocketGetNative (lldb_socket), CFDataGetBytePtr (data), CFDataGetLength (data)); From 48f7881a0b02afb4f5033adf7b8194f31c1c2137 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 2 Mar 2015 16:04:43 -0800 Subject: [PATCH 098/219] Fixes #105 - ios-deploy --version returns a non-zero exit code --- ios-deploy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index 561aeee8..23cb9580 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1710,7 +1710,7 @@ int main(int argc, char *argv[]) { break; case 'V': show_version(); - return exitcode_error; + return 0; case 'p': port = atoi(optarg); break; From 05edec95621f6e95e4d627637ca20019d6d38b2b Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 2 Mar 2015 16:09:07 -0800 Subject: [PATCH 099/219] Fixes #90, #91 - EXC_BAD_ACCESS crash --- ios-deploy.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ios-deploy.c b/ios-deploy.c index 23cb9580..5b011259 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -319,6 +319,10 @@ CFStringRef copy_xcode_path_for(CFStringRef subPath, CFStringRef search) { const CFStringRef get_device_hardware_name(const AMDeviceRef device) { CFStringRef model = AMDeviceCopyValue(device, 0, CFSTR("HardwareModel")); + if (model == NULL) { + return CFSTR("Unknown Device"); + } + // iPod Touch GET_FRIENDLY_MODEL_NAME(model, "N45AP", "iPod Touch") From 56abf4e92e390350a79999df277eb6a8cc067a31 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 2 Mar 2015 16:15:11 -0800 Subject: [PATCH 100/219] Updated version to 1.4.0 --- ios-deploy.c | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 5b011259..e1af3c2b 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -16,7 +16,7 @@ #include #include "MobileDevice.h" -#define APP_VERSION "1.3.2" +#define APP_VERSION "1.4.0" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH /* diff --git a/package.json b/package.json index 53b15d9e..d6b1d6b0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ios-deploy", - "version": "1.3.2", + "version": "1.4.0", "description": "launch iOS apps iOS devices from the command line (Xcode 6)", "main": "ios-deploy", "scripts": { From cab5a31ab5f9752d9fdec1afd6d177bf556115cc Mon Sep 17 00:00:00 2001 From: Ugur Kilic Date: Sat, 7 Mar 2015 16:33:12 +0200 Subject: [PATCH 101/219] =?UTF-8?q?=E2=80=9Cexists=E2=80=9D=20command=20ad?= =?UTF-8?q?ded=20to=20check=20if=20an=20app=20with=20given=20bundle=20id?= =?UTF-8?q?=20is=20installed=20on=20device=20or=20not=20(closes=20#107)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ios-deploy.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index e1af3c2b..cad9ec31 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1274,6 +1274,40 @@ void list_files(AMDeviceRef device) } } +int app_exists(AMDeviceRef device) +{ + if (bundle_id == NULL) { + printf("Bundle id is not specified\n"); + return false; + } + + AMDeviceConnect(device); + assert(AMDeviceIsPaired(device)); + assert(AMDeviceValidatePairing(device) == 0); + assert(AMDeviceStartSession(device) == 0); + + CFStringRef cf_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingASCII); + + NSArray *a = [NSArray arrayWithObjects:@"CFBundleIdentifier", nil]; + NSDictionary *optionsDict = [NSDictionary dictionaryWithObject:a forKey:@"ReturnAttributes"]; + CFDictionaryRef options = (CFDictionaryRef)optionsDict; + + CFDictionaryRef result = nil; + afc_error_t resultStatus = AMDeviceLookupApplications(device, options, &result); + assert(resultStatus == 0); + + CFDictionaryRef app_dict = CFDictionaryGetValue(result, cf_bundle_id); + + int appExists = (app_dict == NULL) ? -1 : 0; + + CFRelease(cf_bundle_id); + + assert(AMDeviceStopSession(device) == 0); + assert(AMDeviceDisconnect(device) == 0); + + return appExists; +} + void copy_file_callback(afc_connection* afc_conn_p, const char *name,int file) { const char *local_name=name; @@ -1456,6 +1490,8 @@ void handle_device(AMDeviceRef device) { upload_file(device); } else if (strcmp("download", command) == 0) { download_tree(device); + } else if (strcmp("exists", command) == 0) { + exit(app_exists(device)); } exit(0); } @@ -1636,7 +1672,8 @@ void usage(const char* app) { " -o, --upload upload file\n" " -w, --download download app tree\n" " -2, --to use together with up/download file/tree. specify target\n" - " -V, --version print the executable version \n", + " -V, --version print the executable version \n" + " -e, --exists check if the app with given bundle_id is installed or not \n", app); } @@ -1666,11 +1703,12 @@ int main(int argc, char *argv[]) { { "upload", required_argument, NULL, 'o'}, { "download", optional_argument, NULL, 'w'}, { "to", required_argument, NULL, '2'}, + { "exists", no_argument, NULL, 'e'}, { NULL, 0, NULL, 0 }, }; char ch; - while ((ch = getopt_long(argc, argv, "VmcdvunrILi:b:a:t:g:x:p:1:2:o:l::w::", longopts, NULL)) != -1) + while ((ch = getopt_long(argc, argv, "VmcdvunrILei:b:a:t:g:x:p:1:2:o:l::w::", longopts, NULL)) != -1) { switch (ch) { case 'm': @@ -1742,6 +1780,10 @@ int main(int argc, char *argv[]) { command = "download"; list_root = optarg; break; + case 'e': + command_only = true; + command = "exists"; + break; default: usage(argv[0]); return exitcode_error; From e8829320531f34f66b020d32a6427ce06a3a7813 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 6 Apr 2015 13:43:15 -0700 Subject: [PATCH 102/219] Added doc for --exists option --- README.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 07b4d007..b17b2726 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Install and debug iOS apps without using Xcode. Designed to work on un-jailbroke * Xcode 6.1 should be installed ## Installation -ios-deploy installation is made simple using the node.js package manager. If you use [Homebrew](http://brew.sh/), install node.js: +ios-deploy installation is made simple using the node.js package manager. If you use [Homebrew](http://brew.sh/), install node.js: ```bash brew install node ``` @@ -34,14 +34,16 @@ $ npm install -g ios-deploy -L, --justlaunch just launch the app and exit lldb -v, --verbose enable verbose output -m, --noinstall directly start debugging without app install (-d not required) - -p, --port port used for device, default: 12345 - -r, --uninstall uninstall the app before install (do not use with -m; app cache and data are cleared) + -p, --port port used for device, default: 12345 + -r, --uninstall uninstall the app before install (do not use with -m; app cache and data are cleared) -1, --bundle_id specify bundle id for list and upload -l, --list list files -o, --upload upload file -w, --download download app tree -2, --to use together with up/download file/tree. specify target - -V, --version print the executable version + -V, --version print the executable version + -e, --exists check if the app with given bundle_id is installed or not + ## Examples @@ -58,7 +60,7 @@ The commands below assume that you have an app called `my.app` with bundle id `b // Upload a file to your app's Documents folder ios-deploy --bundle_id 'bundle.id' --upload test.txt --to Documents/test.txt - + // Download your app's Documents, Library and tmp folders ios-deploy --bundle_id 'bundle.id' --download --to MyDestinationFolder @@ -67,7 +69,10 @@ The commands below assume that you have an app called `my.app` with bundle id `b // deploy and debug your app to a connected device, uninstall the app first ios-deploy --uninstall --debug --bundle my.app - + + // check whether an app by bundle id exists on the device (check return code `echo $?`) + ios-deploy --exists --bundle_id com.apple.mobilemail + ## Demo * The included demo.app represents the minimum required to get code running on iOS. From 54818aae5c897979abb93ca03f47c81a6f2dc104 Mon Sep 17 00:00:00 2001 From: Andy Polyakov Date: Mon, 6 Apr 2015 15:52:17 +0200 Subject: [PATCH 103/219] Number of fixes: - allow to pass command line arguments from (lldb) prompt; - make lldb exit as opposite to relying on kill (which is problematics because it messes up tty settings); - handle event timeout in autoexit_command to avoid endless loop; - use dynamic TCP port and listen on localhost (no need to expose the port to Internet); - close accept socket once connection is established; (fixes #112) --- ios-deploy.c | 106 +++++++++++++++++++++++++-------------------------- 1 file changed, 52 insertions(+), 54 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index cad9ec31..dfc4d296 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -61,6 +61,7 @@ const char* lldb_prep_noninteractive_cmds = "\ */ #define LLDB_FRUITSTRAP_MODULE CFSTR("\ import lldb\n\ +import os\n\ import sys\n\ import shlex\n\ \n\ @@ -90,13 +91,14 @@ def connect_command(debugger, command, result, internal_dict):\n\ \n\ def run_command(debugger, command, result, internal_dict):\n\ device_app = internal_dict['fruitstrap_device_app']\n\ + args = command.split('--',1)\n\ error = lldb.SBError()\n\ lldb.target.modules[0].SetPlatformFileSpec(lldb.SBFileSpec(device_app))\n\ - lldb.target.Launch(lldb.SBLaunchInfo(shlex.split('{args}')), error)\n\ + lldb.target.Launch(lldb.SBLaunchInfo(shlex.split(args[1] and args[1] or '{args}')), error)\n\ lockedstr = ': Locked'\n\ if lockedstr in str(error):\n\ print('\\nDevice Locked\\n')\n\ - sys.exit(254)\n\ + os._exit(254)\n\ else:\n\ print(str(error))\n\ \n\ @@ -106,12 +108,16 @@ def safequit_command(debugger, command, result, internal_dict):\n\ listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR)\n\ event = lldb.SBEvent()\n\ while True:\n\ - if listener.WaitForEvent(1, event):\n\ - state = process.GetStateFromEvent(event)\n\ + if listener.WaitForEvent(1, event) and lldb.SBProcess.EventIsProcessEvent(event):\n\ + state = lldb.SBProcess.GetStateFromEvent(event)\n\ else:\n\ - state = lldb.eStateInvalid\n\ - process.Detach()\n\ - sys.exit(0)\n\ + state = process.GetState()\n\ +\n\ + if state == lldb.eStateRunning:\n\ + process.Detach()\n\ + os._exit(0)\n\ + elif state > lldb.eStateRunning:\n\ + os._exit(state)\n\ \n\ def autoexit_command(debugger, command, result, internal_dict):\n\ process = lldb.target.process\n\ @@ -119,10 +125,16 @@ def autoexit_command(debugger, command, result, internal_dict):\n\ listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR)\n\ event = lldb.SBEvent()\n\ while True:\n\ - if listener.WaitForEvent(1, event):\n\ - state = process.GetStateFromEvent(event)\n\ + if listener.WaitForEvent(1, event) and lldb.SBProcess.EventIsProcessEvent(event):\n\ + state = lldb.SBProcess.GetStateFromEvent(event)\n\ else:\n\ - state = lldb.eStateInvalid\n\ + state = process.GetState()\n\ +\n\ + if state == lldb.eStateExited:\n\ + os._exit(process.GetExitStatus())\n\ + elif state == lldb.eStateStopped:\n\ + debugger.HandleCommand('bt')\n\ + os._exit({exitcode_app_crash})\n\ \n\ stdout = process.GetSTDOUT(1024)\n\ while stdout:\n\ @@ -133,14 +145,6 @@ def autoexit_command(debugger, command, result, internal_dict):\n\ while stderr:\n\ sys.stdout.write(stderr)\n\ stderr = process.GetSTDERR(1024)\n\ -\n\ - if lldb.SBProcess.EventIsProcessEvent(event):\n\ - if state == lldb.eStateExited:\n\ - sys.exit(process.GetExitStatus())\n\ - if state == lldb.eStateStopped:\n\ - debugger.HandleCommand('frame select')\n\ - debugger.HandleCommand('bt')\n\ - sys.exit({exitcode_app_crash})\n\ ") typedef struct am_device * AMDeviceRef; @@ -164,7 +168,7 @@ char *device_id = NULL; char *args = NULL; char *list_root = NULL; int timeout = 0; -int port = 12345; +int port = 0; // 0 means "dynamically assigned" CFStringRef last_path = NULL; service_conn_t gdbfd; pid_t parent = 0; @@ -822,22 +826,9 @@ server_callback (CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef add int res; if (CFDataGetLength (data) == 0) { - // FIXME: Close the socket - //shutdown (CFSocketGetNative (lldb_socket), SHUT_RDWR); - //close (CFSocketGetNative (lldb_socket)); - CFSocketInvalidate(lldb_socket); - CFSocketInvalidate(server_socket); - int mypid = getpid(); - assert((child != 0) && (child != mypid)); //child should not be here - if ((parent != 0) && (parent == mypid) && (child != 0)) - { - if (verbose) - { - printf("Got an empty packet hence killing child (%d) tree\n", child); - } - kill_ptree(child, SIGHUP); - } - exit(exitcode_error); + // close the socket on which we've got end-of-file, the server_socket. + CFSocketInvalidate(s); + CFRelease(s); return; } res = write (CFSocketGetNative (lldb_socket), CFDataGetBytePtr (data), CFDataGetLength (data)); @@ -847,8 +838,12 @@ void lldb_callback(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef a { //printf ("lldb: %s\n", CFDataGetBytePtr (data)); - if (CFDataGetLength (data) == 0) + if (CFDataGetLength (data) == 0) { + // close the socket on which we've got end-of-file, the lldb_socket. + CFSocketInvalidate(s); + CFRelease(s); return; + } write (gdbfd, CFDataGetBytePtr (data), CFDataGetLength (data)); } @@ -859,21 +854,20 @@ void fdvendor_callback(CFSocketRef s, CFSocketCallBackType callbackType, CFDataR //PRINT ("callback!\n"); lldb_socket = CFSocketCreateWithNative(NULL, socket, kCFSocketDataCallBack, &lldb_callback, NULL); + int flag = 1; + int res = setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(flag)); + assert(res == 0); CFRunLoopAddSource(CFRunLoopGetMain(), CFSocketCreateRunLoopSource(NULL, lldb_socket, 0), kCFRunLoopCommonModes); + + CFSocketInvalidate(s); + CFRelease(s); } void start_remote_debug_server(AMDeviceRef device) { - char buf [256]; - int res, err, i; - char msg [256]; - int chsum, len; - struct stat s; - socklen_t buflen; - struct sockaddr name; - int namelen; - - assert(AMDeviceStartService(device, CFSTR("com.apple.debugserver"), &gdbfd, NULL) == 0); - assert (gdbfd); + + int res = AMDeviceStartService(device, CFSTR("com.apple.debugserver"), &gdbfd, NULL); + assert(res == 0); + assert(gdbfd > 0); /* * The debugserver connection is through a fd handle, while lldb requires a host/port to connect, so create an intermediate @@ -887,20 +881,24 @@ void start_remote_debug_server(AMDeviceRef device) { addr4.sin_len = sizeof(addr4); addr4.sin_family = AF_INET; addr4.sin_port = htons(port); - addr4.sin_addr.s_addr = htonl(INADDR_ANY); + addr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); CFSocketRef fdvendor = CFSocketCreate(NULL, PF_INET, 0, 0, kCFSocketAcceptCallBack, &fdvendor_callback, NULL); - int yes = 1; - setsockopt(CFSocketGetNative(fdvendor), SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); - int flag = 1; - res = setsockopt(CFSocketGetNative(fdvendor), IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)); - assert (res == 0); + if (port) { + int yes = 1; + setsockopt(CFSocketGetNative(fdvendor), SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); + } CFDataRef address_data = CFDataCreate(NULL, (const UInt8 *)&addr4, sizeof(addr4)); CFSocketSetAddress(fdvendor, address_data); CFRelease(address_data); + socklen_t addrlen = sizeof(addr4); + res = getsockname(CFSocketGetNative(fdvendor),(struct sockaddr *)&addr4,&addrlen); + assert(res == 0); + port = ntohs(addr4.sin_port); + CFRunLoopAddSource(CFRunLoopGetMain(), CFSocketCreateRunLoopSource(NULL, fdvendor, 0), kCFRunLoopCommonModes); } @@ -1665,7 +1663,7 @@ void usage(const char* app) { " -L, --justlaunch just launch the app and exit lldb\n" " -v, --verbose enable verbose output\n" " -m, --noinstall directly start debugging without app install (-d not required)\n" - " -p, --port port used for device, default: 12345 \n" + " -p, --port port used for device, default: dynamic\n" " -r, --uninstall uninstall the app before install (do not use with -m; app cache and data are cleared) \n" " -1, --bundle_id specify bundle id for list and upload\n" " -l, --list list files\n" From 5efdcae8cec80f6fd15dc31f1b319585ac14b8aa Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 6 Apr 2015 13:53:56 -0700 Subject: [PATCH 104/219] Incremented version to 1.5.0 --- ios-deploy.c | 125 +++++++++++++++++++++++++-------------------------- package.json | 2 +- 2 files changed, 63 insertions(+), 64 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index dfc4d296..0e0b7dd0 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -16,7 +16,7 @@ #include #include "MobileDevice.h" -#define APP_VERSION "1.4.0" +#define APP_VERSION "1.5.0" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH /* @@ -328,16 +328,16 @@ const CFStringRef get_device_hardware_name(const AMDeviceRef device) { } // iPod Touch - + GET_FRIENDLY_MODEL_NAME(model, "N45AP", "iPod Touch") GET_FRIENDLY_MODEL_NAME(model, "N72AP", "iPod Touch 2G") GET_FRIENDLY_MODEL_NAME(model, "N18AP", "iPod Touch 3G") GET_FRIENDLY_MODEL_NAME(model, "N81AP", "iPod Touch 4G") GET_FRIENDLY_MODEL_NAME(model, "N78AP", "iPod Touch 5G") GET_FRIENDLY_MODEL_NAME(model, "N78AAP", "iPod Touch 5G") - + // iPad - + GET_FRIENDLY_MODEL_NAME(model, "K48AP", "iPad") GET_FRIENDLY_MODEL_NAME(model, "K93AP", "iPad 2") GET_FRIENDLY_MODEL_NAME(model, "K94AP", "iPad 2 (GSM)") @@ -349,7 +349,7 @@ const CFStringRef get_device_hardware_name(const AMDeviceRef device) { GET_FRIENDLY_MODEL_NAME(model, "P101AP", "iPad 4") GET_FRIENDLY_MODEL_NAME(model, "P102AP", "iPad 4 (GSM)") GET_FRIENDLY_MODEL_NAME(model, "P103AP", "iPad 4 (CDMA)") - + // iPad Mini GET_FRIENDLY_MODEL_NAME(model, "P105AP", "iPad mini") @@ -357,11 +357,11 @@ const CFStringRef get_device_hardware_name(const AMDeviceRef device) { GET_FRIENDLY_MODEL_NAME(model, "P107AP", "iPad mini (CDMA)") // Apple TV - + GET_FRIENDLY_MODEL_NAME(model, "K66AP", "Apple TV 2G") GET_FRIENDLY_MODEL_NAME(model, "J33AP", "Apple TV 3G") GET_FRIENDLY_MODEL_NAME(model, "J33IAP", "Apple TV 3.1G") - + // iPhone GET_FRIENDLY_MODEL_NAME(model, "M68AP", "iPhone") @@ -407,7 +407,7 @@ CFStringRef get_device_full_name(const AMDeviceRef device) { model_name = NULL; AMDeviceConnect(device); - + device_name = AMDeviceCopyValue(device, 0, CFSTR("DeviceName")), model_name = get_device_hardware_name(device); @@ -418,7 +418,7 @@ CFStringRef get_device_full_name(const AMDeviceRef device) { CFShow(device_name); printf("\n"); free(devName); - + char *mdlName = MYCFStringCopyUTF8String(model_name); printf("Model Name:[%s]\n",mdlName); printf("MM: [%s]\n",CFStringGetCStringPtr(model_name, kCFStringEncodingUTF8)); @@ -658,10 +658,10 @@ CFURLRef copy_device_app_url(AMDeviceRef device, CFStringRef identifier) { @"UIStatusBarHidden", @"UISupportedInterfaceOrientations", nil]; - + NSDictionary *optionsDict = [NSDictionary dictionaryWithObject:a forKey:@"ReturnAttributes"]; CFDictionaryRef options = (CFDictionaryRef)optionsDict; - + afc_error_t resultStatus = AMDeviceLookupApplications(device, options, &result); assert(resultStatus == 0); @@ -717,13 +717,13 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { rangeLLDB.length = CFStringGetLength(pmodule); CFStringFindAndReplace(pmodule, CFSTR("{args}"), cf_args, rangeLLDB, 0); - //printf("write_lldb_prep_cmds:args: [%s][%s]\n", CFStringGetCStringPtr (cmds,kCFStringEncodingMacRoman), + //printf("write_lldb_prep_cmds:args: [%s][%s]\n", CFStringGetCStringPtr (cmds,kCFStringEncodingMacRoman), // CFStringGetCStringPtr(pmodule, kCFStringEncodingMacRoman)); CFRelease(cf_args); } else { CFStringFindAndReplace(cmds, CFSTR("{args}"), CFSTR(""), range, 0); CFStringFindAndReplace(pmodule, CFSTR("{args}"), CFSTR(""), rangeLLDB, 0); - //printf("write_lldb_prep_cmds: [%s][%s]\n", CFStringGetCStringPtr (cmds,kCFStringEncodingMacRoman), + //printf("write_lldb_prep_cmds: [%s][%s]\n", CFStringGetCStringPtr (cmds,kCFStringEncodingMacRoman), // CFStringGetCStringPtr(pmodule, kCFStringEncodingMacRoman)); } range.length = CFStringGetLength(cmds); @@ -974,38 +974,38 @@ void setup_dummy_pipe_on_stdin(int pfd[2]) { void setup_lldb(AMDeviceRef device, CFURLRef url) { CFStringRef device_full_name = get_device_full_name(device), device_interface_name = get_device_interface_name(device); - + AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); assert(AMDeviceValidatePairing(device) == 0); assert(AMDeviceStartSession(device) == 0); - + printf("------ Debug phase ------\n"); - + if(AMDeviceGetInterfaceType(device) == 2) { printf("Cannot debug %s over %s.\n", CFStringGetCStringPtr(device_full_name, CFStringGetSystemEncoding()), CFStringGetCStringPtr(device_interface_name, CFStringGetSystemEncoding())); exit(0); } - + printf("Starting debug of %s connected through %s...\n", CFStringGetCStringPtr(device_full_name, CFStringGetSystemEncoding()), CFStringGetCStringPtr(device_interface_name, CFStringGetSystemEncoding())); - + mount_developer_image(device); // put debugserver on the device start_remote_debug_server(device); // start debugserver write_lldb_prep_cmds(device, url); // dump the necessary lldb commands into a file - + CFRelease(url); - + printf("[100%%] Connecting to remote debug server\n"); printf("-------------------------\n"); - + setpgid(getpid(), 0); signal(SIGHUP, killed); signal(SIGINT, killed); signal(SIGTERM, killed); // Need this before fork to avoid race conditions. For child process we remove this right after fork. signal(SIGLLDB, lldb_finished_handler); - + parent = getpid(); } @@ -1039,7 +1039,7 @@ void launch_debugger(AMDeviceRef device, CFURLRef url) { close(pfd[0]); close(pfd[1]); - + // Notify parent we're exiting kill(parent, SIGLLDB); // Pass lldb exit code @@ -1062,21 +1062,21 @@ void launch_debugger_and_exit(AMDeviceRef device, CFURLRef url) { signal(SIGHUP, SIG_DFL); signal(SIGLLDB, SIG_DFL); child = getpid(); - + if (dup2(pfd[0],STDIN_FILENO) == -1) perror("dup2 failed"); - + char lldb_shell[400]; sprintf(lldb_shell, LLDB_SHELL); if(device_id != NULL) strcat(lldb_shell, device_id); - + int status = system(lldb_shell); // launch lldb if (status == -1) perror("failed launching lldb"); - + close(pfd[0]); - + // Notify parent we're exiting kill(parent, SIGLLDB); // Pass lldb exit code @@ -1127,20 +1127,20 @@ CFStringRef get_bundle_id(CFURLRef app_url) return bundle_id; } - + void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir, void(*callback)(afc_connection *conn,const char *dir,int file)) { char *dir_ent; - + afc_connection afc_conn; if (!afc_conn_p) { afc_conn_p = &afc_conn; AFCConnectionOpen(afcFd, 0, &afc_conn_p); } - + printf("%s\n", dir); - + afc_dictionary* afc_dict_p; char *key, *val; int not_dir = 0; @@ -1150,7 +1150,7 @@ void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir, // there was a problem reading or opening the file to get info on it, abort return; } - + while((AFCKeyValueRead(afc_dict_p,&key,&val) == 0) && key && val) { if (strcmp(key,"st_ifmt")==0) { not_dir = strcmp(val,"S_IFDIR"); @@ -1166,23 +1166,23 @@ void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir, afc_directory* afc_dir_p; afc_error_t err = AFCDirectoryOpen(afc_conn_p, dir, &afc_dir_p); - + if (err != 0) { // Couldn't open dir - was probably a file return; } else { if (callback) (*callback)(afc_conn_p, dir, not_dir); } - + while(true) { err = AFCDirectoryRead(afc_conn_p, afc_dir_p, &dir_ent); - + if (err != 0 || !dir_ent) break; - + if (strcmp(dir_ent, ".") == 0 || strcmp(dir_ent, "..") == 0) continue; - + char* dir_joined = malloc(strlen(dir) + strlen(dir_ent) + 2); strcpy(dir_joined, dir); if (dir_joined[strlen(dir)-1] != '/') @@ -1191,7 +1191,7 @@ void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir, read_dir(afcFd, afc_conn_p, dir_joined, callback); free(dir_joined); } - + AFCDirectoryClose(afc_conn_p, afc_dir_p); } @@ -1202,25 +1202,25 @@ service_conn_t start_house_arrest_service(AMDeviceRef device) { assert(AMDeviceIsPaired(device)); assert(AMDeviceValidatePairing(device) == 0); assert(AMDeviceStartSession(device) == 0); - + service_conn_t houseFd; - + if (bundle_id == NULL) { printf("Bundle id is not specified\n"); exit(1); } - + CFStringRef cf_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingASCII); if (AMDeviceStartHouseArrestService(device, cf_bundle_id, 0, &houseFd, 0) != 0) { printf("Unable to find bundle with id: %s\n", bundle_id); exit(1); } - + assert(AMDeviceStopSession(device) == 0); assert(AMDeviceDisconnect(device) == 0); CFRelease(cf_bundle_id); - + return houseFd; } @@ -1248,7 +1248,7 @@ void* read_file_to_memory(char * path, size_t* file_size) { return NULL; } - + *file_size = buf.st_size; FILE* fd = fopen(path, "r"); char* content = malloc(*file_size); @@ -1264,7 +1264,7 @@ void* read_file_to_memory(char * path, size_t* file_size) void list_files(AMDeviceRef device) { service_conn_t houseFd = start_house_arrest_service(device); - + afc_connection* afc_conn_p; if (AFCConnectionOpen(houseFd, 0, &afc_conn_p) == 0) { read_dir(houseFd, afc_conn_p, list_root?list_root:"/", NULL); @@ -1289,7 +1289,7 @@ int app_exists(AMDeviceRef device) NSArray *a = [NSArray arrayWithObjects:@"CFBundleIdentifier", nil]; NSDictionary *optionsDict = [NSDictionary dictionaryWithObject:a forKey:@"ReturnAttributes"]; CFDictionaryRef options = (CFDictionaryRef)optionsDict; - + CFDictionaryRef result = nil; afc_error_t resultStatus = AMDeviceLookupApplications(device, options, &result); assert(resultStatus == 0); @@ -1399,15 +1399,15 @@ void download_tree(AMDeviceRef device) void upload_file(AMDeviceRef device) { service_conn_t houseFd = start_house_arrest_service(device); - + afc_file_ref file_ref; - + afc_connection afc_conn; afc_connection* afc_conn_p = &afc_conn; AFCConnectionOpen(houseFd, 0, &afc_conn_p); - + // read_dir(houseFd, NULL, "/", NULL); - + if (!target_filename) { target_filename = get_filename_from_path(upload_pathname); @@ -1415,7 +1415,7 @@ void upload_file(AMDeviceRef device) { size_t file_size; void* file_content = read_file_to_memory(upload_pathname, &file_size); - + if (!file_content) { printf("Could not open file: %s\n", upload_pathname); @@ -1435,7 +1435,7 @@ void upload_file(AMDeviceRef device) { *lastSlash = '\0'; assert(AFCDirectoryCreate(afc_conn_p, dirpath) == 0); } - + int ret = AFCFileRefOpen(afc_conn_p, target_filename, 3, &file_ref); if (ret == 0x000a) { @@ -1450,12 +1450,12 @@ void upload_file(AMDeviceRef device) { assert(AFCFileRefWrite(afc_conn_p, file_ref, file_content, file_size) == 0); assert(AFCFileRefClose(afc_conn_p, file_ref) == 0); assert(AFCConnectionClose(afc_conn_p) == 0); - + free(file_content); } void handle_device(AMDeviceRef device) { - //if (found_device) + //if (found_device) // return; // handle one device only CFStringRef found_device_id = AMDeviceCopyDeviceIdentifier(device), @@ -1480,7 +1480,7 @@ void handle_device(AMDeviceRef device) { } printf("[....] Using %s (%s).\n", CFStringGetCStringPtr(device_full_name, CFStringGetSystemEncoding()), CFStringGetCStringPtr(found_device_id, CFStringGetSystemEncoding())); - + if (command_only) { if (strcmp("list", command) == 0) { list_files(device); @@ -1514,7 +1514,7 @@ void handle_device(AMDeviceRef device) { assert(AMDeviceIsPaired(device)); assert(AMDeviceValidatePairing(device) == 0); assert(AMDeviceStartSession(device) == 0); - + int code = AMDeviceSecureUninstallApplication(0, device, bundle_id, 0, NULL, 0); if (code == 0) { printf("[ OK ] Uninstalled package with bundle id %s\n", CFStringGetCStringPtr(bundle_id, CFStringGetSystemEncoding())); @@ -1551,7 +1551,7 @@ void handle_device(AMDeviceRef device) { close(afcFd); - + AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); @@ -1587,9 +1587,9 @@ void handle_device(AMDeviceRef device) { printf("[100%%] Installed package %s\n", app_path); } - if (!debug) + if (!debug) exit(0); // no debug phase - + if (justlaunch) launch_debugger_and_exit(device, url); else @@ -1602,7 +1602,7 @@ void device_callback(struct am_device_notification_callback_info *info, void *ar if(device_id != NULL || !debug || AMDeviceGetInterfaceType(info->dev) != 2) { handle_device(info->dev); } else if(best_device_match == NULL) { - best_device_match = info->dev; + best_device_match = info->dev; CFRetain(best_device_match); } default: @@ -1629,7 +1629,7 @@ void timeout_callback(CFRunLoopTimerRef timer, void *info) { if (!debug) { printf("[....] No more devices found.\n"); } - + if (detect_only && !found_device) { exit(exitcode_error); return; @@ -1822,4 +1822,3 @@ int main(int argc, char *argv[]) { AMDeviceNotificationSubscribe(&device_callback, 0, 0, NULL, ¬ify); CFRunLoopRun(); } - diff --git a/package.json b/package.json index d6b1d6b0..cd62282a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ios-deploy", - "version": "1.4.0", + "version": "1.5.0", "description": "launch iOS apps iOS devices from the command line (Xcode 6)", "main": "ios-deploy", "scripts": { From c1a0623e493e096a92eaffc8a642c39c8906678e Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 6 Apr 2015 14:06:52 -0700 Subject: [PATCH 105/219] Added doc to download specific directory (ie Documents) from an installed app (closes #108) --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index b17b2726..7e00feaa 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,9 @@ The commands below assume that you have an app called `my.app` with bundle id `b // check whether an app by bundle id exists on the device (check return code `echo $?`) ios-deploy --exists --bundle_id com.apple.mobilemail + // Download the Documents directory of the app *only* + ios-deploy --download=/Documents -bundle_id my.app.id --to ./my_download_location + ## Demo * The included demo.app represents the minimum required to get code running on iOS. From 02c23792eedbe49bacd89df787cae65896cb245a Mon Sep 17 00:00:00 2001 From: senthil Date: Sat, 11 Apr 2015 14:18:54 -0400 Subject: [PATCH 106/219] merged with version 1.5.0 Updated for devices that use japanese Updated the version to 1.5.1 --- ios-deploy.c | 340 ++++++++++++++++++++++++++++----------------------- 1 file changed, 190 insertions(+), 150 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index ea722d6b..584f84dc 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -16,7 +16,7 @@ #include #include "MobileDevice.h" -#define APP_VERSION "1.3.7" +#define APP_VERSION "1.5.1" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH /* @@ -61,6 +61,7 @@ const char* lldb_prep_noninteractive_cmds = "\ */ #define LLDB_FRUITSTRAP_MODULE CFSTR("\ import lldb\n\ +import os\n\ import sys\n\ import shlex\n\ \n\ @@ -90,13 +91,14 @@ def connect_command(debugger, command, result, internal_dict):\n\ \n\ def run_command(debugger, command, result, internal_dict):\n\ device_app = internal_dict['fruitstrap_device_app']\n\ + args = command.split('--',1)\n\ error = lldb.SBError()\n\ lldb.target.modules[0].SetPlatformFileSpec(lldb.SBFileSpec(device_app))\n\ - lldb.target.Launch(lldb.SBLaunchInfo(shlex.split('{args}')), error)\n\ + lldb.target.Launch(lldb.SBLaunchInfo(shlex.split(args[1] and args[1] or '{args}')), error)\n\ lockedstr = ': Locked'\n\ if lockedstr in str(error):\n\ print('\\nDevice Locked\\n')\n\ - sys.exit({exitcode_error})\n\ + os._exit(254)\n\ else:\n\ print(str(error))\n\ \n\ @@ -106,12 +108,16 @@ def safequit_command(debugger, command, result, internal_dict):\n\ listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR)\n\ event = lldb.SBEvent()\n\ while True:\n\ - if listener.WaitForEvent(1, event):\n\ - state = process.GetStateFromEvent(event)\n\ + if listener.WaitForEvent(1, event) and lldb.SBProcess.EventIsProcessEvent(event):\n\ + state = lldb.SBProcess.GetStateFromEvent(event)\n\ else:\n\ - state = lldb.eStateInvalid\n\ - process.Detach()\n\ - sys.exit(0)\n\ + state = process.GetState()\n\ +\n\ + if state == lldb.eStateRunning:\n\ + process.Detach()\n\ + os._exit(0)\n\ + elif state > lldb.eStateRunning:\n\ + os._exit(state)\n\ \n\ def autoexit_command(debugger, command, result, internal_dict):\n\ process = lldb.target.process\n\ @@ -119,10 +125,16 @@ def autoexit_command(debugger, command, result, internal_dict):\n\ listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR)\n\ event = lldb.SBEvent()\n\ while True:\n\ - if listener.WaitForEvent(1, event):\n\ - state = process.GetStateFromEvent(event)\n\ + if listener.WaitForEvent(1, event) and lldb.SBProcess.EventIsProcessEvent(event):\n\ + state = lldb.SBProcess.GetStateFromEvent(event)\n\ else:\n\ - state = lldb.eStateInvalid\n\ + state = process.GetState()\n\ +\n\ + if state == lldb.eStateExited:\n\ + os._exit(process.GetExitStatus())\n\ + elif state == lldb.eStateStopped:\n\ + debugger.HandleCommand('bt')\n\ + os._exit({exitcode_app_crash})\n\ \n\ stdout = process.GetSTDOUT(1024)\n\ while stdout:\n\ @@ -133,14 +145,6 @@ def autoexit_command(debugger, command, result, internal_dict):\n\ while stderr:\n\ sys.stdout.write(stderr)\n\ stderr = process.GetSTDERR(1024)\n\ -\n\ - if lldb.SBProcess.EventIsProcessEvent(event):\n\ - if state == lldb.eStateExited:\n\ - sys.exit(process.GetExitStatus())\n\ - if state == lldb.eStateStopped:\n\ - debugger.HandleCommand('frame select')\n\ - debugger.HandleCommand('bt')\n\ - sys.exit({exitcode_app_crash})\n\ ") typedef struct am_device * AMDeviceRef; @@ -164,7 +168,7 @@ char *device_id = NULL; char *args = NULL; char *list_root = NULL; int timeout = 0; -int port = 12345; +int port = 0; // 0 means "dynamically assigned" CFStringRef last_path = NULL; service_conn_t gdbfd; pid_t parent = 0; @@ -176,8 +180,26 @@ AMDeviceRef best_device_match = NULL; // Error codes we report on different failures, so scripts can distinguish between user app exit // codes and our exit codes. For non app errors we use codes in reserved 128-255 range. -const int exitcode_error = SIGTERM; -const int exitcode_app_crash = SIGABRT; +const int exitcode_error = 253; +const int exitcode_app_crash = 254; + +void fprintCFSTR(FILE* console, CFStringRef formatString, ...) { + CFStringRef resultString; + CFDataRef data; + va_list argList; + va_start(argList, formatString); + resultString = CFStringCreateWithFormatAndArguments(NULL, NULL, + formatString, argList); + va_end(argList); + data = CFStringCreateExternalRepresentation(NULL, resultString, + kCFStringEncodingUTF8, '?'); + if (data != NULL) { + fprintf (console, "%.*s\n\n", (int)CFDataGetLength(data), + CFDataGetBytePtr(data)); + CFRelease(data); + } + CFRelease(resultString); +} Boolean path_exists(CFTypeRef path) { if (CFGetTypeID(path) == CFStringGetTypeID()) { @@ -318,14 +340,12 @@ CFStringRef copy_xcode_path_for(CFStringRef subPath, CFStringRef search) { // Please ensure that device is connected or the name will be unknown const CFStringRef get_device_hardware_name(const AMDeviceRef device) { CFStringRef model = AMDeviceCopyValue(device, 0, CFSTR("HardwareModel")); - - if (model == NULL) - { - return CFSTR("Unknown Device"); + + if (model == NULL) { + return CFSTR("Unknown Device"); } - //printf("Device model: %s\n", CFStringGetCStringPtr(model, CFStringGetSystemEncoding())); - //iPod Touch + // iPod Touch GET_FRIENDLY_MODEL_NAME(model, "N45AP", "iPod Touch") GET_FRIENDLY_MODEL_NAME(model, "N72AP", "iPod Touch 2G") @@ -335,7 +355,7 @@ const CFStringRef get_device_hardware_name(const AMDeviceRef device) { GET_FRIENDLY_MODEL_NAME(model, "N78AAP", "iPod Touch 5G") // iPad - + GET_FRIENDLY_MODEL_NAME(model, "K48AP", "iPad") GET_FRIENDLY_MODEL_NAME(model, "K93AP", "iPad 2") GET_FRIENDLY_MODEL_NAME(model, "K94AP", "iPad 2 (GSM)") @@ -347,7 +367,7 @@ const CFStringRef get_device_hardware_name(const AMDeviceRef device) { GET_FRIENDLY_MODEL_NAME(model, "P101AP", "iPad 4") GET_FRIENDLY_MODEL_NAME(model, "P102AP", "iPad 4 (GSM)") GET_FRIENDLY_MODEL_NAME(model, "P103AP", "iPad 4 (CDMA)") - + // iPad Mini GET_FRIENDLY_MODEL_NAME(model, "P105AP", "iPad mini") @@ -355,11 +375,11 @@ const CFStringRef get_device_hardware_name(const AMDeviceRef device) { GET_FRIENDLY_MODEL_NAME(model, "P107AP", "iPad mini (CDMA)") // Apple TV - + GET_FRIENDLY_MODEL_NAME(model, "K66AP", "Apple TV 2G") GET_FRIENDLY_MODEL_NAME(model, "J33AP", "Apple TV 3G") GET_FRIENDLY_MODEL_NAME(model, "J33IAP", "Apple TV 3.1G") - + // iPhone GET_FRIENDLY_MODEL_NAME(model, "M68AP", "iPhone") @@ -405,24 +425,16 @@ CFStringRef get_device_full_name(const AMDeviceRef device) { model_name = NULL; AMDeviceConnect(device); - + device_name = AMDeviceCopyValue(device, 0, CFSTR("DeviceName")), model_name = get_device_hardware_name(device); if (verbose) { - char *devName = MYCFStringCopyUTF8String(device_name); - printf("Device Name:[%s]\n",devName); - CFShow(device_name); - printf("\n"); - free(devName); - - char *mdlName = MYCFStringCopyUTF8String(model_name); - printf("Model Name:[%s]\n",mdlName); - printf("MM: [%s]\n",CFStringGetCStringPtr(model_name, kCFStringEncodingUTF8)); - CFShow(model_name); - printf("\n"); - free(mdlName); + if (device_name != NULL) + fprintCFSTR(stdout, CFSTR("Device Name:[%@]\n"), device_name); + if (model_name != NULL) + fprintCFSTR(stdout, CFSTR("Model Name:[%@]\n"), model_name); } if(device_name != NULL && model_name != NULL) @@ -656,10 +668,10 @@ CFURLRef copy_device_app_url(AMDeviceRef device, CFStringRef identifier) { @"UIStatusBarHidden", @"UISupportedInterfaceOrientations", nil]; - + NSDictionary *optionsDict = [NSDictionary dictionaryWithObject:a forKey:@"ReturnAttributes"]; CFDictionaryRef options = (CFDictionaryRef)optionsDict; - + afc_error_t resultStatus = AMDeviceLookupApplications(device, options, &result); assert(resultStatus == 0); @@ -705,8 +717,6 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { CFMutableStringRef pmodule = CFStringCreateMutableCopy(NULL, 0, LLDB_FRUITSTRAP_MODULE); CFRange rangeLLDB = { 0, CFStringGetLength(pmodule) }; - CFStringRef exitcode_error_str = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), exitcode_error); - CFStringFindAndReplace(pmodule, CFSTR("{exitcode_error}"), exitcode_error_str, rangeLLDB, 0); CFStringRef exitcode_app_crash_str = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), exitcode_app_crash); CFStringFindAndReplace(pmodule, CFSTR("{exitcode_app_crash}"), exitcode_app_crash_str, rangeLLDB, 0); rangeLLDB.length = CFStringGetLength(pmodule); @@ -717,13 +727,13 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { rangeLLDB.length = CFStringGetLength(pmodule); CFStringFindAndReplace(pmodule, CFSTR("{args}"), cf_args, rangeLLDB, 0); - //printf("write_lldb_prep_cmds:args: [%s][%s]\n", CFStringGetCStringPtr (cmds,kCFStringEncodingMacRoman), + //printf("write_lldb_prep_cmds:args: [%s][%s]\n", CFStringGetCStringPtr (cmds,kCFStringEncodingMacRoman), // CFStringGetCStringPtr(pmodule, kCFStringEncodingMacRoman)); CFRelease(cf_args); } else { CFStringFindAndReplace(cmds, CFSTR("{args}"), CFSTR(""), range, 0); CFStringFindAndReplace(pmodule, CFSTR("{args}"), CFSTR(""), rangeLLDB, 0); - //printf("write_lldb_prep_cmds: [%s][%s]\n", CFStringGetCStringPtr (cmds,kCFStringEncodingMacRoman), + //printf("write_lldb_prep_cmds: [%s][%s]\n", CFStringGetCStringPtr (cmds,kCFStringEncodingMacRoman), // CFStringGetCStringPtr(pmodule, kCFStringEncodingMacRoman)); } range.length = CFStringGetLength(cmds); @@ -826,27 +836,9 @@ server_callback (CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef add int res; if (CFDataGetLength (data) == 0) { - // FIXME: Close the socket - //shutdown (CFSocketGetNative (lldb_socket), SHUT_RDWR); - //close (CFSocketGetNative (lldb_socket)); - CFSocketInvalidate(lldb_socket); - CFSocketInvalidate(server_socket); - int mypid = getpid(); - assert((child != 0) && (child != mypid)); //child should not be here - if ((parent != 0) && (parent == mypid) && (child != 0)) - { - if (verbose) - { - printf("Got an empty packet hence killing child (%d) tree\n", child); - } - kill_ptree(child, SIGHUP); - } - if (justlaunch) - //when in justlaunch at times, we get an empty packet at the end. - //Assume everything is ok - exit(0); - else - exit(exitcode_error); + // close the socket on which we've got end-of-file, the server_socket. + CFSocketInvalidate(s); + CFRelease(s); return; } res = write (CFSocketGetNative (lldb_socket), CFDataGetBytePtr (data), CFDataGetLength (data)); @@ -856,8 +848,12 @@ void lldb_callback(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef a { //printf ("lldb: %s\n", CFDataGetBytePtr (data)); - if (CFDataGetLength (data) == 0) + if (CFDataGetLength (data) == 0) { + // close the socket on which we've got end-of-file, the lldb_socket. + CFSocketInvalidate(s); + CFRelease(s); return; + } write (gdbfd, CFDataGetBytePtr (data), CFDataGetLength (data)); } @@ -868,21 +864,20 @@ void fdvendor_callback(CFSocketRef s, CFSocketCallBackType callbackType, CFDataR //PRINT ("callback!\n"); lldb_socket = CFSocketCreateWithNative(NULL, socket, kCFSocketDataCallBack, &lldb_callback, NULL); + int flag = 1; + int res = setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(flag)); + assert(res == 0); CFRunLoopAddSource(CFRunLoopGetMain(), CFSocketCreateRunLoopSource(NULL, lldb_socket, 0), kCFRunLoopCommonModes); + + CFSocketInvalidate(s); + CFRelease(s); } void start_remote_debug_server(AMDeviceRef device) { - char buf [256]; - int res, err, i; - char msg [256]; - int chsum, len; - struct stat s; - socklen_t buflen; - struct sockaddr name; - int namelen; - - assert(AMDeviceStartService(device, CFSTR("com.apple.debugserver"), &gdbfd, NULL) == 0); - assert (gdbfd); + + int res = AMDeviceStartService(device, CFSTR("com.apple.debugserver"), &gdbfd, NULL); + assert(res == 0); + assert(gdbfd > 0); /* * The debugserver connection is through a fd handle, while lldb requires a host/port to connect, so create an intermediate @@ -896,20 +891,24 @@ void start_remote_debug_server(AMDeviceRef device) { addr4.sin_len = sizeof(addr4); addr4.sin_family = AF_INET; addr4.sin_port = htons(port); - addr4.sin_addr.s_addr = htonl(INADDR_ANY); + addr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); CFSocketRef fdvendor = CFSocketCreate(NULL, PF_INET, 0, 0, kCFSocketAcceptCallBack, &fdvendor_callback, NULL); - int yes = 1; - setsockopt(CFSocketGetNative(fdvendor), SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); - int flag = 1; - res = setsockopt(CFSocketGetNative(fdvendor), IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)); - assert (res == 0); + if (port) { + int yes = 1; + setsockopt(CFSocketGetNative(fdvendor), SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); + } CFDataRef address_data = CFDataCreate(NULL, (const UInt8 *)&addr4, sizeof(addr4)); CFSocketSetAddress(fdvendor, address_data); CFRelease(address_data); + socklen_t addrlen = sizeof(addr4); + res = getsockname(CFSocketGetNative(fdvendor),(struct sockaddr *)&addr4,&addrlen); + assert(res == 0); + port = ntohs(addr4.sin_port); + CFRunLoopAddSource(CFRunLoopGetMain(), CFSocketCreateRunLoopSource(NULL, fdvendor, 0), kCFRunLoopCommonModes); } @@ -985,38 +984,38 @@ void setup_dummy_pipe_on_stdin(int pfd[2]) { void setup_lldb(AMDeviceRef device, CFURLRef url) { CFStringRef device_full_name = get_device_full_name(device), device_interface_name = get_device_interface_name(device); - + AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); assert(AMDeviceValidatePairing(device) == 0); assert(AMDeviceStartSession(device) == 0); - + printf("------ Debug phase ------\n"); - + if(AMDeviceGetInterfaceType(device) == 2) { - printf("Cannot debug %s over %s.\n", CFStringGetCStringPtr(device_full_name, CFStringGetSystemEncoding()), CFStringGetCStringPtr(device_interface_name, CFStringGetSystemEncoding())); + fprintCFSTR(stdout, CFSTR("Cannot debug %@ over %@.\n"), device_full_name, device_interface_name); exit(0); } - - printf("Starting debug of %s connected through %s...\n", CFStringGetCStringPtr(device_full_name, CFStringGetSystemEncoding()), CFStringGetCStringPtr(device_interface_name, CFStringGetSystemEncoding())); - + + fprintCFSTR(stdout, CFSTR("Starting debug of %@ connected through %@...\n"), device_full_name, device_interface_name); + mount_developer_image(device); // put debugserver on the device start_remote_debug_server(device); // start debugserver write_lldb_prep_cmds(device, url); // dump the necessary lldb commands into a file - + CFRelease(url); - + printf("[100%%] Connecting to remote debug server\n"); printf("-------------------------\n"); - + setpgid(getpid(), 0); signal(SIGHUP, killed); signal(SIGINT, killed); signal(SIGTERM, killed); // Need this before fork to avoid race conditions. For child process we remove this right after fork. signal(SIGLLDB, lldb_finished_handler); - + parent = getpid(); } @@ -1050,7 +1049,7 @@ void launch_debugger(AMDeviceRef device, CFURLRef url) { close(pfd[0]); close(pfd[1]); - + // Notify parent we're exiting kill(parent, SIGLLDB); // Pass lldb exit code @@ -1073,21 +1072,21 @@ void launch_debugger_and_exit(AMDeviceRef device, CFURLRef url) { signal(SIGHUP, SIG_DFL); signal(SIGLLDB, SIG_DFL); child = getpid(); - + if (dup2(pfd[0],STDIN_FILENO) == -1) perror("dup2 failed"); - + char lldb_shell[400]; sprintf(lldb_shell, LLDB_SHELL); if(device_id != NULL) strcat(lldb_shell, device_id); - + int status = system(lldb_shell); // launch lldb if (status == -1) perror("failed launching lldb"); - + close(pfd[0]); - + // Notify parent we're exiting kill(parent, SIGLLDB); // Pass lldb exit code @@ -1138,20 +1137,20 @@ CFStringRef get_bundle_id(CFURLRef app_url) return bundle_id; } - + void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir, void(*callback)(afc_connection *conn,const char *dir,int file)) { char *dir_ent; - + afc_connection afc_conn; if (!afc_conn_p) { afc_conn_p = &afc_conn; AFCConnectionOpen(afcFd, 0, &afc_conn_p); } - + printf("%s\n", dir); - + afc_dictionary* afc_dict_p; char *key, *val; int not_dir = 0; @@ -1161,7 +1160,7 @@ void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir, // there was a problem reading or opening the file to get info on it, abort return; } - + while((AFCKeyValueRead(afc_dict_p,&key,&val) == 0) && key && val) { if (strcmp(key,"st_ifmt")==0) { not_dir = strcmp(val,"S_IFDIR"); @@ -1177,23 +1176,23 @@ void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir, afc_directory* afc_dir_p; afc_error_t err = AFCDirectoryOpen(afc_conn_p, dir, &afc_dir_p); - + if (err != 0) { // Couldn't open dir - was probably a file return; } else { if (callback) (*callback)(afc_conn_p, dir, not_dir); } - + while(true) { err = AFCDirectoryRead(afc_conn_p, afc_dir_p, &dir_ent); - + if (err != 0 || !dir_ent) break; - + if (strcmp(dir_ent, ".") == 0 || strcmp(dir_ent, "..") == 0) continue; - + char* dir_joined = malloc(strlen(dir) + strlen(dir_ent) + 2); strcpy(dir_joined, dir); if (dir_joined[strlen(dir)-1] != '/') @@ -1202,7 +1201,7 @@ void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir, read_dir(afcFd, afc_conn_p, dir_joined, callback); free(dir_joined); } - + AFCDirectoryClose(afc_conn_p, afc_dir_p); } @@ -1213,25 +1212,25 @@ service_conn_t start_house_arrest_service(AMDeviceRef device) { assert(AMDeviceIsPaired(device)); assert(AMDeviceValidatePairing(device) == 0); assert(AMDeviceStartSession(device) == 0); - + service_conn_t houseFd; - + if (bundle_id == NULL) { printf("Bundle id is not specified\n"); exit(1); } - + CFStringRef cf_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingASCII); if (AMDeviceStartHouseArrestService(device, cf_bundle_id, 0, &houseFd, 0) != 0) { printf("Unable to find bundle with id: %s\n", bundle_id); exit(1); } - + assert(AMDeviceStopSession(device) == 0); assert(AMDeviceDisconnect(device) == 0); CFRelease(cf_bundle_id); - + return houseFd; } @@ -1259,7 +1258,7 @@ void* read_file_to_memory(char * path, size_t* file_size) { return NULL; } - + *file_size = buf.st_size; FILE* fd = fopen(path, "r"); char* content = malloc(*file_size); @@ -1275,7 +1274,7 @@ void* read_file_to_memory(char * path, size_t* file_size) void list_files(AMDeviceRef device) { service_conn_t houseFd = start_house_arrest_service(device); - + afc_connection* afc_conn_p; if (AFCConnectionOpen(houseFd, 0, &afc_conn_p) == 0) { read_dir(houseFd, afc_conn_p, list_root?list_root:"/", NULL); @@ -1283,6 +1282,40 @@ void list_files(AMDeviceRef device) } } +int app_exists(AMDeviceRef device) +{ + if (bundle_id == NULL) { + printf("Bundle id is not specified\n"); + return false; + } + + AMDeviceConnect(device); + assert(AMDeviceIsPaired(device)); + assert(AMDeviceValidatePairing(device) == 0); + assert(AMDeviceStartSession(device) == 0); + + CFStringRef cf_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingASCII); + + NSArray *a = [NSArray arrayWithObjects:@"CFBundleIdentifier", nil]; + NSDictionary *optionsDict = [NSDictionary dictionaryWithObject:a forKey:@"ReturnAttributes"]; + CFDictionaryRef options = (CFDictionaryRef)optionsDict; + + CFDictionaryRef result = nil; + afc_error_t resultStatus = AMDeviceLookupApplications(device, options, &result); + assert(resultStatus == 0); + + CFDictionaryRef app_dict = CFDictionaryGetValue(result, cf_bundle_id); + + int appExists = (app_dict == NULL) ? -1 : 0; + + CFRelease(cf_bundle_id); + + assert(AMDeviceStopSession(device) == 0); + assert(AMDeviceDisconnect(device) == 0); + + return appExists; +} + void copy_file_callback(afc_connection* afc_conn_p, const char *name,int file) { const char *local_name=name; @@ -1376,15 +1409,15 @@ void download_tree(AMDeviceRef device) void upload_file(AMDeviceRef device) { service_conn_t houseFd = start_house_arrest_service(device); - + afc_file_ref file_ref; - + afc_connection afc_conn; afc_connection* afc_conn_p = &afc_conn; AFCConnectionOpen(houseFd, 0, &afc_conn_p); - + // read_dir(houseFd, NULL, "/", NULL); - + if (!target_filename) { target_filename = get_filename_from_path(upload_pathname); @@ -1392,7 +1425,7 @@ void upload_file(AMDeviceRef device) { size_t file_size; void* file_content = read_file_to_memory(upload_pathname, &file_size); - + if (!file_content) { printf("Could not open file: %s\n", upload_pathname); @@ -1412,7 +1445,7 @@ void upload_file(AMDeviceRef device) { *lastSlash = '\0'; assert(AFCDirectoryCreate(afc_conn_p, dirpath) == 0); } - + int ret = AFCFileRefOpen(afc_conn_p, target_filename, 3, &file_ref); if (ret == 0x000a) { @@ -1427,12 +1460,12 @@ void upload_file(AMDeviceRef device) { assert(AFCFileRefWrite(afc_conn_p, file_ref, file_content, file_size) == 0); assert(AFCFileRefClose(afc_conn_p, file_ref) == 0); assert(AFCConnectionClose(afc_conn_p) == 0); - + free(file_content); } void handle_device(AMDeviceRef device) { - //if (found_device) + //if (found_device) // return; // handle one device only CFStringRef found_device_id = AMDeviceCopyDeviceIdentifier(device), @@ -1440,7 +1473,8 @@ void handle_device(AMDeviceRef device) { device_interface_name = get_device_interface_name(device); if (detect_only) { - printf("[....] Found %s connected through %s.\n", CFStringGetCStringPtr(device_full_name, CFStringGetSystemEncoding()), CFStringGetCStringPtr(device_interface_name, CFStringGetSystemEncoding())); + fprintCFSTR(stdout, CFSTR("[....] Found %@ connected through %@.\n"), device_full_name, device_interface_name); + //printf("[....] Found %s connected through %s.\n", CFStringGetCStringPtr(device_full_name, CFStringGetSystemEncoding()), CFStringGetCStringPtr(device_interface_name, CFStringGetSystemEncoding())); found_device = true; return; } @@ -1448,7 +1482,7 @@ void handle_device(AMDeviceRef device) { if(strcmp(device_id, CFStringGetCStringPtr(found_device_id, CFStringGetSystemEncoding())) == 0) { found_device = true; } else { - printf("Skipping %s.\n", CFStringGetCStringPtr(device_full_name, CFStringGetSystemEncoding())); + fprintCFSTR(stdout, CFSTR("Skipping %@.\n"), device_full_name); return; } } else { @@ -1456,8 +1490,8 @@ void handle_device(AMDeviceRef device) { found_device = true; } - printf("[....] Using %s (%s).\n", CFStringGetCStringPtr(device_full_name, CFStringGetSystemEncoding()), CFStringGetCStringPtr(found_device_id, CFStringGetSystemEncoding())); - + fprintCFSTR(stdout, CFSTR("[....] Using %@ (%@).\n"), device_full_name, found_device_id); + if (command_only) { if (strcmp("list", command) == 0) { list_files(device); @@ -1465,6 +1499,8 @@ void handle_device(AMDeviceRef device) { upload_file(device); } else if (strcmp("download", command) == 0) { download_tree(device); + } else if (strcmp("exists", command) == 0) { + exit(app_exists(device)); } exit(0); } @@ -1489,7 +1525,7 @@ void handle_device(AMDeviceRef device) { assert(AMDeviceIsPaired(device)); assert(AMDeviceValidatePairing(device) == 0); assert(AMDeviceStartSession(device) == 0); - + int code = AMDeviceSecureUninstallApplication(0, device, bundle_id, 0, NULL, 0); if (code == 0) { printf("[ OK ] Uninstalled package with bundle id %s\n", CFStringGetCStringPtr(bundle_id, CFStringGetSystemEncoding())); @@ -1503,7 +1539,7 @@ void handle_device(AMDeviceRef device) { if(install) { printf("------ Install phase ------\n"); - printf("[ 0%%] Found %s connected through %s, beginning install\n", CFStringGetCStringPtr(device_full_name, CFStringGetSystemEncoding()), CFStringGetCStringPtr(device_interface_name, CFStringGetSystemEncoding())); + fprintCFSTR(stdout, CFSTR("[ 0%%] Found %@ connected through %@, beginning install\n"), device_full_name, device_interface_name); AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); @@ -1526,7 +1562,7 @@ void handle_device(AMDeviceRef device) { close(afcFd); - + AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); @@ -1562,9 +1598,9 @@ void handle_device(AMDeviceRef device) { printf("[100%%] Installed package %s\n", app_path); } - if (!debug) + if (!debug) exit(0); // no debug phase - + if (justlaunch) launch_debugger_and_exit(device, url); else @@ -1577,7 +1613,7 @@ void device_callback(struct am_device_notification_callback_info *info, void *ar if(device_id != NULL || !debug || AMDeviceGetInterfaceType(info->dev) != 2) { handle_device(info->dev); } else if(best_device_match == NULL) { - best_device_match = info->dev; + best_device_match = info->dev; CFRetain(best_device_match); } default: @@ -1604,7 +1640,7 @@ void timeout_callback(CFRunLoopTimerRef timer, void *info) { if (!debug) { printf("[....] No more devices found.\n"); } - + if (detect_only && !found_device) { exit(exitcode_error); return; @@ -1638,14 +1674,15 @@ void usage(const char* app) { " -L, --justlaunch just launch the app and exit lldb\n" " -v, --verbose enable verbose output\n" " -m, --noinstall directly start debugging without app install (-d not required)\n" - " -p, --port port used for device, default: 12345 \n" + " -p, --port port used for device, default: dynamic\n" " -r, --uninstall uninstall the app before install (do not use with -m; app cache and data are cleared) \n" " -1, --bundle_id specify bundle id for list and upload\n" " -l, --list list files\n" " -o, --upload upload file\n" " -w, --download download app tree\n" " -2, --to use together with up/download file/tree. specify target\n" - " -V, --version print the executable version \n", + " -V, --version print the executable version \n" + " -e, --exists check if the app with given bundle_id is installed or not \n", app); } @@ -1675,11 +1712,12 @@ int main(int argc, char *argv[]) { { "upload", required_argument, NULL, 'o'}, { "download", optional_argument, NULL, 'w'}, { "to", required_argument, NULL, '2'}, + { "exists", no_argument, NULL, 'e'}, { NULL, 0, NULL, 0 }, }; char ch; - while ((ch = getopt_long(argc, argv, "VmcdvunrILi:b:a:t:g:x:p:1:2:o:l::w::", longopts, NULL)) != -1) + while ((ch = getopt_long(argc, argv, "VmcdvunrILei:b:a:t:g:x:p:1:2:o:l::w::", longopts, NULL)) != -1) { switch (ch) { case 'm': @@ -1716,7 +1754,6 @@ int main(int argc, char *argv[]) { case 'L': interactive = false; justlaunch = true; - debug = 1; break; case 'c': detect_only = true; @@ -1724,7 +1761,7 @@ int main(int argc, char *argv[]) { break; case 'V': show_version(); - return exitcode_error; + return 0; case 'p': port = atoi(optarg); break; @@ -1752,6 +1789,10 @@ int main(int argc, char *argv[]) { command = "download"; list_root = optarg; break; + case 'e': + command_only = true; + command = "exists"; + break; default: usage(argv[0]); return exitcode_error; @@ -1792,4 +1833,3 @@ int main(int argc, char *argv[]) { AMDeviceNotificationSubscribe(&device_callback, 0, 0, NULL, ¬ify); CFRunLoopRun(); } - From d90171d8e71a6a804881e65cdff41cc68b572afa Mon Sep 17 00:00:00 2001 From: senthil Date: Sat, 11 Apr 2015 14:40:49 -0400 Subject: [PATCH 107/219] updated to merge with phonegap --- README.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 07b4d007..4c566e10 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ $ npm install -g ios-deploy -w, --download download app tree -2, --to use together with up/download file/tree. specify target -V, --version print the executable version + -e, --exists check if the app with given bundle_id is installed or not ## Examples @@ -68,6 +69,12 @@ The commands below assume that you have an app called `my.app` with bundle id `b // deploy and debug your app to a connected device, uninstall the app first ios-deploy --uninstall --debug --bundle my.app + // check whether an app by bundle id exists on the device (check return code `echo $?`) + ios-deploy --exists --bundle_id com.apple.mobilemail + + // Download the Documents directory of the app *only* + ios-deploy --download=/Documents -bundle_id my.app.id --to ./my_download_location + ## Demo * The included demo.app represents the minimum required to get code running on iOS. diff --git a/package.json b/package.json index 53b15d9e..1bd9e2ed 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ios-deploy", - "version": "1.3.2", + "version": "1.5.1", "description": "launch iOS apps iOS devices from the command line (Xcode 6)", "main": "ios-deploy", "scripts": { From 54a04e203f2e8d91939d1e909e38ae69fbf1b297 Mon Sep 17 00:00:00 2001 From: Ted Mielczarek Date: Wed, 15 Apr 2015 11:42:09 -0400 Subject: [PATCH 108/219] Add --mkdir and --rm options --- ios-deploy.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/ios-deploy.c b/ios-deploy.c index 0e0b7dd0..9d5c15fa 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1454,6 +1454,33 @@ void upload_file(AMDeviceRef device) { free(file_content); } +void make_directory(AMDeviceRef device) { + service_conn_t houseFd = start_house_arrest_service(device); + + afc_file_ref file_ref; + + afc_connection afc_conn; + afc_connection* afc_conn_p = &afc_conn; + AFCConnectionOpen(houseFd, 0, &afc_conn_p); + + assert(AFCDirectoryCreate(afc_conn_p, target_filename) == 0); + assert(AFCConnectionClose(afc_conn_p) == 0); +} + +void remove_path(AMDeviceRef device) { + service_conn_t houseFd = start_house_arrest_service(device); + + afc_file_ref file_ref; + + afc_connection afc_conn; + afc_connection* afc_conn_p = &afc_conn; + AFCConnectionOpen(houseFd, 0, &afc_conn_p); + + + assert(AFCRemovePath(afc_conn_p, target_filename) == 0); + assert(AFCConnectionClose(afc_conn_p) == 0); +} + void handle_device(AMDeviceRef device) { //if (found_device) // return; // handle one device only @@ -1488,6 +1515,10 @@ void handle_device(AMDeviceRef device) { upload_file(device); } else if (strcmp("download", command) == 0) { download_tree(device); + } else if (strcmp("mkdir", command) == 0) { + make_directory(device); + } else if (strcmp("rm", command) == 0) { + remove_path(device); } else if (strcmp("exists", command) == 0) { exit(app_exists(device)); } @@ -1670,6 +1701,8 @@ void usage(const char* app) { " -o, --upload upload file\n" " -w, --download download app tree\n" " -2, --to use together with up/download file/tree. specify target\n" + " -D, --mkdir make directory on device\n" + " -R, --rm remove file or directory on device (directories must be empty)\n" " -V, --version print the executable version \n" " -e, --exists check if the app with given bundle_id is installed or not \n", app); @@ -1701,6 +1734,8 @@ int main(int argc, char *argv[]) { { "upload", required_argument, NULL, 'o'}, { "download", optional_argument, NULL, 'w'}, { "to", required_argument, NULL, '2'}, + { "mkdir", required_argument, NULL, 'D'}, + { "rm", required_argument, NULL, 'R'}, { "exists", no_argument, NULL, 'e'}, { NULL, 0, NULL, 0 }, }; @@ -1778,6 +1813,16 @@ int main(int argc, char *argv[]) { command = "download"; list_root = optarg; break; + case 'D': + command_only = true; + target_filename = optarg; + command = "mkdir"; + break; + case 'R': + command_only = true; + target_filename = optarg; + command = "rm"; + break; case 'e': command_only = true; command = "exists"; From 8d1f79d27c81fddb0b4929e865920b322e67449b Mon Sep 17 00:00:00 2001 From: Ted Mielczarek Date: Wed, 22 Apr 2015 07:43:31 -0400 Subject: [PATCH 109/219] Update README to include --mkdir and --rm --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 7e00feaa..98906f6f 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,8 @@ $ npm install -g ios-deploy -o, --upload upload file -w, --download download app tree -2, --to use together with up/download file/tree. specify target + -D, --mkdir make directory on device + -R, --rm remove file or directory on device (directories must be empty) -V, --version print the executable version -e, --exists check if the app with given bundle_id is installed or not From b72d31b81651325f0c5b0754441f1a1027364612 Mon Sep 17 00:00:00 2001 From: Manickavasagam Senthil Date: Fri, 1 May 2015 14:18:22 -0400 Subject: [PATCH 110/219] Fixed a segv happening in non english locale --- ios-deploy.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index ffabd33d..988f81f4 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1518,10 +1518,13 @@ void handle_device(AMDeviceRef device) { return; } if (device_id != NULL) { - if(strcmp(device_id, CFStringGetCStringPtr(found_device_id, CFStringGetSystemEncoding())) == 0) { + CFStringRef deviceCFSTR = CFStringCreateWithCString(NULL, device_id, kCFStringEncodingASCII); + if (CFStringCompare(deviceCFSTR, found_device_id, kCFCompareCaseInsensitive) == kCFCompareEqualTo) { found_device = true; + CFRelease(deviceCFSTR); } else { fprintCFSTR(stdout, CFSTR("Skipping %@.\n"), device_full_name); + CFRelease(deviceCFSTR); return; } } else { From 0940a4d079111509cf39a6d0f302274da1cdccb2 Mon Sep 17 00:00:00 2001 From: Manickavasagam Senthil Date: Fri, 1 May 2015 14:19:58 -0400 Subject: [PATCH 111/219] Fixed a segv happening in non english locale --- ios-deploy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index 988f81f4..3c2b5c7d 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -16,7 +16,7 @@ #include #include "MobileDevice.h" -#define APP_VERSION "1.5.2" +#define APP_VERSION "1.5.3" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH /* From 2119c1045579a51f928e16ca556c1f6e402669da Mon Sep 17 00:00:00 2001 From: Michael Lupo Date: Thu, 7 May 2015 14:07:47 -0400 Subject: [PATCH 112/219] Adding in standalone uninstall option --uninstall_only Usage: ios-deploy --uninstall_only --bundle_id my.bundle.id --- ios-deploy.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 7 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 9d5c15fa..dc361d34 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1481,6 +1481,40 @@ void remove_path(AMDeviceRef device) { assert(AFCConnectionClose(afc_conn_p) == 0); } +void uninstall_app(AMDeviceRef device) { + CFRetain(device); // don't know if this is necessary? + + printf("------ Uninstall phase ------\n"); + + //Do we already have the bundle_id passed in via the command line? if so, use it. + CFStringRef cf_uninstall_bundle_id = NULL; + if (bundle_id != NULL) + { + cf_uninstall_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingASCII); + } else { + printf ("Error: you need to pass in the bundle id, (i.e. --bundle_id com.my.app)"); + exit(1); + } + + if (cf_uninstall_bundle_id == NULL) { + printf("Error: Unable to get bundle id from user command or package %s\n Uninstall failed\n", app_path); + } else { + AMDeviceConnect(device); + assert(AMDeviceIsPaired(device)); + assert(AMDeviceValidatePairing(device) == 0); + assert(AMDeviceStartSession(device) == 0); + + int code = AMDeviceSecureUninstallApplication(0, device, cf_uninstall_bundle_id, 0, NULL, 0); + if (code == 0) { + printf("[ OK ] Uninstalled package with bundle id %s\n", CFStringGetCStringPtr(cf_uninstall_bundle_id, CFStringGetSystemEncoding())); + } else { + printf("[ ERROR ] Could not uninstall package with bundle id %s\n", CFStringGetCStringPtr(cf_uninstall_bundle_id, CFStringGetSystemEncoding())); + } + assert(AMDeviceStopSession(device) == 0); + assert(AMDeviceDisconnect(device) == 0); + } +} + void handle_device(AMDeviceRef device) { //if (found_device) // return; // handle one device only @@ -1521,6 +1555,8 @@ void handle_device(AMDeviceRef device) { remove_path(device); } else if (strcmp("exists", command) == 0) { exit(app_exists(device)); + } else if (strcmp("uninstall_only", command) == 0) { + uninstall_app(device); } exit(0); } @@ -1537,20 +1573,28 @@ void handle_device(AMDeviceRef device) { if (uninstall) { printf("------ Uninstall phase ------\n"); - CFStringRef bundle_id = get_bundle_id(url); - if (bundle_id == NULL) { - printf("Error: Unable to get bundle id from package %s\n Uninstall failed\n", app_path); + //Do we already have the bundle_id passed in via the command line? if so, use it. + CFStringRef cf_uninstall_bundle_id = NULL; + if (bundle_id != NULL) + { + cf_uninstall_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingASCII); + } else { + cf_uninstall_bundle_id = get_bundle_id(url); + } + + if (cf_uninstall_bundle_id == NULL) { + printf("Error: Unable to get bundle id from user command or package %s\n Uninstall failed\n", app_path); } else { AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); assert(AMDeviceValidatePairing(device) == 0); assert(AMDeviceStartSession(device) == 0); - int code = AMDeviceSecureUninstallApplication(0, device, bundle_id, 0, NULL, 0); + int code = AMDeviceSecureUninstallApplication(0, device, cf_uninstall_bundle_id, 0, NULL, 0); if (code == 0) { - printf("[ OK ] Uninstalled package with bundle id %s\n", CFStringGetCStringPtr(bundle_id, CFStringGetSystemEncoding())); + printf("[ OK ] Uninstalled package with bundle id %s\n", CFStringGetCStringPtr(cf_uninstall_bundle_id, CFStringGetSystemEncoding())); } else { - printf("[ ERROR ] Could not uninstall package with bundle id %s\n", CFStringGetCStringPtr(bundle_id, CFStringGetSystemEncoding())); + printf("[ ERROR ] Could not uninstall package with bundle id %s\n", CFStringGetCStringPtr(cf_uninstall_bundle_id, CFStringGetSystemEncoding())); } assert(AMDeviceStopSession(device) == 0); assert(AMDeviceDisconnect(device) == 0); @@ -1696,6 +1740,7 @@ void usage(const char* app) { " -m, --noinstall directly start debugging without app install (-d not required)\n" " -p, --port port used for device, default: dynamic\n" " -r, --uninstall uninstall the app before install (do not use with -m; app cache and data are cleared) \n" + " -9, --uninstall_only uninstall the app ONLY. Use only with -1 \n" " -1, --bundle_id specify bundle id for list and upload\n" " -l, --list list files\n" " -o, --upload upload file\n" @@ -1729,6 +1774,7 @@ int main(int argc, char *argv[]) { { "noinstall", no_argument, NULL, 'm' }, { "port", required_argument, NULL, 'p' }, { "uninstall", no_argument, NULL, 'r' }, + { "uninstall_only", no_argument, NULL, '9'}, { "list", optional_argument, NULL, 'l' }, { "bundle_id", required_argument, NULL, '1'}, { "upload", required_argument, NULL, 'o'}, @@ -1741,7 +1787,7 @@ int main(int argc, char *argv[]) { }; char ch; - while ((ch = getopt_long(argc, argv, "VmcdvunrILei:b:a:t:g:x:p:1:2:o:l::w::", longopts, NULL)) != -1) + while ((ch = getopt_long(argc, argv, "VmcdvunrILei:b:a:t:g:x:p:1:2:o:l::w::9::", longopts, NULL)) != -1) { switch (ch) { case 'm': @@ -1792,6 +1838,10 @@ int main(int argc, char *argv[]) { case 'r': uninstall = 1; break; + case '9': + command_only = true; + command = "uninstall_only"; + break; case '1': bundle_id = optarg; break; @@ -1835,6 +1885,7 @@ int main(int argc, char *argv[]) { if (!app_path && !detect_only && !command_only) { usage(argv[0]); + printf ("ERROR: One of -[b|c|o|l|w|D|R|e|9] is required to proceed!\n"); exit(exitcode_error); } From fc667bc42340ee8c09538561062b758a677f04a1 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 12 May 2015 14:01:22 -0700 Subject: [PATCH 113/219] Added os key to package.json (for OS X) --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index cd62282a..7499ba68 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "name": "ios-deploy", "version": "1.5.0", + "os" : [ "darwin" ], "description": "launch iOS apps iOS devices from the command line (Xcode 6)", "main": "ios-deploy", "scripts": { From 6e4df1cc07089d3043f2ca722280bbf1a6c8f697 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 12 May 2015 14:18:13 -0700 Subject: [PATCH 114/219] Fixes #119 - new -R is unrecognized --- ios-deploy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index 9d5c15fa..c6b0a53f 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1741,7 +1741,7 @@ int main(int argc, char *argv[]) { }; char ch; - while ((ch = getopt_long(argc, argv, "VmcdvunrILei:b:a:t:g:x:p:1:2:o:l::w::", longopts, NULL)) != -1) + while ((ch = getopt_long(argc, argv, "VmcdvunrILeR:i:b:a:t:g:x:p:1:2:o:l::w::", longopts, NULL)) != -1) { switch (ch) { case 'm': From a89b71bdf42e1f9b3af04fdc2022d7758b2eeb01 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 12 May 2015 14:19:11 -0700 Subject: [PATCH 115/219] Fixes #124 - new -D is unrecognized --- ios-deploy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index c6b0a53f..0a691e52 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1741,7 +1741,7 @@ int main(int argc, char *argv[]) { }; char ch; - while ((ch = getopt_long(argc, argv, "VmcdvunrILeR:i:b:a:t:g:x:p:1:2:o:l::w::", longopts, NULL)) != -1) + while ((ch = getopt_long(argc, argv, "VmcdvunrILeD:R:i:b:a:t:g:x:p:1:2:o:l::w::", longopts, NULL)) != -1) { switch (ch) { case 'm': From 91566897203bd51b2d582ab45950bd3a19ca3899 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 12 May 2015 14:28:21 -0700 Subject: [PATCH 116/219] Fixes #122 - Using the -c option for listing device UUIDs instead the system_profiler --- README.md | 10 +++------- ios-deploy.c | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 98906f6f..16a66f5c 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,9 @@ The commands below assume that you have an app called `my.app` with bundle id `b // Download the Documents directory of the app *only* ios-deploy --download=/Documents -bundle_id my.app.id --to ./my_download_location + + // List ids and names of connected devices + ios-deploy -c ## Demo @@ -87,10 +90,3 @@ The commands below assume that you have an app called `my.app` with bundle id `b ## Notes * With some modifications, it may be possible to use this without Xcode installed; however, you would need a copy of the relevant DeveloperDiskImage.dmg (included with Xcode). lldb would also run slower as symbols would be downloaded from the device on-the-fly. - - -## Listing Device Ids - -Device Ids are the UDIDs of the iOS devices. From the command line, you can list device ids [this way](http://javierhz.blogspot.com/2012/06/how-to-get-udid-of-iphone-using-shell.html): - - system_profiler SPUSBDataType | sed -n -e '/iPod/,/Serial/p' | sed -n -e '/iPad/,/Serial/p' -e '/iPhone/,/Serial/p' | grep "Serial Number:" | awk -F ": " '{print $2}' diff --git a/ios-deploy.c b/ios-deploy.c index 0a691e52..cda5fb9e 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1844,7 +1844,7 @@ int main(int argc, char *argv[]) { } if (detect_only && timeout == 0) { - timeout = 5; + timeout = 0; } if (app_path) { From 7c1372041d532f664b5fd7b8dea76a5592033aa7 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 12 May 2015 15:01:06 -0700 Subject: [PATCH 117/219] Updated README for --uninstall_only --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 16a66f5c..be1495db 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ $ npm install -g ios-deploy -m, --noinstall directly start debugging without app install (-d not required) -p, --port port used for device, default: 12345 -r, --uninstall uninstall the app before install (do not use with -m; app cache and data are cleared) - -1, --bundle_id specify bundle id for list and upload + -1, --bundle_id specify bundle id for list, upload, and uninstall_only -l, --list list files -o, --upload upload file -w, --download download app tree @@ -45,6 +45,7 @@ $ npm install -g ios-deploy -R, --rm remove file or directory on device (directories must be empty) -V, --version print the executable version -e, --exists check if the app with given bundle_id is installed or not + -9, --uninstall_only uninstall an app only, by bundle_id ## Examples @@ -80,6 +81,9 @@ The commands below assume that you have an app called `my.app` with bundle id `b // List ids and names of connected devices ios-deploy -c + + // Uninstall an app + ios-deploy --uninstall_only --bundle_id my.bundle.id ## Demo From ea8202c5062548e9dd16032dff8d0453d19d37d9 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 12 May 2015 15:02:00 -0700 Subject: [PATCH 118/219] Updated version to 1.6.0 --- ios-deploy.c | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 3f583cb2..b072f334 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -16,7 +16,7 @@ #include #include "MobileDevice.h" -#define APP_VERSION "1.5.0" +#define APP_VERSION "1.6.0" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH /* diff --git a/package.json b/package.json index 7499ba68..919547d5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ios-deploy", - "version": "1.5.0", + "version": "1.6.0", "os" : [ "darwin" ], "description": "launch iOS apps iOS devices from the command line (Xcode 6)", "main": "ios-deploy", From 2c35b70ff7ff6a15a6194081a2adc11fc64b8d72 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 12 May 2015 15:25:41 -0700 Subject: [PATCH 119/219] Updated README for --uninstall_only from help text --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index be1495db..41ee5907 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ $ npm install -g ios-deploy -m, --noinstall directly start debugging without app install (-d not required) -p, --port port used for device, default: 12345 -r, --uninstall uninstall the app before install (do not use with -m; app cache and data are cleared) + -9, --uninstall_only uninstall the app ONLY. Use only with -1 -1, --bundle_id specify bundle id for list, upload, and uninstall_only -l, --list list files -o, --upload upload file @@ -45,7 +46,6 @@ $ npm install -g ios-deploy -R, --rm remove file or directory on device (directories must be empty) -V, --version print the executable version -e, --exists check if the app with given bundle_id is installed or not - -9, --uninstall_only uninstall an app only, by bundle_id ## Examples From d712420e60a232ae98d82ebfb3053f580a6213f3 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 12 May 2015 15:38:03 -0700 Subject: [PATCH 120/219] Fixes #118 - How to install without npm? --- Makefile | 6 +++--- README.md | 34 +++++++++++++++++++++++----------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index bef1d321..26974ee8 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,10 @@ -IOS_SDK_VERSION = 7.1 +IOS_SDK_VERSION = 8.3 IOS_CC = gcc -ObjC DEVICE_SUPPORT = $(shell xcode-select --print-path)/Platforms/iPhoneOS.platform/DeviceSupport IOS_SDK = $(shell xcode-select --print-path)/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS$(IOS_SDK_VERSION).sdk -all: clean ios-deploy +all: clean ios-deploy demo.app demo.app: demo Info.plist mkdir -p demo.app @@ -32,4 +32,4 @@ debug: all ./ios-deploy --debug --bundle demo.app clean: - rm -rf *.app demo ios-deploy + @rm -rf *.app demo ios-deploy diff --git a/README.md b/README.md index 41ee5907..667bae1e 100644 --- a/README.md +++ b/README.md @@ -4,21 +4,32 @@ Install and debug iOS apps without using Xcode. Designed to work on un-jailbroke ## Requirements -* Mac OS X. Tested on 10.10 Yosemite and iOS 8.1 -* You need to have a valid iOS development certificate installed. -* Xcode 6.1 should be installed +* Mac OS X. Tested on 10.10 Yosemite and iOS 8.3 +* You need to have a valid iOS Development certificate installed. +* Xcode 6 or greater should be installed ## Installation -ios-deploy installation is made simple using the node.js package manager. If you use [Homebrew](http://brew.sh/), install node.js: -```bash + +ios-deploy installation is made simple using the node.js package manager. If you use [Homebrew](http://brew.sh/), install [node.js](https://nodejs.org): + +``` brew install node ``` -Now install ios-deploy with the node.js package manager: -```bash -$ npm install -g ios-deploy +Now install ios-deploy with the [node.js](https://nodejs.org) package manager: + +``` +npm install -g ios-deploy ``` +To install from source: + +``` +make install prefix=/usr/local +``` + +This will install ios-deploy in the `bin` folder of `/usr/local`, i.e. `/usr/local/bin` + ## Usage Usage: ios-deploy [OPTION]... @@ -87,9 +98,10 @@ The commands below assume that you have an app called `my.app` with bundle id `b ## Demo -* The included demo.app represents the minimum required to get code running on iOS. -* `make install` will install demo.app to the device. -* `make debug` will install demo.app and launch a GDB session. +The included demo.app represents the minimum required to get code running on iOS. + +* `make demo.app` will generate the demo.app executable. If it doesn't compile, modify IOS_SDK_VERSION in the Makefile. +* `make debug` will install demo.app and launch a LLDB session. ## Notes From 707062343223f90997c1328862e272dbbb3e21ca Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Wed, 13 May 2015 11:00:56 -0700 Subject: [PATCH 121/219] Fixes #129 - "ios-deploy -c" never returns (partial revert of #122) --- ios-deploy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index b072f334..66caf3a7 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1895,7 +1895,7 @@ int main(int argc, char *argv[]) { } if (detect_only && timeout == 0) { - timeout = 0; + timeout = 5; } if (app_path) { From 125cd8de645104ec773e0e0d7512bab2623492a6 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Wed, 13 May 2015 11:01:16 -0700 Subject: [PATCH 122/219] Updated version to 1.6.1 --- ios-deploy.c | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 66caf3a7..7fe11b0a 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -16,7 +16,7 @@ #include #include "MobileDevice.h" -#define APP_VERSION "1.6.0" +#define APP_VERSION "1.6.1" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH /* diff --git a/package.json b/package.json index 919547d5..6b647c26 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ios-deploy", - "version": "1.6.0", + "version": "1.6.1", "os" : [ "darwin" ], "description": "launch iOS apps iOS devices from the command line (Xcode 6)", "main": "ios-deploy", From 3857c9afc65557d565bd4f79fb631a98c89b56cd Mon Sep 17 00:00:00 2001 From: Julius Trinkunas Date: Thu, 14 May 2015 19:54:01 +0300 Subject: [PATCH 123/219] Unify error reporting. --- ios-deploy.c | 70 +++++++++++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 7fe11b0a..184e4d9b 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -183,6 +183,31 @@ AMDeviceRef best_device_match = NULL; const int exitcode_error = 253; const int exitcode_app_crash = 254; +// Print error message and exit +void on_error(const char* fmt, ...) { + char buf[256]; + va_list args; + va_start(args, fmt); + fprintf(stderr, "[ !! ] "); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); + va_end(args); + + exit(exitcode_error); +} + +// Print error message getting last errno and exit +void on_sys_error(const char* fmt, ...) { + const char* errstr = strerror(errno); + + char buf[256]; + va_list args; + va_start(args, fmt); + vsnprintf(buf, 256, fmt, args); + on_error("%s: %s", buf, errstr); + va_end(args); +} + Boolean path_exists(CFTypeRef path) { if (CFGetTypeID(path) == CFStringGetTypeID()) { CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, true); @@ -222,10 +247,7 @@ CFStringRef find_path(CFStringRef rootPath, CFStringRef namePattern, CFStringRef CFRelease(cf_command); if (!(fpipe = (FILE *)popen(command, "r"))) - { - perror("Error encountered while opening pipe"); - exit(exitcode_error); - } + on_sys_error("Error encountered while opening pipe"); char buffer[256] = { '\0' }; @@ -247,10 +269,7 @@ CFStringRef copy_xcode_dev_path() { char *command = "xcode-select -print-path"; if (!(fpipe = (FILE *)popen(command, "r"))) - { - perror("Error encountered while opening pipe"); - exit(exitcode_error); - } + on_sys_error("Error encountered while opening pipe"); char buffer[256] = { '\0' }; @@ -503,10 +522,7 @@ CFStringRef copy_device_support_path(AMDeviceRef device) { CFRelease(build); if (path == NULL) - { - printf("[ !! ] Unable to locate DeviceSupport directory.\n[ !! ] This probably means you don't have Xcode installed, you will need to launch the app manually and logging output will not be shown!\n"); - exit(exitcode_error); - } + on_error("Unable to locate DeviceSupport directory. This probably means you don't have Xcode installed, you will need to launch the app manually and logging output will not be shown!"); return path; } @@ -544,10 +560,7 @@ CFStringRef copy_developer_disk_image_path(AMDeviceRef device) { CFRelease(version_parts); CFRelease(build); if (path == NULL) - { - printf("[ !! ] Unable to locate DeveloperDiskImage.dmg.\n[ !! ] This probably means you don't have Xcode installed, you will need to launch the app manually and logging output will not be shown!\n"); - exit(exitcode_error); - } + on_error("Unable to locate DeveloperDiskImage.dmg. This probably means you don't have Xcode installed, you will need to launch the app manually and logging output will not be shown!"); return path; } @@ -593,8 +606,7 @@ void mount_developer_image(AMDeviceRef device) { } else if (result == 0xe8000076 /* already mounted */) { printf("[ 95%%] Developer disk image already mounted\n"); } else { - printf("[ !! ] Unable to mount developer disk image. (%x)\n", result); - exit(exitcode_error); + on_error("Unable to mount developer disk image. (%x)", result); } CFRelease(image_path); @@ -1047,8 +1059,7 @@ void launch_debugger(AMDeviceRef device, CFURLRef url) { } else if (pid > 0) { child = pid; } else { - perror("fork failed"); - exit(exitcode_error); + on_sys_error("Fork failed"); } } @@ -1086,8 +1097,7 @@ void launch_debugger_and_exit(AMDeviceRef device, CFURLRef url) { if (verbose) printf("Waiting for child [Child: %d][Parent: %d]\n", child, parent); } else { - perror("fork failed"); - exit(exitcode_error); + on_sys_error("Fork failed"); } } @@ -1647,8 +1657,7 @@ void handle_device(AMDeviceRef device) { char* error = "Unknown error."; if (result == 0xe8008015) error = "Your application failed code-signing checks. Check your certificates, provisioning profiles, and bundle ids."; - printf("AMDeviceInstallApplication failed: 0x%X: %s\n", result, error); - exit(exitcode_error); + on_error("AMDeviceInstallApplication failed: 0x%X: %s", result, error); } // close(installFd); @@ -1694,10 +1703,8 @@ void timeout_callback(CFRunLoopTimerRef timer, void *info) { best_device_match = NULL; } - if(!found_device) { - printf("[....] Timed out waiting for device.\n"); - exit(exitcode_error); - } + if(!found_device) + on_error("Timed out waiting for device."); } else { @@ -1885,8 +1892,7 @@ int main(int argc, char *argv[]) { if (!app_path && !detect_only && !command_only) { usage(argv[0]); - printf ("ERROR: One of -[b|c|o|l|w|D|R|e|9] is required to proceed!\n"); - exit(exitcode_error); + on_error("One of -[b|c|o|l|w|D|R|e|9] is required to proceed!"); } if (unbuffered) { @@ -1899,7 +1905,9 @@ int main(int argc, char *argv[]) { } if (app_path) { - assert(access(app_path, F_OK) == 0); + if (access(app_path, F_OK) != 0) { + on_sys_error("Can't access app path '%s'", app_path); + } } AMDSetLogLevel(5); // otherwise syslog gets flooded with crap From 9e45cc0edb5a2a35c5b9050102efbd55ee871651 Mon Sep 17 00:00:00 2001 From: Incont Date: Fri, 15 May 2015 14:05:27 +0300 Subject: [PATCH 124/219] fixed not working --exists --- ios-deploy.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 7fe11b0a..8d4465b4 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1272,13 +1272,12 @@ void list_files(AMDeviceRef device) } } -int app_exists(AMDeviceRef device) +void app_exists(AMDeviceRef device) { if (bundle_id == NULL) { printf("Bundle id is not specified\n"); - return false; + return; } - AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); assert(AMDeviceValidatePairing(device) == 0); @@ -1289,21 +1288,17 @@ int app_exists(AMDeviceRef device) NSArray *a = [NSArray arrayWithObjects:@"CFBundleIdentifier", nil]; NSDictionary *optionsDict = [NSDictionary dictionaryWithObject:a forKey:@"ReturnAttributes"]; CFDictionaryRef options = (CFDictionaryRef)optionsDict; - CFDictionaryRef result = nil; afc_error_t resultStatus = AMDeviceLookupApplications(device, options, &result); assert(resultStatus == 0); CFDictionaryRef app_dict = CFDictionaryGetValue(result, cf_bundle_id); - - int appExists = (app_dict == NULL) ? -1 : 0; - + bool appExists = (app_dict == NULL) ? false : true; + printf("%s", appExists ? "true\n" : "false\n"); CFRelease(cf_bundle_id); assert(AMDeviceStopSession(device) == 0); assert(AMDeviceDisconnect(device) == 0); - - return appExists; } void copy_file_callback(afc_connection* afc_conn_p, const char *name,int file) @@ -1554,7 +1549,7 @@ void handle_device(AMDeviceRef device) { } else if (strcmp("rm", command) == 0) { remove_path(device); } else if (strcmp("exists", command) == 0) { - exit(app_exists(device)); + app_exists(device); } else if (strcmp("uninstall_only", command) == 0) { uninstall_app(device); } From 8a3dbce11fc55bdd6f5282d00277aea2c43481ef Mon Sep 17 00:00:00 2001 From: Julius Trinkunas Date: Fri, 15 May 2015 17:23:53 +0300 Subject: [PATCH 125/219] More user friendly error messages. --- errors.h | 358 +++++++++++++++++++++++++++++++++++++++++++++++++++ ios-deploy.c | 91 ++++++------- 2 files changed, 405 insertions(+), 44 deletions(-) create mode 100644 errors.h diff --git a/errors.h b/errors.h new file mode 100644 index 00000000..106ab28a --- /dev/null +++ b/errors.h @@ -0,0 +1,358 @@ + +typedef struct errorcode_to_id { + unsigned int error; + const char* id; +} errorcode_to_id_t; + +typedef struct error_id_to_message { + const char* id; + const char* message; +} error_id_to_message_t; + +// Taken from https://github.com/samdmarshall/SDMMobileDevice/blob/master/Framework/MobileDevice/Error/SDMMD_Error.h +static errorcode_to_id_t errorcode_to_id[] = { + { 0xe8000001, "kAMDUndefinedError" }, + { 0xe8000002, "kAMDBadHeaderError" }, + { 0xe8000003, "kAMDNoResourcesError" }, + { 0xe8000004, "kAMDReadError" }, + { 0xe8000005, "kAMDWriteError" }, + { 0xe8000006, "kAMDUnknownPacketError" }, + { 0xe8000007, "kAMDInvalidArgumentError" }, + { 0xe8000008, "kAMDNotFoundError" }, + { 0xe8000009, "kAMDIsDirectoryError" }, + { 0xe800000a, "kAMDPermissionError" }, + { 0xe800000b, "kAMDNotConnectedError" }, + { 0xe800000c, "kAMDTimeOutError" }, + { 0xe800000d, "kAMDOverrunError" }, + { 0xe800000e, "kAMDEOFError" }, + { 0xe800000f, "kAMDUnsupportedError" }, + { 0xe8000010, "kAMDFileExistsError" }, + { 0xe8000011, "kAMDBusyError" }, + { 0xe8000012, "kAMDCryptoError" }, + { 0xe8000013, "kAMDInvalidResponseError" }, + { 0xe8000014, "kAMDMissingKeyError" }, + { 0xe8000015, "kAMDMissingValueError" }, + { 0xe8000016, "kAMDGetProhibitedError" }, + { 0xe8000017, "kAMDSetProhibitedError" }, + { 0xe8000018, "kAMDRemoveProhibitedError" }, + { 0xe8000019, "kAMDImmutableValueError" }, + { 0xe800001a, "kAMDPasswordProtectedError" }, + { 0xe800001b, "kAMDMissingHostIDError" }, + { 0xe800001c, "kAMDInvalidHostIDError" }, + { 0xe800001d, "kAMDSessionActiveError" }, + { 0xe800001e, "kAMDSessionInactiveError" }, + { 0xe800001f, "kAMDMissingSessionIDError" }, + { 0xe8000020, "kAMDInvalidSessionIDError" }, + { 0xe8000021, "kAMDMissingServiceError" }, + { 0xe8000022, "kAMDInvalidServiceError" }, + { 0xe8000023, "kAMDInvalidCheckinError" }, + { 0xe8000024, "kAMDCheckinTimeoutError" }, + { 0xe8000025, "kAMDMissingPairRecordError" }, + { 0xe8000026, "kAMDInvalidActivationRecordError" }, + { 0xe8000027, "kAMDMissingActivationRecordError" }, + { 0xe8000028, "kAMDWrongDroidError" }, + { 0xe8000029, "kAMDSUVerificationError" }, + { 0xe800002a, "kAMDSUPatchError" }, + { 0xe800002b, "kAMDSUFirmwareError" }, + { 0xe800002c, "kAMDProvisioningProfileNotValid" }, + { 0xe800002d, "kAMDSendMessageError" }, + { 0xe800002e, "kAMDReceiveMessageError" }, + { 0xe800002f, "kAMDMissingOptionsError" }, + { 0xe8000030, "kAMDMissingImageTypeError" }, + { 0xe8000031, "kAMDDigestFailedError" }, + { 0xe8000032, "kAMDStartServiceError" }, + { 0xe8000033, "kAMDInvalidDiskImageError" }, + { 0xe8000034, "kAMDMissingDigestError" }, + { 0xe8000035, "kAMDMuxError" }, + { 0xe8000036, "kAMDApplicationAlreadyInstalledError" }, + { 0xe8000037, "kAMDApplicationMoveFailedError" }, + { 0xe8000038, "kAMDApplicationSINFCaptureFailedError" }, + { 0xe8000039, "kAMDApplicationSandboxFailedError" }, + { 0xe800003a, "kAMDApplicationVerificationFailedError" }, + { 0xe800003b, "kAMDArchiveDestructionFailedError" }, + { 0xe800003c, "kAMDBundleVerificationFailedError" }, + { 0xe800003d, "kAMDCarrierBundleCopyFailedError" }, + { 0xe800003e, "kAMDCarrierBundleDirectoryCreationFailedError" }, + { 0xe800003f, "kAMDCarrierBundleMissingSupportedSIMsError" }, + { 0xe8000040, "kAMDCommCenterNotificationFailedError" }, + { 0xe8000041, "kAMDContainerCreationFailedError" }, + { 0xe8000042, "kAMDContainerP0wnFailedError" }, + { 0xe8000043, "kAMDContainerRemovalFailedError" }, + { 0xe8000044, "kAMDEmbeddedProfileInstallFailedError" }, + { 0xe8000045, "kAMDErrorError" }, + { 0xe8000046, "kAMDExecutableTwiddleFailedError" }, + { 0xe8000047, "kAMDExistenceCheckFailedError" }, + { 0xe8000048, "kAMDInstallMapUpdateFailedError" }, + { 0xe8000049, "kAMDManifestCaptureFailedError" }, + { 0xe800004a, "kAMDMapGenerationFailedError" }, + { 0xe800004b, "kAMDMissingBundleExecutableError" }, + { 0xe800004c, "kAMDMissingBundleIdentifierError" }, + { 0xe800004d, "kAMDMissingBundlePathError" }, + { 0xe800004e, "kAMDMissingContainerError" }, + { 0xe800004f, "kAMDNotificationFailedError" }, + { 0xe8000050, "kAMDPackageExtractionFailedError" }, + { 0xe8000051, "kAMDPackageInspectionFailedError" }, + { 0xe8000052, "kAMDPackageMoveFailedError" }, + { 0xe8000053, "kAMDPathConversionFailedError" }, + { 0xe8000054, "kAMDRestoreContainerFailedError" }, + { 0xe8000055, "kAMDSeatbeltProfileRemovalFailedError" }, + { 0xe8000056, "kAMDStageCreationFailedError" }, + { 0xe8000057, "kAMDSymlinkFailedError" }, + { 0xe8000058, "kAMDiTunesArtworkCaptureFailedError" }, + { 0xe8000059, "kAMDiTunesMetadataCaptureFailedError" }, + { 0xe800005a, "kAMDAlreadyArchivedError" }, + { 0xe800005b, "kAMDServiceLimitError" }, + { 0xe800005c, "kAMDInvalidPairRecordError" }, + { 0xe800005d, "kAMDServiceProhibitedError" }, + { 0xe800005e, "kAMDCheckinSetupFailedError" }, + { 0xe800005f, "kAMDCheckinConnectionFailedError" }, + { 0xe8000060, "kAMDCheckinReceiveFailedError" }, + { 0xe8000061, "kAMDCheckinResponseFailedError" }, + { 0xe8000062, "kAMDCheckinSendFailedError" }, + { 0xe8000063, "kAMDMuxCreateListenerError" }, + { 0xe8000064, "kAMDMuxGetListenerError" }, + { 0xe8000065, "kAMDMuxConnectError" }, + { 0xe8000066, "kAMDUnknownCommandError" }, + { 0xe8000067, "kAMDAPIInternalError" }, + { 0xe8000068, "kAMDSavePairRecordFailedError" }, + { 0xe8000069, "kAMDCheckinOutOfMemoryError" }, + { 0xe800006a, "kAMDDeviceTooNewError" }, + { 0xe800006b, "kAMDDeviceRefNoGood" }, + { 0xe800006c, "kAMDCannotTranslateError" }, + { 0xe800006d, "kAMDMobileImageMounterMissingImageSignature" }, + { 0xe800006e, "kAMDMobileImageMounterResponseCreationFailed" }, + { 0xe800006f, "kAMDMobileImageMounterMissingImageType" }, + { 0xe8000070, "kAMDMobileImageMounterMissingImagePath" }, + { 0xe8000071, "kAMDMobileImageMounterImageMapLoadFailed" }, + { 0xe8000072, "kAMDMobileImageMounterAlreadyMounted" }, + { 0xe8000073, "kAMDMobileImageMounterImageMoveFailed" }, + { 0xe8000074, "kAMDMobileImageMounterMountPathMissing" }, + { 0xe8000075, "kAMDMobileImageMounterMountPathNotEmpty" }, + { 0xe8000076, "kAMDMobileImageMounterImageMountFailed" }, + { 0xe8000077, "kAMDMobileImageMounterTrustCacheLoadFailed" }, + { 0xe8000078, "kAMDMobileImageMounterDigestFailed" }, + { 0xe8000079, "kAMDMobileImageMounterDigestCreationFailed" }, + { 0xe800007a, "kAMDMobileImageMounterImageVerificationFailed" }, + { 0xe800007b, "kAMDMobileImageMounterImageInfoCreationFailed" }, + { 0xe800007c, "kAMDMobileImageMounterImageMapStoreFailed" }, + { 0xe800007d, "kAMDBonjourSetupError" }, + { 0xe800007e, "kAMDDeviceOSVersionTooLow" }, + { 0xe800007f, "kAMDNoWifiSyncSupportError" }, + { 0xe8000080, "kAMDDeviceFamilyNotSupported" }, + { 0xe8000081, "kAMDEscrowLockedError" }, + { 0xe8000082, "kAMDPairingProhibitedError" }, + { 0xe8000083, "kAMDProhibitedBySupervision" }, + { 0xe8000084, "kAMDDeviceDisconnectedError" }, + { 0xe8000085, "kAMDTooBigError" }, + { 0xe8000086, "kAMDPackagePatchFailedError" }, + { 0xe8000087, "kAMDIncorrectArchitectureError" }, + { 0xe8000088, "kAMDPluginCopyFailedError" }, + { 0xe8000089, "kAMDBreadcrumbFailedError" }, + { 0xe800008a, "kAMDBreadcrumbUnlockError" }, + { 0xe800008b, "kAMDGeoJSONCaptureFailedError" }, + { 0xe800008c, "kAMDNewsstandArtworkCaptureFailedError" }, + { 0xe800008d, "kAMDMissingCommandError" }, + { 0xe800008e, "kAMDNotEntitledError" }, + { 0xe800008f, "kAMDMissingPackagePathError" }, + { 0xe8000090, "kAMDMissingContainerPathError" }, + { 0xe8000091, "kAMDMissingApplicationIdentifierError" }, + { 0xe8000092, "kAMDMissingAttributeValueError" }, + { 0xe8000093, "kAMDLookupFailedError" }, + { 0xe8000094, "kAMDDictCreationFailedError" }, + { 0xe8000095, "kAMDUserDeniedPairingError" }, + { 0xe8000096, "kAMDPairingDialogResponsePendingError" }, + { 0xe8000097, "kAMDInstallProhibitedError" }, + { 0xe8000098, "kAMDUninstallProhibitedError" }, + { 0xe8000099, "kAMDFMiPProtectedError" }, + { 0xe800009a, "kAMDMCProtected" }, + { 0xe800009b, "kAMDMCChallengeRequired" }, + { 0xe800009c, "kAMDMissingBundleVersionError" }, + + { 0xe8008015, "A valid provisioning profile for this executable was not found."}, +}; + +const int errorcode_to_id_count = sizeof(errorcode_to_id) / sizeof(errorcode_to_id_t); + +// Taken from /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/PrivateFrameworks/MobileDevice.framework/Versions/A/Resources/en_GB.lproj/Localizable.strings +error_id_to_message_t error_id_to_message[] = { + { "kAMDAPIInternalError", "There was an internal API error." }, + { "kAMDAlreadyArchivedError", "The application is already archived." }, + { "kAMDAppBlacklistedError", "This app is not allowed to be installed on this device." }, + { "kAMDApplicationAlreadyInstalledError", "A system application with the given bundle identifier is already installed on the device and cannot be replaced." }, + { "kAMDApplicationMoveFailedError", "The application could not be moved into place on the device." }, + { "kAMDApplicationSandboxFailedError", "The application could not be sandboxed." }, + { "kAMDApplicationVerificationFailedError", "The application could not be verified." }, + { "kAMDArchiveDestructionFailedError", "Could not remove the application archive." }, + { "kAMDBadHeaderError", "Could not transfer file." }, + { "kAMDBreadcrumbFailedError", "Could not write installation breadcrumb." }, + { "kAMDBreadcrumbUnlockError", "Could not update installation breadcrumb." }, + { "kAMDBundleVerificationFailedError", "The carrier bundle could not be verified." }, + { "kAMDBusyError", "The device is busy." }, + { "kAMDCannotTranslateError", "Could not translate messages from device" }, + { "kAMDCarrierBundleCopyFailedError", "Could not install the carrier bundle." }, + { "kAMDCarrierBundleDirectoryCreationFailedError", "Could not create the carrier bundle directory." }, + { "kAMDCarrierBundleMissingSupportedSIMsError", "There are no supported SIMs for this carrier bundle." }, + { "kAMDCheckinConnectionFailedError", "The service did not start properly on the device." }, + { "kAMDCheckinOutOfMemoryError", "The service did not start properly on the device." }, + { "kAMDCheckinReceiveFailedError", "The service did not start properly on the device." }, + { "kAMDCheckinResponseFailedError", "The service did not start properly on the device." }, + { "kAMDCheckinSendFailedError", "The service did not start properly on the device." }, + { "kAMDCheckinSetupFailedError", "Could not start service on device" }, + { "kAMDCheckinTimeoutError", "The service did not start properly on the device." }, + { "kAMDCommCenterNotificationFailedError", "Could not listen for notification from the baseband." }, + { "kAMDContainerCreationFailedError", "Could not create application container." }, + { "kAMDContainerP0wnFailedError", "Could not repair permissions on application container." }, + { "kAMDContainerRemovalFailedError", "Could not remove the application container." }, + { "kAMDCryptoError", "Could not establish a secure connection to the device." }, + { "kAMDDeviceDisconnectedError", "This device is no longer connected." }, + { "kAMDDeviceFamilyNotSupported", "This application does not support this kind of device." }, + { "kAMDDeviceOSVersionTooLow", "The device OS version is too low." }, + { "kAMDDeviceRefNoGood", "This device is no longer connected." }, + { "kAMDDeviceTooNewError", "This application needs to be updated." }, + { "kAMDDictCreationFailedError", "Could not extract capabilities from the request." }, + { "kAMDDigestFailedError", "Could not read disk image." }, + { "kAMDEOFError", "End of file." }, + { "kAMDEmbeddedProfileInstallFailedError", "Could not install the embedded provisioning profile." }, + { "kAMDErrorError", "An error occurred." }, + { "kAMDEscrowLockedError", "Device is not available until first unlock after boot." }, + { "kAMDExecutableTwiddleFailedError", "Could not change executable permissions on the application." }, + { "kAMDExistenceCheckFailedError", "Could not check to see if the application already exists." }, + { "kAMDFMiPProtectedError", "The device is in lost mode." }, + { "kAMDFileExistsError", "The file already exists." }, + { "kAMDGeoJSONCaptureFailedError", "Could not save the GeoJSON data." }, + { "kAMDGetProhibitedError", "Cannot retrieve value from the passcode-locked device." }, + { "kAMDImmutableValueError", "This value cannot be changed." }, + { "kAMDIncorrectArchitectureError", "This application does not support this device's CPU type." }, + { "kAMDInstallMapUpdateFailedError", "Could not update the installed applications list." }, + { "kAMDInstallProhibitedError", "Installation of apps is prohibited by a policy on the device." }, + { "kAMDInvalidActivationRecordError", "The activation record is not valid." }, + { "kAMDInvalidArgumentError", "The argument is invalid." }, + { "kAMDInvalidCheckinError", "Could not start service on device" }, + { "kAMDInvalidDiskImageError", "The disk image is invalid." }, + { "kAMDInvalidHostIDError", "The device does not recognise this host." }, + { "kAMDInvalidPairRecordError", "The host is no longer paired with the device." }, + { "kAMDInvalidResponseError", "Received an unexpected response from the device." }, + { "kAMDInvalidServiceError", "The service is invalid." }, + { "kAMDInvalidSessionIDError", "The session ID is invalid." }, + { "kAMDIsDirectoryError", "The path is a directory." }, + { "kAMDLookupFailedError", "Could not list installed applications." }, + { "kAMDMCChallengeRequired", "A policy on the device requires secure pairing." }, + { "kAMDMCProtected", "Pairing is prohibited by a policy on the device." }, + { "kAMDManifestCaptureFailedError", "Could not save the application manifest." }, + { "kAMDMapGenerationFailedError", "Could not generate the map." }, + { "kAMDMissingActivationRecordError", "The activation record could not be found." }, + { "kAMDMissingApplicationIdentifierError", "Request was missing the application identifier." }, + { "kAMDMissingAttributeValueError", "Request was missing a required value." }, + { "kAMDMissingBundleExecutableError", "The application bundle does not contain an executable." }, + { "kAMDMissingBundleIdentifierError", "The application bundle does not contain a valid identifier." }, + { "kAMDMissingBundlePathError", "Could not determine the application bundle path." }, + { "kAMDMissingBundleVersionError", "The bundle's Info.plist does not contain a CFBundleVersion key or its value is not a string." }, + { "kAMDMissingCommandError", "The request did not contain a command." }, + { "kAMDMissingContainerError", "Could not find the container for the installed application." }, + { "kAMDMissingContainerPathError", "Request was missing the container path." }, + { "kAMDMissingDigestError", "The digest is missing." }, + { "kAMDMissingHostIDError", "The device does not recognise this host." }, + { "kAMDMissingImageTypeError", "The image is missing." }, + { "kAMDMissingKeyError", "The key is missing." }, + { "kAMDMissingOptionsError", "The options are missing." }, + { "kAMDMissingPackagePathError", "Request was missing the package path." }, + { "kAMDMissingPairRecordError", "The host is not paired with the device." }, + { "kAMDMissingServiceError", "The service is missing." }, + { "kAMDMissingSessionIDError", "The session ID is missing." }, + { "kAMDMissingValueError", "The value is missing." }, + { "kAMDMobileImageMounterAlreadyMounted", "Could not support development." }, + { "kAMDMobileImageMounterDigestCreationFailed", "Could not support development." }, + { "kAMDMobileImageMounterDigestFailed", "Could not support development." }, + { "kAMDMobileImageMounterImageInfoCreationFailed", "Could not support development." }, + { "kAMDMobileImageMounterImageMapLoadFailed", "Could not support development." }, + { "kAMDMobileImageMounterImageMapStoreFailed", "Could not support development." }, + { "kAMDMobileImageMounterImageMountFailed", "Could not support development." }, + { "kAMDMobileImageMounterImageMoveFailed", "Could not support development." }, + { "kAMDMobileImageMounterImageVerificationFailed", "Could not support development." }, + { "kAMDMobileImageMounterMissingImagePath", "Could not support development." }, + { "kAMDMobileImageMounterMissingImageSignature", "Could not support development." }, + { "kAMDMobileImageMounterMissingImageType", "Could not support development." }, + { "kAMDMobileImageMounterMountPathMissing", "Could not support development." }, + { "kAMDMobileImageMounterMountPathNotEmpty", "Could not support development." }, + { "kAMDMobileImageMounterResponseCreationFailed", "Could not support development." }, + { "kAMDMobileImageMounterTrustCacheLoadFailed", "Could not support development." }, + { "kAMDMuxConnectError", "Could not connect to the device." }, + { "kAMDMuxCreateListenerError", "Could not listen for USB devices." }, + { "kAMDMuxError", "There was an error with the USB device multiplexor." }, + { "kAMDMuxGetListenerError", "Could not get the USB listener." }, + { "kAMDNewsstandArtworkCaptureFailedError", "Could not save the Newsstand artwork." }, + { "kAMDNoResourcesError", "Could not allocate a resource." }, + { "kAMDNoWifiSyncSupportError", "Device doesn't support wireless sync." }, + { "kAMDNotConnectedError", "Not connected to the device." }, + { "kAMDNotEntitledError", "The requesting application is not allowed to make this request." }, + { "kAMDNotFoundError", "The file could not be found." }, + { "kAMDNotificationFailedError", "Could not post a notification." }, + { "kAMDOverrunError", "There was a buffer overrun." }, + { "kAMDPackageExtractionFailedError", "Could not open the application package." }, + { "kAMDPackageInspectionFailedError", "Could not inspect the application package." }, + { "kAMDPackageMoveFailedError", "Could not move the application package into the staging location." }, + { "kAMDPackagePatchFailedError", "Could not apply patch update to application." }, + { "kAMDPairingDialogResponsePendingError", "The user has not yet responded to the pairing request." }, + { "kAMDPairingProhibitedError", "Pairing only allowed over USB." }, + { "kAMDPasswordProtectedError", "The device is passcode protected." }, + { "kAMDPathConversionFailedError", "Could not convert the path." }, + { "kAMDPermissionError", "You do not have permission." }, + { "kAMDPluginCopyFailedError", "Could not copy VPN Plug-in into app container." }, + { "kAMDProhibitedBySupervision", "Operation prohibited on supervised devices." }, + { "kAMDProvisioningProfileNotValid", "The provisioning profile is not valid." }, + { "kAMDReadError", "Could not read from the device." }, + { "kAMDReceiveMessageError", "Could not receive a message from the device." }, + { "kAMDRemoveProhibitedError", "Cannot remove value on device." }, + { "kAMDRestoreContainerFailedError", "Could not restore the application container." }, + { "kAMDSUFirmwareError", "Could not flash the firmware." }, + { "kAMDSUPatchError", "Could not patch the file." }, + { "kAMDSUVerificationError", "The software update package could not be verified." }, + { "kAMDSavePairRecordFailedError", "Could not save the pairing record." }, + { "kAMDSeatbeltProfileRemovalFailedError", "Could not remove the application seatbelt profile." }, + { "kAMDSendMessageError", "Could not send a message to the device." }, + { "kAMDServiceLimitError", "Too many instances of this service are already running." }, + { "kAMDServiceProhibitedError", "The service could not be started on the device." }, + { "kAMDSessionActiveError", "The session is active." }, + { "kAMDSessionInactiveError", "The session is inactive." }, + { "kAMDSetProhibitedError", "Cannot set value on device." }, + { "kAMDStageCreationFailedError", "Could not create the staging directory." }, + { "kAMDStartServiceError", "The service could not be started." }, + { "kAMDSuccess", "There was no error." }, + { "kAMDSymlinkFailedError", "Could not create the symlink." }, + { "kAMDTimeOutError", "The operation timed out." }, + { "kAMDTooBigError", "The message is too big." }, + { "kAMDUndefinedError", "An unknown error occurred." }, + { "kAMDUninstallProhibitedError", "Uninstallation of apps is prohibited by a policy on the device." }, + { "kAMDUnknownCommandError", "The device does not recognise the command." }, + { "kAMDUnknownPacketError", "The packet is unknown." }, + { "kAMDUnsupportedError", "This operation is unsupported." }, + { "kAMDUserDeniedPairingError", "The device rejected the pairing attempt." }, + { "kAMDWriteError", "Could not write to the device." }, + { "kAMDWrongDroidError", "The device is in recovery mode." }, + { "kAMDiTunesArtworkCaptureFailedError", "Could not save the iTunes artwork." }, + { "kAMDiTunesMetadataCaptureFailedError", "Could not save the iTunes metadata." }, +}; + +const int error_id_to_message_count = sizeof(error_id_to_message) / sizeof(error_id_to_message_t); + +const char* get_error_message(unsigned int error) { + const char* id = NULL; + + // Lookup error localization id + for (int i = 0; i < errorcode_to_id_count; i++) { + if (errorcode_to_id[i].error == error) { + id = errorcode_to_id[i].id; + break; + } + } + + // Lookup error message + if (id) { + for (int i = 0; i < error_id_to_message_count; i++) + if (strcmp(error_id_to_message[i].id, id) == 0) + return error_id_to_message[i].message; + } + + // If message is not found, then at least return id if it was found, otherwise NULL + return id; +}; diff --git a/ios-deploy.c b/ios-deploy.c index 184e4d9b..2421743a 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -14,7 +14,9 @@ #include #include #include + #include "MobileDevice.h" +#include "errors.h" #define APP_VERSION "1.6.1" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" @@ -183,6 +185,17 @@ AMDeviceRef best_device_match = NULL; const int exitcode_error = 253; const int exitcode_app_crash = 254; +// Checks for MobileDevice.framework errors, tries to print them and exits. +#define check_error(call) \ + do { \ + unsigned int err = (unsigned int)call; \ + if (err != 0) \ + { \ + const char* msg = get_error_message(err); \ + on_error("Error 0x%x: %s " #call, err, msg ? msg : "unknown."); \ + } \ + } while (false); + // Print error message and exit void on_error(const char* fmt, ...) { char buf[256]; @@ -674,8 +687,7 @@ CFURLRef copy_device_app_url(AMDeviceRef device, CFStringRef identifier) { NSDictionary *optionsDict = [NSDictionary dictionaryWithObject:a forKey:@"ReturnAttributes"]; CFDictionaryRef options = (CFDictionaryRef)optionsDict; - afc_error_t resultStatus = AMDeviceLookupApplications(device, options, &result); - assert(resultStatus == 0); + check_error(AMDeviceLookupApplications(device, options, &result)); CFDictionaryRef app_dict = CFDictionaryGetValue(result, identifier); assert(app_dict != NULL); @@ -877,8 +889,7 @@ void fdvendor_callback(CFSocketRef s, CFSocketCallBackType callbackType, CFDataR void start_remote_debug_server(AMDeviceRef device) { - int res = AMDeviceStartService(device, CFSTR("com.apple.debugserver"), &gdbfd, NULL); - assert(res == 0); + check_error(AMDeviceStartService(device, CFSTR("com.apple.debugserver"), &gdbfd, NULL)); assert(gdbfd > 0); /* @@ -907,7 +918,7 @@ void start_remote_debug_server(AMDeviceRef device) { CFSocketSetAddress(fdvendor, address_data); CFRelease(address_data); socklen_t addrlen = sizeof(addr4); - res = getsockname(CFSocketGetNative(fdvendor),(struct sockaddr *)&addr4,&addrlen); + int res = getsockname(CFSocketGetNative(fdvendor),(struct sockaddr *)&addr4,&addrlen); assert(res == 0); port = ntohs(addr4.sin_port); @@ -989,8 +1000,8 @@ void setup_lldb(AMDeviceRef device, CFURLRef url) { AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); - assert(AMDeviceValidatePairing(device) == 0); - assert(AMDeviceStartSession(device) == 0); + check_error(AMDeviceValidatePairing(device)); + check_error(AMDeviceStartSession(device)); printf("------ Debug phase ------\n"); @@ -1210,8 +1221,8 @@ void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir, service_conn_t start_house_arrest_service(AMDeviceRef device) { AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); - assert(AMDeviceValidatePairing(device) == 0); - assert(AMDeviceStartSession(device) == 0); + check_error(AMDeviceValidatePairing(device)); + check_error(AMDeviceStartSession(device)); service_conn_t houseFd; @@ -1227,8 +1238,8 @@ service_conn_t start_house_arrest_service(AMDeviceRef device) { exit(1); } - assert(AMDeviceStopSession(device) == 0); - assert(AMDeviceDisconnect(device) == 0); + check_error(AMDeviceStopSession(device)); + check_error(AMDeviceDisconnect(device)); CFRelease(cf_bundle_id); return houseFd; @@ -1291,8 +1302,8 @@ int app_exists(AMDeviceRef device) AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); - assert(AMDeviceValidatePairing(device) == 0); - assert(AMDeviceStartSession(device) == 0); + check_error(AMDeviceValidatePairing(device)); + check_error(AMDeviceStartSession(device)); CFStringRef cf_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingASCII); @@ -1301,8 +1312,7 @@ int app_exists(AMDeviceRef device) CFDictionaryRef options = (CFDictionaryRef)optionsDict; CFDictionaryRef result = nil; - afc_error_t resultStatus = AMDeviceLookupApplications(device, options, &result); - assert(resultStatus == 0); + check_error(AMDeviceLookupApplications(device, options, &result)); CFDictionaryRef app_dict = CFDictionaryGetValue(result, cf_bundle_id); @@ -1310,8 +1320,8 @@ int app_exists(AMDeviceRef device) CFRelease(cf_bundle_id); - assert(AMDeviceStopSession(device) == 0); - assert(AMDeviceDisconnect(device) == 0); + check_error(AMDeviceStopSession(device)); + check_error(AMDeviceDisconnect(device)); return appExists; } @@ -1443,7 +1453,7 @@ void upload_file(AMDeviceRef device) { c++; } *lastSlash = '\0'; - assert(AFCDirectoryCreate(afc_conn_p, dirpath) == 0); + check_error(AFCDirectoryCreate(afc_conn_p, dirpath)); } @@ -1511,8 +1521,8 @@ void uninstall_app(AMDeviceRef device) { } else { AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); - assert(AMDeviceValidatePairing(device) == 0); - assert(AMDeviceStartSession(device) == 0); + check_error(AMDeviceValidatePairing(device)); + check_error(AMDeviceStartSession(device)); int code = AMDeviceSecureUninstallApplication(0, device, cf_uninstall_bundle_id, 0, NULL, 0); if (code == 0) { @@ -1520,8 +1530,8 @@ void uninstall_app(AMDeviceRef device) { } else { printf("[ ERROR ] Could not uninstall package with bundle id %s\n", CFStringGetCStringPtr(cf_uninstall_bundle_id, CFStringGetSystemEncoding())); } - assert(AMDeviceStopSession(device) == 0); - assert(AMDeviceDisconnect(device) == 0); + check_error(AMDeviceStopSession(device)); + check_error(AMDeviceDisconnect(device)); } } @@ -1597,8 +1607,8 @@ void handle_device(AMDeviceRef device) { } else { AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); - assert(AMDeviceValidatePairing(device) == 0); - assert(AMDeviceStartSession(device) == 0); + check_error(AMDeviceValidatePairing(device)); + check_error(AMDeviceStartSession(device)); int code = AMDeviceSecureUninstallApplication(0, device, cf_uninstall_bundle_id, 0, NULL, 0); if (code == 0) { @@ -1606,8 +1616,8 @@ void handle_device(AMDeviceRef device) { } else { printf("[ ERROR ] Could not uninstall package with bundle id %s\n", CFStringGetCStringPtr(cf_uninstall_bundle_id, CFStringGetSystemEncoding())); } - assert(AMDeviceStopSession(device) == 0); - assert(AMDeviceDisconnect(device) == 0); + check_error(AMDeviceStopSession(device)); + check_error(AMDeviceDisconnect(device)); } } @@ -1617,22 +1627,22 @@ void handle_device(AMDeviceRef device) { AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); - assert(AMDeviceValidatePairing(device) == 0); - assert(AMDeviceStartSession(device) == 0); + check_error(AMDeviceValidatePairing(device)); + check_error(AMDeviceStartSession(device)); // NOTE: the secure version doesn't seem to require us to start the AFC service service_conn_t afcFd; - assert(AMDeviceSecureStartService(device, CFSTR("com.apple.afc"), NULL, &afcFd) == 0); - assert(AMDeviceStopSession(device) == 0); - assert(AMDeviceDisconnect(device) == 0); + check_error(AMDeviceSecureStartService(device, CFSTR("com.apple.afc"), NULL, &afcFd)); + check_error(AMDeviceStopSession(device)); + check_error(AMDeviceDisconnect(device)); CFStringRef keys[] = { CFSTR("PackageType") }; CFStringRef values[] = { CFSTR("Developer") }; CFDictionaryRef options = CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&values, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); //assert(AMDeviceTransferApplication(afcFd, path, NULL, transfer_callback, NULL) == 0); - assert(AMDeviceSecureTransferPath(0, device, url, options, transfer_callback, 0)==0); + check_error(AMDeviceSecureTransferPath(0, device, url, options, transfer_callback, 0)); close(afcFd); @@ -1640,8 +1650,8 @@ void handle_device(AMDeviceRef device) { AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); - assert(AMDeviceValidatePairing(device) == 0); - assert(AMDeviceStartSession(device) == 0); + check_error(AMDeviceValidatePairing(device)); + check_error(AMDeviceStartSession(device)); // // NOTE: the secure version doesn't seem to require us to start the installation_proxy service // // Although I can't find it right now, I in some code that the first param of AMDeviceSecureInstallApplication was a "dontStartInstallProxy" @@ -1651,19 +1661,12 @@ void handle_device(AMDeviceRef device) { //assert(AMDeviceSecureStartService(device, CFSTR("com.apple.mobile.installation_proxy"), NULL, &installFd) == 0); //mach_error_t result = AMDeviceInstallApplication(installFd, path, options, install_callback, NULL); - mach_error_t result = AMDeviceSecureInstallApplication(0, device, url, options, install_callback, 0); - if (result != 0) - { - char* error = "Unknown error."; - if (result == 0xe8008015) - error = "Your application failed code-signing checks. Check your certificates, provisioning profiles, and bundle ids."; - on_error("AMDeviceInstallApplication failed: 0x%X: %s", result, error); - } + check_error(AMDeviceSecureInstallApplication(0, device, url, options, install_callback, 0)); // close(installFd); - assert(AMDeviceStopSession(device) == 0); - assert(AMDeviceDisconnect(device) == 0); + check_error(AMDeviceStopSession(device)); + check_error(AMDeviceDisconnect(device)); CFRelease(path); CFRelease(options); From 041d12e0b1e2f56eb4ac56ae8457cb354ba39a79 Mon Sep 17 00:00:00 2001 From: Incont Date: Fri, 15 May 2015 20:21:39 +0300 Subject: [PATCH 126/219] reverted return errorCode --- ios-deploy.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 8d4465b4..a1993873 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1272,11 +1272,11 @@ void list_files(AMDeviceRef device) } } -void app_exists(AMDeviceRef device) +int app_exists(AMDeviceRef device) { if (bundle_id == NULL) { printf("Bundle id is not specified\n"); - return; + return 1; } AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); @@ -1299,6 +1299,9 @@ void app_exists(AMDeviceRef device) assert(AMDeviceStopSession(device) == 0); assert(AMDeviceDisconnect(device) == 0); + if (appExists) + return 0; + return -1; } void copy_file_callback(afc_connection* afc_conn_p, const char *name,int file) @@ -1549,7 +1552,7 @@ void handle_device(AMDeviceRef device) { } else if (strcmp("rm", command) == 0) { remove_path(device); } else if (strcmp("exists", command) == 0) { - app_exists(device); + exit(app_exists(device)); } else if (strcmp("uninstall_only", command) == 0) { uninstall_app(device); } From d65b94fa0648486cff1628e3383e54c7077b3825 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Fri, 15 May 2015 15:44:59 -0700 Subject: [PATCH 127/219] Updated version to 1.6.2 --- ios-deploy.c | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index c8dcd66e..02677d93 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -18,7 +18,7 @@ #include "MobileDevice.h" #include "errors.h" -#define APP_VERSION "1.6.1" +#define APP_VERSION "1.6.2" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH /* diff --git a/package.json b/package.json index 6b647c26..b7830cad 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ios-deploy", - "version": "1.6.1", + "version": "1.6.2", "os" : [ "darwin" ], "description": "launch iOS apps iOS devices from the command line (Xcode 6)", "main": "ios-deploy", From ed09a029de430e910fae68678d96c66a5bd498fe Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Fri, 15 May 2015 17:05:46 -0700 Subject: [PATCH 128/219] Fixes #132 - ios-deploy -c not listing devices with unicode characters --- ios-deploy.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 02677d93..1d737041 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -446,16 +446,11 @@ CFStringRef get_device_full_name(const AMDeviceRef device) { if (verbose) { char *devName = MYCFStringCopyUTF8String(device_name); - printf("Device Name:[%s]\n",devName); - CFShow(device_name); - printf("\n"); + CFShow([NSString stringWithFormat:@"Device Name: %s\n", devName]); free(devName); char *mdlName = MYCFStringCopyUTF8String(model_name); - printf("Model Name:[%s]\n",mdlName); - printf("MM: [%s]\n",CFStringGetCStringPtr(model_name, kCFStringEncodingUTF8)); - CFShow(model_name); - printf("\n"); + CFShow([NSString stringWithFormat:@"Model Name: %s\n", mdlName]); free(mdlName); } @@ -1540,9 +1535,9 @@ void handle_device(AMDeviceRef device) { CFStringRef found_device_id = AMDeviceCopyDeviceIdentifier(device), device_full_name = get_device_full_name(device), device_interface_name = get_device_interface_name(device); - + if (detect_only) { - printf("[....] Found %s connected through %s.\n", CFStringGetCStringPtr(device_full_name, CFStringGetSystemEncoding()), CFStringGetCStringPtr(device_interface_name, CFStringGetSystemEncoding())); + CFShow([NSString stringWithFormat:@"[....] Found %@ connected through %@.\n", device_full_name, device_interface_name]); found_device = true; return; } @@ -1550,7 +1545,7 @@ void handle_device(AMDeviceRef device) { if(strcmp(device_id, CFStringGetCStringPtr(found_device_id, CFStringGetSystemEncoding())) == 0) { found_device = true; } else { - printf("Skipping %s.\n", CFStringGetCStringPtr(device_full_name, CFStringGetSystemEncoding())); + CFShow([NSString stringWithFormat:@"Skipping %@.\n", device_full_name]); return; } } else { @@ -1558,7 +1553,7 @@ void handle_device(AMDeviceRef device) { found_device = true; } - printf("[....] Using %s (%s).\n", CFStringGetCStringPtr(device_full_name, CFStringGetSystemEncoding()), CFStringGetCStringPtr(found_device_id, CFStringGetSystemEncoding())); + CFShow([NSString stringWithFormat:@"[....] Using %@ (%@).\n", device_full_name, found_device_id]); if (command_only) { if (strcmp("list", command) == 0) { @@ -1621,7 +1616,7 @@ void handle_device(AMDeviceRef device) { if(install) { printf("------ Install phase ------\n"); - printf("[ 0%%] Found %s connected through %s, beginning install\n", CFStringGetCStringPtr(device_full_name, CFStringGetSystemEncoding()), CFStringGetCStringPtr(device_interface_name, CFStringGetSystemEncoding())); + CFShow([NSString stringWithFormat:@"[ 0%%] Found %@ connected through %@, beginning install\n", device_full_name, device_interface_name]); AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); From 18873b834067578d8265ce6700d13b8972d307fd Mon Sep 17 00:00:00 2001 From: Incont Date: Sat, 16 May 2015 18:07:27 +0300 Subject: [PATCH 129/219] small correction in app_exists --- ios-deploy.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index c8dcd66e..4d799006 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1312,8 +1312,7 @@ int app_exists(AMDeviceRef device) CFDictionaryRef result = nil; check_error(AMDeviceLookupApplications(device, options, &result)); - CFDictionaryRef app_dict = CFDictionaryGetValue(result, cf_bundle_id); - bool appExists = (app_dict == NULL) ? false : true; + bool appExists = CFDictionaryContainsKey(result, cf_bundle_id); printf("%s", appExists ? "true\n" : "false\n"); CFRelease(cf_bundle_id); From e5fc9799982f03f4982130af2d45a9b17d63f605 Mon Sep 17 00:00:00 2001 From: Incont Date: Sat, 16 May 2015 18:47:33 +0300 Subject: [PATCH 130/219] added options --list_bundle_id --- ios-deploy.c | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 4d799006..afff6e0b 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1323,6 +1323,33 @@ int app_exists(AMDeviceRef device) return -1; } +void list_bundle_id(AMDeviceRef device) +{ + AMDeviceConnect(device); + assert(AMDeviceIsPaired(device)); + check_error(AMDeviceValidatePairing(device)); + check_error(AMDeviceStartSession(device)); + + NSArray *a = [NSArray arrayWithObjects:@"CFBundleIdentifier", nil]; + NSDictionary *optionsDict = [NSDictionary dictionaryWithObject:a forKey:@"ReturnAttributes"]; + CFDictionaryRef options = (CFDictionaryRef)optionsDict; + CFDictionaryRef result = nil; + check_error(AMDeviceLookupApplications(device, options, &result)); + + CFIndex count; + count = CFDictionaryGetCount(result); + const void *keys[count]; + CFDictionaryGetKeysAndValues(result, keys, NULL); + for(int i = 0; i < count; ++i) { + CFStringRef test = (CFStringRef)keys[i]; + const char * key = CFStringGetCStringPtr((CFStringRef)keys[i], kCFStringEncodingASCII); + printf("%s\n", key); + } + + check_error(AMDeviceStopSession(device)); + check_error(AMDeviceDisconnect(device)); +} + void copy_file_callback(afc_connection* afc_conn_p, const char *name,int file) { const char *local_name=name; @@ -1574,6 +1601,8 @@ void handle_device(AMDeviceRef device) { exit(app_exists(device)); } else if (strcmp("uninstall_only", command) == 0) { uninstall_app(device); + } else if (strcmp("list_bundle_id", command) == 0) { + list_bundle_id(device); } exit(0); } @@ -1756,7 +1785,8 @@ void usage(const char* app) { " -D, --mkdir make directory on device\n" " -R, --rm remove file or directory on device (directories must be empty)\n" " -V, --version print the executable version \n" - " -e, --exists check if the app with given bundle_id is installed or not \n", + " -e, --exists check if the app with given bundle_id is installed or not \n" + " -B, --list_bundle_id list bundle_id \n", app); } @@ -1790,11 +1820,12 @@ int main(int argc, char *argv[]) { { "mkdir", required_argument, NULL, 'D'}, { "rm", required_argument, NULL, 'R'}, { "exists", no_argument, NULL, 'e'}, + { "list_bundle_id", no_argument, NULL, 'B'}, { NULL, 0, NULL, 0 }, }; char ch; - while ((ch = getopt_long(argc, argv, "VmcdvunrILeD:R:i:b:a:t:g:x:p:1:2:o:l::w::9::", longopts, NULL)) != -1) + while ((ch = getopt_long(argc, argv, "VmcdvunrILeD:R:i:b:a:t:g:x:p:1:2:o:l::w::9::B::", longopts, NULL)) != -1) { switch (ch) { case 'm': @@ -1884,6 +1915,10 @@ int main(int argc, char *argv[]) { command_only = true; command = "exists"; break; + case 'B': + command_only = true; + command = "list_bundle_id"; + break; default: usage(argv[0]); return exitcode_error; From 5d2a0d5c8b65db9581330488e2758a98c5b2e800 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Sat, 16 May 2015 09:54:56 -0700 Subject: [PATCH 131/219] Updated version to 1.6.3 --- ios-deploy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index 1d737041..3389d9b1 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -18,7 +18,7 @@ #include "MobileDevice.h" #include "errors.h" -#define APP_VERSION "1.6.2" +#define APP_VERSION "1.6.3" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH /* From cdbe112ec6ebaa73bb959a8f14c1cd78064f90a3 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Sun, 17 May 2015 00:50:33 -0700 Subject: [PATCH 132/219] Forgot to increment package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b7830cad..653a63a6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ios-deploy", - "version": "1.6.2", + "version": "1.6.3", "os" : [ "darwin" ], "description": "launch iOS apps iOS devices from the command line (Xcode 6)", "main": "ios-deploy", From 250794ce986d26d4fd3956ea01e28b7124abd3d5 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Sun, 17 May 2015 01:03:04 -0700 Subject: [PATCH 133/219] Added --list_bundle_id help text in README, added example --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 667bae1e..fa2acf4e 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ This will install ios-deploy in the `bin` folder of `/usr/local`, i.e. `/usr/loc -R, --rm remove file or directory on device (directories must be empty) -V, --version print the executable version -e, --exists check if the app with given bundle_id is installed or not - + -B, --list_bundle_id list bundle_id ## Examples @@ -95,6 +95,9 @@ The commands below assume that you have an app called `my.app` with bundle id `b // Uninstall an app ios-deploy --uninstall_only --bundle_id my.bundle.id + + // list all bundle ids of all apps on your device + ios-deploy --list_bundle_id ## Demo From 522f7bd66737875a6f6a3fe2856895268bf1718d Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Sun, 17 May 2015 01:03:24 -0700 Subject: [PATCH 134/219] Incremented version to 1.7.0 --- ios-deploy.c | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 53672816..7b3ba006 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -18,7 +18,7 @@ #include "MobileDevice.h" #include "errors.h" -#define APP_VERSION "1.6.3" +#define APP_VERSION "1.7.0" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH /* diff --git a/package.json b/package.json index 653a63a6..c040f38a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ios-deploy", - "version": "1.6.3", + "version": "1.7.0", "os" : [ "darwin" ], "description": "launch iOS apps iOS devices from the command line (Xcode 6)", "main": "ios-deploy", From 3dadb53b3b87d974ca344d433b2d06c84efab38f Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 18 May 2015 13:53:47 -0700 Subject: [PATCH 135/219] Revert version to 1.7.0 --- ios-deploy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index 9d65dde8..5f8abb44 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -18,7 +18,7 @@ #include "MobileDevice.h" #include "errors.h" -#define APP_VERSION "1.7.1" +#define APP_VERSION "1.7.0" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH /* From 1cb611098528dff0c79379d2c5a09d7111cdafb2 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 18 May 2015 14:22:55 -0700 Subject: [PATCH 136/219] Added Roadmap to README --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 5525f7f1..262c8bc3 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,15 @@ Install and debug iOS apps without using Xcode. Designed to work on un-jailbroke * You need to have a valid iOS Development certificate installed. * Xcode 6 or greater should be installed +## Roadmap + +See our [milestones](https://github.com/phonegap/ios-deploy/milestones). + +Significant changes: + + 1.8.0 will use an Xcode project instead of a Makefile (to prepare for 2.0.0) + 2.0.0 will break out the commands into their own files, and create ios-deploy-lib for node.js use + ## Installation ======= From c97b9721722b367db18c56bd0901b7b63b509b70 Mon Sep 17 00:00:00 2001 From: Incont Date: Mon, 18 May 2015 18:37:48 +0300 Subject: [PATCH 137/219] fixed bug: Unable to load the empty file (closes #141) --- ios-deploy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index 5f8abb44..d3c84b1a 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1268,7 +1268,7 @@ void* read_file_to_memory(char * path, size_t* file_size) *file_size = buf.st_size; FILE* fd = fopen(path, "r"); char* content = malloc(*file_size); - if (fread(content, *file_size, 1, fd) != 1) + if (*file_size != 0 && fread(content, *file_size, 1, fd) != 1) { fclose(fd); return NULL; From 11f1a891284bee3994ed5f01a7be39245fa33be6 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 18 May 2015 16:01:19 -0700 Subject: [PATCH 138/219] Added NSLogOut method. Same signature as NSLog, but logs to stdout instead of stderr. --- ios-deploy.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ios-deploy.c b/ios-deploy.c index d3c84b1a..7dac093d 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -221,6 +221,15 @@ void on_sys_error(const char* fmt, ...) { va_end(args); } +void NSLogOut(NSString* format, ...) { + va_list valist; + va_start(valist, format); + NSString* str = [[[NSString alloc] initWithFormat:format arguments:valist] autorelease]; + va_end(valist); + + [[str stringByAppendingString:@"\n"] writeToFile:@"/dev/stdout" atomically:NO encoding:NSUTF8StringEncoding error:nil]; +} + Boolean path_exists(CFTypeRef path) { if (CFGetTypeID(path) == CFStringGetTypeID()) { CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, true); From ddcb4932ab52b576d0867d705a66a61e580b6479 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 18 May 2015 16:57:54 -0700 Subject: [PATCH 139/219] Fixes #139 - stderr incorrect. Converted on_error, on_sys_log to use NSLog --- ios-deploy.c | 208 +++++++++++++++++++++++++-------------------------- 1 file changed, 101 insertions(+), 107 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 7dac093d..049677ba 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -192,33 +192,33 @@ const int exitcode_app_crash = 254; if (err != 0) \ { \ const char* msg = get_error_message(err); \ - on_error("Error 0x%x: %s " #call, err, msg ? msg : "unknown."); \ + /*on_error("Error 0x%x: %s " #call, err, msg ? msg : "unknown.");*/ \ + on_error(@"Error 0x%x: %s " #call, err, msg ? [NSString stringWithUTF8String:msg] : @"unknown."); \ } \ } while (false); -// Print error message and exit -void on_error(const char* fmt, ...) { - char buf[256]; - va_list args; - va_start(args, fmt); - fprintf(stderr, "[ !! ] "); - vfprintf(stderr, fmt, args); - fprintf(stderr, "\n"); - va_end(args); +void on_error(NSString* format, ...) +{ + va_list valist; + va_start(valist, format); + NSString* str = [[[NSString alloc] initWithFormat:format arguments:valist] autorelease]; + va_end(valist); + NSLog(@"[ !! ] %@", str); + exit(exitcode_error); } // Print error message getting last errno and exit -void on_sys_error(const char* fmt, ...) { +void on_sys_error(NSString* format, ...) { const char* errstr = strerror(errno); - char buf[256]; - va_list args; - va_start(args, fmt); - vsnprintf(buf, 256, fmt, args); - on_error("%s: %s", buf, errstr); - va_end(args); + va_list valist; + va_start(valist, format); + NSString* str = [[[NSString alloc] initWithFormat:format arguments:valist] autorelease]; + va_end(valist); + + on_error(@"%@ : %@", str, errstr); } void NSLogOut(NSString* format, ...) { @@ -269,7 +269,7 @@ CFStringRef find_path(CFStringRef rootPath, CFStringRef namePattern, CFStringRef CFRelease(cf_command); if (!(fpipe = (FILE *)popen(command, "r"))) - on_sys_error("Error encountered while opening pipe"); + on_sys_error(@"Error encountered while opening pipe"); char buffer[256] = { '\0' }; @@ -291,7 +291,7 @@ CFStringRef copy_xcode_dev_path() { char *command = "xcode-select -print-path"; if (!(fpipe = (FILE *)popen(command, "r"))) - on_sys_error("Error encountered while opening pipe"); + on_sys_error(@"Error encountered while opening pipe"); char buffer[256] = { '\0' }; @@ -455,11 +455,11 @@ CFStringRef get_device_full_name(const AMDeviceRef device) { if (verbose) { char *devName = MYCFStringCopyUTF8String(device_name); - CFShow([NSString stringWithFormat:@"Device Name: %s\n", devName]); + NSLogOut(@"Device Name: %@\n", devName); free(devName); char *mdlName = MYCFStringCopyUTF8String(model_name); - CFShow([NSString stringWithFormat:@"Model Name: %s\n", mdlName]); + NSLogOut(@"Model Name: %@\n", mdlName); free(mdlName); } @@ -539,7 +539,7 @@ CFStringRef copy_device_support_path(AMDeviceRef device) { CFRelease(build); if (path == NULL) - on_error("Unable to locate DeviceSupport directory. This probably means you don't have Xcode installed, you will need to launch the app manually and logging output will not be shown!"); + on_error(@"Unable to locate DeviceSupport directory. This probably means you don't have Xcode installed, you will need to launch the app manually and logging output will not be shown!"); return path; } @@ -577,7 +577,7 @@ CFStringRef copy_developer_disk_image_path(AMDeviceRef device) { CFRelease(version_parts); CFRelease(build); if (path == NULL) - on_error("Unable to locate DeveloperDiskImage.dmg. This probably means you don't have Xcode installed, you will need to launch the app manually and logging output will not be shown!"); + on_error(@"Unable to locate DeveloperDiskImage.dmg. This probably means you don't have Xcode installed, you will need to launch the app manually and logging output will not be shown!"); return path; } @@ -586,11 +586,11 @@ void mount_callback(CFDictionaryRef dict, int arg) { CFStringRef status = CFDictionaryGetValue(dict, CFSTR("Status")); if (CFEqual(status, CFSTR("LookingUpImage"))) { - printf("[ 0%%] Looking up developer disk image\n"); + NSLogOut(@"[ 0%%] Looking up developer disk image"); } else if (CFEqual(status, CFSTR("CopyingImage"))) { - printf("[ 30%%] Copying DeveloperDiskImage.dmg to device\n"); + NSLogOut(@"[ 30%%] Copying DeveloperDiskImage.dmg to device"); } else if (CFEqual(status, CFSTR("MountingImage"))) { - printf("[ 90%%] Mounting developer disk image\n"); + NSLogOut(@"[ 90%%] Mounting developer disk image"); } } @@ -600,8 +600,8 @@ void mount_developer_image(AMDeviceRef device) { CFStringRef sig_path = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@.signature"), image_path); if (verbose) { - printf("Device support path: %s\n", CFStringGetCStringPtr(ds_path, CFStringGetSystemEncoding())); - printf("Developer disk image: %s\n", CFStringGetCStringPtr(image_path, CFStringGetSystemEncoding())); + NSLogOut(@"Device support path: %@", ds_path); + NSLogOut(@"Developer disk image: %@", image_path); } CFRelease(ds_path); @@ -619,11 +619,11 @@ void mount_developer_image(AMDeviceRef device) { int result = AMDeviceMountImage(device, image_path, options, &mount_callback, 0); if (result == 0) { - printf("[ 95%%] Developer disk image mounted successfully\n"); + NSLogOut(@"[ 95%%] Developer disk image mounted successfully"); } else if (result == 0xe8000076 /* already mounted */) { - printf("[ 95%%] Developer disk image already mounted\n"); + NSLogOut(@"[ 95%%] Developer disk image already mounted"); } else { - on_error("Unable to mount developer disk image. (%x)", result); + on_error(@"Unable to mount developer disk image. (%x)", result); } CFRelease(image_path); @@ -639,7 +639,7 @@ mach_error_t transfer_callback(CFDictionaryRef dict, int arg) { CFStringRef path = CFDictionaryGetValue(dict, CFSTR("Path")); if ((last_path == NULL || !CFEqual(path, last_path)) && !CFStringHasSuffix(path, CFSTR(".ipa"))) { - printf("[%3d%%] Copying %s to device\n", percent / 2, CFStringGetCStringPtr(path, kCFStringEncodingMacRoman)); + NSLogOut(@"[%3d%%] Copying %@ to device", percent / 2, path); } if (last_path != NULL) { @@ -656,7 +656,7 @@ mach_error_t install_callback(CFDictionaryRef dict, int arg) { CFStringRef status = CFDictionaryGetValue(dict, CFSTR("Status")); CFNumberGetValue(CFDictionaryGetValue(dict, CFSTR("PercentComplete")), kCFNumberSInt32Type, &percent); - printf("[%3d%%] %s\n", (percent / 2) + 50, CFStringGetCStringPtr(status, kCFStringEncodingMacRoman)); + NSLogOut(@"[%3d%%] %@\n", (percent / 2) + 50, status); return 0; } @@ -1007,15 +1007,15 @@ void setup_lldb(AMDeviceRef device, CFURLRef url) { check_error(AMDeviceValidatePairing(device)); check_error(AMDeviceStartSession(device)); - printf("------ Debug phase ------\n"); + NSLogOut(@"------ Debug phase ------"); if(AMDeviceGetInterfaceType(device) == 2) { - CFShow([NSString stringWithFormat:@"Cannot debug %@ over %@.\n", device_full_name, device_interface_name]); + NSLogOut(@"Cannot debug %@ over %@.\n", device_full_name, device_interface_name); exit(0); } - CFShow([NSString stringWithFormat:@"Starting debug of %@ connected through %@...\n", device_full_name, device_interface_name]); + NSLogOut(@"Starting debug of %@ connected through %@...\n", device_full_name, device_interface_name); mount_developer_image(device); // put debugserver on the device start_remote_debug_server(device); // start debugserver @@ -1023,8 +1023,8 @@ void setup_lldb(AMDeviceRef device, CFURLRef url) { CFRelease(url); - printf("[100%%] Connecting to remote debug server\n"); - printf("-------------------------\n"); + NSLogOut(@"[100%%] Connecting to remote debug server"); + NSLogOut(@"-------------------------"); setpgid(getpid(), 0); signal(SIGHUP, killed); @@ -1074,7 +1074,7 @@ void launch_debugger(AMDeviceRef device, CFURLRef url) { } else if (pid > 0) { child = pid; } else { - on_sys_error("Fork failed"); + on_sys_error(@"Fork failed"); } } @@ -1110,9 +1110,9 @@ void launch_debugger_and_exit(AMDeviceRef device, CFURLRef url) { } else if (pid > 0) { child = pid; if (verbose) - printf("Waiting for child [Child: %d][Parent: %d]\n", child, parent); + NSLogOut(@"Waiting for child [Child: %d][Parent: %d]\n", child, parent); } else { - on_sys_error("Fork failed"); + on_sys_error(@"Fork failed"); } } @@ -1164,7 +1164,7 @@ void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir, AFCConnectionOpen(afcFd, 0, &afc_conn_p); } - printf("%s\n", dir); + NSLogOut(@"%@\n", dir); afc_dictionary* afc_dict_p; char *key, *val; @@ -1231,15 +1231,13 @@ service_conn_t start_house_arrest_service(AMDeviceRef device) { service_conn_t houseFd; if (bundle_id == NULL) { - printf("Bundle id is not specified\n"); - exit(1); + on_error(@"Bundle id is not specified"); } CFStringRef cf_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingASCII); if (AMDeviceStartHouseArrestService(device, cf_bundle_id, 0, &houseFd, 0) != 0) { - printf("Unable to find bundle with id: %s\n", bundle_id); - exit(1); + on_error(@"Unable to find bundle with id: %@", bundle_id); } check_error(AMDeviceStopSession(device)); @@ -1300,7 +1298,7 @@ void list_files(AMDeviceRef device) int app_exists(AMDeviceRef device) { if (bundle_id == NULL) { - printf("Bundle id is not specified\n"); + NSLogOut(@"Bundle id is not specified."); return 1; } AMDeviceConnect(device); @@ -1317,7 +1315,7 @@ int app_exists(AMDeviceRef device) check_error(AMDeviceLookupApplications(device, options, &result)); bool appExists = CFDictionaryContainsKey(result, cf_bundle_id); - printf("%s", appExists ? "true\n" : "false\n"); + NSLogOut(@"%@", appExists ? @"true" : @"false"); CFRelease(cf_bundle_id); check_error(AMDeviceStopSession(device)); @@ -1347,7 +1345,7 @@ void list_bundle_id(AMDeviceRef device) for(int i = 0; i < count; ++i) { CFStringRef test = (CFStringRef)keys[i]; const char * key = CFStringGetCStringPtr((CFStringRef)keys[i], kCFStringEncodingASCII); - printf("%s\n", key); + NSLogOut(@"%@", key); } check_error(AMDeviceStopSession(device)); @@ -1466,8 +1464,7 @@ void upload_file(AMDeviceRef device) { if (!file_content) { - printf("Could not open file: %s\n", upload_pathname); - exit(-1); + on_error(@"Could not open file: %@", upload_pathname); } // Make sure the directory was created @@ -1487,12 +1484,10 @@ void upload_file(AMDeviceRef device) { int ret = AFCFileRefOpen(afc_conn_p, target_filename, 3, &file_ref); if (ret == 0x000a) { - printf("Cannot write to %s. Permission error.\n", target_filename); - exit(1); + on_error(@"Cannot write to %@. Permission error.", target_filename); } if (ret == 0x0009) { - printf("Target %s is a directory.\n", target_filename); - exit(1); + on_error(@"Target %@ is a directory.", target_filename); } assert(ret == 0); assert(AFCFileRefWrite(afc_conn_p, file_ref, file_content, file_size) == 0); @@ -1532,7 +1527,7 @@ void remove_path(AMDeviceRef device) { void uninstall_app(AMDeviceRef device) { CFRetain(device); // don't know if this is necessary? - printf("------ Uninstall phase ------\n"); + NSLogOut(@"------ Uninstall phase ------"); //Do we already have the bundle_id passed in via the command line? if so, use it. CFStringRef cf_uninstall_bundle_id = NULL; @@ -1540,12 +1535,11 @@ void uninstall_app(AMDeviceRef device) { { cf_uninstall_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingASCII); } else { - printf ("Error: you need to pass in the bundle id, (i.e. --bundle_id com.my.app)"); - exit(1); + on_error(@"Error: you need to pass in the bundle id, (i.e. --bundle_id com.my.app)"); } if (cf_uninstall_bundle_id == NULL) { - printf("Error: Unable to get bundle id from user command or package %s\n Uninstall failed\n", app_path); + on_error(@"Error: Unable to get bundle id from user command or package %@.\nUninstall failed.", app_path); } else { AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); @@ -1554,9 +1548,9 @@ void uninstall_app(AMDeviceRef device) { int code = AMDeviceSecureUninstallApplication(0, device, cf_uninstall_bundle_id, 0, NULL, 0); if (code == 0) { - printf("[ OK ] Uninstalled package with bundle id %s\n", CFStringGetCStringPtr(cf_uninstall_bundle_id, CFStringGetSystemEncoding())); + NSLogOut(@"[ OK ] Uninstalled package with bundle id %@", cf_uninstall_bundle_id); } else { - printf("[ ERROR ] Could not uninstall package with bundle id %s\n", CFStringGetCStringPtr(cf_uninstall_bundle_id, CFStringGetSystemEncoding())); + on_error(@"[ ERROR ] Could not uninstall package with bundle id %@", cf_uninstall_bundle_id); } check_error(AMDeviceStopSession(device)); check_error(AMDeviceDisconnect(device)); @@ -1572,7 +1566,7 @@ void handle_device(AMDeviceRef device) { device_interface_name = get_device_interface_name(device); if (detect_only) { - CFShow([NSString stringWithFormat:@"[....] Found %@ connected through %@.\n", device_full_name, device_interface_name]); + NSLogOut(@"[....] Found %@ connected through %@.", device_full_name, device_interface_name); found_device = true; return; } @@ -1582,7 +1576,7 @@ void handle_device(AMDeviceRef device) { found_device = true; CFRelease(deviceCFSTR); } else { - CFShow([NSString stringWithFormat:@"Skipping %@.\n", device_full_name]); + NSLogOut(@"Skipping %@.", device_full_name); return; } } else { @@ -1590,7 +1584,7 @@ void handle_device(AMDeviceRef device) { found_device = true; } - CFShow([NSString stringWithFormat:@"[....] Using %@ (%@).\n", device_full_name, found_device_id]); + NSLogOut(@"[....] Using %@ (%@).", device_full_name, found_device_id); if (command_only) { if (strcmp("list", command) == 0) { @@ -1623,7 +1617,7 @@ void handle_device(AMDeviceRef device) { CFRelease(relative_url); if (uninstall) { - printf("------ Uninstall phase ------\n"); + NSLogOut(@"------ Uninstall phase ------"); //Do we already have the bundle_id passed in via the command line? if so, use it. CFStringRef cf_uninstall_bundle_id = NULL; @@ -1635,7 +1629,7 @@ void handle_device(AMDeviceRef device) { } if (cf_uninstall_bundle_id == NULL) { - printf("Error: Unable to get bundle id from user command or package %s\n Uninstall failed\n", app_path); + on_error(@"Error: Unable to get bundle id from user command or package %@.\nUninstall failed.", app_path); } else { AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); @@ -1644,9 +1638,9 @@ void handle_device(AMDeviceRef device) { int code = AMDeviceSecureUninstallApplication(0, device, cf_uninstall_bundle_id, 0, NULL, 0); if (code == 0) { - printf("[ OK ] Uninstalled package with bundle id %s\n", CFStringGetCStringPtr(cf_uninstall_bundle_id, CFStringGetSystemEncoding())); + NSLogOut(@"[ OK ] Uninstalled package with bundle id %@", cf_uninstall_bundle_id); } else { - printf("[ ERROR ] Could not uninstall package with bundle id %s\n", CFStringGetCStringPtr(cf_uninstall_bundle_id, CFStringGetSystemEncoding())); + on_error(@"[ ERROR ] Could not uninstall package with bundle id %@", cf_uninstall_bundle_id); } check_error(AMDeviceStopSession(device)); check_error(AMDeviceDisconnect(device)); @@ -1654,8 +1648,8 @@ void handle_device(AMDeviceRef device) { } if(install) { - printf("------ Install phase ------\n"); - CFShow([NSString stringWithFormat:@"[ 0%%] Found %@ connected through %@, beginning install\n", device_full_name, device_interface_name]); + NSLogOut(@"------ Install phase ------"); + NSLogOut(@"[ 0%%] Found %@ connected through %@, beginning install", device_full_name, device_interface_name); AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); @@ -1703,7 +1697,7 @@ void handle_device(AMDeviceRef device) { CFRelease(path); CFRelease(options); - printf("[100%%] Installed package %s\n", app_path); + NSLogOut(@"[100%%] Installed package %@", app_path); } if (!debug) @@ -1739,12 +1733,12 @@ void timeout_callback(CFRunLoopTimerRef timer, void *info) { } if(!found_device) - on_error("Timed out waiting for device."); + on_error(@"Timed out waiting for device."); } else { if (!debug) { - printf("[....] No more devices found.\n"); + NSLogOut(@"[....] No more devices found."); } if (detect_only && !found_device) { @@ -1756,7 +1750,7 @@ void timeout_callback(CFRunLoopTimerRef timer, void *info) { { if (verbose) { - printf("Timeout. Killing child (%d) tree\n", child); + NSLogOut(@"Timeout. Killing child (%d) tree.", child); } kill_ptree(child, SIGHUP); } @@ -1766,38 +1760,38 @@ void timeout_callback(CFRunLoopTimerRef timer, void *info) { } void usage(const char* app) { - printf( - "Usage: %s [OPTION]...\n" - " -d, --debug launch the app in lldb after installation\n" - " -i, --id the id of the device to connect to\n" - " -c, --detect only detect if the device is connected\n" - " -b, --bundle the path to the app bundle to be installed\n" - " -a, --args command line arguments to pass to the app when launching it\n" - " -t, --timeout number of seconds to wait for a device to be connected\n" - " -u, --unbuffered don't buffer stdout\n" - " -n, --nostart do not start the app when debugging\n" - " -I, --noninteractive start in non interactive mode (quit when app crashes or exits)\n" - " -L, --justlaunch just launch the app and exit lldb\n" - " -v, --verbose enable verbose output\n" - " -m, --noinstall directly start debugging without app install (-d not required)\n" - " -p, --port port used for device, default: dynamic\n" - " -r, --uninstall uninstall the app before install (do not use with -m; app cache and data are cleared) \n" - " -9, --uninstall_only uninstall the app ONLY. Use only with -1 \n" - " -1, --bundle_id specify bundle id for list and upload\n" - " -l, --list list files\n" - " -o, --upload upload file\n" - " -w, --download download app tree\n" - " -2, --to use together with up/download file/tree. specify target\n" - " -D, --mkdir make directory on device\n" - " -R, --rm remove file or directory on device (directories must be empty)\n" - " -V, --version print the executable version \n" - " -e, --exists check if the app with given bundle_id is installed or not \n" - " -B, --list_bundle_id list bundle_id \n", - app); + NSLog( + @"Usage: %@ [OPTION]...\n" + @" -d, --debug launch the app in lldb after installation\n" + @" -i, --id the id of the device to connect to\n" + @" -c, --detect only detect if the device is connected\n" + @" -b, --bundle the path to the app bundle to be installed\n" + @" -a, --args command line arguments to pass to the app when launching it\n" + @" -t, --timeout number of seconds to wait for a device to be connected\n" + @" -u, --unbuffered don't buffer stdout\n" + @" -n, --nostart do not start the app when debugging\n" + @" -I, --noninteractive start in non interactive mode (quit when app crashes or exits)\n" + @" -L, --justlaunch just launch the app and exit lldb\n" + @" -v, --verbose enable verbose output\n" + @" -m, --noinstall directly start debugging without app install (-d not required)\n" + @" -p, --port port used for device, default: dynamic\n" + @" -r, --uninstall uninstall the app before install (do not use with -m; app cache and data are cleared) \n" + @" -9, --uninstall_only uninstall the app ONLY. Use only with -1 \n" + @" -1, --bundle_id specify bundle id for list and upload\n" + @" -l, --list list files\n" + @" -o, --upload upload file\n" + @" -w, --download download app tree\n" + @" -2, --to use together with up/download file/tree. specify target\n" + @" -D, --mkdir make directory on device\n" + @" -R, --rm remove file or directory on device (directories must be empty)\n" + @" -V, --version print the executable version \n" + @" -e, --exists check if the app with given bundle_id is installed or not \n" + @" -B, --list_bundle_id list bundle_id \n", + [NSString stringWithUTF8String:app]); } void show_version() { - printf("%s\n", APP_VERSION); + NSLogOut(@"%@", APP_VERSION); } int main(int argc, char *argv[]) { @@ -1933,7 +1927,7 @@ int main(int argc, char *argv[]) { if (!app_path && !detect_only && !command_only) { usage(argv[0]); - on_error("One of -[b|c|o|l|w|D|R|e|9] is required to proceed!"); + on_error(@"One of -[b|c|o|l|w|D|R|e|9] is required to proceed!"); } if (unbuffered) { @@ -1947,7 +1941,7 @@ int main(int argc, char *argv[]) { if (app_path) { if (access(app_path, F_OK) != 0) { - on_sys_error("Can't access app path '%s'", app_path); + on_sys_error(@"Can't access app path '%@'", app_path); } } @@ -1956,11 +1950,11 @@ int main(int argc, char *argv[]) { { CFRunLoopTimerRef timer = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent() + timeout, 0, 0, 0, timeout_callback, NULL); CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopCommonModes); - printf("[....] Waiting up to %d seconds for iOS device to be connected\n", timeout); + NSLogOut(@"[....] Waiting up to %d seconds for iOS device to be connected", timeout); } else { - printf("[....] Waiting for iOS device to be connected\n"); + NSLogOut(@"[....] Waiting for iOS device to be connected"); } struct am_device_notification *notify; From 84aeaad03b37420aa69b9ea233a4526d7d43eaf4 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 18 May 2015 17:26:48 -0700 Subject: [PATCH 140/219] Fixed SIGSEV due to new NSLogOut changes. --- ios-deploy.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 049677ba..4da5b7f5 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -18,7 +18,7 @@ #include "MobileDevice.h" #include "errors.h" -#define APP_VERSION "1.7.0" +#define APP_VERSION @"1.7.0" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH /* @@ -454,13 +454,8 @@ CFStringRef get_device_full_name(const AMDeviceRef device) { if (verbose) { - char *devName = MYCFStringCopyUTF8String(device_name); - NSLogOut(@"Device Name: %@\n", devName); - free(devName); - - char *mdlName = MYCFStringCopyUTF8String(model_name); - NSLogOut(@"Model Name: %@\n", mdlName); - free(mdlName); + NSLogOut(@"Device Name: %@", device_name); + NSLogOut(@"Model Name: %@", model_name); } if(device_name != NULL && model_name != NULL) @@ -656,7 +651,7 @@ mach_error_t install_callback(CFDictionaryRef dict, int arg) { CFStringRef status = CFDictionaryGetValue(dict, CFSTR("Status")); CFNumberGetValue(CFDictionaryGetValue(dict, CFSTR("PercentComplete")), kCFNumberSInt32Type, &percent); - NSLogOut(@"[%3d%%] %@\n", (percent / 2) + 50, status); + NSLogOut(@"[%3d%%] %@", (percent / 2) + 50, status); return 0; } @@ -1011,11 +1006,11 @@ void setup_lldb(AMDeviceRef device, CFURLRef url) { if(AMDeviceGetInterfaceType(device) == 2) { - NSLogOut(@"Cannot debug %@ over %@.\n", device_full_name, device_interface_name); + NSLogOut(@"Cannot debug %@ over %@.", device_full_name, device_interface_name); exit(0); } - NSLogOut(@"Starting debug of %@ connected through %@...\n", device_full_name, device_interface_name); + NSLogOut(@"Starting debug of %@ connected through %@...", device_full_name, device_interface_name); mount_developer_image(device); // put debugserver on the device start_remote_debug_server(device); // start debugserver @@ -1164,7 +1159,7 @@ void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir, AFCConnectionOpen(afcFd, 0, &afc_conn_p); } - NSLogOut(@"%@\n", dir); + NSLogOut(@"%@", [NSString stringWithUTF8String:dir]); afc_dictionary* afc_dict_p; char *key, *val; @@ -1344,8 +1339,7 @@ void list_bundle_id(AMDeviceRef device) CFDictionaryGetKeysAndValues(result, keys, NULL); for(int i = 0; i < count; ++i) { CFStringRef test = (CFStringRef)keys[i]; - const char * key = CFStringGetCStringPtr((CFStringRef)keys[i], kCFStringEncodingASCII); - NSLogOut(@"%@", key); + NSLogOut(@"%@", (CFStringRef)keys[i]); } check_error(AMDeviceStopSession(device)); @@ -1584,7 +1578,7 @@ void handle_device(AMDeviceRef device) { found_device = true; } - NSLogOut(@"[....] Using %@ (%@).", device_full_name, found_device_id); + NSLogOut(@"[....] Using %@.", device_full_name); if (command_only) { if (strcmp("list", command) == 0) { @@ -1697,7 +1691,7 @@ void handle_device(AMDeviceRef device) { CFRelease(path); CFRelease(options); - NSLogOut(@"[100%%] Installed package %@", app_path); + NSLogOut(@"[100%%] Installed package %@", [NSString stringWithUTF8String:app_path]); } if (!debug) From 3ba7403a39438eed6515f9fd4a9e2e91b0df6846 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 18 May 2015 17:48:16 -0700 Subject: [PATCH 141/219] Fixed crash in upload due to NSLogOut changes --- ios-deploy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 4da5b7f5..0edc7a17 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1478,10 +1478,10 @@ void upload_file(AMDeviceRef device) { int ret = AFCFileRefOpen(afc_conn_p, target_filename, 3, &file_ref); if (ret == 0x000a) { - on_error(@"Cannot write to %@. Permission error.", target_filename); + on_error(@"Cannot write to %@. Permission error.", [NSString stringWithUTF8String:target_filename]); } if (ret == 0x0009) { - on_error(@"Target %@ is a directory.", target_filename); + on_error(@"Target %@ is a directory.", [NSString stringWithUTF8String:target_filename]); } assert(ret == 0); assert(AFCFileRefWrite(afc_conn_p, file_ref, file_content, file_size) == 0); From 8749a579368f71f41f2831be610521351292c060 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 19 May 2015 13:50:47 -0700 Subject: [PATCH 142/219] Fixes #126 - --download option works incorrectly --- ios-deploy.c | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 0edc7a17..c93f794a 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1387,25 +1387,13 @@ void copy_file_callback(afc_connection* afc_conn_p, const char *name,int file) } } -void mkdirhier(char *path) -{ - char *slash; - struct stat buf; - - if (path[0]=='.' && path[1]=='/') path+=2; - - if ((slash = strrchr(path,'/'))) { - *slash = '\0'; - if (stat(path,&buf)==0) { - *slash = '/'; - return; - } - mkdirhier(path); - mkdir (path,0777); - *slash = '/'; - } - - return; +BOOL mkdirp(NSString* path) { + NSError* error = nil; + BOOL success = [[NSFileManager defaultManager] createDirectoryAtPath:path + withIntermediateDirectories:YES + attributes:nil + error:&error]; + return success; } void download_tree(AMDeviceRef device) @@ -1413,12 +1401,15 @@ void download_tree(AMDeviceRef device) service_conn_t houseFd = start_house_arrest_service(device); afc_connection* afc_conn_p = NULL; char *dirname = NULL; + + NSString* targetPath = [NSString pathWithComponents:@[ @(target_filename), @(list_root)] ]; + mkdirp([targetPath stringByDeletingLastPathComponent]); if (AFCConnectionOpen(houseFd, 0, &afc_conn_p) == 0) do { if (target_filename) { dirname = strdup(target_filename); - mkdirhier(dirname); + mkdirp(@(dirname)); if (mkdir(dirname,0777) && errno!=EEXIST) { fprintf(stderr,"mkdir(\"%s\") failed: %s\n",dirname,strerror(errno)); break; From 590da67714d0a4a7225b559fecb945a2accabf5f Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 19 May 2015 13:57:39 -0700 Subject: [PATCH 143/219] Fixes #84 - Enhancement to --noninteractive (implicit --debug) --- ios-deploy.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ios-deploy.c b/ios-deploy.c index c93f794a..e6d24a94 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1843,6 +1843,7 @@ int main(int argc, char *argv[]) { break; case 'I': interactive = false; + debug = 1; break; case 'L': interactive = false; From 6d61b7ca7c0ff16caea4e87a91ee7535db888621 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 19 May 2015 14:02:00 -0700 Subject: [PATCH 144/219] Fixes #83 - Enhancement to --justlaunch (implicit --debug) --- ios-deploy.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ios-deploy.c b/ios-deploy.c index e6d24a94..9966ccde 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1848,6 +1848,7 @@ int main(int argc, char *argv[]) { case 'L': interactive = false; justlaunch = true; + debug = 1; break; case 'c': detect_only = true; From 7d997b89c76153b85bf5c3f4a5dff49a115aa92a Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Thu, 16 Jul 2015 16:57:24 -0700 Subject: [PATCH 145/219] Removed buildbox shell script --- resources/buildbox/build.sh | 3 --- 1 file changed, 3 deletions(-) delete mode 100755 resources/buildbox/build.sh diff --git a/resources/buildbox/build.sh b/resources/buildbox/build.sh deleted file mode 100755 index aea6cbfa..00000000 --- a/resources/buildbox/build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash -echo "$ make" -make \ No newline at end of file From bc1bb0d3200d06148cec8914f1522e7fe38c71c8 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Thu, 16 Jul 2015 17:26:48 -0700 Subject: [PATCH 146/219] Fixes #135 - convert Makefile to Xcode project --- Entitlements.plist | 8 - Info.plist | 24 -- ResourceRules.plist | 25 -- demo.c | 9 - ios-deploy-demo/main.m | 17 ++ ios-deploy.xcodeproj/project.pbxproj | 394 +++++++++++++++++++++++++++ MobileDevice.h => src/MobileDevice.h | 0 errors.h => src/errors.h | 0 ios-deploy.c => src/ios-deploy.c | 25 +- 9 files changed, 421 insertions(+), 81 deletions(-) delete mode 100644 Entitlements.plist delete mode 100644 Info.plist delete mode 100644 ResourceRules.plist delete mode 100644 demo.c create mode 100644 ios-deploy-demo/main.m create mode 100644 ios-deploy.xcodeproj/project.pbxproj rename MobileDevice.h => src/MobileDevice.h (100%) rename errors.h => src/errors.h (100%) rename ios-deploy.c => src/ios-deploy.c (99%) diff --git a/Entitlements.plist b/Entitlements.plist deleted file mode 100644 index 929c4e96..00000000 --- a/Entitlements.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - get-task-allow - - - \ No newline at end of file diff --git a/Info.plist b/Info.plist deleted file mode 100644 index c2ade143..00000000 --- a/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleName - demo - CFBundleSupportedPlatforms - - iPhoneOS - - CFBundleExecutable - demo - CFBundleVersion - 1.0 - CFBundleIdentifier - demo - CFBundleResourceSpecification - ResourceRules.plist - LSRequiresIPhoneOS - - CFBundleDisplayName - demo - - \ No newline at end of file diff --git a/ResourceRules.plist b/ResourceRules.plist deleted file mode 100644 index e7ec329d..00000000 --- a/ResourceRules.plist +++ /dev/null @@ -1,25 +0,0 @@ - - - - - rules - - .* - - Info.plist - - omit - - weight - 10 - - ResourceRules.plist - - omit - - weight - 100 - - - - diff --git a/demo.c b/demo.c deleted file mode 100644 index 583f43b6..00000000 --- a/demo.c +++ /dev/null @@ -1,9 +0,0 @@ -#include - -int main(int argc, const char* argv[]) { - int i; - for (i = 0; i < argc; i++) { - printf("argv[%d] = %s\n", i, argv[i]); - } - return 0; -} diff --git a/ios-deploy-demo/main.m b/ios-deploy-demo/main.m new file mode 100644 index 00000000..c64512eb --- /dev/null +++ b/ios-deploy-demo/main.m @@ -0,0 +1,17 @@ +// +// main.m +// ios-deploy-demo +// +// Created by shazron on 7/16/15. +// Copyright (c) 2015 PhoneGap. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + @autoreleasepool { + // insert code here... + NSLog(@"Hello, World!"); + } + return 0; +} diff --git a/ios-deploy.xcodeproj/project.pbxproj b/ios-deploy.xcodeproj/project.pbxproj new file mode 100644 index 00000000..63e23854 --- /dev/null +++ b/ios-deploy.xcodeproj/project.pbxproj @@ -0,0 +1,394 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 7E70899C1B587DE4004D23AA /* ios-deploy.c in Sources */ = {isa = PBXBuildFile; fileRef = 7E7089991B587DE4004D23AA /* ios-deploy.c */; settings = {COMPILER_FLAGS = "-x objective-c -fno-objc-arc"; }; }; + 7E70899E1B587F29004D23AA /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E70899D1B587F29004D23AA /* CoreFoundation.framework */; }; + 7E7089A01B58801E004D23AA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E70899F1B58801E004D23AA /* Foundation.framework */; }; + 7E7089B31B58826A004D23AA /* demo.c in Sources */ = {isa = PBXBuildFile; fileRef = 7E7089AF1B58826A004D23AA /* demo.c */; }; + 7E7089B41B5882C3004D23AA /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E70899D1B587F29004D23AA /* CoreFoundation.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 7E70898C1B587BF3004D23AA /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; + 7E7089A51B58825B004D23AA /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 7E70898E1B587BF3004D23AA /* ios-deploy */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "ios-deploy"; sourceTree = BUILT_PRODUCTS_DIR; }; + 7E7089991B587DE4004D23AA /* ios-deploy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "ios-deploy.c"; path = "src/ios-deploy.c"; sourceTree = SOURCE_ROOT; }; + 7E70899A1B587DE4004D23AA /* errors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = errors.h; path = src/errors.h; sourceTree = SOURCE_ROOT; }; + 7E70899B1B587DE4004D23AA /* MobileDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MobileDevice.h; path = src/MobileDevice.h; sourceTree = SOURCE_ROOT; }; + 7E70899D1B587F29004D23AA /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; + 7E70899F1B58801E004D23AA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 7E7089A71B58825B004D23AA /* ios-deploy-demo */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "ios-deploy-demo"; sourceTree = BUILT_PRODUCTS_DIR; }; + 7E7089A91B58825B004D23AA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 7E7089AF1B58826A004D23AA /* demo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = demo.c; sourceTree = ""; }; + 7E7089B01B58826A004D23AA /* Entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Entitlements.plist; sourceTree = ""; }; + 7E7089B11B58826A004D23AA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 7E7089B21B58826A004D23AA /* ResourceRules.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = ResourceRules.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7E70898B1B587BF3004D23AA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7E7089A01B58801E004D23AA /* Foundation.framework in Frameworks */, + 7E70899E1B587F29004D23AA /* CoreFoundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7E7089A41B58825B004D23AA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7E7089B41B5882C3004D23AA /* CoreFoundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7E7089851B587BF3004D23AA = { + isa = PBXGroup; + children = ( + 7E7089AE1B58826A004D23AA /* demo */, + 7E7089901B587BF3004D23AA /* ios-deploy */, + 7E7089A81B58825B004D23AA /* ios-deploy-demo */, + 7E7089A21B588219004D23AA /* Frameworks */, + 7E70898F1B587BF3004D23AA /* Products */, + ); + sourceTree = ""; + }; + 7E70898F1B587BF3004D23AA /* Products */ = { + isa = PBXGroup; + children = ( + 7E70898E1B587BF3004D23AA /* ios-deploy */, + 7E7089A71B58825B004D23AA /* ios-deploy-demo */, + ); + name = Products; + sourceTree = ""; + }; + 7E7089901B587BF3004D23AA /* ios-deploy */ = { + isa = PBXGroup; + children = ( + 7E7089991B587DE4004D23AA /* ios-deploy.c */, + 7E70899A1B587DE4004D23AA /* errors.h */, + 7E70899B1B587DE4004D23AA /* MobileDevice.h */, + ); + path = "ios-deploy"; + sourceTree = ""; + }; + 7E7089A21B588219004D23AA /* Frameworks */ = { + isa = PBXGroup; + children = ( + 7E70899F1B58801E004D23AA /* Foundation.framework */, + 7E70899D1B587F29004D23AA /* CoreFoundation.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 7E7089A81B58825B004D23AA /* ios-deploy-demo */ = { + isa = PBXGroup; + children = ( + 7E7089A91B58825B004D23AA /* main.m */, + ); + path = "ios-deploy-demo"; + sourceTree = ""; + }; + 7E7089AE1B58826A004D23AA /* demo */ = { + isa = PBXGroup; + children = ( + 7E7089AF1B58826A004D23AA /* demo.c */, + 7E7089B01B58826A004D23AA /* Entitlements.plist */, + 7E7089B11B58826A004D23AA /* Info.plist */, + 7E7089B21B58826A004D23AA /* ResourceRules.plist */, + ); + path = demo; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7E70898D1B587BF3004D23AA /* ios-deploy */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7E7089951B587BF3004D23AA /* Build configuration list for PBXNativeTarget "ios-deploy" */; + buildPhases = ( + 7E70898A1B587BF3004D23AA /* Sources */, + 7E70898B1B587BF3004D23AA /* Frameworks */, + 7E70898C1B587BF3004D23AA /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "ios-deploy"; + productName = "ios-deploy"; + productReference = 7E70898E1B587BF3004D23AA /* ios-deploy */; + productType = "com.apple.product-type.tool"; + }; + 7E7089A61B58825B004D23AA /* ios-deploy-demo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7E7089AB1B58825B004D23AA /* Build configuration list for PBXNativeTarget "ios-deploy-demo" */; + buildPhases = ( + 7E7089A31B58825B004D23AA /* Sources */, + 7E7089A41B58825B004D23AA /* Frameworks */, + 7E7089A51B58825B004D23AA /* CopyFiles */, + 7E7089B51B5882EC004D23AA /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "ios-deploy-demo"; + productName = "ios-deploy-demo"; + productReference = 7E7089A71B58825B004D23AA /* ios-deploy-demo */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7E7089861B587BF3004D23AA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0640; + ORGANIZATIONNAME = PhoneGap; + TargetAttributes = { + 7E70898D1B587BF3004D23AA = { + CreatedOnToolsVersion = 6.4; + }; + 7E7089A61B58825B004D23AA = { + CreatedOnToolsVersion = 6.4; + }; + }; + }; + buildConfigurationList = 7E7089891B587BF3004D23AA /* Build configuration list for PBXProject "ios-deploy" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 7E7089851B587BF3004D23AA; + productRefGroup = 7E70898F1B587BF3004D23AA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7E70898D1B587BF3004D23AA /* ios-deploy */, + 7E7089A61B58825B004D23AA /* ios-deploy-demo */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + 7E7089B51B5882EC004D23AA /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "#mkdir -p demo.app\n#cp demo demo.app/\n#cp Info.plist ResourceRules.plist demo.app/\n#codesign -f -s \"iPhone Developer\" --entitlements Entitlements.plist demo.app"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7E70898A1B587BF3004D23AA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7E70899C1B587DE4004D23AA /* ios-deploy.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7E7089A31B58825B004D23AA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7E7089B31B58826A004D23AA /* demo.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7E7089931B587BF3004D23AA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.8; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = ( + "-framework", + MobileDevice, + "-F/System/Library/PrivateFrameworks", + ); + SDKROOT = macosx; + }; + name = Debug; + }; + 7E7089941B587BF3004D23AA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.8; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ( + "-framework", + MobileDevice, + "-F/System/Library/PrivateFrameworks", + ); + SDKROOT = macosx; + }; + name = Release; + }; + 7E7089961B587BF3004D23AA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 7E7089971B587BF3004D23AA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 7E7089AC1B58825B004D23AA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + MACOSX_DEPLOYMENT_TARGET = 10.8; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 7E7089AD1B58825B004D23AA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + MACOSX_DEPLOYMENT_TARGET = 10.8; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7E7089891B587BF3004D23AA /* Build configuration list for PBXProject "ios-deploy" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7E7089931B587BF3004D23AA /* Debug */, + 7E7089941B587BF3004D23AA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7E7089951B587BF3004D23AA /* Build configuration list for PBXNativeTarget "ios-deploy" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7E7089961B587BF3004D23AA /* Debug */, + 7E7089971B587BF3004D23AA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7E7089AB1B58825B004D23AA /* Build configuration list for PBXNativeTarget "ios-deploy-demo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7E7089AC1B58825B004D23AA /* Debug */, + 7E7089AD1B58825B004D23AA /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7E7089861B587BF3004D23AA /* Project object */; +} diff --git a/MobileDevice.h b/src/MobileDevice.h similarity index 100% rename from MobileDevice.h rename to src/MobileDevice.h diff --git a/errors.h b/src/errors.h similarity index 100% rename from errors.h rename to src/errors.h diff --git a/ios-deploy.c b/src/ios-deploy.c similarity index 99% rename from ios-deploy.c rename to src/ios-deploy.c index 9966ccde..7a601e14 100644 --- a/ios-deploy.c +++ b/src/ios-deploy.c @@ -169,7 +169,7 @@ char *app_path = NULL; char *device_id = NULL; char *args = NULL; char *list_root = NULL; -int timeout = 0; +int _timeout = 0; int port = 0; // 0 means "dynamically assigned" CFStringRef last_path = NULL; service_conn_t gdbfd; @@ -315,7 +315,7 @@ const char *get_home() { CFStringRef copy_xcode_path_for(CFStringRef subPath, CFStringRef search) { CFStringRef xcodeDevPath = copy_xcode_dev_path(); - CFStringRef path; + CFStringRef path = NULL; bool found = false; const char* home = get_home(); CFRange slashLocation; @@ -846,7 +846,7 @@ int kill_ptree(pid_t root, int signum); void server_callback (CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, const void *data, void *info) { - int res; + ssize_t res; if (CFDataGetLength (data) == 0) { // close the socket on which we've got end-of-file, the server_socket. @@ -956,7 +956,7 @@ int kill_ptree(pid_t root, int signum) { return -1; } - kill_ptree_inner(root, signum, kp, len / sizeof(struct kinfo_proc)); + kill_ptree_inner(root, signum, kp, (int)(len / sizeof(struct kinfo_proc))); free(kp); return 0; @@ -1338,7 +1338,6 @@ void list_bundle_id(AMDeviceRef device) const void *keys[count]; CFDictionaryGetKeysAndValues(result, keys, NULL); for(int i = 0; i < count; ++i) { - CFStringRef test = (CFStringRef)keys[i]; NSLogOut(@"%@", (CFStringRef)keys[i]); } @@ -1485,8 +1484,6 @@ void upload_file(AMDeviceRef device) { void make_directory(AMDeviceRef device) { service_conn_t houseFd = start_house_arrest_service(device); - afc_file_ref file_ref; - afc_connection afc_conn; afc_connection* afc_conn_p = &afc_conn; AFCConnectionOpen(houseFd, 0, &afc_conn_p); @@ -1498,8 +1495,6 @@ void make_directory(AMDeviceRef device) { void remove_path(AMDeviceRef device) { service_conn_t houseFd = start_house_arrest_service(device); - afc_file_ref file_ref; - afc_connection afc_conn; afc_connection* afc_conn_p = &afc_conn; AFCConnectionOpen(houseFd, 0, &afc_conn_p); @@ -1833,7 +1828,7 @@ int main(int argc, char *argv[]) { verbose = 1; break; case 't': - timeout = atoi(optarg); + _timeout = atoi(optarg); break; case 'u': unbuffered = 1; @@ -1922,8 +1917,8 @@ int main(int argc, char *argv[]) { setbuf(stderr, NULL); } - if (detect_only && timeout == 0) { - timeout = 5; + if (detect_only && _timeout == 0) { + _timeout = 5; } if (app_path) { @@ -1933,11 +1928,11 @@ int main(int argc, char *argv[]) { } AMDSetLogLevel(5); // otherwise syslog gets flooded with crap - if (timeout > 0) + if (_timeout > 0) { - CFRunLoopTimerRef timer = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent() + timeout, 0, 0, 0, timeout_callback, NULL); + CFRunLoopTimerRef timer = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent() + _timeout, 0, 0, 0, timeout_callback, NULL); CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopCommonModes); - NSLogOut(@"[....] Waiting up to %d seconds for iOS device to be connected", timeout); + NSLogOut(@"[....] Waiting up to %d seconds for iOS device to be connected", _timeout); } else { From be506a9f7fc49602ffb677a5a94fc96a726149ec Mon Sep 17 00:00:00 2001 From: Julius Trinkunas Date: Wed, 22 Jul 2015 18:16:31 +0300 Subject: [PATCH 147/219] Fixes #157 - Bad error formatting string in check_error() --- ios-deploy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index 9966ccde..e734fbaf 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -193,7 +193,7 @@ const int exitcode_app_crash = 254; { \ const char* msg = get_error_message(err); \ /*on_error("Error 0x%x: %s " #call, err, msg ? msg : "unknown.");*/ \ - on_error(@"Error 0x%x: %s " #call, err, msg ? [NSString stringWithUTF8String:msg] : @"unknown."); \ + on_error(@"Error 0x%x: %@ " #call, err, msg ? [NSString stringWithUTF8String:msg] : @"unknown."); \ } \ } while (false); From 73f30fdfed7cb4a6d0002e30b204571434d1fb3a Mon Sep 17 00:00:00 2001 From: Julius Trinkunas Date: Wed, 22 Jul 2015 18:19:02 +0300 Subject: [PATCH 148/219] Add text for 0xe8008019 error. --- errors.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/errors.h b/errors.h index 106ab28a..4cdebec5 100644 --- a/errors.h +++ b/errors.h @@ -168,7 +168,9 @@ static errorcode_to_id_t errorcode_to_id[] = { { 0xe800009b, "kAMDMCChallengeRequired" }, { 0xe800009c, "kAMDMissingBundleVersionError" }, + // Errors without id->string mapping. { 0xe8008015, "A valid provisioning profile for this executable was not found."}, + { 0xe8008019, "The application does not have a valid signature." }, }; const int errorcode_to_id_count = sizeof(errorcode_to_id) / sizeof(errorcode_to_id_t); From 835e161f6665f364a1f7d742aafd514f6a7085e7 Mon Sep 17 00:00:00 2001 From: Julius Trinkunas Date: Wed, 22 Jul 2015 18:33:51 +0300 Subject: [PATCH 149/219] Add text for 0xe800801c error. --- errors.h | 1 + 1 file changed, 1 insertion(+) diff --git a/errors.h b/errors.h index 4cdebec5..b3b48156 100644 --- a/errors.h +++ b/errors.h @@ -171,6 +171,7 @@ static errorcode_to_id_t errorcode_to_id[] = { // Errors without id->string mapping. { 0xe8008015, "A valid provisioning profile for this executable was not found."}, { 0xe8008019, "The application does not have a valid signature." }, + { 0xe800801c, "No code signature found." }, }; const int errorcode_to_id_count = sizeof(errorcode_to_id) / sizeof(errorcode_to_id_t); From 307a5f94528e92cc2d8a02855731b69f5a155c0b Mon Sep 17 00:00:00 2001 From: Julius Trinkunas Date: Tue, 28 Jul 2015 13:00:15 +0300 Subject: [PATCH 150/219] Add text for error 0xe8008018. --- errors.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/errors.h b/errors.h index b3b48156..6a3160a2 100644 --- a/errors.h +++ b/errors.h @@ -169,7 +169,8 @@ static errorcode_to_id_t errorcode_to_id[] = { { 0xe800009c, "kAMDMissingBundleVersionError" }, // Errors without id->string mapping. - { 0xe8008015, "A valid provisioning profile for this executable was not found."}, + { 0xe8008015, "A valid provisioning profile for this executable was not found." }, + { 0xe8008018, "The identity used to sign the executable is no longer valid. Please verify that your device’s clock is properly set, and that your signing certificate is not expired." }, { 0xe8008019, "The application does not have a valid signature." }, { 0xe800801c, "No code signature found." }, }; From 5eb12202b29216e9242a9f6048aeffae7a177c6a Mon Sep 17 00:00:00 2001 From: Julius Trinkunas Date: Mon, 10 Aug 2015 16:01:13 +0300 Subject: [PATCH 151/219] Add attribution for error code reverse engineering. --- LICENSE | 6 ++++++ errors.h | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index e8010a30..f8e017ae 100644 --- a/LICENSE +++ b/LICENSE @@ -1,2 +1,8 @@ ios-deploy is available under the provisions of the GNU General Public License, version 3 (or later), available here: http://www.gnu.org/licenses/gpl-3.0.html + + +Error codes used for error messages were taken from SDMMobileDevice framework, +originally reverse engineered by Sam Marshall. SDMMobileDevice is distributed +under BSD 3-Clause license and is available here: +https://github.com/samdmarshall/SDMMobileDevice diff --git a/errors.h b/errors.h index 6a3160a2..616ec70a 100644 --- a/errors.h +++ b/errors.h @@ -9,7 +9,8 @@ typedef struct error_id_to_message { const char* message; } error_id_to_message_t; -// Taken from https://github.com/samdmarshall/SDMMobileDevice/blob/master/Framework/MobileDevice/Error/SDMMD_Error.h +// Most error codes are taken from SDMMobileDevice framework, and were reverse engineered by Sam Marshall. +// https://github.com/samdmarshall/SDMMobileDevice/blob/master/Framework/MobileDevice/Error/SDMMD_Error.h static errorcode_to_id_t errorcode_to_id[] = { { 0xe8000001, "kAMDUndefinedError" }, { 0xe8000002, "kAMDBadHeaderError" }, From 2c9ea8f16ef1aa251e4cfa5f41d9cab8d088c57a Mon Sep 17 00:00:00 2001 From: Julius Trinkunas Date: Tue, 11 Aug 2015 13:28:04 +0300 Subject: [PATCH 152/219] Add attribution for error code reverse engineering. Second try. --- errors.h | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/errors.h b/errors.h index 616ec70a..fe8f42f2 100644 --- a/errors.h +++ b/errors.h @@ -9,8 +9,29 @@ typedef struct error_id_to_message { const char* message; } error_id_to_message_t; -// Most error codes are taken from SDMMobileDevice framework, and were reverse engineered by Sam Marshall. +// Parts of error code to localization id map is taken from SDMMobileDevice framework. Associated license is bellow. // https://github.com/samdmarshall/SDMMobileDevice/blob/master/Framework/MobileDevice/Error/SDMMD_Error.h +// +// Copyright (c) 2014, Sam Marshall +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +// following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of Sam Marshall nor the names of its contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. static errorcode_to_id_t errorcode_to_id[] = { { 0xe8000001, "kAMDUndefinedError" }, { 0xe8000002, "kAMDBadHeaderError" }, From cf9d024a2b806c35440c83c90ce099a3b4173839 Mon Sep 17 00:00:00 2001 From: Julius Trinkunas Date: Tue, 15 Sep 2015 18:14:37 +0300 Subject: [PATCH 153/219] Add text for errors 0xe8008016 and 0xe8008017. --- errors.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/errors.h b/errors.h index fe8f42f2..868c880c 100644 --- a/errors.h +++ b/errors.h @@ -192,6 +192,8 @@ static errorcode_to_id_t errorcode_to_id[] = { // Errors without id->string mapping. { 0xe8008015, "A valid provisioning profile for this executable was not found." }, + { 0xe8008016, "The entitlements specified in your application’s Code Signing Entitlements file do not match those specified in your provisioning profile." }, + { 0xe8008017, "A signed resource has been added, modified, or deleted." }, { 0xe8008018, "The identity used to sign the executable is no longer valid. Please verify that your device’s clock is properly set, and that your signing certificate is not expired." }, { 0xe8008019, "The application does not have a valid signature." }, { 0xe800801c, "No code signature found." }, From 7b834b0e31d8eae47a625934ce0933765313f701 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 13:14:21 -0700 Subject: [PATCH 154/219] Fixes #153 - Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** +[NSString stringWithUTF8String:]: NULL cString' #153 --- ios-deploy.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index e734fbaf..87168b21 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1402,6 +1402,9 @@ void download_tree(AMDeviceRef device) afc_connection* afc_conn_p = NULL; char *dirname = NULL; + list_root = list_root? list_root : "/"; + target_filename = target_filename? target_filename : "."; + NSString* targetPath = [NSString pathWithComponents:@[ @(target_filename), @(list_root)] ]; mkdirp([targetPath stringByDeletingLastPathComponent]); @@ -1420,7 +1423,7 @@ void download_tree(AMDeviceRef device) } } - read_dir(houseFd, afc_conn_p, list_root?list_root:"/", copy_file_callback); + read_dir(houseFd, afc_conn_p, list_root, copy_file_callback); } while(0); From 34540ce545c2c767e838e1ef1f48cbe28aef4ed6 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 13:18:50 -0700 Subject: [PATCH 155/219] Fixed typo in README example. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 262c8bc3..fadcfb2f 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ The commands below assume that you have an app called `my.app` with bundle id `b ios-deploy --exists --bundle_id com.apple.mobilemail // Download the Documents directory of the app *only* - ios-deploy --download=/Documents -bundle_id my.app.id --to ./my_download_location + ios-deploy --download=/Documents --bundle_id my.app.id --to ./my_download_location // List ids and names of connected devices ios-deploy -c From 21c8dc9cf5b83b1d240bf711a027ec4411e1ee83 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 13:33:51 -0700 Subject: [PATCH 156/219] Fixes #56 - Assertion failed AMDeviceSecureTransferPath (app name has non-ASCII characters) --- ios-deploy.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 87168b21..65c4de6b 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -735,7 +735,7 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { rangeLLDB.length = CFStringGetLength(pmodule); if (args) { - CFStringRef cf_args = CFStringCreateWithCString(NULL, args, kCFStringEncodingASCII); + CFStringRef cf_args = CFStringCreateWithCString(NULL, args, kCFStringEncodingUTF8); CFStringFindAndReplace(cmds, CFSTR("{args}"), cf_args, range, 0); rangeLLDB.length = CFStringGetLength(pmodule); CFStringFindAndReplace(pmodule, CFSTR("{args}"), cf_args, rangeLLDB, 0); @@ -786,14 +786,14 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { } strcat(python_file_path, ".py"); - CFStringRef cf_python_command = CFStringCreateWithCString(NULL, python_command, kCFStringEncodingASCII); + CFStringRef cf_python_command = CFStringCreateWithCString(NULL, python_command, kCFStringEncodingUTF8); CFStringFindAndReplace(cmds, CFSTR("{python_command}"), cf_python_command, range, 0); range.length = CFStringGetLength(cmds); - CFStringRef cf_python_file_path = CFStringCreateWithCString(NULL, python_file_path, kCFStringEncodingASCII); + CFStringRef cf_python_file_path = CFStringCreateWithCString(NULL, python_file_path, kCFStringEncodingUTF8); CFStringFindAndReplace(cmds, CFSTR("{python_file_path}"), cf_python_file_path, range, 0); range.length = CFStringGetLength(cmds); - CFDataRef cmds_data = CFStringCreateExternalRepresentation(NULL, cmds, kCFStringEncodingASCII, 0); + CFDataRef cmds_data = CFStringCreateExternalRepresentation(NULL, cmds, kCFStringEncodingUTF8, 0); char prep_cmds_path[300] = PREP_CMDS_PATH; if(device_id != NULL) strcat(prep_cmds_path, device_id); @@ -815,7 +815,7 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { fwrite(extra_cmds, strlen(extra_cmds), 1, out); fclose(out); - CFDataRef pmodule_data = CFStringCreateExternalRepresentation(NULL, pmodule, kCFStringEncodingASCII, 0); + CFDataRef pmodule_data = CFStringCreateExternalRepresentation(NULL, pmodule, kCFStringEncodingUTF8, 0); out = fopen(python_file_path, "w"); fwrite(CFDataGetBytePtr(pmodule_data), CFDataGetLength(pmodule_data), 1, out); @@ -1229,7 +1229,7 @@ service_conn_t start_house_arrest_service(AMDeviceRef device) { on_error(@"Bundle id is not specified"); } - CFStringRef cf_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingASCII); + CFStringRef cf_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingUTF8); if (AMDeviceStartHouseArrestService(device, cf_bundle_id, 0, &houseFd, 0) != 0) { on_error(@"Unable to find bundle with id: %@", bundle_id); @@ -1301,7 +1301,7 @@ int app_exists(AMDeviceRef device) check_error(AMDeviceValidatePairing(device)); check_error(AMDeviceStartSession(device)); - CFStringRef cf_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingASCII); + CFStringRef cf_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingUTF8); NSArray *a = [NSArray arrayWithObjects:@"CFBundleIdentifier", nil]; NSDictionary *optionsDict = [NSDictionary dictionaryWithObject:a forKey:@"ReturnAttributes"]; @@ -1521,7 +1521,7 @@ void uninstall_app(AMDeviceRef device) { CFStringRef cf_uninstall_bundle_id = NULL; if (bundle_id != NULL) { - cf_uninstall_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingASCII); + cf_uninstall_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingUTF8); } else { on_error(@"Error: you need to pass in the bundle id, (i.e. --bundle_id com.my.app)"); } @@ -1559,7 +1559,7 @@ void handle_device(AMDeviceRef device) { return; } if (device_id != NULL) { - CFStringRef deviceCFSTR = CFStringCreateWithCString(NULL, device_id, kCFStringEncodingASCII); + CFStringRef deviceCFSTR = CFStringCreateWithCString(NULL, device_id, kCFStringEncodingUTF8); if (CFStringCompare(deviceCFSTR, found_device_id, kCFCompareCaseInsensitive) == kCFCompareEqualTo) { found_device = true; CFRelease(deviceCFSTR); @@ -1598,7 +1598,7 @@ void handle_device(AMDeviceRef device) { CFRetain(device); // don't know if this is necessary? - CFStringRef path = CFStringCreateWithCString(NULL, app_path, kCFStringEncodingASCII); + CFStringRef path = CFStringCreateWithCString(NULL, app_path, kCFStringEncodingUTF8); CFURLRef relative_url = CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, false); CFURLRef url = CFURLCopyAbsoluteURL(relative_url); @@ -1611,7 +1611,7 @@ void handle_device(AMDeviceRef device) { CFStringRef cf_uninstall_bundle_id = NULL; if (bundle_id != NULL) { - cf_uninstall_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingASCII); + cf_uninstall_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingUTF8); } else { cf_uninstall_bundle_id = get_bundle_id(url); } From 16f52589db0333aca2676cb1a4e385d78f38c8cf Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 13:43:28 -0700 Subject: [PATCH 157/219] Fixes #168 - Segmentation Fault 11 (when deploying an .ipa file) --- ios-deploy.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ios-deploy.c b/ios-deploy.c index 65c4de6b..d59847d4 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -702,7 +702,10 @@ CFURLRef copy_device_app_url(AMDeviceRef device, CFStringRef identifier) { CFStringRef copy_disk_app_identifier(CFURLRef disk_app_url) { CFURLRef plist_url = CFURLCreateCopyAppendingPathComponent(NULL, disk_app_url, CFSTR("Info.plist"), false); CFReadStreamRef plist_stream = CFReadStreamCreateWithFile(NULL, plist_url); - CFReadStreamOpen(plist_stream); + if (!CFReadStreamOpen(plist_stream)) { + on_error(@"Cannot read Info.plist file: %@", plist_url); + } + CFPropertyListRef plist = CFPropertyListCreateWithStream(NULL, plist_stream, 0, kCFPropertyListImmutable, NULL, NULL); CFStringRef bundle_identifier = CFRetain(CFDictionaryGetValue(plist, CFSTR("CFBundleIdentifier"))); CFReadStreamClose(plist_stream); From 75820a0979ee6748f5d444c845e1bb8e2c7acf52 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 14:00:42 -0700 Subject: [PATCH 158/219] Fixes #166 - Segfault when passed a non-existent bundle #166 --- ios-deploy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index d59847d4..cf9114fc 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -218,7 +218,7 @@ void on_sys_error(NSString* format, ...) { NSString* str = [[[NSString alloc] initWithFormat:format arguments:valist] autorelease]; va_end(valist); - on_error(@"%@ : %@", str, errstr); + on_error(@"%@ : %@", str, [NSString stringWithUTF8String:errstr]); } void NSLogOut(NSString* format, ...) { @@ -1934,7 +1934,7 @@ int main(int argc, char *argv[]) { if (app_path) { if (access(app_path, F_OK) != 0) { - on_sys_error(@"Can't access app path '%@'", app_path); + on_sys_error(@"Can't access app path '%@'", [NSString stringWithUTF8String:app_path]); } } From bb25caf586d3e9702e1f3eae1ceaccbdaeb7e035 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 15:39:57 -0700 Subject: [PATCH 159/219] Fixes #164 - Error when launch application in multi-user context --- ios-deploy.c | 86 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 37 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index cf9114fc..11b97185 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -19,8 +19,8 @@ #include "errors.h" #define APP_VERSION @"1.7.0" -#define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" -#define LLDB_SHELL "lldb -s " PREP_CMDS_PATH +#define PREP_CMDS_PATH @"/tmp/%@/fruitstrap-lldb-prep-cmds-" +#define LLDB_SHELL @"lldb -s %@" /* * Startup script passed to lldb. * To see how xcode interacts with lldb, put this into .lldbinit: @@ -179,6 +179,7 @@ pid_t child = 0; // Signal sent from child to parent process when LLDB finishes. const int SIGLLDB = SIGUSR1; AMDeviceRef best_device_match = NULL; +NSString* tmpUUID; // Error codes we report on different failures, so scripts can distinguish between user app exit // codes and our exit codes. For non app errors we use codes in reserved 128-255 range. @@ -230,6 +231,15 @@ void NSLogOut(NSString* format, ...) { [[str stringByAppendingString:@"\n"] writeToFile:@"/dev/stdout" atomically:NO encoding:NSUTF8StringEncoding error:nil]; } +BOOL mkdirp(NSString* path) { + NSError* error = nil; + BOOL success = [[NSFileManager defaultManager] createDirectoryAtPath:path + withIntermediateDirectories:YES + attributes:nil + error:&error]; + return success; +} + Boolean path_exists(CFTypeRef path) { if (CFGetTypeID(path) == CFStringGetTypeID()) { CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, true); @@ -781,26 +791,27 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { CFStringRef disk_container_path = CFURLCopyFileSystemPath(disk_container_url, kCFURLPOSIXPathStyle); CFStringFindAndReplace(cmds, CFSTR("{disk_container}"), disk_container_path, range, 0); - char python_file_path[300] = "/tmp/fruitstrap_"; - char python_command[300] = "fruitstrap_"; + NSString* python_file_path = [NSString stringWithFormat:@"/tmp/%@/fruitstrap_", tmpUUID]; + mkdirp(python_file_path); + + NSString* python_command = @"fruitstrap_"; if(device_id != NULL) { - strcat(python_file_path, device_id); - strcat(python_command, device_id); + python_file_path = [python_file_path stringByAppendingString:[NSString stringWithUTF8String:device_id]]; + python_command = [python_command stringByAppendingString:[NSString stringWithUTF8String:device_id]]; } - strcat(python_file_path, ".py"); + python_file_path = [python_file_path stringByAppendingString:@".py"]; - CFStringRef cf_python_command = CFStringCreateWithCString(NULL, python_command, kCFStringEncodingUTF8); - CFStringFindAndReplace(cmds, CFSTR("{python_command}"), cf_python_command, range, 0); + CFStringFindAndReplace(cmds, CFSTR("{python_command}"), (CFStringRef)python_command, range, 0); range.length = CFStringGetLength(cmds); - CFStringRef cf_python_file_path = CFStringCreateWithCString(NULL, python_file_path, kCFStringEncodingUTF8); - CFStringFindAndReplace(cmds, CFSTR("{python_file_path}"), cf_python_file_path, range, 0); + CFStringFindAndReplace(cmds, CFSTR("{python_file_path}"), (CFStringRef)python_file_path, range, 0); range.length = CFStringGetLength(cmds); CFDataRef cmds_data = CFStringCreateExternalRepresentation(NULL, cmds, kCFStringEncodingUTF8, 0); - char prep_cmds_path[300] = PREP_CMDS_PATH; - if(device_id != NULL) - strcat(prep_cmds_path, device_id); - FILE *out = fopen(prep_cmds_path, "w"); + NSString* prep_cmds_path = [NSString stringWithFormat:PREP_CMDS_PATH, tmpUUID]; + if(device_id != NULL) { + prep_cmds_path = [prep_cmds_path stringByAppendingString:[NSString stringWithUTF8String:device_id]]; + } + FILE *out = fopen([prep_cmds_path UTF8String], "w"); fwrite(CFDataGetBytePtr(cmds_data), CFDataGetLength(cmds_data), 1, out); // Write additional commands based on mode we're running in const char* extra_cmds; @@ -820,7 +831,7 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { CFDataRef pmodule_data = CFStringCreateExternalRepresentation(NULL, pmodule, kCFStringEncodingUTF8, 0); - out = fopen(python_file_path, "w"); + out = fopen([python_file_path UTF8String], "w"); fwrite(CFDataGetBytePtr(pmodule_data), CFDataGetLength(pmodule_data), 1, out); fclose(out); @@ -836,8 +847,6 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { CFRelease(disk_container_url); CFRelease(disk_container_path); CFRelease(cmds_data); - CFRelease(cf_python_command); - CFRelease(cf_python_file_path); } CFSocketRef server_socket; @@ -1053,12 +1062,15 @@ void launch_debugger(AMDeviceRef device, CFURLRef url) { // this we setup a dummy pipe on stdin, so read() would block expecting "user's" input. setup_dummy_pipe_on_stdin(pfd); - char lldb_shell[400]; - sprintf(lldb_shell, LLDB_SHELL); - if(device_id != NULL) - strcat(lldb_shell, device_id); + NSString* lldb_shell; + NSString* prep_cmds = [NSString stringWithFormat:PREP_CMDS_PATH, tmpUUID]; + lldb_shell = [NSString stringWithFormat:LLDB_SHELL, prep_cmds]; + + if(device_id != NULL) { + lldb_shell = [lldb_shell stringByAppendingString: [NSString stringWithUTF8String:device_id]]; + } - int status = system(lldb_shell); // launch lldb + int status = system([lldb_shell UTF8String]); // launch lldb if (status == -1) perror("failed launching lldb"); @@ -1090,12 +1102,14 @@ void launch_debugger_and_exit(AMDeviceRef device, CFURLRef url) { if (dup2(pfd[0],STDIN_FILENO) == -1) perror("dup2 failed"); - char lldb_shell[400]; - sprintf(lldb_shell, LLDB_SHELL); - if(device_id != NULL) - strcat(lldb_shell, device_id); - int status = system(lldb_shell); // launch lldb + NSString* prep_cmds = [NSString stringWithFormat:PREP_CMDS_PATH, tmpUUID]; + NSString* lldb_shell = [NSString stringWithFormat:LLDB_SHELL, prep_cmds]; + if(device_id != NULL) { + lldb_shell = [lldb_shell stringByAppendingString:[NSString stringWithUTF8String:device_id]]; + } + + int status = system([lldb_shell UTF8String]); // launch lldb if (status == -1) perror("failed launching lldb"); @@ -1390,15 +1404,6 @@ void copy_file_callback(afc_connection* afc_conn_p, const char *name,int file) } } -BOOL mkdirp(NSString* path) { - NSError* error = nil; - BOOL success = [[NSFileManager defaultManager] createDirectoryAtPath:path - withIntermediateDirectories:YES - attributes:nil - error:&error]; - return success; -} - void download_tree(AMDeviceRef device) { service_conn_t houseFd = start_house_arrest_service(device); @@ -1786,6 +1791,13 @@ void show_version() { } int main(int argc, char *argv[]) { + + // create a UUID for tmp purposes + CFUUIDRef uuid = CFUUIDCreate(NULL); + CFStringRef str = CFUUIDCreateString(NULL, uuid); + CFRelease(uuid); + tmpUUID = [(NSString*)str autorelease]; + static struct option longopts[] = { { "debug", no_argument, NULL, 'd' }, { "id", required_argument, NULL, 'i' }, From adc8a5b9c298d901d4388bb5cba20f9049b2dc83 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 15:47:59 -0700 Subject: [PATCH 160/219] Added iPhone 6s and 6s Plus models. --- ios-deploy.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ios-deploy.c b/ios-deploy.c index 11b97185..b9babc13 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -431,6 +431,11 @@ const CFStringRef get_device_hardware_name(const AMDeviceRef device) { GET_FRIENDLY_MODEL_NAME(model, "N61AP", "iPhone 6 (GSM)") GET_FRIENDLY_MODEL_NAME(model, "N56AP", "iPhone 6 Plus") + GET_FRIENDLY_MODEL_NAME(model, "N71mAP", "iPhone 6s") + GET_FRIENDLY_MODEL_NAME(model, "N71AP", "iPhone 6s") + GET_FRIENDLY_MODEL_NAME(model, "N66AP", "iPhone 6s Plus") + GET_FRIENDLY_MODEL_NAME(model, "N66mAP", "iPhone 6s Plus") + return model; } From 37563856511ab2333f7762c7f64cc3c17db1ad45 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 16:51:27 -0700 Subject: [PATCH 161/219] Fixes #170 - ios-deploy installing over both USB and WiFi --- MobileDevice.h | 4 ++++ ios-deploy.c | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/MobileDevice.h b/MobileDevice.h index d97eafb5..8c9ff91a 100644 --- a/MobileDevice.h +++ b/MobileDevice.h @@ -195,6 +195,10 @@ mach_error_t AMDeviceNotificationSubscribe(am_device_notification_callback callback, unsigned int unused0, unsigned int unused1, void* //unsigned int dn_unknown3, struct am_device_notification **notification); + +mach_error_t AMDeviceNotificationUnsubscribe(am_device_notification subscription); + + /* Connects to the iPhone. Pass in the am_device structure that the * notification callback will give to you. * diff --git a/ios-deploy.c b/ios-deploy.c index b9babc13..2cf16eb6 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -180,6 +180,7 @@ pid_t child = 0; const int SIGLLDB = SIGUSR1; AMDeviceRef best_device_match = NULL; NSString* tmpUUID; +struct am_device_notification *notify; // Error codes we report on different failures, so scripts can distinguish between user app exit // codes and our exit codes. For non app errors we use codes in reserved 128-255 range. @@ -1714,7 +1715,8 @@ void device_callback(struct am_device_notification_callback_info *info, void *ar switch (info->msg) { case ADNCI_MSG_CONNECTED: if(device_id != NULL || !debug || AMDeviceGetInterfaceType(info->dev) != 2) { - handle_device(info->dev); + AMDeviceNotificationUnsubscribe(*notify); + handle_device(info->dev); } else if(best_device_match == NULL) { best_device_match = info->dev; CFRetain(best_device_match); @@ -1967,7 +1969,6 @@ int main(int argc, char *argv[]) { NSLogOut(@"[....] Waiting for iOS device to be connected"); } - struct am_device_notification *notify; AMDeviceNotificationSubscribe(&device_callback, 0, 0, NULL, ¬ify); CFRunLoopRun(); } From 55d076b8054055c0ffb236ee262585c6379ffdd1 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 17:11:14 -0700 Subject: [PATCH 162/219] Incremented version to 1.8.0 --- ios-deploy.c | 2 +- package.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index 2cf16eb6..b4309872 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -18,7 +18,7 @@ #include "MobileDevice.h" #include "errors.h" -#define APP_VERSION @"1.7.0" +#define APP_VERSION @"1.8.0" #define PREP_CMDS_PATH @"/tmp/%@/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL @"lldb -s %@" /* diff --git a/package.json b/package.json index c040f38a..1a1f71d9 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "ios-deploy", - "version": "1.7.0", + "version": "1.8.0", "os" : [ "darwin" ], - "description": "launch iOS apps iOS devices from the command line (Xcode 6)", + "description": "launch iOS apps iOS devices from the command line (Xcode 7)", "main": "ios-deploy", "scripts": { "preinstall": "make ios-deploy" From 6aa7b57014e0bebd234028547efbc14b1ec1d386 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 17:46:50 -0700 Subject: [PATCH 163/219] Fixes #167 - On El Cap, detect Xcode 7 properly installed --- check_reqs.js | 32 ++++++++++++++++++++++++++++++++ package.json | 11 ++++++++--- 2 files changed, 40 insertions(+), 3 deletions(-) create mode 100755 check_reqs.js diff --git a/check_reqs.js b/check_reqs.js new file mode 100755 index 00000000..fda89dae --- /dev/null +++ b/check_reqs.js @@ -0,0 +1,32 @@ +#!/usr/bin/env node + +var shell = require('shelljs'); +var util = require('util'); +var os = require('os'); + +var XCODEBUILD_MIN_VERSION = '6.4'; +var XCODEBUILD_NOT_FOUND_MESSAGE = + 'Please install Xcode version ' + XCODEBUILD_MIN_VERSION + ' or greater from App Store'; + +var tool = 'xcodebuild' +var tool_command = shell.which(tool); +if (!tool_command) { + console.log(tool + ' : ' + XCODEBUILD_NOT_FOUND_MESSAGE); + process.exit(1); +} + +shell.exec(tool + ' -version', { silent: true }, function(code, output) { + if (code === 0) { + var arr = output.match(/^Xcode (\d+\.\d+)/); + var ver = arr[1]; + + if (os.release() >= '15.0.0' && ver < '7.0') { + console.log(util.format('You need at least Xcode 7.0 on OS X 10.11 El Capitan (you have version %s)', ver)); + process.exit(1); + } + + if (ver < XCODEBUILD_MIN_VERSION) { + console.log(util.format('%s : %s. (you have version %s)', tool, XCODEBUILD_NOT_FOUND_MESSAGE, ver)); + } + } +}); \ No newline at end of file diff --git a/package.json b/package.json index 1a1f71d9..564034a3 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,22 @@ { "name": "ios-deploy", "version": "1.8.0", - "os" : [ "darwin" ], + "os": [ + "darwin" + ], "description": "launch iOS apps iOS devices from the command line (Xcode 7)", "main": "ios-deploy", "scripts": { - "preinstall": "make ios-deploy" + "preinstall": "./check_reqs.js && make ios-deploy" }, - "bin" : "./ios-deploy" , + "bin": "./ios-deploy", "repository": { "type": "git", "url": "https://github.com/phonegap/ios-deploy" }, + "dependencies": { + "shelljs": "^0.2.6" + }, "keywords": [ "ios-deploy", "deploy to iOS device" From 92f6238bba280c684479e629d7393b306147b6da Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 22:01:36 -0700 Subject: [PATCH 164/219] check_reqs - removed shelljs dependency --- check_reqs.js | 47 ++++++++++++++++++++++++++++++----------------- package.json | 3 --- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/check_reqs.js b/check_reqs.js index fda89dae..ce06b733 100755 --- a/check_reqs.js +++ b/check_reqs.js @@ -1,32 +1,45 @@ #!/usr/bin/env node -var shell = require('shelljs'); var util = require('util'); var os = require('os'); +var child_process = require('child_process'); var XCODEBUILD_MIN_VERSION = '6.4'; -var XCODEBUILD_NOT_FOUND_MESSAGE = - 'Please install Xcode version ' + XCODEBUILD_MIN_VERSION + ' or greater from App Store'; - -var tool = 'xcodebuild' -var tool_command = shell.which(tool); -if (!tool_command) { - console.log(tool + ' : ' + XCODEBUILD_NOT_FOUND_MESSAGE); - process.exit(1); -} - -shell.exec(tool + ' -version', { silent: true }, function(code, output) { +var XCODEBUILD_NOT_FOUND_MESSAGE = util.format('Please install Xcode version %s or greater from the Mac App Store.', XCODEBUILD_MIN_VERSION); +var TOOL = 'xcodebuild'; + +var xcode_version = child_process.spawn(TOOL, ['-version']), + version_string = ''; + +xcode_version.stdout.on('data', function (data) { + version_string += data; +}); + +xcode_version.stderr.on('data', function (data) { + console.log('stderr: ' + data); +}); + +xcode_version.on('error', function (err) { + console.log(util.format('Tool %s was not found. %s', TOOL, XCODEBUILD_NOT_FOUND_MESSAGE)); +}); + +xcode_version.on('close', function (code) { if (code === 0) { - var arr = output.match(/^Xcode (\d+\.\d+)/); + var arr = version_string.match(/^Xcode (\d+\.\d+)/); var ver = arr[1]; if (os.release() >= '15.0.0' && ver < '7.0') { - console.log(util.format('You need at least Xcode 7.0 on OS X 10.11 El Capitan (you have version %s)', ver)); + console.log(util.format('You need at least Xcode 7.0 when you are on OS X 10.11 El Capitan (you have version %s)', ver)); process.exit(1); } - + if (ver < XCODEBUILD_MIN_VERSION) { console.log(util.format('%s : %s. (you have version %s)', tool, XCODEBUILD_NOT_FOUND_MESSAGE, ver)); } - } -}); \ No newline at end of file + } + process.exit(code); +}); + + + + diff --git a/package.json b/package.json index 564034a3..c279b078 100644 --- a/package.json +++ b/package.json @@ -14,9 +14,6 @@ "type": "git", "url": "https://github.com/phonegap/ios-deploy" }, - "dependencies": { - "shelljs": "^0.2.6" - }, "keywords": [ "ios-deploy", "deploy to iOS device" From d2aee71a92757fd06844c1a6a5bd0d1e62c1a0b8 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 22:06:28 -0700 Subject: [PATCH 165/219] Fixes #156 - --list command add trailing slash for directories --- ios-deploy.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ios-deploy.c b/ios-deploy.c index b4309872..f5620797 100644 --- a/ios-deploy.c +++ b/ios-deploy.c @@ -1182,8 +1182,6 @@ void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir, AFCConnectionOpen(afcFd, 0, &afc_conn_p); } - NSLogOut(@"%@", [NSString stringWithUTF8String:dir]); - afc_dictionary* afc_dict_p; char *key, *val; int not_dir = 0; @@ -1201,6 +1199,12 @@ void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir, } } AFCKeyValueClose(afc_dict_p); + + if (not_dir) { + NSLogOut(@"%@", [NSString stringWithUTF8String:dir]); + } else { + NSLogOut(@"%@/", [NSString stringWithUTF8String:dir]); + } if (not_dir) { if (callback) (*callback)(afc_conn_p, dir, not_dir); From bf58b61561032b11917079d408ac02341378c486 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 22:13:04 -0700 Subject: [PATCH 166/219] Fixes #176 - Add documentation issue for node preinstall script (workaround) --- README.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index fadcfb2f..79355060 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,9 @@ Install and debug iOS apps without using Xcode. Designed to work on un-jailbroke ## Requirements -* Mac OS X. Tested on 10.10 Yosemite and iOS 8.3 +* Mac OS X. Tested on 10.11 El Capitan and iOS 9.0 * You need to have a valid iOS Development certificate installed. -* Xcode 6 or greater should be installed +* Xcode 6.4 or greater should be installed ## Roadmap @@ -40,6 +40,14 @@ make install prefix=/usr/local This will install ios-deploy in the `bin` folder of `/usr/local`, i.e. `/usr/local/bin` + +### OS X 10.11 El Capitan + +If you are *not* using a node version manager like [nvm](https://github.com/creationix/nvm) or [n](https://github.com/tj/n), you may have to do either of these two things below when under El Capitan: + +1. Add the `--unsafe-perm` flag when installing ios-deploy +2. Ensure the `nobody` user has write access to `/usr/local/lib/node_modules/ios-deploy/ios-deploy` + ## Usage Usage: ios-deploy [OPTION]... @@ -113,7 +121,7 @@ The commands below assume that you have an app called `my.app` with bundle id `b The included demo.app represents the minimum required to get code running on iOS. -* `make demo.app` will generate the demo.app executable. If it doesn't compile, modify IOS_SDK_VERSION in the Makefile. +* `make demo.app` will generate the demo.app executable. If it doesn't compile, modify `IOS_SDK_VERSION` in the Makefile. * `make debug` will install demo.app and launch a LLDB session. ## Notes From 99dba4e58c8f76bc9c1c7a9b00fb626feb2617dd Mon Sep 17 00:00:00 2001 From: Julius Trinkunas Date: Wed, 22 Jul 2015 18:16:31 +0300 Subject: [PATCH 167/219] Fixes #157 - Bad error formatting string in check_error() --- src/ios-deploy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ios-deploy.c b/src/ios-deploy.c index 7a601e14..779682f3 100644 --- a/src/ios-deploy.c +++ b/src/ios-deploy.c @@ -193,7 +193,7 @@ const int exitcode_app_crash = 254; { \ const char* msg = get_error_message(err); \ /*on_error("Error 0x%x: %s " #call, err, msg ? msg : "unknown.");*/ \ - on_error(@"Error 0x%x: %s " #call, err, msg ? [NSString stringWithUTF8String:msg] : @"unknown."); \ + on_error(@"Error 0x%x: %@ " #call, err, msg ? [NSString stringWithUTF8String:msg] : @"unknown."); \ } \ } while (false); From d10562c501a33a9eedb451fadd96bc884e7457f7 Mon Sep 17 00:00:00 2001 From: Julius Trinkunas Date: Wed, 22 Jul 2015 18:19:02 +0300 Subject: [PATCH 168/219] Add text for 0xe8008019 error. --- src/errors.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/errors.h b/src/errors.h index 106ab28a..4cdebec5 100644 --- a/src/errors.h +++ b/src/errors.h @@ -168,7 +168,9 @@ static errorcode_to_id_t errorcode_to_id[] = { { 0xe800009b, "kAMDMCChallengeRequired" }, { 0xe800009c, "kAMDMissingBundleVersionError" }, + // Errors without id->string mapping. { 0xe8008015, "A valid provisioning profile for this executable was not found."}, + { 0xe8008019, "The application does not have a valid signature." }, }; const int errorcode_to_id_count = sizeof(errorcode_to_id) / sizeof(errorcode_to_id_t); From 4d58838ef11f164439c0fb515f95c4cca787abb1 Mon Sep 17 00:00:00 2001 From: Julius Trinkunas Date: Wed, 22 Jul 2015 18:33:51 +0300 Subject: [PATCH 169/219] Add text for 0xe800801c error. --- src/errors.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/errors.h b/src/errors.h index 4cdebec5..b3b48156 100644 --- a/src/errors.h +++ b/src/errors.h @@ -171,6 +171,7 @@ static errorcode_to_id_t errorcode_to_id[] = { // Errors without id->string mapping. { 0xe8008015, "A valid provisioning profile for this executable was not found."}, { 0xe8008019, "The application does not have a valid signature." }, + { 0xe800801c, "No code signature found." }, }; const int errorcode_to_id_count = sizeof(errorcode_to_id) / sizeof(errorcode_to_id_t); From 093b4b3c9a0c2aa4cfcd2afb5f8453e3fa989b33 Mon Sep 17 00:00:00 2001 From: Julius Trinkunas Date: Tue, 28 Jul 2015 13:00:15 +0300 Subject: [PATCH 170/219] Add text for error 0xe8008018. --- src/errors.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/errors.h b/src/errors.h index b3b48156..6a3160a2 100644 --- a/src/errors.h +++ b/src/errors.h @@ -169,7 +169,8 @@ static errorcode_to_id_t errorcode_to_id[] = { { 0xe800009c, "kAMDMissingBundleVersionError" }, // Errors without id->string mapping. - { 0xe8008015, "A valid provisioning profile for this executable was not found."}, + { 0xe8008015, "A valid provisioning profile for this executable was not found." }, + { 0xe8008018, "The identity used to sign the executable is no longer valid. Please verify that your device’s clock is properly set, and that your signing certificate is not expired." }, { 0xe8008019, "The application does not have a valid signature." }, { 0xe800801c, "No code signature found." }, }; From ed7c70aa593bec97dcd7bf71ab25fbabf724ce70 Mon Sep 17 00:00:00 2001 From: Julius Trinkunas Date: Mon, 10 Aug 2015 16:01:13 +0300 Subject: [PATCH 171/219] Add attribution for error code reverse engineering. --- LICENSE | 6 ++++++ src/errors.h | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index e8010a30..f8e017ae 100644 --- a/LICENSE +++ b/LICENSE @@ -1,2 +1,8 @@ ios-deploy is available under the provisions of the GNU General Public License, version 3 (or later), available here: http://www.gnu.org/licenses/gpl-3.0.html + + +Error codes used for error messages were taken from SDMMobileDevice framework, +originally reverse engineered by Sam Marshall. SDMMobileDevice is distributed +under BSD 3-Clause license and is available here: +https://github.com/samdmarshall/SDMMobileDevice diff --git a/src/errors.h b/src/errors.h index 6a3160a2..616ec70a 100644 --- a/src/errors.h +++ b/src/errors.h @@ -9,7 +9,8 @@ typedef struct error_id_to_message { const char* message; } error_id_to_message_t; -// Taken from https://github.com/samdmarshall/SDMMobileDevice/blob/master/Framework/MobileDevice/Error/SDMMD_Error.h +// Most error codes are taken from SDMMobileDevice framework, and were reverse engineered by Sam Marshall. +// https://github.com/samdmarshall/SDMMobileDevice/blob/master/Framework/MobileDevice/Error/SDMMD_Error.h static errorcode_to_id_t errorcode_to_id[] = { { 0xe8000001, "kAMDUndefinedError" }, { 0xe8000002, "kAMDBadHeaderError" }, From ca2e7a3c75c8e3912d7b7c9eb90f6a4d2e641213 Mon Sep 17 00:00:00 2001 From: Julius Trinkunas Date: Tue, 11 Aug 2015 13:28:04 +0300 Subject: [PATCH 172/219] Add attribution for error code reverse engineering. Second try. --- src/errors.h | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/errors.h b/src/errors.h index 616ec70a..fe8f42f2 100644 --- a/src/errors.h +++ b/src/errors.h @@ -9,8 +9,29 @@ typedef struct error_id_to_message { const char* message; } error_id_to_message_t; -// Most error codes are taken from SDMMobileDevice framework, and were reverse engineered by Sam Marshall. +// Parts of error code to localization id map is taken from SDMMobileDevice framework. Associated license is bellow. // https://github.com/samdmarshall/SDMMobileDevice/blob/master/Framework/MobileDevice/Error/SDMMD_Error.h +// +// Copyright (c) 2014, Sam Marshall +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +// following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of Sam Marshall nor the names of its contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. static errorcode_to_id_t errorcode_to_id[] = { { 0xe8000001, "kAMDUndefinedError" }, { 0xe8000002, "kAMDBadHeaderError" }, From 0390522194aeb42e424d2b3ebe4e17d851127ca3 Mon Sep 17 00:00:00 2001 From: Julius Trinkunas Date: Tue, 15 Sep 2015 18:14:37 +0300 Subject: [PATCH 173/219] Add text for errors 0xe8008016 and 0xe8008017. --- src/errors.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/errors.h b/src/errors.h index fe8f42f2..868c880c 100644 --- a/src/errors.h +++ b/src/errors.h @@ -192,6 +192,8 @@ static errorcode_to_id_t errorcode_to_id[] = { // Errors without id->string mapping. { 0xe8008015, "A valid provisioning profile for this executable was not found." }, + { 0xe8008016, "The entitlements specified in your application’s Code Signing Entitlements file do not match those specified in your provisioning profile." }, + { 0xe8008017, "A signed resource has been added, modified, or deleted." }, { 0xe8008018, "The identity used to sign the executable is no longer valid. Please verify that your device’s clock is properly set, and that your signing certificate is not expired." }, { 0xe8008019, "The application does not have a valid signature." }, { 0xe800801c, "No code signature found." }, From d6216760e4ff33dd0478c2c8e0b090fa17a92575 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 13:14:21 -0700 Subject: [PATCH 174/219] Fixes #153 - Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** +[NSString stringWithUTF8String:]: NULL cString' #153 --- src/ios-deploy.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ios-deploy.c b/src/ios-deploy.c index 779682f3..82d6dae5 100644 --- a/src/ios-deploy.c +++ b/src/ios-deploy.c @@ -1401,6 +1401,9 @@ void download_tree(AMDeviceRef device) afc_connection* afc_conn_p = NULL; char *dirname = NULL; + list_root = list_root? list_root : "/"; + target_filename = target_filename? target_filename : "."; + NSString* targetPath = [NSString pathWithComponents:@[ @(target_filename), @(list_root)] ]; mkdirp([targetPath stringByDeletingLastPathComponent]); @@ -1419,7 +1422,7 @@ void download_tree(AMDeviceRef device) } } - read_dir(houseFd, afc_conn_p, list_root?list_root:"/", copy_file_callback); + read_dir(houseFd, afc_conn_p, list_root, copy_file_callback); } while(0); From 545521954b99bc6d4e368cb99ea3abe5add65944 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 13:18:50 -0700 Subject: [PATCH 175/219] Fixed typo in README example. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 262c8bc3..fadcfb2f 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ The commands below assume that you have an app called `my.app` with bundle id `b ios-deploy --exists --bundle_id com.apple.mobilemail // Download the Documents directory of the app *only* - ios-deploy --download=/Documents -bundle_id my.app.id --to ./my_download_location + ios-deploy --download=/Documents --bundle_id my.app.id --to ./my_download_location // List ids and names of connected devices ios-deploy -c From 5e7420502bd7b04a63e6da21a0fdeac72f11a5ab Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 13:33:51 -0700 Subject: [PATCH 176/219] Fixes #56 - Assertion failed AMDeviceSecureTransferPath (app name has non-ASCII characters) --- src/ios-deploy.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/ios-deploy.c b/src/ios-deploy.c index 82d6dae5..733d5917 100644 --- a/src/ios-deploy.c +++ b/src/ios-deploy.c @@ -735,7 +735,7 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { rangeLLDB.length = CFStringGetLength(pmodule); if (args) { - CFStringRef cf_args = CFStringCreateWithCString(NULL, args, kCFStringEncodingASCII); + CFStringRef cf_args = CFStringCreateWithCString(NULL, args, kCFStringEncodingUTF8); CFStringFindAndReplace(cmds, CFSTR("{args}"), cf_args, range, 0); rangeLLDB.length = CFStringGetLength(pmodule); CFStringFindAndReplace(pmodule, CFSTR("{args}"), cf_args, rangeLLDB, 0); @@ -786,14 +786,14 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { } strcat(python_file_path, ".py"); - CFStringRef cf_python_command = CFStringCreateWithCString(NULL, python_command, kCFStringEncodingASCII); + CFStringRef cf_python_command = CFStringCreateWithCString(NULL, python_command, kCFStringEncodingUTF8); CFStringFindAndReplace(cmds, CFSTR("{python_command}"), cf_python_command, range, 0); range.length = CFStringGetLength(cmds); - CFStringRef cf_python_file_path = CFStringCreateWithCString(NULL, python_file_path, kCFStringEncodingASCII); + CFStringRef cf_python_file_path = CFStringCreateWithCString(NULL, python_file_path, kCFStringEncodingUTF8); CFStringFindAndReplace(cmds, CFSTR("{python_file_path}"), cf_python_file_path, range, 0); range.length = CFStringGetLength(cmds); - CFDataRef cmds_data = CFStringCreateExternalRepresentation(NULL, cmds, kCFStringEncodingASCII, 0); + CFDataRef cmds_data = CFStringCreateExternalRepresentation(NULL, cmds, kCFStringEncodingUTF8, 0); char prep_cmds_path[300] = PREP_CMDS_PATH; if(device_id != NULL) strcat(prep_cmds_path, device_id); @@ -815,7 +815,7 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { fwrite(extra_cmds, strlen(extra_cmds), 1, out); fclose(out); - CFDataRef pmodule_data = CFStringCreateExternalRepresentation(NULL, pmodule, kCFStringEncodingASCII, 0); + CFDataRef pmodule_data = CFStringCreateExternalRepresentation(NULL, pmodule, kCFStringEncodingUTF8, 0); out = fopen(python_file_path, "w"); fwrite(CFDataGetBytePtr(pmodule_data), CFDataGetLength(pmodule_data), 1, out); @@ -1229,7 +1229,7 @@ service_conn_t start_house_arrest_service(AMDeviceRef device) { on_error(@"Bundle id is not specified"); } - CFStringRef cf_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingASCII); + CFStringRef cf_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingUTF8); if (AMDeviceStartHouseArrestService(device, cf_bundle_id, 0, &houseFd, 0) != 0) { on_error(@"Unable to find bundle with id: %@", bundle_id); @@ -1301,7 +1301,7 @@ int app_exists(AMDeviceRef device) check_error(AMDeviceValidatePairing(device)); check_error(AMDeviceStartSession(device)); - CFStringRef cf_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingASCII); + CFStringRef cf_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingUTF8); NSArray *a = [NSArray arrayWithObjects:@"CFBundleIdentifier", nil]; NSDictionary *optionsDict = [NSDictionary dictionaryWithObject:a forKey:@"ReturnAttributes"]; @@ -1516,7 +1516,7 @@ void uninstall_app(AMDeviceRef device) { CFStringRef cf_uninstall_bundle_id = NULL; if (bundle_id != NULL) { - cf_uninstall_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingASCII); + cf_uninstall_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingUTF8); } else { on_error(@"Error: you need to pass in the bundle id, (i.e. --bundle_id com.my.app)"); } @@ -1554,7 +1554,7 @@ void handle_device(AMDeviceRef device) { return; } if (device_id != NULL) { - CFStringRef deviceCFSTR = CFStringCreateWithCString(NULL, device_id, kCFStringEncodingASCII); + CFStringRef deviceCFSTR = CFStringCreateWithCString(NULL, device_id, kCFStringEncodingUTF8); if (CFStringCompare(deviceCFSTR, found_device_id, kCFCompareCaseInsensitive) == kCFCompareEqualTo) { found_device = true; CFRelease(deviceCFSTR); @@ -1593,7 +1593,7 @@ void handle_device(AMDeviceRef device) { CFRetain(device); // don't know if this is necessary? - CFStringRef path = CFStringCreateWithCString(NULL, app_path, kCFStringEncodingASCII); + CFStringRef path = CFStringCreateWithCString(NULL, app_path, kCFStringEncodingUTF8); CFURLRef relative_url = CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, false); CFURLRef url = CFURLCopyAbsoluteURL(relative_url); @@ -1606,7 +1606,7 @@ void handle_device(AMDeviceRef device) { CFStringRef cf_uninstall_bundle_id = NULL; if (bundle_id != NULL) { - cf_uninstall_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingASCII); + cf_uninstall_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingUTF8); } else { cf_uninstall_bundle_id = get_bundle_id(url); } From 2a1844500b52bc5fc8bb33be9ca11eeb0afdc047 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 13:43:28 -0700 Subject: [PATCH 177/219] Fixes #168 - Segmentation Fault 11 (when deploying an .ipa file) --- src/ios-deploy.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ios-deploy.c b/src/ios-deploy.c index 733d5917..546991fc 100644 --- a/src/ios-deploy.c +++ b/src/ios-deploy.c @@ -702,7 +702,10 @@ CFURLRef copy_device_app_url(AMDeviceRef device, CFStringRef identifier) { CFStringRef copy_disk_app_identifier(CFURLRef disk_app_url) { CFURLRef plist_url = CFURLCreateCopyAppendingPathComponent(NULL, disk_app_url, CFSTR("Info.plist"), false); CFReadStreamRef plist_stream = CFReadStreamCreateWithFile(NULL, plist_url); - CFReadStreamOpen(plist_stream); + if (!CFReadStreamOpen(plist_stream)) { + on_error(@"Cannot read Info.plist file: %@", plist_url); + } + CFPropertyListRef plist = CFPropertyListCreateWithStream(NULL, plist_stream, 0, kCFPropertyListImmutable, NULL, NULL); CFStringRef bundle_identifier = CFRetain(CFDictionaryGetValue(plist, CFSTR("CFBundleIdentifier"))); CFReadStreamClose(plist_stream); From ab39342b0fb4ca0d08ab947c4287d243adb4c80e Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 14:00:42 -0700 Subject: [PATCH 178/219] Fixes #166 - Segfault when passed a non-existent bundle #166 --- src/ios-deploy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ios-deploy.c b/src/ios-deploy.c index 546991fc..44d5369d 100644 --- a/src/ios-deploy.c +++ b/src/ios-deploy.c @@ -218,7 +218,7 @@ void on_sys_error(NSString* format, ...) { NSString* str = [[[NSString alloc] initWithFormat:format arguments:valist] autorelease]; va_end(valist); - on_error(@"%@ : %@", str, errstr); + on_error(@"%@ : %@", str, [NSString stringWithUTF8String:errstr]); } void NSLogOut(NSString* format, ...) { @@ -1929,7 +1929,7 @@ int main(int argc, char *argv[]) { if (app_path) { if (access(app_path, F_OK) != 0) { - on_sys_error(@"Can't access app path '%@'", app_path); + on_sys_error(@"Can't access app path '%@'", [NSString stringWithUTF8String:app_path]); } } From 4ce355456100e755d02091d2ec161b35dd02aebc Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 15:39:57 -0700 Subject: [PATCH 179/219] Fixes #164 - Error when launch application in multi-user context --- src/ios-deploy.c | 86 +++++++++++++++++++++++++++--------------------- 1 file changed, 49 insertions(+), 37 deletions(-) diff --git a/src/ios-deploy.c b/src/ios-deploy.c index 44d5369d..779d0035 100644 --- a/src/ios-deploy.c +++ b/src/ios-deploy.c @@ -19,8 +19,8 @@ #include "errors.h" #define APP_VERSION @"1.7.0" -#define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" -#define LLDB_SHELL "lldb -s " PREP_CMDS_PATH +#define PREP_CMDS_PATH @"/tmp/%@/fruitstrap-lldb-prep-cmds-" +#define LLDB_SHELL @"lldb -s %@" /* * Startup script passed to lldb. * To see how xcode interacts with lldb, put this into .lldbinit: @@ -179,6 +179,7 @@ pid_t child = 0; // Signal sent from child to parent process when LLDB finishes. const int SIGLLDB = SIGUSR1; AMDeviceRef best_device_match = NULL; +NSString* tmpUUID; // Error codes we report on different failures, so scripts can distinguish between user app exit // codes and our exit codes. For non app errors we use codes in reserved 128-255 range. @@ -230,6 +231,15 @@ void NSLogOut(NSString* format, ...) { [[str stringByAppendingString:@"\n"] writeToFile:@"/dev/stdout" atomically:NO encoding:NSUTF8StringEncoding error:nil]; } +BOOL mkdirp(NSString* path) { + NSError* error = nil; + BOOL success = [[NSFileManager defaultManager] createDirectoryAtPath:path + withIntermediateDirectories:YES + attributes:nil + error:&error]; + return success; +} + Boolean path_exists(CFTypeRef path) { if (CFGetTypeID(path) == CFStringGetTypeID()) { CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, true); @@ -781,26 +791,27 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { CFStringRef disk_container_path = CFURLCopyFileSystemPath(disk_container_url, kCFURLPOSIXPathStyle); CFStringFindAndReplace(cmds, CFSTR("{disk_container}"), disk_container_path, range, 0); - char python_file_path[300] = "/tmp/fruitstrap_"; - char python_command[300] = "fruitstrap_"; + NSString* python_file_path = [NSString stringWithFormat:@"/tmp/%@/fruitstrap_", tmpUUID]; + mkdirp(python_file_path); + + NSString* python_command = @"fruitstrap_"; if(device_id != NULL) { - strcat(python_file_path, device_id); - strcat(python_command, device_id); + python_file_path = [python_file_path stringByAppendingString:[NSString stringWithUTF8String:device_id]]; + python_command = [python_command stringByAppendingString:[NSString stringWithUTF8String:device_id]]; } - strcat(python_file_path, ".py"); + python_file_path = [python_file_path stringByAppendingString:@".py"]; - CFStringRef cf_python_command = CFStringCreateWithCString(NULL, python_command, kCFStringEncodingUTF8); - CFStringFindAndReplace(cmds, CFSTR("{python_command}"), cf_python_command, range, 0); + CFStringFindAndReplace(cmds, CFSTR("{python_command}"), (CFStringRef)python_command, range, 0); range.length = CFStringGetLength(cmds); - CFStringRef cf_python_file_path = CFStringCreateWithCString(NULL, python_file_path, kCFStringEncodingUTF8); - CFStringFindAndReplace(cmds, CFSTR("{python_file_path}"), cf_python_file_path, range, 0); + CFStringFindAndReplace(cmds, CFSTR("{python_file_path}"), (CFStringRef)python_file_path, range, 0); range.length = CFStringGetLength(cmds); CFDataRef cmds_data = CFStringCreateExternalRepresentation(NULL, cmds, kCFStringEncodingUTF8, 0); - char prep_cmds_path[300] = PREP_CMDS_PATH; - if(device_id != NULL) - strcat(prep_cmds_path, device_id); - FILE *out = fopen(prep_cmds_path, "w"); + NSString* prep_cmds_path = [NSString stringWithFormat:PREP_CMDS_PATH, tmpUUID]; + if(device_id != NULL) { + prep_cmds_path = [prep_cmds_path stringByAppendingString:[NSString stringWithUTF8String:device_id]]; + } + FILE *out = fopen([prep_cmds_path UTF8String], "w"); fwrite(CFDataGetBytePtr(cmds_data), CFDataGetLength(cmds_data), 1, out); // Write additional commands based on mode we're running in const char* extra_cmds; @@ -820,7 +831,7 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { CFDataRef pmodule_data = CFStringCreateExternalRepresentation(NULL, pmodule, kCFStringEncodingUTF8, 0); - out = fopen(python_file_path, "w"); + out = fopen([python_file_path UTF8String], "w"); fwrite(CFDataGetBytePtr(pmodule_data), CFDataGetLength(pmodule_data), 1, out); fclose(out); @@ -836,8 +847,6 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { CFRelease(disk_container_url); CFRelease(disk_container_path); CFRelease(cmds_data); - CFRelease(cf_python_command); - CFRelease(cf_python_file_path); } CFSocketRef server_socket; @@ -1053,12 +1062,15 @@ void launch_debugger(AMDeviceRef device, CFURLRef url) { // this we setup a dummy pipe on stdin, so read() would block expecting "user's" input. setup_dummy_pipe_on_stdin(pfd); - char lldb_shell[400]; - sprintf(lldb_shell, LLDB_SHELL); - if(device_id != NULL) - strcat(lldb_shell, device_id); + NSString* lldb_shell; + NSString* prep_cmds = [NSString stringWithFormat:PREP_CMDS_PATH, tmpUUID]; + lldb_shell = [NSString stringWithFormat:LLDB_SHELL, prep_cmds]; + + if(device_id != NULL) { + lldb_shell = [lldb_shell stringByAppendingString: [NSString stringWithUTF8String:device_id]]; + } - int status = system(lldb_shell); // launch lldb + int status = system([lldb_shell UTF8String]); // launch lldb if (status == -1) perror("failed launching lldb"); @@ -1090,12 +1102,14 @@ void launch_debugger_and_exit(AMDeviceRef device, CFURLRef url) { if (dup2(pfd[0],STDIN_FILENO) == -1) perror("dup2 failed"); - char lldb_shell[400]; - sprintf(lldb_shell, LLDB_SHELL); - if(device_id != NULL) - strcat(lldb_shell, device_id); - int status = system(lldb_shell); // launch lldb + NSString* prep_cmds = [NSString stringWithFormat:PREP_CMDS_PATH, tmpUUID]; + NSString* lldb_shell = [NSString stringWithFormat:LLDB_SHELL, prep_cmds]; + if(device_id != NULL) { + lldb_shell = [lldb_shell stringByAppendingString:[NSString stringWithUTF8String:device_id]]; + } + + int status = system([lldb_shell UTF8String]); // launch lldb if (status == -1) perror("failed launching lldb"); @@ -1389,15 +1403,6 @@ void copy_file_callback(afc_connection* afc_conn_p, const char *name,int file) } } -BOOL mkdirp(NSString* path) { - NSError* error = nil; - BOOL success = [[NSFileManager defaultManager] createDirectoryAtPath:path - withIntermediateDirectories:YES - attributes:nil - error:&error]; - return success; -} - void download_tree(AMDeviceRef device) { service_conn_t houseFd = start_house_arrest_service(device); @@ -1781,6 +1786,13 @@ void show_version() { } int main(int argc, char *argv[]) { + + // create a UUID for tmp purposes + CFUUIDRef uuid = CFUUIDCreate(NULL); + CFStringRef str = CFUUIDCreateString(NULL, uuid); + CFRelease(uuid); + tmpUUID = [(NSString*)str autorelease]; + static struct option longopts[] = { { "debug", no_argument, NULL, 'd' }, { "id", required_argument, NULL, 'i' }, From 342965c16a0a3fbed9cb38c25ee857c184e9f6ae Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 15:47:59 -0700 Subject: [PATCH 180/219] Added iPhone 6s and 6s Plus models. --- src/ios-deploy.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ios-deploy.c b/src/ios-deploy.c index 779d0035..3ad9b256 100644 --- a/src/ios-deploy.c +++ b/src/ios-deploy.c @@ -431,6 +431,11 @@ const CFStringRef get_device_hardware_name(const AMDeviceRef device) { GET_FRIENDLY_MODEL_NAME(model, "N61AP", "iPhone 6 (GSM)") GET_FRIENDLY_MODEL_NAME(model, "N56AP", "iPhone 6 Plus") + GET_FRIENDLY_MODEL_NAME(model, "N71mAP", "iPhone 6s") + GET_FRIENDLY_MODEL_NAME(model, "N71AP", "iPhone 6s") + GET_FRIENDLY_MODEL_NAME(model, "N66AP", "iPhone 6s Plus") + GET_FRIENDLY_MODEL_NAME(model, "N66mAP", "iPhone 6s Plus") + return model; } From a6e94923cf409af5f9d63297785882302bc628ae Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 16:51:27 -0700 Subject: [PATCH 181/219] Fixes #170 - ios-deploy installing over both USB and WiFi --- src/MobileDevice.h | 4 ++++ src/ios-deploy.c | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/MobileDevice.h b/src/MobileDevice.h index d97eafb5..8c9ff91a 100644 --- a/src/MobileDevice.h +++ b/src/MobileDevice.h @@ -195,6 +195,10 @@ mach_error_t AMDeviceNotificationSubscribe(am_device_notification_callback callback, unsigned int unused0, unsigned int unused1, void* //unsigned int dn_unknown3, struct am_device_notification **notification); + +mach_error_t AMDeviceNotificationUnsubscribe(am_device_notification subscription); + + /* Connects to the iPhone. Pass in the am_device structure that the * notification callback will give to you. * diff --git a/src/ios-deploy.c b/src/ios-deploy.c index 3ad9b256..a2ddd19a 100644 --- a/src/ios-deploy.c +++ b/src/ios-deploy.c @@ -180,6 +180,7 @@ pid_t child = 0; const int SIGLLDB = SIGUSR1; AMDeviceRef best_device_match = NULL; NSString* tmpUUID; +struct am_device_notification *notify; // Error codes we report on different failures, so scripts can distinguish between user app exit // codes and our exit codes. For non app errors we use codes in reserved 128-255 range. @@ -1709,7 +1710,8 @@ void device_callback(struct am_device_notification_callback_info *info, void *ar switch (info->msg) { case ADNCI_MSG_CONNECTED: if(device_id != NULL || !debug || AMDeviceGetInterfaceType(info->dev) != 2) { - handle_device(info->dev); + AMDeviceNotificationUnsubscribe(*notify); + handle_device(info->dev); } else if(best_device_match == NULL) { best_device_match = info->dev; CFRetain(best_device_match); @@ -1962,7 +1964,6 @@ int main(int argc, char *argv[]) { NSLogOut(@"[....] Waiting for iOS device to be connected"); } - struct am_device_notification *notify; AMDeviceNotificationSubscribe(&device_callback, 0, 0, NULL, ¬ify); CFRunLoopRun(); } From 2f9fb4304a1d5962f513f9444906ecf7cef69782 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 17:11:14 -0700 Subject: [PATCH 182/219] Incremented version to 1.8.0 --- package.json | 4 ++-- src/ios-deploy.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index c040f38a..1a1f71d9 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "ios-deploy", - "version": "1.7.0", + "version": "1.8.0", "os" : [ "darwin" ], - "description": "launch iOS apps iOS devices from the command line (Xcode 6)", + "description": "launch iOS apps iOS devices from the command line (Xcode 7)", "main": "ios-deploy", "scripts": { "preinstall": "make ios-deploy" diff --git a/src/ios-deploy.c b/src/ios-deploy.c index a2ddd19a..c0febc1a 100644 --- a/src/ios-deploy.c +++ b/src/ios-deploy.c @@ -18,7 +18,7 @@ #include "MobileDevice.h" #include "errors.h" -#define APP_VERSION @"1.7.0" +#define APP_VERSION @"1.8.0" #define PREP_CMDS_PATH @"/tmp/%@/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL @"lldb -s %@" /* From 8d60757e770dcf6c047cb89b41d4a017c7eb41b2 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 17:46:50 -0700 Subject: [PATCH 183/219] Fixes #167 - On El Cap, detect Xcode 7 properly installed --- check_reqs.js | 32 ++++++++++++++++++++++++++++++++ package.json | 11 ++++++++--- 2 files changed, 40 insertions(+), 3 deletions(-) create mode 100755 check_reqs.js diff --git a/check_reqs.js b/check_reqs.js new file mode 100755 index 00000000..fda89dae --- /dev/null +++ b/check_reqs.js @@ -0,0 +1,32 @@ +#!/usr/bin/env node + +var shell = require('shelljs'); +var util = require('util'); +var os = require('os'); + +var XCODEBUILD_MIN_VERSION = '6.4'; +var XCODEBUILD_NOT_FOUND_MESSAGE = + 'Please install Xcode version ' + XCODEBUILD_MIN_VERSION + ' or greater from App Store'; + +var tool = 'xcodebuild' +var tool_command = shell.which(tool); +if (!tool_command) { + console.log(tool + ' : ' + XCODEBUILD_NOT_FOUND_MESSAGE); + process.exit(1); +} + +shell.exec(tool + ' -version', { silent: true }, function(code, output) { + if (code === 0) { + var arr = output.match(/^Xcode (\d+\.\d+)/); + var ver = arr[1]; + + if (os.release() >= '15.0.0' && ver < '7.0') { + console.log(util.format('You need at least Xcode 7.0 on OS X 10.11 El Capitan (you have version %s)', ver)); + process.exit(1); + } + + if (ver < XCODEBUILD_MIN_VERSION) { + console.log(util.format('%s : %s. (you have version %s)', tool, XCODEBUILD_NOT_FOUND_MESSAGE, ver)); + } + } +}); \ No newline at end of file diff --git a/package.json b/package.json index 1a1f71d9..564034a3 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,22 @@ { "name": "ios-deploy", "version": "1.8.0", - "os" : [ "darwin" ], + "os": [ + "darwin" + ], "description": "launch iOS apps iOS devices from the command line (Xcode 7)", "main": "ios-deploy", "scripts": { - "preinstall": "make ios-deploy" + "preinstall": "./check_reqs.js && make ios-deploy" }, - "bin" : "./ios-deploy" , + "bin": "./ios-deploy", "repository": { "type": "git", "url": "https://github.com/phonegap/ios-deploy" }, + "dependencies": { + "shelljs": "^0.2.6" + }, "keywords": [ "ios-deploy", "deploy to iOS device" From 6b7b31d54a11ce7b51ec86b4cbf60657122cff06 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 22:01:36 -0700 Subject: [PATCH 184/219] check_reqs - removed shelljs dependency --- check_reqs.js | 47 ++++++++++++++++++++++++++++++----------------- package.json | 3 --- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/check_reqs.js b/check_reqs.js index fda89dae..ce06b733 100755 --- a/check_reqs.js +++ b/check_reqs.js @@ -1,32 +1,45 @@ #!/usr/bin/env node -var shell = require('shelljs'); var util = require('util'); var os = require('os'); +var child_process = require('child_process'); var XCODEBUILD_MIN_VERSION = '6.4'; -var XCODEBUILD_NOT_FOUND_MESSAGE = - 'Please install Xcode version ' + XCODEBUILD_MIN_VERSION + ' or greater from App Store'; - -var tool = 'xcodebuild' -var tool_command = shell.which(tool); -if (!tool_command) { - console.log(tool + ' : ' + XCODEBUILD_NOT_FOUND_MESSAGE); - process.exit(1); -} - -shell.exec(tool + ' -version', { silent: true }, function(code, output) { +var XCODEBUILD_NOT_FOUND_MESSAGE = util.format('Please install Xcode version %s or greater from the Mac App Store.', XCODEBUILD_MIN_VERSION); +var TOOL = 'xcodebuild'; + +var xcode_version = child_process.spawn(TOOL, ['-version']), + version_string = ''; + +xcode_version.stdout.on('data', function (data) { + version_string += data; +}); + +xcode_version.stderr.on('data', function (data) { + console.log('stderr: ' + data); +}); + +xcode_version.on('error', function (err) { + console.log(util.format('Tool %s was not found. %s', TOOL, XCODEBUILD_NOT_FOUND_MESSAGE)); +}); + +xcode_version.on('close', function (code) { if (code === 0) { - var arr = output.match(/^Xcode (\d+\.\d+)/); + var arr = version_string.match(/^Xcode (\d+\.\d+)/); var ver = arr[1]; if (os.release() >= '15.0.0' && ver < '7.0') { - console.log(util.format('You need at least Xcode 7.0 on OS X 10.11 El Capitan (you have version %s)', ver)); + console.log(util.format('You need at least Xcode 7.0 when you are on OS X 10.11 El Capitan (you have version %s)', ver)); process.exit(1); } - + if (ver < XCODEBUILD_MIN_VERSION) { console.log(util.format('%s : %s. (you have version %s)', tool, XCODEBUILD_NOT_FOUND_MESSAGE, ver)); } - } -}); \ No newline at end of file + } + process.exit(code); +}); + + + + diff --git a/package.json b/package.json index 564034a3..c279b078 100644 --- a/package.json +++ b/package.json @@ -14,9 +14,6 @@ "type": "git", "url": "https://github.com/phonegap/ios-deploy" }, - "dependencies": { - "shelljs": "^0.2.6" - }, "keywords": [ "ios-deploy", "deploy to iOS device" From ede5d2542d71d24208b492ce8e750abdc81c1e44 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 22:06:28 -0700 Subject: [PATCH 185/219] Fixes #156 - --list command add trailing slash for directories --- src/ios-deploy.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/ios-deploy.c b/src/ios-deploy.c index c0febc1a..a2cae066 100644 --- a/src/ios-deploy.c +++ b/src/ios-deploy.c @@ -1182,8 +1182,6 @@ void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir, AFCConnectionOpen(afcFd, 0, &afc_conn_p); } - NSLogOut(@"%@", [NSString stringWithUTF8String:dir]); - afc_dictionary* afc_dict_p; char *key, *val; int not_dir = 0; @@ -1201,6 +1199,12 @@ void read_dir(service_conn_t afcFd, afc_connection* afc_conn_p, const char* dir, } } AFCKeyValueClose(afc_dict_p); + + if (not_dir) { + NSLogOut(@"%@", [NSString stringWithUTF8String:dir]); + } else { + NSLogOut(@"%@/", [NSString stringWithUTF8String:dir]); + } if (not_dir) { if (callback) (*callback)(afc_conn_p, dir, not_dir); From 6ce22c2adc3e344e8afeb7128976eb57ef6c7127 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 22:13:04 -0700 Subject: [PATCH 186/219] Fixes #176 - Add documentation issue for node preinstall script (workaround) --- README.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index fadcfb2f..79355060 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,9 @@ Install and debug iOS apps without using Xcode. Designed to work on un-jailbroke ## Requirements -* Mac OS X. Tested on 10.10 Yosemite and iOS 8.3 +* Mac OS X. Tested on 10.11 El Capitan and iOS 9.0 * You need to have a valid iOS Development certificate installed. -* Xcode 6 or greater should be installed +* Xcode 6.4 or greater should be installed ## Roadmap @@ -40,6 +40,14 @@ make install prefix=/usr/local This will install ios-deploy in the `bin` folder of `/usr/local`, i.e. `/usr/local/bin` + +### OS X 10.11 El Capitan + +If you are *not* using a node version manager like [nvm](https://github.com/creationix/nvm) or [n](https://github.com/tj/n), you may have to do either of these two things below when under El Capitan: + +1. Add the `--unsafe-perm` flag when installing ios-deploy +2. Ensure the `nobody` user has write access to `/usr/local/lib/node_modules/ios-deploy/ios-deploy` + ## Usage Usage: ios-deploy [OPTION]... @@ -113,7 +121,7 @@ The commands below assume that you have an app called `my.app` with bundle id `b The included demo.app represents the minimum required to get code running on iOS. -* `make demo.app` will generate the demo.app executable. If it doesn't compile, modify IOS_SDK_VERSION in the Makefile. +* `make demo.app` will generate the demo.app executable. If it doesn't compile, modify `IOS_SDK_VERSION` in the Makefile. * `make debug` will install demo.app and launch a LLDB session. ## Notes From 5d2166fcef79b44ade04474b8171b03321ff8bca Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 22:23:59 -0700 Subject: [PATCH 187/219] Fixes #135 - Convert Makefile to xcodeproject. Demo in its own folder now with its own Makefile. --- .gitignore | 5 +- Makefile | 35 -------- demo/.gitignore | 5 ++ demo/Entitlements.plist | 8 ++ demo/Info.plist | 24 +++++ demo/Makefile | 24 +++++ demo/ResourceRules.plist | 25 ++++++ demo/demo.c | 9 ++ ios-deploy-demo/main.m | 17 ---- ios-deploy.xcodeproj/project.pbxproj | 125 +-------------------------- package.json | 4 +- 11 files changed, 101 insertions(+), 180 deletions(-) delete mode 100644 Makefile create mode 100644 demo/.gitignore create mode 100644 demo/Entitlements.plist create mode 100644 demo/Info.plist create mode 100644 demo/Makefile create mode 100644 demo/ResourceRules.plist create mode 100644 demo/demo.c delete mode 100644 ios-deploy-demo/main.m diff --git a/.gitignore b/.gitignore index d3423eed..33dbe44e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,3 @@ -demo -demo.app -ios-deploy -ios-deploy.dSYM +build/* /.DS_Store *~ diff --git a/Makefile b/Makefile deleted file mode 100644 index 26974ee8..00000000 --- a/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -IOS_SDK_VERSION = 8.3 - -IOS_CC = gcc -ObjC -DEVICE_SUPPORT = $(shell xcode-select --print-path)/Platforms/iPhoneOS.platform/DeviceSupport -IOS_SDK = $(shell xcode-select --print-path)/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS$(IOS_SDK_VERSION).sdk - -all: clean ios-deploy demo.app - -demo.app: demo Info.plist - mkdir -p demo.app - cp demo demo.app/ - cp Info.plist ResourceRules.plist demo.app/ - codesign -f -s "iPhone Developer" --entitlements Entitlements.plist demo.app - -demo: demo.c - $(IOS_CC) -g -arch armv7 -isysroot $(IOS_SDK) -framework CoreFoundation -o demo demo.c - -ios-deploy: clean ios-deploy.c - $(IOS_CC) -g -o ios-deploy -framework Foundation -framework CoreFoundation -framework MobileDevice -F/System/Library/PrivateFrameworks ios-deploy.c - -symlink: - cd $(DEVICE_SUPPORT); ln -sfn "`find . -type d -maxdepth 1 -exec basename {} \; | tail -1`" Latest - -install: symlink ios-deploy - mkdir -p $(prefix)/bin - cp ios-deploy $(prefix)/bin - -uninstall: - rm $(prefix)/bin/ios-deploy - -debug: all - ./ios-deploy --debug --bundle demo.app - -clean: - @rm -rf *.app demo ios-deploy diff --git a/demo/.gitignore b/demo/.gitignore new file mode 100644 index 00000000..c2ef55db --- /dev/null +++ b/demo/.gitignore @@ -0,0 +1,5 @@ +demo +demo.app +demo.dSYM +/.DS_Store +*~ diff --git a/demo/Entitlements.plist b/demo/Entitlements.plist new file mode 100644 index 00000000..929c4e96 --- /dev/null +++ b/demo/Entitlements.plist @@ -0,0 +1,8 @@ + + + + + get-task-allow + + + \ No newline at end of file diff --git a/demo/Info.plist b/demo/Info.plist new file mode 100644 index 00000000..c2ade143 --- /dev/null +++ b/demo/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleName + demo + CFBundleSupportedPlatforms + + iPhoneOS + + CFBundleExecutable + demo + CFBundleVersion + 1.0 + CFBundleIdentifier + demo + CFBundleResourceSpecification + ResourceRules.plist + LSRequiresIPhoneOS + + CFBundleDisplayName + demo + + \ No newline at end of file diff --git a/demo/Makefile b/demo/Makefile new file mode 100644 index 00000000..cf7c36aa --- /dev/null +++ b/demo/Makefile @@ -0,0 +1,24 @@ +IOS_SDK_VERSION = 9.0 + +IOS_CC = gcc -ObjC +IOS_SDK = $(shell xcode-select --print-path)/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS$(IOS_SDK_VERSION).sdk + +all: clean demo.app + +demo.app: demo Info.plist + mkdir -p demo.app + cp demo demo.app/ + cp Info.plist ResourceRules.plist demo.app/ + codesign -f -s "iPhone Developer" --entitlements Entitlements.plist demo.app + +demo: demo.c + $(IOS_CC) -g -arch armv7 -isysroot $(IOS_SDK) -framework CoreFoundation -o demo demo.c + +debug: all ios-deploy + @../build/Release/ios-deploy --debug --bundle demo.app + +clean: + @rm -rf *.app demo demo.dSYM + +ios-deploy: + @xcodebuild -project ../ios-deploy.xcodeproj diff --git a/demo/ResourceRules.plist b/demo/ResourceRules.plist new file mode 100644 index 00000000..e7ec329d --- /dev/null +++ b/demo/ResourceRules.plist @@ -0,0 +1,25 @@ + + + + + rules + + .* + + Info.plist + + omit + + weight + 10 + + ResourceRules.plist + + omit + + weight + 100 + + + + diff --git a/demo/demo.c b/demo/demo.c new file mode 100644 index 00000000..b366b145 --- /dev/null +++ b/demo/demo.c @@ -0,0 +1,9 @@ +#include + +int main(int argc, const char* argv[]) { + int i; + for (i = 0; i < argc; i++) { + printf("argv[%d] = %s\n", i, argv[i]); + } + return 0; +} \ No newline at end of file diff --git a/ios-deploy-demo/main.m b/ios-deploy-demo/main.m deleted file mode 100644 index c64512eb..00000000 --- a/ios-deploy-demo/main.m +++ /dev/null @@ -1,17 +0,0 @@ -// -// main.m -// ios-deploy-demo -// -// Created by shazron on 7/16/15. -// Copyright (c) 2015 PhoneGap. All rights reserved. -// - -#import - -int main(int argc, const char * argv[]) { - @autoreleasepool { - // insert code here... - NSLog(@"Hello, World!"); - } - return 0; -} diff --git a/ios-deploy.xcodeproj/project.pbxproj b/ios-deploy.xcodeproj/project.pbxproj index 63e23854..2b26eb12 100644 --- a/ios-deploy.xcodeproj/project.pbxproj +++ b/ios-deploy.xcodeproj/project.pbxproj @@ -10,8 +10,6 @@ 7E70899C1B587DE4004D23AA /* ios-deploy.c in Sources */ = {isa = PBXBuildFile; fileRef = 7E7089991B587DE4004D23AA /* ios-deploy.c */; settings = {COMPILER_FLAGS = "-x objective-c -fno-objc-arc"; }; }; 7E70899E1B587F29004D23AA /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E70899D1B587F29004D23AA /* CoreFoundation.framework */; }; 7E7089A01B58801E004D23AA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E70899F1B58801E004D23AA /* Foundation.framework */; }; - 7E7089B31B58826A004D23AA /* demo.c in Sources */ = {isa = PBXBuildFile; fileRef = 7E7089AF1B58826A004D23AA /* demo.c */; }; - 7E7089B41B5882C3004D23AA /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E70899D1B587F29004D23AA /* CoreFoundation.framework */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -24,15 +22,6 @@ ); runOnlyForDeploymentPostprocessing = 1; }; - 7E7089A51B58825B004D23AA /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ @@ -42,12 +31,6 @@ 7E70899B1B587DE4004D23AA /* MobileDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MobileDevice.h; path = src/MobileDevice.h; sourceTree = SOURCE_ROOT; }; 7E70899D1B587F29004D23AA /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; 7E70899F1B58801E004D23AA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 7E7089A71B58825B004D23AA /* ios-deploy-demo */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "ios-deploy-demo"; sourceTree = BUILT_PRODUCTS_DIR; }; - 7E7089A91B58825B004D23AA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 7E7089AF1B58826A004D23AA /* demo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = demo.c; sourceTree = ""; }; - 7E7089B01B58826A004D23AA /* Entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Entitlements.plist; sourceTree = ""; }; - 7E7089B11B58826A004D23AA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7E7089B21B58826A004D23AA /* ResourceRules.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = ResourceRules.plist; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -60,23 +43,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 7E7089A41B58825B004D23AA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 7E7089B41B5882C3004D23AA /* CoreFoundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7E7089851B587BF3004D23AA = { isa = PBXGroup; children = ( - 7E7089AE1B58826A004D23AA /* demo */, 7E7089901B587BF3004D23AA /* ios-deploy */, - 7E7089A81B58825B004D23AA /* ios-deploy-demo */, 7E7089A21B588219004D23AA /* Frameworks */, 7E70898F1B587BF3004D23AA /* Products */, ); @@ -86,7 +59,6 @@ isa = PBXGroup; children = ( 7E70898E1B587BF3004D23AA /* ios-deploy */, - 7E7089A71B58825B004D23AA /* ios-deploy-demo */, ); name = Products; sourceTree = ""; @@ -110,25 +82,6 @@ name = Frameworks; sourceTree = ""; }; - 7E7089A81B58825B004D23AA /* ios-deploy-demo */ = { - isa = PBXGroup; - children = ( - 7E7089A91B58825B004D23AA /* main.m */, - ); - path = "ios-deploy-demo"; - sourceTree = ""; - }; - 7E7089AE1B58826A004D23AA /* demo */ = { - isa = PBXGroup; - children = ( - 7E7089AF1B58826A004D23AA /* demo.c */, - 7E7089B01B58826A004D23AA /* Entitlements.plist */, - 7E7089B11B58826A004D23AA /* Info.plist */, - 7E7089B21B58826A004D23AA /* ResourceRules.plist */, - ); - path = demo; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -149,39 +102,18 @@ productReference = 7E70898E1B587BF3004D23AA /* ios-deploy */; productType = "com.apple.product-type.tool"; }; - 7E7089A61B58825B004D23AA /* ios-deploy-demo */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7E7089AB1B58825B004D23AA /* Build configuration list for PBXNativeTarget "ios-deploy-demo" */; - buildPhases = ( - 7E7089A31B58825B004D23AA /* Sources */, - 7E7089A41B58825B004D23AA /* Frameworks */, - 7E7089A51B58825B004D23AA /* CopyFiles */, - 7E7089B51B5882EC004D23AA /* ShellScript */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "ios-deploy-demo"; - productName = "ios-deploy-demo"; - productReference = 7E7089A71B58825B004D23AA /* ios-deploy-demo */; - productType = "com.apple.product-type.tool"; - }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7E7089861B587BF3004D23AA /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0640; + LastUpgradeCheck = 0710; ORGANIZATIONNAME = PhoneGap; TargetAttributes = { 7E70898D1B587BF3004D23AA = { CreatedOnToolsVersion = 6.4; }; - 7E7089A61B58825B004D23AA = { - CreatedOnToolsVersion = 6.4; - }; }; }; buildConfigurationList = 7E7089891B587BF3004D23AA /* Build configuration list for PBXProject "ios-deploy" */; @@ -190,6 +122,7 @@ hasScannedForEncodings = 0; knownRegions = ( en, + Base, ); mainGroup = 7E7089851B587BF3004D23AA; productRefGroup = 7E70898F1B587BF3004D23AA /* Products */; @@ -197,27 +130,10 @@ projectRoot = ""; targets = ( 7E70898D1B587BF3004D23AA /* ios-deploy */, - 7E7089A61B58825B004D23AA /* ios-deploy-demo */, ); }; /* End PBXProject section */ -/* Begin PBXShellScriptBuildPhase section */ - 7E7089B51B5882EC004D23AA /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "#mkdir -p demo.app\n#cp demo demo.app/\n#cp Info.plist ResourceRules.plist demo.app/\n#codesign -f -s \"iPhone Developer\" --entitlements Entitlements.plist demo.app"; - }; -/* End PBXShellScriptBuildPhase section */ - /* Begin PBXSourcesBuildPhase section */ 7E70898A1B587BF3004D23AA /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -227,14 +143,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 7E7089A31B58825B004D23AA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7E7089B31B58826A004D23AA /* demo.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ @@ -258,6 +166,7 @@ COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -339,26 +248,6 @@ }; name = Release; }; - 7E7089AC1B58825B004D23AA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - MACOSX_DEPLOYMENT_TARGET = 10.8; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 7E7089AD1B58825B004D23AA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - MACOSX_DEPLOYMENT_TARGET = 10.8; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -380,14 +269,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 7E7089AB1B58825B004D23AA /* Build configuration list for PBXNativeTarget "ios-deploy-demo" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7E7089AC1B58825B004D23AA /* Debug */, - 7E7089AD1B58825B004D23AA /* Release */, - ); - defaultConfigurationIsVisible = 0; - }; /* End XCConfigurationList section */ }; rootObject = 7E7089861B587BF3004D23AA /* Project object */; diff --git a/package.json b/package.json index c279b078..cd4bdfbb 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,9 @@ "description": "launch iOS apps iOS devices from the command line (Xcode 7)", "main": "ios-deploy", "scripts": { - "preinstall": "./check_reqs.js && make ios-deploy" + "preinstall": "./check_reqs.js && xcodebuild" }, - "bin": "./ios-deploy", + "bin": "./build/Release/ios-deploy", "repository": { "type": "git", "url": "https://github.com/phonegap/ios-deploy" From 59904aa4c164543aefb93ea324b22b3b967fc5fd Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 6 Oct 2015 23:40:42 -0700 Subject: [PATCH 188/219] Updated README for new build from source instruction --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 79355060..14c8ab6d 100644 --- a/README.md +++ b/README.md @@ -32,13 +32,13 @@ Now install ios-deploy with the [node.js](https://nodejs.org) package manager: npm install -g ios-deploy ``` -To install from source: +To build from source: ``` -make install prefix=/usr/local +xcodebuild ``` -This will install ios-deploy in the `bin` folder of `/usr/local`, i.e. `/usr/local/bin` +This will build `ios-deploy` into the `build/Release` folder. ### OS X 10.11 El Capitan From 612c3561fd0f28c097fcb79839b882bed870f114 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Thu, 8 Oct 2015 16:05:03 -0700 Subject: [PATCH 189/219] Added verbose logging for #170 --- src/ios-deploy.c | 48 +++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/src/ios-deploy.c b/src/ios-deploy.c index a2cae066..3f76daa6 100644 --- a/src/ios-deploy.c +++ b/src/ios-deploy.c @@ -223,15 +223,28 @@ void on_sys_error(NSString* format, ...) { on_error(@"%@ : %@", str, [NSString stringWithUTF8String:errstr]); } +void __NSLogOut(NSString* format, va_list valist) { + NSString* str = [[[NSString alloc] initWithFormat:format arguments:valist] autorelease]; + [[str stringByAppendingString:@"\n"] writeToFile:@"/dev/stdout" atomically:NO encoding:NSUTF8StringEncoding error:nil]; +} + void NSLogOut(NSString* format, ...) { va_list valist; va_start(valist, format); - NSString* str = [[[NSString alloc] initWithFormat:format arguments:valist] autorelease]; + __NSLogOut(format, valist); va_end(valist); +} - [[str stringByAppendingString:@"\n"] writeToFile:@"/dev/stdout" atomically:NO encoding:NSUTF8StringEncoding error:nil]; +void NSLogVerbose(NSString* format, ...) { + if (verbose) { + va_list valist; + va_start(valist, format); + __NSLogOut(format, valist); + va_end(valist); + } } + BOOL mkdirp(NSString* path) { NSError* error = nil; BOOL success = [[NSFileManager defaultManager] createDirectoryAtPath:path @@ -468,11 +481,8 @@ CFStringRef get_device_full_name(const AMDeviceRef device) { device_name = AMDeviceCopyValue(device, 0, CFSTR("DeviceName")), model_name = get_device_hardware_name(device); - if (verbose) - { - NSLogOut(@"Device Name: %@", device_name); - NSLogOut(@"Model Name: %@", model_name); - } + NSLogVerbose(@"Device Name: %@", device_name); + NSLogVerbose(@"Model Name: %@", model_name); if(device_name != NULL && model_name != NULL) { @@ -610,11 +620,9 @@ void mount_developer_image(AMDeviceRef device) { CFStringRef image_path = copy_developer_disk_image_path(device); CFStringRef sig_path = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@.signature"), image_path); - if (verbose) { - NSLogOut(@"Device support path: %@", ds_path); - NSLogOut(@"Developer disk image: %@", image_path); - } - CFRelease(ds_path); + NSLogVerbose(@"Device support path: %@", ds_path); + NSLogVerbose(@"Developer disk image: %@", image_path); + CFRelease(ds_path); FILE* sig = fopen(CFStringGetCStringPtr(sig_path, kCFStringEncodingMacRoman), "rb"); void *sig_buf = malloc(128); @@ -1127,8 +1135,7 @@ void launch_debugger_and_exit(AMDeviceRef device, CFURLRef url) { _exit(WEXITSTATUS(status)); } else if (pid > 0) { child = pid; - if (verbose) - NSLogOut(@"Waiting for child [Child: %d][Parent: %d]\n", child, parent); + NSLogVerbose(@"Waiting for child [Child: %d][Parent: %d]\n", child, parent); } else { on_sys_error(@"Fork failed"); } @@ -1559,8 +1566,7 @@ void uninstall_app(AMDeviceRef device) { } void handle_device(AMDeviceRef device) { - //if (found_device) - // return; // handle one device only + NSLogVerbose(@"Already found device? %d", found_device); CFStringRef found_device_id = AMDeviceCopyDeviceIdentifier(device), device_full_name = get_device_full_name(device), @@ -1715,8 +1721,10 @@ void device_callback(struct am_device_notification_callback_info *info, void *ar case ADNCI_MSG_CONNECTED: if(device_id != NULL || !debug || AMDeviceGetInterfaceType(info->dev) != 2) { AMDeviceNotificationUnsubscribe(*notify); + NSLogVerbose(@"Handling device type: %d", AMDeviceGetInterfaceType(info->dev)); handle_device(info->dev); } else if(best_device_match == NULL) { + NSLogVerbose(@"Best device match: %d", AMDeviceGetInterfaceType(info->dev)); best_device_match = info->dev; CFRetain(best_device_match); } @@ -1728,6 +1736,7 @@ void device_callback(struct am_device_notification_callback_info *info, void *ar void timeout_callback(CFRunLoopTimerRef timer, void *info) { if ((!found_device) && (!detect_only)) { if(best_device_match != NULL) { + NSLogVerbose(@"Handling best device match."); handle_device(best_device_match); CFRelease(best_device_match); @@ -1750,11 +1759,8 @@ void timeout_callback(CFRunLoopTimerRef timer, void *info) { int mypid = getpid(); if ((parent != 0) && (parent == mypid) && (child != 0)) { - if (verbose) - { - NSLogOut(@"Timeout. Killing child (%d) tree.", child); - } - kill_ptree(child, SIGHUP); + NSLogVerbose(@"Timeout. Killing child (%d) tree.", child); + kill_ptree(child, SIGHUP); } } exit(0); From 0320381c673201fbabd3557ab7b1a91d0b61ffcd Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Thu, 8 Oct 2015 16:06:01 -0700 Subject: [PATCH 190/219] Fixes #182 - ios-deploy terminates with code 11 in difficult to pinpoint circumstances --- src/MobileDevice.h | 3 --- src/ios-deploy.c | 1 - 2 files changed, 4 deletions(-) diff --git a/src/MobileDevice.h b/src/MobileDevice.h index 8c9ff91a..1862bc19 100644 --- a/src/MobileDevice.h +++ b/src/MobileDevice.h @@ -196,9 +196,6 @@ mach_error_t AMDeviceNotificationSubscribe(am_device_notification_callback dn_unknown3, struct am_device_notification **notification); -mach_error_t AMDeviceNotificationUnsubscribe(am_device_notification subscription); - - /* Connects to the iPhone. Pass in the am_device structure that the * notification callback will give to you. * diff --git a/src/ios-deploy.c b/src/ios-deploy.c index 3f76daa6..c1b10dc6 100644 --- a/src/ios-deploy.c +++ b/src/ios-deploy.c @@ -1720,7 +1720,6 @@ void device_callback(struct am_device_notification_callback_info *info, void *ar switch (info->msg) { case ADNCI_MSG_CONNECTED: if(device_id != NULL || !debug || AMDeviceGetInterfaceType(info->dev) != 2) { - AMDeviceNotificationUnsubscribe(*notify); NSLogVerbose(@"Handling device type: %d", AMDeviceGetInterfaceType(info->dev)); handle_device(info->dev); } else if(best_device_match == NULL) { From 9909fb854cdfd6d3ac1ec17854f8635783b05d61 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Thu, 8 Oct 2015 16:06:15 -0700 Subject: [PATCH 191/219] Updated version to 1.8.1 --- src/ios-deploy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ios-deploy.c b/src/ios-deploy.c index c1b10dc6..0622cbcf 100644 --- a/src/ios-deploy.c +++ b/src/ios-deploy.c @@ -18,7 +18,7 @@ #include "MobileDevice.h" #include "errors.h" -#define APP_VERSION @"1.8.0" +#define APP_VERSION @"1.8.1" #define PREP_CMDS_PATH @"/tmp/%@/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL @"lldb -s %@" /* From 23ea3b7097b7ebdea2fcbc73b12766d7bf47d595 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Thu, 8 Oct 2015 16:07:12 -0700 Subject: [PATCH 192/219] Updated package.json ver to 1.8.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cd4bdfbb..c2a3870d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ios-deploy", - "version": "1.8.0", + "version": "1.8.1", "os": [ "darwin" ], From 7af1a9d79b056fbd6ba4c0689f4af6f6dfbcfdae Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 12 Oct 2015 16:48:41 -0700 Subject: [PATCH 193/219] Fixes #184 - Change min xcode version for Travis CI --- check_reqs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/check_reqs.js b/check_reqs.js index ce06b733..45f9eb6d 100755 --- a/check_reqs.js +++ b/check_reqs.js @@ -4,7 +4,7 @@ var util = require('util'); var os = require('os'); var child_process = require('child_process'); -var XCODEBUILD_MIN_VERSION = '6.4'; +var XCODEBUILD_MIN_VERSION = '6.0'; var XCODEBUILD_NOT_FOUND_MESSAGE = util.format('Please install Xcode version %s or greater from the Mac App Store.', XCODEBUILD_MIN_VERSION); var TOOL = 'xcodebuild'; From 6f65bb687e68616316d11f1bdc10a2cc003af592 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 12 Oct 2015 16:49:04 -0700 Subject: [PATCH 194/219] Fixes #183 - 'tool' undefined in check_reqs.js --- check_reqs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/check_reqs.js b/check_reqs.js index 45f9eb6d..b6b5ee58 100755 --- a/check_reqs.js +++ b/check_reqs.js @@ -34,7 +34,7 @@ xcode_version.on('close', function (code) { } if (ver < XCODEBUILD_MIN_VERSION) { - console.log(util.format('%s : %s. (you have version %s)', tool, XCODEBUILD_NOT_FOUND_MESSAGE, ver)); + console.log(util.format('%s : %s. (you have version %s)', TOOL, XCODEBUILD_NOT_FOUND_MESSAGE, ver)); } } process.exit(code); From 1220cac6e418479e789e059b636c1c83ac9a11e9 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 12 Oct 2015 16:55:08 -0700 Subject: [PATCH 195/219] Moved check_reqs.js to src, added jshint to npm test --- package.json | 12 +++++++++++- src/check_reqs.js | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100755 src/check_reqs.js diff --git a/package.json b/package.json index c2a3870d..7bc5158e 100644 --- a/package.json +++ b/package.json @@ -7,17 +7,27 @@ "description": "launch iOS apps iOS devices from the command line (Xcode 7)", "main": "ios-deploy", "scripts": { - "preinstall": "./check_reqs.js && xcodebuild" + "preinstall": "./src/check_reqs.js && xcodebuild" }, "bin": "./build/Release/ios-deploy", "repository": { "type": "git", "url": "https://github.com/phonegap/ios-deploy" }, + "devDependencies": { + "jshint": "2.5.8" + }, + "scripts": { + "test": "npm run jshint", + "jshint": "node node_modules/jshint/bin/jshint src" + }, "keywords": [ "ios-deploy", "deploy to iOS device" ], + "bugs": { + "url": "https://github.com/phonegap/ios-deploy/issues" + }, "author": "Greg Hughes", "license": "GPLv3" } diff --git a/src/check_reqs.js b/src/check_reqs.js new file mode 100755 index 00000000..b6b5ee58 --- /dev/null +++ b/src/check_reqs.js @@ -0,0 +1,45 @@ +#!/usr/bin/env node + +var util = require('util'); +var os = require('os'); +var child_process = require('child_process'); + +var XCODEBUILD_MIN_VERSION = '6.0'; +var XCODEBUILD_NOT_FOUND_MESSAGE = util.format('Please install Xcode version %s or greater from the Mac App Store.', XCODEBUILD_MIN_VERSION); +var TOOL = 'xcodebuild'; + +var xcode_version = child_process.spawn(TOOL, ['-version']), + version_string = ''; + +xcode_version.stdout.on('data', function (data) { + version_string += data; +}); + +xcode_version.stderr.on('data', function (data) { + console.log('stderr: ' + data); +}); + +xcode_version.on('error', function (err) { + console.log(util.format('Tool %s was not found. %s', TOOL, XCODEBUILD_NOT_FOUND_MESSAGE)); +}); + +xcode_version.on('close', function (code) { + if (code === 0) { + var arr = version_string.match(/^Xcode (\d+\.\d+)/); + var ver = arr[1]; + + if (os.release() >= '15.0.0' && ver < '7.0') { + console.log(util.format('You need at least Xcode 7.0 when you are on OS X 10.11 El Capitan (you have version %s)', ver)); + process.exit(1); + } + + if (ver < XCODEBUILD_MIN_VERSION) { + console.log(util.format('%s : %s. (you have version %s)', TOOL, XCODEBUILD_NOT_FOUND_MESSAGE, ver)); + } + } + process.exit(code); +}); + + + + From b1c717ebd86dc200ff321dd68152a4b8f3b075c2 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 12 Oct 2015 16:55:43 -0700 Subject: [PATCH 196/219] Removed check_reqs.js --- check_reqs.js | 45 --------------------------------------------- 1 file changed, 45 deletions(-) delete mode 100755 check_reqs.js diff --git a/check_reqs.js b/check_reqs.js deleted file mode 100755 index b6b5ee58..00000000 --- a/check_reqs.js +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env node - -var util = require('util'); -var os = require('os'); -var child_process = require('child_process'); - -var XCODEBUILD_MIN_VERSION = '6.0'; -var XCODEBUILD_NOT_FOUND_MESSAGE = util.format('Please install Xcode version %s or greater from the Mac App Store.', XCODEBUILD_MIN_VERSION); -var TOOL = 'xcodebuild'; - -var xcode_version = child_process.spawn(TOOL, ['-version']), - version_string = ''; - -xcode_version.stdout.on('data', function (data) { - version_string += data; -}); - -xcode_version.stderr.on('data', function (data) { - console.log('stderr: ' + data); -}); - -xcode_version.on('error', function (err) { - console.log(util.format('Tool %s was not found. %s', TOOL, XCODEBUILD_NOT_FOUND_MESSAGE)); -}); - -xcode_version.on('close', function (code) { - if (code === 0) { - var arr = version_string.match(/^Xcode (\d+\.\d+)/); - var ver = arr[1]; - - if (os.release() >= '15.0.0' && ver < '7.0') { - console.log(util.format('You need at least Xcode 7.0 when you are on OS X 10.11 El Capitan (you have version %s)', ver)); - process.exit(1); - } - - if (ver < XCODEBUILD_MIN_VERSION) { - console.log(util.format('%s : %s. (you have version %s)', TOOL, XCODEBUILD_NOT_FOUND_MESSAGE, ver)); - } - } - process.exit(code); -}); - - - - From f6b4c3f951faeacc63139627c0354f45bec55af9 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 12 Oct 2015 16:55:59 -0700 Subject: [PATCH 197/219] Ignore node_modules --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 33dbe44e..5e502cb6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ build/* +node_modules/* /.DS_Store *~ From fccfde865ab0cf7fb7a0ede56c5d54c2ba0ebe4c Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 12 Oct 2015 16:56:13 -0700 Subject: [PATCH 198/219] Increment version to 1.8.2 --- package.json | 2 +- src/ios-deploy.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 7bc5158e..fdb3d7ec 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ios-deploy", - "version": "1.8.1", + "version": "1.8.2", "os": [ "darwin" ], diff --git a/src/ios-deploy.c b/src/ios-deploy.c index 0622cbcf..8c9af24e 100644 --- a/src/ios-deploy.c +++ b/src/ios-deploy.c @@ -18,7 +18,7 @@ #include "MobileDevice.h" #include "errors.h" -#define APP_VERSION @"1.8.1" +#define APP_VERSION @"1.8.2" #define PREP_CMDS_PATH @"/tmp/%@/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL @"lldb -s %@" /* From 3ee31bc67790196a906b2de07bd46e6fedbe5c59 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 12 Oct 2015 17:02:05 -0700 Subject: [PATCH 199/219] Typo: had two "scripts" sections in package.son --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index fdb3d7ec..68d50187 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,6 @@ "description": "launch iOS apps iOS devices from the command line (Xcode 7)", "main": "ios-deploy", "scripts": { - "preinstall": "./src/check_reqs.js && xcodebuild" }, "bin": "./build/Release/ios-deploy", "repository": { @@ -18,8 +17,9 @@ "jshint": "2.5.8" }, "scripts": { - "test": "npm run jshint", - "jshint": "node node_modules/jshint/bin/jshint src" + "preinstall": "./src/check_reqs.js && xcodebuild", + "test": "npm run jshint", + "jshint": "node node_modules/jshint/bin/jshint src" }, "keywords": [ "ios-deploy", From 6a8ad1e8995da69de8ba736eadb7c13d7a3ef36a Mon Sep 17 00:00:00 2001 From: "John C. Worsley" Date: Mon, 9 Nov 2015 16:26:19 -0800 Subject: [PATCH 200/219] Added no-wifi option to explicitly skip wifi connectivity. --- src/ios-deploy.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/ios-deploy.c b/src/ios-deploy.c index 8c9af24e..50285da2 100644 --- a/src/ios-deploy.c +++ b/src/ios-deploy.c @@ -157,7 +157,7 @@ int AMDeviceMountImage(AMDeviceRef device, CFStringRef image, CFDictionaryRef op mach_error_t AMDeviceLookupApplications(AMDeviceRef device, CFDictionaryRef options, CFDictionaryRef *result); int AMDeviceGetInterfaceType(struct am_device *device); -bool found_device = false, debug = false, verbose = false, unbuffered = false, nostart = false, detect_only = false, install = true, uninstall = false; +bool found_device = false, debug = false, verbose = false, unbuffered = false, nostart = false, detect_only = false, install = true, uninstall = false, no_wifi = false; bool command_only = false; char *command = NULL; char *target_filename = NULL; @@ -1720,8 +1720,15 @@ void device_callback(struct am_device_notification_callback_info *info, void *ar switch (info->msg) { case ADNCI_MSG_CONNECTED: if(device_id != NULL || !debug || AMDeviceGetInterfaceType(info->dev) != 2) { - NSLogVerbose(@"Handling device type: %d", AMDeviceGetInterfaceType(info->dev)); - handle_device(info->dev); + if (no_wifi && AMDeviceGetInterfaceType(info->dev) == 2) + { + NSLogVerbose(@"Skipping wifi device (type: %d)", AMDeviceGetInterfaceType(info->dev)); + } + else + { + NSLogVerbose(@"Handling device type: %d", AMDeviceGetInterfaceType(info->dev)); + handle_device(info->dev); + } } else if(best_device_match == NULL) { NSLogVerbose(@"Best device match: %d", AMDeviceGetInterfaceType(info->dev)); best_device_match = info->dev; @@ -1793,7 +1800,8 @@ void usage(const char* app) { @" -R, --rm remove file or directory on device (directories must be empty)\n" @" -V, --version print the executable version \n" @" -e, --exists check if the app with given bundle_id is installed or not \n" - @" -B, --list_bundle_id list bundle_id \n", + @" -B, --list_bundle_id list bundle_id \n" + @" -W, --no-wifi ignore wifi devices\n", [NSString stringWithUTF8String:app]); } @@ -1835,11 +1843,12 @@ int main(int argc, char *argv[]) { { "rm", required_argument, NULL, 'R'}, { "exists", no_argument, NULL, 'e'}, { "list_bundle_id", no_argument, NULL, 'B'}, + { "no-wifi", no_argument, NULL, 'W'}, { NULL, 0, NULL, 0 }, }; char ch; - while ((ch = getopt_long(argc, argv, "VmcdvunrILeD:R:i:b:a:t:g:x:p:1:2:o:l::w::9::B::", longopts, NULL)) != -1) + while ((ch = getopt_long(argc, argv, "VmcdvunrILeD:R:i:b:a:t:g:x:p:1:2:o:l::w::9::B::W", longopts, NULL)) != -1) { switch (ch) { case 'm': @@ -1935,6 +1944,9 @@ int main(int argc, char *argv[]) { command_only = true; command = "list_bundle_id"; break; + case 'W': + no_wifi = true; + break; default: usage(argv[0]); return exitcode_error; From f17fd4c73a36c98ddc2f73e4e224898453bf4716 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 23 Nov 2015 17:21:59 -0800 Subject: [PATCH 201/219] Updated version to 1.8.3 --- package.json | 2 +- src/ios-deploy.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 68d50187..7d9aef88 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ios-deploy", - "version": "1.8.2", + "version": "1.8.3", "os": [ "darwin" ], diff --git a/src/ios-deploy.c b/src/ios-deploy.c index 50285da2..78962a7e 100644 --- a/src/ios-deploy.c +++ b/src/ios-deploy.c @@ -18,7 +18,7 @@ #include "MobileDevice.h" #include "errors.h" -#define APP_VERSION @"1.8.2" +#define APP_VERSION @"1.8.3" #define PREP_CMDS_PATH @"/tmp/%@/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL @"lldb -s %@" /* From 94d56d74c4c4574e39ed9f3914c593b8c53e3203 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 23 Nov 2015 17:27:39 -0800 Subject: [PATCH 202/219] Updated demo Makefile for Xcode 7.1 (iOS 9.1) --- demo/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/Makefile b/demo/Makefile index cf7c36aa..319e9f88 100644 --- a/demo/Makefile +++ b/demo/Makefile @@ -1,4 +1,4 @@ -IOS_SDK_VERSION = 9.0 +IOS_SDK_VERSION = 9.1 IOS_CC = gcc -ObjC IOS_SDK = $(shell xcode-select --print-path)/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS$(IOS_SDK_VERSION).sdk From 551cdc58046ab51b8cc0505c01faa1722be04982 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 23 Nov 2015 17:27:52 -0800 Subject: [PATCH 203/219] Added docs for --no-wifi option --- README.md | 54 +++++++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 14c8ab6d..a2689ee9 100644 --- a/README.md +++ b/README.md @@ -51,31 +51,32 @@ If you are *not* using a node version manager like [nvm](https://github.com/crea ## Usage Usage: ios-deploy [OPTION]... - -d, --debug launch the app in GDB after installation - -i, --id the id of the device to connect to - -c, --detect only detect if the device is connected - -b, --bundle the path to the app bundle to be installed - -a, --args command line arguments to pass to the app when launching it - -t, --timeout number of seconds to wait for a device to be connected - -u, --unbuffered don't buffer stdout - -n, --nostart do not start the app when debugging - -I, --noninteractive start in non interactive mode (quit when app crashes or exits) - -L, --justlaunch just launch the app and exit lldb - -v, --verbose enable verbose output - -m, --noinstall directly start debugging without app install (-d not required) - -p, --port port used for device, default: 12345 - -r, --uninstall uninstall the app before install (do not use with -m; app cache and data are cleared) - -9, --uninstall_only uninstall the app ONLY. Use only with -1 - -1, --bundle_id specify bundle id for list, upload, and uninstall_only - -l, --list list files - -o, --upload upload file - -w, --download download app tree - -2, --to use together with up/download file/tree. specify target - -D, --mkdir make directory on device - -R, --rm remove file or directory on device (directories must be empty) - -V, --version print the executable version - -e, --exists check if the app with given bundle_id is installed or not - -B, --list_bundle_id list bundle_id + -d, --debug launch the app in lldb after installation + -i, --id the id of the device to connect to + -c, --detect only detect if the device is connected + -b, --bundle the path to the app bundle to be installed + -a, --args command line arguments to pass to the app when launching it + -t, --timeout number of seconds to wait for a device to be connected + -u, --unbuffered don't buffer stdout + -n, --nostart do not start the app when debugging + -I, --noninteractive start in non interactive mode (quit when app crashes or exits) + -L, --justlaunch just launch the app and exit lldb + -v, --verbose enable verbose output + -m, --noinstall directly start debugging without app install (-d not required) + -p, --port port used for device, default: dynamic + -r, --uninstall uninstall the app before install (do not use with -m; app cache and data are cleared) + -9, --uninstall_only uninstall the app ONLY. Use only with -1 + -1, --bundle_id specify bundle id for list and upload + -l, --list list files + -o, --upload upload file + -w, --download download app tree + -2, --to use together with up/download file/tree. specify target + -D, --mkdir make directory on device + -R, --rm remove file or directory on device (directories must be empty) + -V, --version print the executable version + -e, --exists check if the app with given bundle_id is installed or not + -B, --list_bundle_id list bundle_id + -W, --no-wifi ignore wifi devices ## Examples @@ -84,6 +85,9 @@ The commands below assume that you have an app called `my.app` with bundle id `b // deploy and debug your app to a connected device ios-deploy --debug --bundle my.app + // deploy and debug your app to a connected device, skipping any wi-fi connection (use USB) + ios-deploy --debug --bundle my.app --no-wifi + // deploy and launch your app to a connected device, but quit the debugger after ios-deploy --justlaunch --debug --bundle my.app From a36b1697821dc88e41e9326ef548b44ac3b7bcb0 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Mon, 4 Jan 2016 17:40:06 -0800 Subject: [PATCH 204/219] Added --allow-root to El-Capitan notes, and =true to --unsafe-perm --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a2689ee9..705c4f65 100644 --- a/README.md +++ b/README.md @@ -45,8 +45,9 @@ This will build `ios-deploy` into the `build/Release` folder. If you are *not* using a node version manager like [nvm](https://github.com/creationix/nvm) or [n](https://github.com/tj/n), you may have to do either of these two things below when under El Capitan: -1. Add the `--unsafe-perm` flag when installing ios-deploy -2. Ensure the `nobody` user has write access to `/usr/local/lib/node_modules/ios-deploy/ios-deploy` +1. Add the `--unsafe-perm=true` flag when installing ios-deploy +2. Add the `--allow-root` flag when installing ios-deploy +3. Ensure the `nobody` user has write access to `/usr/local/lib/node_modules/ios-deploy/ios-deploy` ## Usage From c0988f07e56caa80c91f2ffedce882515309de8f Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 5 Jan 2016 10:50:53 -0800 Subject: [PATCH 205/219] Fix README - El Capitan section. Closes #200 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 705c4f65..81c5ae4a 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ This will build `ios-deploy` into the `build/Release` folder. ### OS X 10.11 El Capitan -If you are *not* using a node version manager like [nvm](https://github.com/creationix/nvm) or [n](https://github.com/tj/n), you may have to do either of these two things below when under El Capitan: +If you are *not* using a node version manager like [nvm](https://github.com/creationix/nvm) or [n](https://github.com/tj/n), you may have to do either of these three things below when under El Capitan: 1. Add the `--unsafe-perm=true` flag when installing ios-deploy 2. Add the `--allow-root` flag when installing ios-deploy From f0ae11a93fb0af5038b5bf809e5d2ea8596b7efd Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 5 Jan 2016 10:52:36 -0800 Subject: [PATCH 206/219] Add a note in CONTRIBUTING.md to check out the El Capitan section of the README. Closes #201 --- CONTRIBUTING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2b87cddc..3b4bd41d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -23,6 +23,8 @@ Please run the commands below in your Terminal.app and include it in the issue: ``` Also include **command line arguments** you used for ios-deploy. +Don't forget to check out the [El Capitan](https://github.com/phonegap/ios-deploy/blob/master/README.md#os-x-1011-el-capitan) section of the [README](https://github.com/phonegap/ios-deploy/blob/master/README.md) before filing that issue! + ## Sending a Pull Request From 922f8483a78b1904c020b8c22058de204e4e32ca Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 5 Jan 2016 13:19:20 -0800 Subject: [PATCH 207/219] Updated version to 1.8.4 --- package.json | 2 +- src/ios-deploy.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 7d9aef88..dd98a309 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ios-deploy", - "version": "1.8.3", + "version": "1.8.4", "os": [ "darwin" ], diff --git a/src/ios-deploy.c b/src/ios-deploy.c index 78962a7e..44c7a919 100644 --- a/src/ios-deploy.c +++ b/src/ios-deploy.c @@ -18,7 +18,7 @@ #include "MobileDevice.h" #include "errors.h" -#define APP_VERSION @"1.8.3" +#define APP_VERSION @"1.8.4" #define PREP_CMDS_PATH @"/tmp/%@/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL @"lldb -s %@" /* From a9e96416a820f5fd4683f9a3a291b866f47c3cfd Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 5 Jan 2016 16:00:12 -0800 Subject: [PATCH 208/219] Fixes #194 - Segmentation fault: 11 --- src/ios-deploy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ios-deploy.c b/src/ios-deploy.c index 44c7a919..7d039b69 100644 --- a/src/ios-deploy.c +++ b/src/ios-deploy.c @@ -1266,7 +1266,7 @@ service_conn_t start_house_arrest_service(AMDeviceRef device) { CFStringRef cf_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingUTF8); if (AMDeviceStartHouseArrestService(device, cf_bundle_id, 0, &houseFd, 0) != 0) { - on_error(@"Unable to find bundle with id: %@", bundle_id); + on_error(@"Unable to find bundle with id: %@", [NSString stringWithUTF8String:bundle_id]); } check_error(AMDeviceStopSession(device)); From e57a4da1082881f365494b1a665606c95819a211 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 5 Jan 2016 16:04:22 -0800 Subject: [PATCH 209/219] Fixes #194 - Segmentation fault: 11 (related) --- src/ios-deploy.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ios-deploy.c b/src/ios-deploy.c index 7d039b69..65feb96f 100644 --- a/src/ios-deploy.c +++ b/src/ios-deploy.c @@ -1476,7 +1476,7 @@ void upload_file(AMDeviceRef device) { if (!file_content) { - on_error(@"Could not open file: %@", upload_pathname); + on_error(@"Could not open file: %@", [NSString stringWithUTF8String:upload_pathname]); } // Make sure the directory was created @@ -1547,7 +1547,7 @@ void uninstall_app(AMDeviceRef device) { } if (cf_uninstall_bundle_id == NULL) { - on_error(@"Error: Unable to get bundle id from user command or package %@.\nUninstall failed.", app_path); + on_error(@"Error: Unable to get bundle id from user command or package %@.\nUninstall failed.", [NSString stringWithUTF8String:app_path]); } else { AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); @@ -1636,7 +1636,7 @@ void handle_device(AMDeviceRef device) { } if (cf_uninstall_bundle_id == NULL) { - on_error(@"Error: Unable to get bundle id from user command or package %@.\nUninstall failed.", app_path); + on_error(@"Error: Unable to get bundle id from user command or package %@.\nUninstall failed.", [NSString stringWithUTF8String:app_path]); } else { AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); From ca29173c8095c367d06e15c3c12474e449226a64 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 5 Jan 2016 16:21:19 -0800 Subject: [PATCH 210/219] Externalize version string into a header file (version must be in double quotes) --- ios-deploy.xcodeproj/project.pbxproj | 2 ++ src/ios-deploy.c | 5 +++-- src/version.h | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 src/version.h diff --git a/ios-deploy.xcodeproj/project.pbxproj b/ios-deploy.xcodeproj/project.pbxproj index 2b26eb12..706ff87f 100644 --- a/ios-deploy.xcodeproj/project.pbxproj +++ b/ios-deploy.xcodeproj/project.pbxproj @@ -25,6 +25,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 7E1C00CC1C3C93AF00D686B5 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = version.h; path = src/version.h; sourceTree = SOURCE_ROOT; }; 7E70898E1B587BF3004D23AA /* ios-deploy */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "ios-deploy"; sourceTree = BUILT_PRODUCTS_DIR; }; 7E7089991B587DE4004D23AA /* ios-deploy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "ios-deploy.c"; path = "src/ios-deploy.c"; sourceTree = SOURCE_ROOT; }; 7E70899A1B587DE4004D23AA /* errors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = errors.h; path = src/errors.h; sourceTree = SOURCE_ROOT; }; @@ -66,6 +67,7 @@ 7E7089901B587BF3004D23AA /* ios-deploy */ = { isa = PBXGroup; children = ( + 7E1C00CC1C3C93AF00D686B5 /* version.h */, 7E7089991B587DE4004D23AA /* ios-deploy.c */, 7E70899A1B587DE4004D23AA /* errors.h */, 7E70899B1B587DE4004D23AA /* MobileDevice.h */, diff --git a/src/ios-deploy.c b/src/ios-deploy.c index 65feb96f..19cf0c92 100644 --- a/src/ios-deploy.c +++ b/src/ios-deploy.c @@ -18,7 +18,6 @@ #include "MobileDevice.h" #include "errors.h" -#define APP_VERSION @"1.8.4" #define PREP_CMDS_PATH @"/tmp/%@/fruitstrap-lldb-prep-cmds-" #define LLDB_SHELL @"lldb -s %@" /* @@ -1806,7 +1805,9 @@ void usage(const char* app) { } void show_version() { - NSLogOut(@"%@", APP_VERSION); + NSLogOut(@"%@", @ +#include "version.h" + ); } int main(int argc, char *argv[]) { diff --git a/src/version.h b/src/version.h new file mode 100644 index 00000000..ec8dea70 --- /dev/null +++ b/src/version.h @@ -0,0 +1 @@ +"1.8.4" \ No newline at end of file From 3fef0a5600343f26cf009dec83d9744c8c7fd73c Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 5 Jan 2016 17:33:53 -0800 Subject: [PATCH 211/219] Externalized LLDB_FRUITSTRAP_MODULE python commands into external file (source in src/scripts/lldb.py) --- ios-deploy.xcodeproj/project.pbxproj | 30 +++ src/ios-deploy.c | 93 +------- src/lldb.py.h | 341 +++++++++++++++++++++++++++ src/scripts/lldb.py | 85 +++++++ 4 files changed, 461 insertions(+), 88 deletions(-) create mode 100644 src/lldb.py.h create mode 100644 src/scripts/lldb.py diff --git a/ios-deploy.xcodeproj/project.pbxproj b/ios-deploy.xcodeproj/project.pbxproj index 706ff87f..30773281 100644 --- a/ios-deploy.xcodeproj/project.pbxproj +++ b/ios-deploy.xcodeproj/project.pbxproj @@ -26,6 +26,8 @@ /* Begin PBXFileReference section */ 7E1C00CC1C3C93AF00D686B5 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = version.h; path = src/version.h; sourceTree = SOURCE_ROOT; }; + 7E1C00CF1C3C9ABB00D686B5 /* lldb.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; name = lldb.py; path = src/scripts/lldb.py; sourceTree = SOURCE_ROOT; }; + 7E1C00D11C3C9CB000D686B5 /* lldb.py.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = lldb.py.h; path = src/lldb.py.h; sourceTree = SOURCE_ROOT; }; 7E70898E1B587BF3004D23AA /* ios-deploy */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "ios-deploy"; sourceTree = BUILT_PRODUCTS_DIR; }; 7E7089991B587DE4004D23AA /* ios-deploy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "ios-deploy.c"; path = "src/ios-deploy.c"; sourceTree = SOURCE_ROOT; }; 7E70899A1B587DE4004D23AA /* errors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = errors.h; path = src/errors.h; sourceTree = SOURCE_ROOT; }; @@ -47,6 +49,14 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 7E1C00CE1C3C9A7700D686B5 /* scripts */ = { + isa = PBXGroup; + children = ( + 7E1C00CF1C3C9ABB00D686B5 /* lldb.py */, + ); + name = scripts; + sourceTree = ""; + }; 7E7089851B587BF3004D23AA = { isa = PBXGroup; children = ( @@ -67,6 +77,8 @@ 7E7089901B587BF3004D23AA /* ios-deploy */ = { isa = PBXGroup; children = ( + 7E1C00CE1C3C9A7700D686B5 /* scripts */, + 7E1C00D11C3C9CB000D686B5 /* lldb.py.h */, 7E1C00CC1C3C93AF00D686B5 /* version.h */, 7E7089991B587DE4004D23AA /* ios-deploy.c */, 7E70899A1B587DE4004D23AA /* errors.h */, @@ -91,6 +103,7 @@ isa = PBXNativeTarget; buildConfigurationList = 7E7089951B587BF3004D23AA /* Build configuration list for PBXNativeTarget "ios-deploy" */; buildPhases = ( + 7E1C00D01C3C9C0700D686B5 /* Run Script */, 7E70898A1B587BF3004D23AA /* Sources */, 7E70898B1B587BF3004D23AA /* Frameworks */, 7E70898C1B587BF3004D23AA /* CopyFiles */, @@ -136,6 +149,23 @@ }; /* End PBXProject section */ +/* Begin PBXShellScriptBuildPhase section */ + 7E1C00D01C3C9C0700D686B5 /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"\\\"# AUTO-GENERATED - DO NOT MODIFY\\n\\\"\" > src/lldb.h\nawk '{ print \"\\\"\"$0\"\\\\n\\\"\"}' src/scripts/lldb.py >> src/lldb.py.h\n"; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 7E70898A1B587BF3004D23AA /* Sources */ = { isa = PBXSourcesBuildPhase; diff --git a/src/ios-deploy.c b/src/ios-deploy.c index 19cf0c92..5681e577 100644 --- a/src/ios-deploy.c +++ b/src/ios-deploy.c @@ -60,93 +60,10 @@ const char* lldb_prep_noninteractive_cmds = "\ * through the python interface. Also, Launch () doesn't seem to work when ran from init_module (), so we add * a command which can be used by the user to run it. */ -#define LLDB_FRUITSTRAP_MODULE CFSTR("\ -import lldb\n\ -import os\n\ -import sys\n\ -import shlex\n\ -\n\ -def connect_command(debugger, command, result, internal_dict):\n\ - # These two are passed in by the script which loads us\n\ - connect_url = internal_dict['fruitstrap_connect_url']\n\ - error = lldb.SBError()\n\ -\n\ - process = lldb.target.ConnectRemote(lldb.target.GetDebugger().GetListener(), connect_url, None, error)\n\ -\n\ - # Wait for connection to succeed\n\ - listener = lldb.target.GetDebugger().GetListener()\n\ - listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged)\n\ - events = []\n\ - state = (process.GetState() or lldb.eStateInvalid)\n\ - while state != lldb.eStateConnected:\n\ - event = lldb.SBEvent()\n\ - if listener.WaitForEvent(1, event):\n\ - state = process.GetStateFromEvent(event)\n\ - events.append(event)\n\ - else:\n\ - state = lldb.eStateInvalid\n\ -\n\ - # Add events back to queue, otherwise lldb freezes\n\ - for event in events:\n\ - listener.AddEvent(event)\n\ -\n\ -def run_command(debugger, command, result, internal_dict):\n\ - device_app = internal_dict['fruitstrap_device_app']\n\ - args = command.split('--',1)\n\ - error = lldb.SBError()\n\ - lldb.target.modules[0].SetPlatformFileSpec(lldb.SBFileSpec(device_app))\n\ - lldb.target.Launch(lldb.SBLaunchInfo(shlex.split(args[1] and args[1] or '{args}')), error)\n\ - lockedstr = ': Locked'\n\ - if lockedstr in str(error):\n\ - print('\\nDevice Locked\\n')\n\ - os._exit(254)\n\ - else:\n\ - print(str(error))\n\ -\n\ -def safequit_command(debugger, command, result, internal_dict):\n\ - process = lldb.target.process\n\ - listener = debugger.GetListener()\n\ - listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR)\n\ - event = lldb.SBEvent()\n\ - while True:\n\ - if listener.WaitForEvent(1, event) and lldb.SBProcess.EventIsProcessEvent(event):\n\ - state = lldb.SBProcess.GetStateFromEvent(event)\n\ - else:\n\ - state = process.GetState()\n\ -\n\ - if state == lldb.eStateRunning:\n\ - process.Detach()\n\ - os._exit(0)\n\ - elif state > lldb.eStateRunning:\n\ - os._exit(state)\n\ -\n\ -def autoexit_command(debugger, command, result, internal_dict):\n\ - process = lldb.target.process\n\ - listener = debugger.GetListener()\n\ - listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR)\n\ - event = lldb.SBEvent()\n\ - while True:\n\ - if listener.WaitForEvent(1, event) and lldb.SBProcess.EventIsProcessEvent(event):\n\ - state = lldb.SBProcess.GetStateFromEvent(event)\n\ - else:\n\ - state = process.GetState()\n\ -\n\ - if state == lldb.eStateExited:\n\ - os._exit(process.GetExitStatus())\n\ - elif state == lldb.eStateStopped:\n\ - debugger.HandleCommand('bt')\n\ - os._exit({exitcode_app_crash})\n\ -\n\ - stdout = process.GetSTDOUT(1024)\n\ - while stdout:\n\ - sys.stdout.write(stdout)\n\ - stdout = process.GetSTDOUT(1024)\n\ -\n\ - stderr = process.GetSTDERR(1024)\n\ - while stderr:\n\ - sys.stdout.write(stderr)\n\ - stderr = process.GetSTDERR(1024)\n\ -") +NSString* LLDB_FRUITSTRAP_MODULE = @ + #include "lldb.py.h" +; + typedef struct am_device * AMDeviceRef; mach_error_t AMDeviceSecureStartService(struct am_device *device, CFStringRef service_name, unsigned int *unknown, service_conn_t *handle); @@ -753,7 +670,7 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) { CFStringFindAndReplace(cmds, CFSTR("{ds_path}"), ds_path, range, 0); range.length = CFStringGetLength(cmds); - CFMutableStringRef pmodule = CFStringCreateMutableCopy(NULL, 0, LLDB_FRUITSTRAP_MODULE); + CFMutableStringRef pmodule = CFStringCreateMutableCopy(NULL, 0, (CFStringRef)LLDB_FRUITSTRAP_MODULE); CFRange rangeLLDB = { 0, CFStringGetLength(pmodule) }; CFStringRef exitcode_app_crash_str = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), exitcode_app_crash); diff --git a/src/lldb.py.h b/src/lldb.py.h new file mode 100644 index 00000000..64a40b98 --- /dev/null +++ b/src/lldb.py.h @@ -0,0 +1,341 @@ +"# AUTO-GENERATED - DO NOT MODIFY\n" +"import lldb\n" +"import os\n" +"import sys\n" +"import shlex\n" +"\n" +"def connect_command(debugger, command, result, internal_dict):\n" +" # These two are passed in by the script which loads us\n" +" connect_url = internal_dict['fruitstrap_connect_url']\n" +" error = lldb.SBError()\n" +"\n" +" process = lldb.target.ConnectRemote(lldb.target.GetDebugger().GetListener(), connect_url, None, error)\n" +"\n" +" # Wait for connection to succeed\n" +" listener = lldb.target.GetDebugger().GetListener()\n" +" listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged)\n" +" events = []\n" +" state = (process.GetState() or lldb.eStateInvalid)\n" +" while state != lldb.eStateConnected:\n" +" event = lldb.SBEvent()\n" +" if listener.WaitForEvent(1, event):\n" +" state = process.GetStateFromEvent(event)\n" +" events.append(event)\n" +" else:\n" +" state = lldb.eStateInvalid\n" +"\n" +" # Add events back to queue, otherwise lldb freezes\n" +" for event in events:\n" +" listener.AddEvent(event)\n" +"\n" +"def run_command(debugger, command, result, internal_dict):\n" +" device_app = internal_dict['fruitstrap_device_app']\n" +" args = command.split('--',1)\n" +" error = lldb.SBError()\n" +" lldb.target.modules[0].SetPlatformFileSpec(lldb.SBFileSpec(device_app))\n" +" lldb.target.Launch(lldb.SBLaunchInfo(shlex.split(args[1] and args[1] or '{args}')), error)\n" +" lockedstr = ': Locked'\n" +" if lockedstr in str(error):\n" +" print('\\nDevice Locked\\n')\n" +" os._exit(254)\n" +" else:\n" +" print(str(error))\n" +"\n" +"def safequit_command(debugger, command, result, internal_dict):\n" +" process = lldb.target.process\n" +" listener = debugger.GetListener()\n" +" listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR)\n" +" event = lldb.SBEvent()\n" +" while True:\n" +" if listener.WaitForEvent(1, event) and lldb.SBProcess.EventIsProcessEvent(event):\n" +" state = lldb.SBProcess.GetStateFromEvent(event)\n" +" else:\n" +" state = process.GetState()\n" +"\n" +" if state == lldb.eStateRunning:\n" +" process.Detach()\n" +" os._exit(0)\n" +" elif state > lldb.eStateRunning:\n" +" os._exit(state)\n" +"\n" +"def autoexit_command(debugger, command, result, internal_dict):\n" +" process = lldb.target.process\n" +" listener = debugger.GetListener()\n" +" listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR)\n" +" event = lldb.SBEvent()\n" +" while True:\n" +" if listener.WaitForEvent(1, event) and lldb.SBProcess.EventIsProcessEvent(event):\n" +" state = lldb.SBProcess.GetStateFromEvent(event)\n" +" else:\n" +" state = process.GetState()\n" +"\n" +" if state == lldb.eStateExited:\n" +" os._exit(process.GetExitStatus())\n" +" elif state == lldb.eStateStopped:\n" +" debugger.HandleCommand('bt')\n" +" os._exit({exitcode_app_crash})\n" +"\n" +" stdout = process.GetSTDOUT(1024)\n" +" while stdout:\n" +" sys.stdout.write(stdout)\n" +" stdout = process.GetSTDOUT(1024)\n" +"\n" +" stderr = process.GetSTDERR(1024)\n" +" while stderr:\n" +" sys.stdout.write(stderr)\n" +" stderr = process.GetSTDERR(1024)\n" +"import lldb\n" +"import os\n" +"import sys\n" +"import shlex\n" +"\n" +"def connect_command(debugger, command, result, internal_dict):\n" +" # These two are passed in by the script which loads us\n" +" connect_url = internal_dict['fruitstrap_connect_url']\n" +" error = lldb.SBError()\n" +"\n" +" process = lldb.target.ConnectRemote(lldb.target.GetDebugger().GetListener(), connect_url, None, error)\n" +"\n" +" # Wait for connection to succeed\n" +" listener = lldb.target.GetDebugger().GetListener()\n" +" listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged)\n" +" events = []\n" +" state = (process.GetState() or lldb.eStateInvalid)\n" +" while state != lldb.eStateConnected:\n" +" event = lldb.SBEvent()\n" +" if listener.WaitForEvent(1, event):\n" +" state = process.GetStateFromEvent(event)\n" +" events.append(event)\n" +" else:\n" +" state = lldb.eStateInvalid\n" +"\n" +" # Add events back to queue, otherwise lldb freezes\n" +" for event in events:\n" +" listener.AddEvent(event)\n" +"\n" +"def run_command(debugger, command, result, internal_dict):\n" +" device_app = internal_dict['fruitstrap_device_app']\n" +" args = command.split('--',1)\n" +" error = lldb.SBError()\n" +" lldb.target.modules[0].SetPlatformFileSpec(lldb.SBFileSpec(device_app))\n" +" lldb.target.Launch(lldb.SBLaunchInfo(shlex.split(args[1] and args[1] or '{args}')), error)\n" +" lockedstr = ': Locked'\n" +" if lockedstr in str(error):\n" +" print('\\nDevice Locked\\n')\n" +" os._exit(254)\n" +" else:\n" +" print(str(error))\n" +"\n" +"def safequit_command(debugger, command, result, internal_dict):\n" +" process = lldb.target.process\n" +" listener = debugger.GetListener()\n" +" listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR)\n" +" event = lldb.SBEvent()\n" +" while True:\n" +" if listener.WaitForEvent(1, event) and lldb.SBProcess.EventIsProcessEvent(event):\n" +" state = lldb.SBProcess.GetStateFromEvent(event)\n" +" else:\n" +" state = process.GetState()\n" +"\n" +" if state == lldb.eStateRunning:\n" +" process.Detach()\n" +" os._exit(0)\n" +" elif state > lldb.eStateRunning:\n" +" os._exit(state)\n" +"\n" +"def autoexit_command(debugger, command, result, internal_dict):\n" +" process = lldb.target.process\n" +" listener = debugger.GetListener()\n" +" listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR)\n" +" event = lldb.SBEvent()\n" +" while True:\n" +" if listener.WaitForEvent(1, event) and lldb.SBProcess.EventIsProcessEvent(event):\n" +" state = lldb.SBProcess.GetStateFromEvent(event)\n" +" else:\n" +" state = process.GetState()\n" +"\n" +" if state == lldb.eStateExited:\n" +" os._exit(process.GetExitStatus())\n" +" elif state == lldb.eStateStopped:\n" +" debugger.HandleCommand('bt')\n" +" os._exit({exitcode_app_crash})\n" +"\n" +" stdout = process.GetSTDOUT(1024)\n" +" while stdout:\n" +" sys.stdout.write(stdout)\n" +" stdout = process.GetSTDOUT(1024)\n" +"\n" +" stderr = process.GetSTDERR(1024)\n" +" while stderr:\n" +" sys.stdout.write(stderr)\n" +" stderr = process.GetSTDERR(1024)\n" +"import lldb\n" +"import os\n" +"import sys\n" +"import shlex\n" +"\n" +"def connect_command(debugger, command, result, internal_dict):\n" +" # These two are passed in by the script which loads us\n" +" connect_url = internal_dict['fruitstrap_connect_url']\n" +" error = lldb.SBError()\n" +"\n" +" process = lldb.target.ConnectRemote(lldb.target.GetDebugger().GetListener(), connect_url, None, error)\n" +"\n" +" # Wait for connection to succeed\n" +" listener = lldb.target.GetDebugger().GetListener()\n" +" listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged)\n" +" events = []\n" +" state = (process.GetState() or lldb.eStateInvalid)\n" +" while state != lldb.eStateConnected:\n" +" event = lldb.SBEvent()\n" +" if listener.WaitForEvent(1, event):\n" +" state = process.GetStateFromEvent(event)\n" +" events.append(event)\n" +" else:\n" +" state = lldb.eStateInvalid\n" +"\n" +" # Add events back to queue, otherwise lldb freezes\n" +" for event in events:\n" +" listener.AddEvent(event)\n" +"\n" +"def run_command(debugger, command, result, internal_dict):\n" +" device_app = internal_dict['fruitstrap_device_app']\n" +" args = command.split('--',1)\n" +" error = lldb.SBError()\n" +" lldb.target.modules[0].SetPlatformFileSpec(lldb.SBFileSpec(device_app))\n" +" lldb.target.Launch(lldb.SBLaunchInfo(shlex.split(args[1] and args[1] or '{args}')), error)\n" +" lockedstr = ': Locked'\n" +" if lockedstr in str(error):\n" +" print('\\nDevice Locked\\n')\n" +" os._exit(254)\n" +" else:\n" +" print(str(error))\n" +"\n" +"def safequit_command(debugger, command, result, internal_dict):\n" +" process = lldb.target.process\n" +" listener = debugger.GetListener()\n" +" listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR)\n" +" event = lldb.SBEvent()\n" +" while True:\n" +" if listener.WaitForEvent(1, event) and lldb.SBProcess.EventIsProcessEvent(event):\n" +" state = lldb.SBProcess.GetStateFromEvent(event)\n" +" else:\n" +" state = process.GetState()\n" +"\n" +" if state == lldb.eStateRunning:\n" +" process.Detach()\n" +" os._exit(0)\n" +" elif state > lldb.eStateRunning:\n" +" os._exit(state)\n" +"\n" +"def autoexit_command(debugger, command, result, internal_dict):\n" +" process = lldb.target.process\n" +" listener = debugger.GetListener()\n" +" listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR)\n" +" event = lldb.SBEvent()\n" +" while True:\n" +" if listener.WaitForEvent(1, event) and lldb.SBProcess.EventIsProcessEvent(event):\n" +" state = lldb.SBProcess.GetStateFromEvent(event)\n" +" else:\n" +" state = process.GetState()\n" +"\n" +" if state == lldb.eStateExited:\n" +" os._exit(process.GetExitStatus())\n" +" elif state == lldb.eStateStopped:\n" +" debugger.HandleCommand('bt')\n" +" os._exit({exitcode_app_crash})\n" +"\n" +" stdout = process.GetSTDOUT(1024)\n" +" while stdout:\n" +" sys.stdout.write(stdout)\n" +" stdout = process.GetSTDOUT(1024)\n" +"\n" +" stderr = process.GetSTDERR(1024)\n" +" while stderr:\n" +" sys.stdout.write(stderr)\n" +" stderr = process.GetSTDERR(1024)\n" +"import lldb\n" +"import os\n" +"import sys\n" +"import shlex\n" +"\n" +"def connect_command(debugger, command, result, internal_dict):\n" +" # These two are passed in by the script which loads us\n" +" connect_url = internal_dict['fruitstrap_connect_url']\n" +" error = lldb.SBError()\n" +"\n" +" process = lldb.target.ConnectRemote(lldb.target.GetDebugger().GetListener(), connect_url, None, error)\n" +"\n" +" # Wait for connection to succeed\n" +" listener = lldb.target.GetDebugger().GetListener()\n" +" listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged)\n" +" events = []\n" +" state = (process.GetState() or lldb.eStateInvalid)\n" +" while state != lldb.eStateConnected:\n" +" event = lldb.SBEvent()\n" +" if listener.WaitForEvent(1, event):\n" +" state = process.GetStateFromEvent(event)\n" +" events.append(event)\n" +" else:\n" +" state = lldb.eStateInvalid\n" +"\n" +" # Add events back to queue, otherwise lldb freezes\n" +" for event in events:\n" +" listener.AddEvent(event)\n" +"\n" +"def run_command(debugger, command, result, internal_dict):\n" +" device_app = internal_dict['fruitstrap_device_app']\n" +" args = command.split('--',1)\n" +" error = lldb.SBError()\n" +" lldb.target.modules[0].SetPlatformFileSpec(lldb.SBFileSpec(device_app))\n" +" lldb.target.Launch(lldb.SBLaunchInfo(shlex.split(args[1] and args[1] or '{args}')), error)\n" +" lockedstr = ': Locked'\n" +" if lockedstr in str(error):\n" +" print('\\nDevice Locked\\n')\n" +" os._exit(254)\n" +" else:\n" +" print(str(error))\n" +"\n" +"def safequit_command(debugger, command, result, internal_dict):\n" +" process = lldb.target.process\n" +" listener = debugger.GetListener()\n" +" listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR)\n" +" event = lldb.SBEvent()\n" +" while True:\n" +" if listener.WaitForEvent(1, event) and lldb.SBProcess.EventIsProcessEvent(event):\n" +" state = lldb.SBProcess.GetStateFromEvent(event)\n" +" else:\n" +" state = process.GetState()\n" +"\n" +" if state == lldb.eStateRunning:\n" +" process.Detach()\n" +" os._exit(0)\n" +" elif state > lldb.eStateRunning:\n" +" os._exit(state)\n" +"\n" +"def autoexit_command(debugger, command, result, internal_dict):\n" +" process = lldb.target.process\n" +" listener = debugger.GetListener()\n" +" listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR)\n" +" event = lldb.SBEvent()\n" +" while True:\n" +" if listener.WaitForEvent(1, event) and lldb.SBProcess.EventIsProcessEvent(event):\n" +" state = lldb.SBProcess.GetStateFromEvent(event)\n" +" else:\n" +" state = process.GetState()\n" +"\n" +" if state == lldb.eStateExited:\n" +" os._exit(process.GetExitStatus())\n" +" elif state == lldb.eStateStopped:\n" +" debugger.HandleCommand('bt')\n" +" os._exit({exitcode_app_crash})\n" +"\n" +" stdout = process.GetSTDOUT(1024)\n" +" while stdout:\n" +" sys.stdout.write(stdout)\n" +" stdout = process.GetSTDOUT(1024)\n" +"\n" +" stderr = process.GetSTDERR(1024)\n" +" while stderr:\n" +" sys.stdout.write(stderr)\n" +" stderr = process.GetSTDERR(1024)\n" diff --git a/src/scripts/lldb.py b/src/scripts/lldb.py new file mode 100644 index 00000000..ec02219e --- /dev/null +++ b/src/scripts/lldb.py @@ -0,0 +1,85 @@ +import lldb +import os +import sys +import shlex + +def connect_command(debugger, command, result, internal_dict): + # These two are passed in by the script which loads us + connect_url = internal_dict['fruitstrap_connect_url'] + error = lldb.SBError() + + process = lldb.target.ConnectRemote(lldb.target.GetDebugger().GetListener(), connect_url, None, error) + + # Wait for connection to succeed + listener = lldb.target.GetDebugger().GetListener() + listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged) + events = [] + state = (process.GetState() or lldb.eStateInvalid) + while state != lldb.eStateConnected: + event = lldb.SBEvent() + if listener.WaitForEvent(1, event): + state = process.GetStateFromEvent(event) + events.append(event) + else: + state = lldb.eStateInvalid + + # Add events back to queue, otherwise lldb freezes + for event in events: + listener.AddEvent(event) + +def run_command(debugger, command, result, internal_dict): + device_app = internal_dict['fruitstrap_device_app'] + args = command.split('--',1) + error = lldb.SBError() + lldb.target.modules[0].SetPlatformFileSpec(lldb.SBFileSpec(device_app)) + lldb.target.Launch(lldb.SBLaunchInfo(shlex.split(args[1] and args[1] or '{args}')), error) + lockedstr = ': Locked' + if lockedstr in str(error): + print('\\nDevice Locked\\n') + os._exit(254) + else: + print(str(error)) + +def safequit_command(debugger, command, result, internal_dict): + process = lldb.target.process + listener = debugger.GetListener() + listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR) + event = lldb.SBEvent() + while True: + if listener.WaitForEvent(1, event) and lldb.SBProcess.EventIsProcessEvent(event): + state = lldb.SBProcess.GetStateFromEvent(event) + else: + state = process.GetState() + + if state == lldb.eStateRunning: + process.Detach() + os._exit(0) + elif state > lldb.eStateRunning: + os._exit(state) + +def autoexit_command(debugger, command, result, internal_dict): + process = lldb.target.process + listener = debugger.GetListener() + listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR) + event = lldb.SBEvent() + while True: + if listener.WaitForEvent(1, event) and lldb.SBProcess.EventIsProcessEvent(event): + state = lldb.SBProcess.GetStateFromEvent(event) + else: + state = process.GetState() + + if state == lldb.eStateExited: + os._exit(process.GetExitStatus()) + elif state == lldb.eStateStopped: + debugger.HandleCommand('bt') + os._exit({exitcode_app_crash}) + + stdout = process.GetSTDOUT(1024) + while stdout: + sys.stdout.write(stdout) + stdout = process.GetSTDOUT(1024) + + stderr = process.GetSTDERR(1024) + while stderr: + sys.stdout.write(stderr) + stderr = process.GetSTDERR(1024) From 3555b1222c2e73df68059ec16f100a29dc6725a8 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 5 Jan 2016 17:42:36 -0800 Subject: [PATCH 212/219] Typo in Run Script that resulted in appending contents to lldb.py.h --- ios-deploy.xcodeproj/project.pbxproj | 2 +- src/lldb.py.h | 255 --------------------------- 2 files changed, 1 insertion(+), 256 deletions(-) diff --git a/ios-deploy.xcodeproj/project.pbxproj b/ios-deploy.xcodeproj/project.pbxproj index 30773281..ded654e2 100644 --- a/ios-deploy.xcodeproj/project.pbxproj +++ b/ios-deploy.xcodeproj/project.pbxproj @@ -162,7 +162,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "echo \"\\\"# AUTO-GENERATED - DO NOT MODIFY\\n\\\"\" > src/lldb.h\nawk '{ print \"\\\"\"$0\"\\\\n\\\"\"}' src/scripts/lldb.py >> src/lldb.py.h\n"; + shellScript = "echo \"\\\"# AUTO-GENERATED - DO NOT MODIFY\\n\\\"\" > src/lldb.py.h\nawk '{ print \"\\\"\"$0\"\\\\n\\\"\"}' src/scripts/lldb.py >> src/lldb.py.h\n"; }; /* End PBXShellScriptBuildPhase section */ diff --git a/src/lldb.py.h b/src/lldb.py.h index 64a40b98..ef800838 100644 --- a/src/lldb.py.h +++ b/src/lldb.py.h @@ -84,258 +84,3 @@ " while stderr:\n" " sys.stdout.write(stderr)\n" " stderr = process.GetSTDERR(1024)\n" -"import lldb\n" -"import os\n" -"import sys\n" -"import shlex\n" -"\n" -"def connect_command(debugger, command, result, internal_dict):\n" -" # These two are passed in by the script which loads us\n" -" connect_url = internal_dict['fruitstrap_connect_url']\n" -" error = lldb.SBError()\n" -"\n" -" process = lldb.target.ConnectRemote(lldb.target.GetDebugger().GetListener(), connect_url, None, error)\n" -"\n" -" # Wait for connection to succeed\n" -" listener = lldb.target.GetDebugger().GetListener()\n" -" listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged)\n" -" events = []\n" -" state = (process.GetState() or lldb.eStateInvalid)\n" -" while state != lldb.eStateConnected:\n" -" event = lldb.SBEvent()\n" -" if listener.WaitForEvent(1, event):\n" -" state = process.GetStateFromEvent(event)\n" -" events.append(event)\n" -" else:\n" -" state = lldb.eStateInvalid\n" -"\n" -" # Add events back to queue, otherwise lldb freezes\n" -" for event in events:\n" -" listener.AddEvent(event)\n" -"\n" -"def run_command(debugger, command, result, internal_dict):\n" -" device_app = internal_dict['fruitstrap_device_app']\n" -" args = command.split('--',1)\n" -" error = lldb.SBError()\n" -" lldb.target.modules[0].SetPlatformFileSpec(lldb.SBFileSpec(device_app))\n" -" lldb.target.Launch(lldb.SBLaunchInfo(shlex.split(args[1] and args[1] or '{args}')), error)\n" -" lockedstr = ': Locked'\n" -" if lockedstr in str(error):\n" -" print('\\nDevice Locked\\n')\n" -" os._exit(254)\n" -" else:\n" -" print(str(error))\n" -"\n" -"def safequit_command(debugger, command, result, internal_dict):\n" -" process = lldb.target.process\n" -" listener = debugger.GetListener()\n" -" listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR)\n" -" event = lldb.SBEvent()\n" -" while True:\n" -" if listener.WaitForEvent(1, event) and lldb.SBProcess.EventIsProcessEvent(event):\n" -" state = lldb.SBProcess.GetStateFromEvent(event)\n" -" else:\n" -" state = process.GetState()\n" -"\n" -" if state == lldb.eStateRunning:\n" -" process.Detach()\n" -" os._exit(0)\n" -" elif state > lldb.eStateRunning:\n" -" os._exit(state)\n" -"\n" -"def autoexit_command(debugger, command, result, internal_dict):\n" -" process = lldb.target.process\n" -" listener = debugger.GetListener()\n" -" listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR)\n" -" event = lldb.SBEvent()\n" -" while True:\n" -" if listener.WaitForEvent(1, event) and lldb.SBProcess.EventIsProcessEvent(event):\n" -" state = lldb.SBProcess.GetStateFromEvent(event)\n" -" else:\n" -" state = process.GetState()\n" -"\n" -" if state == lldb.eStateExited:\n" -" os._exit(process.GetExitStatus())\n" -" elif state == lldb.eStateStopped:\n" -" debugger.HandleCommand('bt')\n" -" os._exit({exitcode_app_crash})\n" -"\n" -" stdout = process.GetSTDOUT(1024)\n" -" while stdout:\n" -" sys.stdout.write(stdout)\n" -" stdout = process.GetSTDOUT(1024)\n" -"\n" -" stderr = process.GetSTDERR(1024)\n" -" while stderr:\n" -" sys.stdout.write(stderr)\n" -" stderr = process.GetSTDERR(1024)\n" -"import lldb\n" -"import os\n" -"import sys\n" -"import shlex\n" -"\n" -"def connect_command(debugger, command, result, internal_dict):\n" -" # These two are passed in by the script which loads us\n" -" connect_url = internal_dict['fruitstrap_connect_url']\n" -" error = lldb.SBError()\n" -"\n" -" process = lldb.target.ConnectRemote(lldb.target.GetDebugger().GetListener(), connect_url, None, error)\n" -"\n" -" # Wait for connection to succeed\n" -" listener = lldb.target.GetDebugger().GetListener()\n" -" listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged)\n" -" events = []\n" -" state = (process.GetState() or lldb.eStateInvalid)\n" -" while state != lldb.eStateConnected:\n" -" event = lldb.SBEvent()\n" -" if listener.WaitForEvent(1, event):\n" -" state = process.GetStateFromEvent(event)\n" -" events.append(event)\n" -" else:\n" -" state = lldb.eStateInvalid\n" -"\n" -" # Add events back to queue, otherwise lldb freezes\n" -" for event in events:\n" -" listener.AddEvent(event)\n" -"\n" -"def run_command(debugger, command, result, internal_dict):\n" -" device_app = internal_dict['fruitstrap_device_app']\n" -" args = command.split('--',1)\n" -" error = lldb.SBError()\n" -" lldb.target.modules[0].SetPlatformFileSpec(lldb.SBFileSpec(device_app))\n" -" lldb.target.Launch(lldb.SBLaunchInfo(shlex.split(args[1] and args[1] or '{args}')), error)\n" -" lockedstr = ': Locked'\n" -" if lockedstr in str(error):\n" -" print('\\nDevice Locked\\n')\n" -" os._exit(254)\n" -" else:\n" -" print(str(error))\n" -"\n" -"def safequit_command(debugger, command, result, internal_dict):\n" -" process = lldb.target.process\n" -" listener = debugger.GetListener()\n" -" listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR)\n" -" event = lldb.SBEvent()\n" -" while True:\n" -" if listener.WaitForEvent(1, event) and lldb.SBProcess.EventIsProcessEvent(event):\n" -" state = lldb.SBProcess.GetStateFromEvent(event)\n" -" else:\n" -" state = process.GetState()\n" -"\n" -" if state == lldb.eStateRunning:\n" -" process.Detach()\n" -" os._exit(0)\n" -" elif state > lldb.eStateRunning:\n" -" os._exit(state)\n" -"\n" -"def autoexit_command(debugger, command, result, internal_dict):\n" -" process = lldb.target.process\n" -" listener = debugger.GetListener()\n" -" listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR)\n" -" event = lldb.SBEvent()\n" -" while True:\n" -" if listener.WaitForEvent(1, event) and lldb.SBProcess.EventIsProcessEvent(event):\n" -" state = lldb.SBProcess.GetStateFromEvent(event)\n" -" else:\n" -" state = process.GetState()\n" -"\n" -" if state == lldb.eStateExited:\n" -" os._exit(process.GetExitStatus())\n" -" elif state == lldb.eStateStopped:\n" -" debugger.HandleCommand('bt')\n" -" os._exit({exitcode_app_crash})\n" -"\n" -" stdout = process.GetSTDOUT(1024)\n" -" while stdout:\n" -" sys.stdout.write(stdout)\n" -" stdout = process.GetSTDOUT(1024)\n" -"\n" -" stderr = process.GetSTDERR(1024)\n" -" while stderr:\n" -" sys.stdout.write(stderr)\n" -" stderr = process.GetSTDERR(1024)\n" -"import lldb\n" -"import os\n" -"import sys\n" -"import shlex\n" -"\n" -"def connect_command(debugger, command, result, internal_dict):\n" -" # These two are passed in by the script which loads us\n" -" connect_url = internal_dict['fruitstrap_connect_url']\n" -" error = lldb.SBError()\n" -"\n" -" process = lldb.target.ConnectRemote(lldb.target.GetDebugger().GetListener(), connect_url, None, error)\n" -"\n" -" # Wait for connection to succeed\n" -" listener = lldb.target.GetDebugger().GetListener()\n" -" listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged)\n" -" events = []\n" -" state = (process.GetState() or lldb.eStateInvalid)\n" -" while state != lldb.eStateConnected:\n" -" event = lldb.SBEvent()\n" -" if listener.WaitForEvent(1, event):\n" -" state = process.GetStateFromEvent(event)\n" -" events.append(event)\n" -" else:\n" -" state = lldb.eStateInvalid\n" -"\n" -" # Add events back to queue, otherwise lldb freezes\n" -" for event in events:\n" -" listener.AddEvent(event)\n" -"\n" -"def run_command(debugger, command, result, internal_dict):\n" -" device_app = internal_dict['fruitstrap_device_app']\n" -" args = command.split('--',1)\n" -" error = lldb.SBError()\n" -" lldb.target.modules[0].SetPlatformFileSpec(lldb.SBFileSpec(device_app))\n" -" lldb.target.Launch(lldb.SBLaunchInfo(shlex.split(args[1] and args[1] or '{args}')), error)\n" -" lockedstr = ': Locked'\n" -" if lockedstr in str(error):\n" -" print('\\nDevice Locked\\n')\n" -" os._exit(254)\n" -" else:\n" -" print(str(error))\n" -"\n" -"def safequit_command(debugger, command, result, internal_dict):\n" -" process = lldb.target.process\n" -" listener = debugger.GetListener()\n" -" listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR)\n" -" event = lldb.SBEvent()\n" -" while True:\n" -" if listener.WaitForEvent(1, event) and lldb.SBProcess.EventIsProcessEvent(event):\n" -" state = lldb.SBProcess.GetStateFromEvent(event)\n" -" else:\n" -" state = process.GetState()\n" -"\n" -" if state == lldb.eStateRunning:\n" -" process.Detach()\n" -" os._exit(0)\n" -" elif state > lldb.eStateRunning:\n" -" os._exit(state)\n" -"\n" -"def autoexit_command(debugger, command, result, internal_dict):\n" -" process = lldb.target.process\n" -" listener = debugger.GetListener()\n" -" listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR)\n" -" event = lldb.SBEvent()\n" -" while True:\n" -" if listener.WaitForEvent(1, event) and lldb.SBProcess.EventIsProcessEvent(event):\n" -" state = lldb.SBProcess.GetStateFromEvent(event)\n" -" else:\n" -" state = process.GetState()\n" -"\n" -" if state == lldb.eStateExited:\n" -" os._exit(process.GetExitStatus())\n" -" elif state == lldb.eStateStopped:\n" -" debugger.HandleCommand('bt')\n" -" os._exit({exitcode_app_crash})\n" -"\n" -" stdout = process.GetSTDOUT(1024)\n" -" while stdout:\n" -" sys.stdout.write(stdout)\n" -" stdout = process.GetSTDOUT(1024)\n" -"\n" -" stderr = process.GetSTDERR(1024)\n" -" while stderr:\n" -" sys.stdout.write(stderr)\n" -" stderr = process.GetSTDERR(1024)\n" From ecb228aad406a209e5d3510751cca241a1f5a77e Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 12 Jan 2016 17:19:51 -0800 Subject: [PATCH 213/219] Added libios-deploy target stub, and XCTests stub. ios-deploy dependent on lib-ios-deploy target --- ios-deploy-lib/ios_deploy_lib.h | 5 + ios-deploy-lib/ios_deploy_lib.m | 5 + ios-deploy-tests/Info.plist | 24 +++ ios-deploy-tests/ios_deploy_tests.m | 31 ++++ ios-deploy.xcodeproj/project.pbxproj | 260 ++++++++++++++++++++++++--- src/{ios-deploy.c => ios-deploy.m} | 0 6 files changed, 305 insertions(+), 20 deletions(-) create mode 100644 ios-deploy-lib/ios_deploy_lib.h create mode 100644 ios-deploy-lib/ios_deploy_lib.m create mode 100644 ios-deploy-tests/Info.plist create mode 100644 ios-deploy-tests/ios_deploy_tests.m rename src/{ios-deploy.c => ios-deploy.m} (100%) diff --git a/ios-deploy-lib/ios_deploy_lib.h b/ios-deploy-lib/ios_deploy_lib.h new file mode 100644 index 00000000..78323bc9 --- /dev/null +++ b/ios-deploy-lib/ios_deploy_lib.h @@ -0,0 +1,5 @@ +#import + +@interface ios_deploy_lib : NSObject + +@end diff --git a/ios-deploy-lib/ios_deploy_lib.m b/ios-deploy-lib/ios_deploy_lib.m new file mode 100644 index 00000000..61a1c18b --- /dev/null +++ b/ios-deploy-lib/ios_deploy_lib.m @@ -0,0 +1,5 @@ +#import "ios_deploy_lib.h" + +@implementation ios_deploy_lib + +@end diff --git a/ios-deploy-tests/Info.plist b/ios-deploy-tests/Info.plist new file mode 100644 index 00000000..ba72822e --- /dev/null +++ b/ios-deploy-tests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/ios-deploy-tests/ios_deploy_tests.m b/ios-deploy-tests/ios_deploy_tests.m new file mode 100644 index 00000000..f58e9493 --- /dev/null +++ b/ios-deploy-tests/ios_deploy_tests.m @@ -0,0 +1,31 @@ +#import + +@interface ios_deploy_tests : XCTestCase + +@end + +@implementation ios_deploy_tests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testExample { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. +} + +- (void)testPerformanceExample { + // This is an example of a performance test case. + [self measureBlock:^{ + // Put the code you want to measure the time of here. + }]; +} + +@end diff --git a/ios-deploy.xcodeproj/project.pbxproj b/ios-deploy.xcodeproj/project.pbxproj index ded654e2..0df1e7e2 100644 --- a/ios-deploy.xcodeproj/project.pbxproj +++ b/ios-deploy.xcodeproj/project.pbxproj @@ -7,33 +7,49 @@ objects = { /* Begin PBXBuildFile section */ - 7E70899C1B587DE4004D23AA /* ios-deploy.c in Sources */ = {isa = PBXBuildFile; fileRef = 7E7089991B587DE4004D23AA /* ios-deploy.c */; settings = {COMPILER_FLAGS = "-x objective-c -fno-objc-arc"; }; }; 7E70899E1B587F29004D23AA /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E70899D1B587F29004D23AA /* CoreFoundation.framework */; }; 7E7089A01B58801E004D23AA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E70899F1B58801E004D23AA /* Foundation.framework */; }; + 7E8E3A861C45D4CE0017F6C1 /* ios_deploy_tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E8E3A851C45D4CE0017F6C1 /* ios_deploy_tests.m */; }; + 7E8E3A921C45D5380017F6C1 /* ios_deploy_lib.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E8E3A911C45D5380017F6C1 /* ios_deploy_lib.h */; }; + 7E8E3A941C45D5380017F6C1 /* ios_deploy_lib.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E8E3A931C45D5380017F6C1 /* ios_deploy_lib.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 7E8E3A9B1C45D5970017F6C1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E70899F1B58801E004D23AA /* Foundation.framework */; }; + 7E8E3A9D1C45D6290017F6C1 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E70899D1B587F29004D23AA /* CoreFoundation.framework */; }; + 7EDCC3CD1C45DC94002F9851 /* ios-deploy.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E7089991B587DE4004D23AA /* ios-deploy.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; /* End PBXBuildFile section */ -/* Begin PBXCopyFilesBuildPhase section */ - 7E70898C1B587BF3004D23AA /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; +/* Begin PBXContainerItemProxy section */ + 7E8E3A991C45D5850017F6C1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 7E7089861B587BF3004D23AA /* Project object */; + proxyType = 1; + remoteGlobalIDString = 7E8E3A8E1C45D5380017F6C1; + remoteInfo = "ios-deploy-lib"; + }; + 7EDCC3CA1C45D933002F9851 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 7E7089861B587BF3004D23AA /* Project object */; + proxyType = 1; + remoteGlobalIDString = 7E8E3A8E1C45D5380017F6C1; + remoteInfo = "ios-deploy-lib"; }; -/* End PBXCopyFilesBuildPhase section */ +/* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ 7E1C00CC1C3C93AF00D686B5 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = version.h; path = src/version.h; sourceTree = SOURCE_ROOT; }; 7E1C00CF1C3C9ABB00D686B5 /* lldb.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; name = lldb.py; path = src/scripts/lldb.py; sourceTree = SOURCE_ROOT; }; 7E1C00D11C3C9CB000D686B5 /* lldb.py.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = lldb.py.h; path = src/lldb.py.h; sourceTree = SOURCE_ROOT; }; 7E70898E1B587BF3004D23AA /* ios-deploy */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "ios-deploy"; sourceTree = BUILT_PRODUCTS_DIR; }; - 7E7089991B587DE4004D23AA /* ios-deploy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "ios-deploy.c"; path = "src/ios-deploy.c"; sourceTree = SOURCE_ROOT; }; + 7E7089991B587DE4004D23AA /* ios-deploy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "ios-deploy.m"; path = "src/ios-deploy.m"; sourceTree = SOURCE_ROOT; }; 7E70899A1B587DE4004D23AA /* errors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = errors.h; path = src/errors.h; sourceTree = SOURCE_ROOT; }; 7E70899B1B587DE4004D23AA /* MobileDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MobileDevice.h; path = src/MobileDevice.h; sourceTree = SOURCE_ROOT; }; 7E70899D1B587F29004D23AA /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; 7E70899F1B58801E004D23AA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 7E8E3A831C45D4CE0017F6C1 /* ios-deploy-tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "ios-deploy-tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 7E8E3A851C45D4CE0017F6C1 /* ios_deploy_tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ios_deploy_tests.m; sourceTree = ""; }; + 7E8E3A871C45D4CE0017F6C1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 7E8E3A8F1C45D5380017F6C1 /* libios-deploy.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libios-deploy.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 7E8E3A911C45D5380017F6C1 /* ios_deploy_lib.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ios_deploy_lib.h; sourceTree = ""; }; + 7E8E3A931C45D5380017F6C1 /* ios_deploy_lib.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ios_deploy_lib.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -46,6 +62,22 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 7E8E3A801C45D4CE0017F6C1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7E8E3A8C1C45D5380017F6C1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7E8E3A9D1C45D6290017F6C1 /* CoreFoundation.framework in Frameworks */, + 7E8E3A9B1C45D5970017F6C1 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -61,6 +93,8 @@ isa = PBXGroup; children = ( 7E7089901B587BF3004D23AA /* ios-deploy */, + 7E8E3A841C45D4CE0017F6C1 /* ios-deploy-tests */, + 7E8E3A901C45D5380017F6C1 /* ios-deploy-lib */, 7E7089A21B588219004D23AA /* Frameworks */, 7E70898F1B587BF3004D23AA /* Products */, ); @@ -70,6 +104,8 @@ isa = PBXGroup; children = ( 7E70898E1B587BF3004D23AA /* ios-deploy */, + 7E8E3A831C45D4CE0017F6C1 /* ios-deploy-tests.xctest */, + 7E8E3A8F1C45D5380017F6C1 /* libios-deploy.a */, ); name = Products; sourceTree = ""; @@ -80,7 +116,7 @@ 7E1C00CE1C3C9A7700D686B5 /* scripts */, 7E1C00D11C3C9CB000D686B5 /* lldb.py.h */, 7E1C00CC1C3C93AF00D686B5 /* version.h */, - 7E7089991B587DE4004D23AA /* ios-deploy.c */, + 7E7089991B587DE4004D23AA /* ios-deploy.m */, 7E70899A1B587DE4004D23AA /* errors.h */, 7E70899B1B587DE4004D23AA /* MobileDevice.h */, ); @@ -96,27 +132,91 @@ name = Frameworks; sourceTree = ""; }; + 7E8E3A841C45D4CE0017F6C1 /* ios-deploy-tests */ = { + isa = PBXGroup; + children = ( + 7E8E3A851C45D4CE0017F6C1 /* ios_deploy_tests.m */, + 7E8E3A871C45D4CE0017F6C1 /* Info.plist */, + ); + path = "ios-deploy-tests"; + sourceTree = ""; + }; + 7E8E3A901C45D5380017F6C1 /* ios-deploy-lib */ = { + isa = PBXGroup; + children = ( + 7E8E3A911C45D5380017F6C1 /* ios_deploy_lib.h */, + 7E8E3A931C45D5380017F6C1 /* ios_deploy_lib.m */, + ); + path = "ios-deploy-lib"; + sourceTree = ""; + }; /* End PBXGroup section */ +/* Begin PBXHeadersBuildPhase section */ + 7E8E3A8D1C45D5380017F6C1 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 7E8E3A921C45D5380017F6C1 /* ios_deploy_lib.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + /* Begin PBXNativeTarget section */ 7E70898D1B587BF3004D23AA /* ios-deploy */ = { isa = PBXNativeTarget; buildConfigurationList = 7E7089951B587BF3004D23AA /* Build configuration list for PBXNativeTarget "ios-deploy" */; buildPhases = ( - 7E1C00D01C3C9C0700D686B5 /* Run Script */, - 7E70898A1B587BF3004D23AA /* Sources */, 7E70898B1B587BF3004D23AA /* Frameworks */, - 7E70898C1B587BF3004D23AA /* CopyFiles */, + 7EDCC3CC1C45DC89002F9851 /* Sources */, ); buildRules = ( ); dependencies = ( + 7E8E3A9A1C45D5850017F6C1 /* PBXTargetDependency */, ); name = "ios-deploy"; productName = "ios-deploy"; productReference = 7E70898E1B587BF3004D23AA /* ios-deploy */; productType = "com.apple.product-type.tool"; }; + 7E8E3A821C45D4CE0017F6C1 /* ios-deploy-tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7E8E3A8A1C45D4CE0017F6C1 /* Build configuration list for PBXNativeTarget "ios-deploy-tests" */; + buildPhases = ( + 7E8E3A7F1C45D4CE0017F6C1 /* Sources */, + 7E8E3A801C45D4CE0017F6C1 /* Frameworks */, + 7E8E3A811C45D4CE0017F6C1 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 7EDCC3CB1C45D933002F9851 /* PBXTargetDependency */, + ); + name = "ios-deploy-tests"; + productName = "ios-deploy-tests"; + productReference = 7E8E3A831C45D4CE0017F6C1 /* ios-deploy-tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 7E8E3A8E1C45D5380017F6C1 /* ios-deploy-lib */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7E8E3A951C45D5380017F6C1 /* Build configuration list for PBXNativeTarget "ios-deploy-lib" */; + buildPhases = ( + 7E8E3A981C45D5610017F6C1 /* ShellScript */, + 7E8E3A8B1C45D5380017F6C1 /* Sources */, + 7E8E3A8C1C45D5380017F6C1 /* Frameworks */, + 7E8E3A8D1C45D5380017F6C1 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "ios-deploy-lib"; + productName = "ios-deploy-lib"; + productReference = 7E8E3A8F1C45D5380017F6C1 /* libios-deploy.a */; + productType = "com.apple.product-type.library.static"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -129,6 +229,12 @@ 7E70898D1B587BF3004D23AA = { CreatedOnToolsVersion = 6.4; }; + 7E8E3A821C45D4CE0017F6C1 = { + CreatedOnToolsVersion = 7.2; + }; + 7E8E3A8E1C45D5380017F6C1 = { + CreatedOnToolsVersion = 7.2; + }; }; }; buildConfigurationList = 7E7089891B587BF3004D23AA /* Build configuration list for PBXProject "ios-deploy" */; @@ -145,19 +251,30 @@ projectRoot = ""; targets = ( 7E70898D1B587BF3004D23AA /* ios-deploy */, + 7E8E3A821C45D4CE0017F6C1 /* ios-deploy-tests */, + 7E8E3A8E1C45D5380017F6C1 /* ios-deploy-lib */, ); }; /* End PBXProject section */ +/* Begin PBXResourcesBuildPhase section */ + 7E8E3A811C45D4CE0017F6C1 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + /* Begin PBXShellScriptBuildPhase section */ - 7E1C00D01C3C9C0700D686B5 /* Run Script */ = { + 7E8E3A981C45D5610017F6C1 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Run Script"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; @@ -167,16 +284,45 @@ /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 7E70898A1B587BF3004D23AA /* Sources */ = { + 7E8E3A7F1C45D4CE0017F6C1 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 7E70899C1B587DE4004D23AA /* ios-deploy.c in Sources */, + 7E8E3A861C45D4CE0017F6C1 /* ios_deploy_tests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7E8E3A8B1C45D5380017F6C1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7E8E3A941C45D5380017F6C1 /* ios_deploy_lib.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7EDCC3CC1C45DC89002F9851 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7EDCC3CD1C45DC94002F9851 /* ios-deploy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + 7E8E3A9A1C45D5850017F6C1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 7E8E3A8E1C45D5380017F6C1 /* ios-deploy-lib */; + targetProxy = 7E8E3A991C45D5850017F6C1 /* PBXContainerItemProxy */; + }; + 7EDCC3CB1C45D933002F9851 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 7E8E3A8E1C45D5380017F6C1 /* ios-deploy-lib */; + targetProxy = 7EDCC3CA1C45D933002F9851 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin XCBuildConfiguration section */ 7E7089931B587BF3004D23AA /* Debug */ = { isa = XCBuildConfiguration; @@ -280,6 +426,62 @@ }; name = Release; }; + 7E8E3A881C45D4CE0017F6C1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = "ios-deploy-tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "com.phonegap.ios-deploy-tests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 7E8E3A891C45D4CE0017F6C1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = "ios-deploy-tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "com.phonegap.ios-deploy-tests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 7E8E3A961C45D5380017F6C1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "-"; + EXECUTABLE_PREFIX = lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + OTHER_LDFLAGS = ( + "-framework", + MobileDevice, + "-F/System/Library/PrivateFrameworks", + ); + PRODUCT_NAME = "ios-deploy"; + }; + name = Debug; + }; + 7E8E3A971C45D5380017F6C1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "-"; + EXECUTABLE_PREFIX = lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + OTHER_LDFLAGS = ( + "-framework", + MobileDevice, + "-F/System/Library/PrivateFrameworks", + ); + PRODUCT_NAME = "ios-deploy"; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -301,6 +503,24 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 7E8E3A8A1C45D4CE0017F6C1 /* Build configuration list for PBXNativeTarget "ios-deploy-tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7E8E3A881C45D4CE0017F6C1 /* Debug */, + 7E8E3A891C45D4CE0017F6C1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7E8E3A951C45D5380017F6C1 /* Build configuration list for PBXNativeTarget "ios-deploy-lib" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7E8E3A961C45D5380017F6C1 /* Debug */, + 7E8E3A971C45D5380017F6C1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = 7E7089861B587BF3004D23AA /* Project object */; diff --git a/src/ios-deploy.c b/src/ios-deploy.m similarity index 100% rename from src/ios-deploy.c rename to src/ios-deploy.m From fd12c317b7e2dfcceba969f3a9567e026824564b Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 12 Jan 2016 17:35:59 -0800 Subject: [PATCH 214/219] Restructured folders into src/ --- ios-deploy.xcodeproj/project.pbxproj | 34 +++++++++++-------- package.json | 2 +- .../ios-deploy-lib}/ios_deploy_lib.h | 0 .../ios-deploy-lib}/ios_deploy_lib.m | 0 .../ios-deploy-tests}/Info.plist | 0 .../ios-deploy-tests}/ios_deploy_tests.m | 0 src/{ => ios-deploy}/MobileDevice.h | 0 src/{ => ios-deploy}/errors.h | 0 src/{ => ios-deploy}/ios-deploy.m | 0 src/{ => ios-deploy}/lldb.py.h | 0 src/{ => ios-deploy}/version.h | 0 src/{ => scripts}/check_reqs.js | 0 12 files changed, 21 insertions(+), 15 deletions(-) rename {ios-deploy-lib => src/ios-deploy-lib}/ios_deploy_lib.h (100%) rename {ios-deploy-lib => src/ios-deploy-lib}/ios_deploy_lib.m (100%) rename {ios-deploy-tests => src/ios-deploy-tests}/Info.plist (100%) rename {ios-deploy-tests => src/ios-deploy-tests}/ios_deploy_tests.m (100%) rename src/{ => ios-deploy}/MobileDevice.h (100%) rename src/{ => ios-deploy}/errors.h (100%) rename src/{ => ios-deploy}/ios-deploy.m (100%) rename src/{ => ios-deploy}/lldb.py.h (100%) rename src/{ => ios-deploy}/version.h (100%) rename src/{ => scripts}/check_reqs.js (100%) diff --git a/ios-deploy.xcodeproj/project.pbxproj b/ios-deploy.xcodeproj/project.pbxproj index 0df1e7e2..a13fe298 100644 --- a/ios-deploy.xcodeproj/project.pbxproj +++ b/ios-deploy.xcodeproj/project.pbxproj @@ -35,13 +35,13 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 7E1C00CC1C3C93AF00D686B5 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = version.h; path = src/version.h; sourceTree = SOURCE_ROOT; }; + 7E1C00CC1C3C93AF00D686B5 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; 7E1C00CF1C3C9ABB00D686B5 /* lldb.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; name = lldb.py; path = src/scripts/lldb.py; sourceTree = SOURCE_ROOT; }; - 7E1C00D11C3C9CB000D686B5 /* lldb.py.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = lldb.py.h; path = src/lldb.py.h; sourceTree = SOURCE_ROOT; }; + 7E1C00D11C3C9CB000D686B5 /* lldb.py.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lldb.py.h; sourceTree = ""; }; 7E70898E1B587BF3004D23AA /* ios-deploy */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "ios-deploy"; sourceTree = BUILT_PRODUCTS_DIR; }; - 7E7089991B587DE4004D23AA /* ios-deploy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "ios-deploy.m"; path = "src/ios-deploy.m"; sourceTree = SOURCE_ROOT; }; - 7E70899A1B587DE4004D23AA /* errors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = errors.h; path = src/errors.h; sourceTree = SOURCE_ROOT; }; - 7E70899B1B587DE4004D23AA /* MobileDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MobileDevice.h; path = src/MobileDevice.h; sourceTree = SOURCE_ROOT; }; + 7E7089991B587DE4004D23AA /* ios-deploy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "ios-deploy.m"; sourceTree = ""; }; + 7E70899A1B587DE4004D23AA /* errors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = errors.h; sourceTree = ""; }; + 7E70899B1B587DE4004D23AA /* MobileDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MobileDevice.h; sourceTree = ""; }; 7E70899D1B587F29004D23AA /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; 7E70899F1B58801E004D23AA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 7E8E3A831C45D4CE0017F6C1 /* ios-deploy-tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "ios-deploy-tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -50,6 +50,7 @@ 7E8E3A8F1C45D5380017F6C1 /* libios-deploy.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libios-deploy.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 7E8E3A911C45D5380017F6C1 /* ios_deploy_lib.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ios_deploy_lib.h; sourceTree = ""; }; 7E8E3A931C45D5380017F6C1 /* ios_deploy_lib.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ios_deploy_lib.m; sourceTree = ""; }; + 7EDCC3CE1C45DFF0002F9851 /* check_reqs.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = check_reqs.js; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -84,14 +85,17 @@ 7E1C00CE1C3C9A7700D686B5 /* scripts */ = { isa = PBXGroup; children = ( + 7EDCC3CE1C45DFF0002F9851 /* check_reqs.js */, 7E1C00CF1C3C9ABB00D686B5 /* lldb.py */, ); name = scripts; + path = src/scripts; sourceTree = ""; }; 7E7089851B587BF3004D23AA = { isa = PBXGroup; children = ( + 7E1C00CE1C3C9A7700D686B5 /* scripts */, 7E7089901B587BF3004D23AA /* ios-deploy */, 7E8E3A841C45D4CE0017F6C1 /* ios-deploy-tests */, 7E8E3A901C45D5380017F6C1 /* ios-deploy-lib */, @@ -113,14 +117,14 @@ 7E7089901B587BF3004D23AA /* ios-deploy */ = { isa = PBXGroup; children = ( - 7E1C00CE1C3C9A7700D686B5 /* scripts */, 7E1C00D11C3C9CB000D686B5 /* lldb.py.h */, 7E1C00CC1C3C93AF00D686B5 /* version.h */, 7E7089991B587DE4004D23AA /* ios-deploy.m */, 7E70899A1B587DE4004D23AA /* errors.h */, 7E70899B1B587DE4004D23AA /* MobileDevice.h */, ); - path = "ios-deploy"; + name = "ios-deploy"; + path = "src/ios-deploy"; sourceTree = ""; }; 7E7089A21B588219004D23AA /* Frameworks */ = { @@ -138,7 +142,8 @@ 7E8E3A851C45D4CE0017F6C1 /* ios_deploy_tests.m */, 7E8E3A871C45D4CE0017F6C1 /* Info.plist */, ); - path = "ios-deploy-tests"; + name = "ios-deploy-tests"; + path = "src/ios-deploy-tests"; sourceTree = ""; }; 7E8E3A901C45D5380017F6C1 /* ios-deploy-lib */ = { @@ -147,7 +152,8 @@ 7E8E3A911C45D5380017F6C1 /* ios_deploy_lib.h */, 7E8E3A931C45D5380017F6C1 /* ios_deploy_lib.m */, ); - path = "ios-deploy-lib"; + name = "ios-deploy-lib"; + path = "src/ios-deploy-lib"; sourceTree = ""; }; /* End PBXGroup section */ @@ -168,6 +174,7 @@ isa = PBXNativeTarget; buildConfigurationList = 7E7089951B587BF3004D23AA /* Build configuration list for PBXNativeTarget "ios-deploy" */; buildPhases = ( + 7EDCC3CF1C45E03B002F9851 /* ShellScript */, 7E70898B1B587BF3004D23AA /* Frameworks */, 7EDCC3CC1C45DC89002F9851 /* Sources */, ); @@ -203,7 +210,6 @@ isa = PBXNativeTarget; buildConfigurationList = 7E8E3A951C45D5380017F6C1 /* Build configuration list for PBXNativeTarget "ios-deploy-lib" */; buildPhases = ( - 7E8E3A981C45D5610017F6C1 /* ShellScript */, 7E8E3A8B1C45D5380017F6C1 /* Sources */, 7E8E3A8C1C45D5380017F6C1 /* Frameworks */, 7E8E3A8D1C45D5380017F6C1 /* Headers */, @@ -268,7 +274,7 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 7E8E3A981C45D5610017F6C1 /* ShellScript */ = { + 7EDCC3CF1C45E03B002F9851 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -279,7 +285,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "echo \"\\\"# AUTO-GENERATED - DO NOT MODIFY\\n\\\"\" > src/lldb.py.h\nawk '{ print \"\\\"\"$0\"\\\\n\\\"\"}' src/scripts/lldb.py >> src/lldb.py.h\n"; + shellScript = "echo \"\\\"# AUTO-GENERATED - DO NOT MODIFY\\n\\\"\" > src/ios-deploy/lldb.py.h\nawk '{ print \"\\\"\"$0\"\\\\n\\\"\"}' src/scripts/lldb.py >> src/ios-deploy/lldb.py.h"; }; /* End PBXShellScriptBuildPhase section */ @@ -431,7 +437,7 @@ buildSettings = { CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = "ios-deploy-tests/Info.plist"; + INFOPLIST_FILE = "src/ios-deploy-tests/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.11; PRODUCT_BUNDLE_IDENTIFIER = "com.phonegap.ios-deploy-tests"; @@ -444,7 +450,7 @@ buildSettings = { CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = "ios-deploy-tests/Info.plist"; + INFOPLIST_FILE = "src/ios-deploy-tests/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.11; PRODUCT_BUNDLE_IDENTIFIER = "com.phonegap.ios-deploy-tests"; diff --git a/package.json b/package.json index dd98a309..cf1ea153 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "jshint": "2.5.8" }, "scripts": { - "preinstall": "./src/check_reqs.js && xcodebuild", + "preinstall": "./src/scripts/check_reqs.js && xcodebuild", "test": "npm run jshint", "jshint": "node node_modules/jshint/bin/jshint src" }, diff --git a/ios-deploy-lib/ios_deploy_lib.h b/src/ios-deploy-lib/ios_deploy_lib.h similarity index 100% rename from ios-deploy-lib/ios_deploy_lib.h rename to src/ios-deploy-lib/ios_deploy_lib.h diff --git a/ios-deploy-lib/ios_deploy_lib.m b/src/ios-deploy-lib/ios_deploy_lib.m similarity index 100% rename from ios-deploy-lib/ios_deploy_lib.m rename to src/ios-deploy-lib/ios_deploy_lib.m diff --git a/ios-deploy-tests/Info.plist b/src/ios-deploy-tests/Info.plist similarity index 100% rename from ios-deploy-tests/Info.plist rename to src/ios-deploy-tests/Info.plist diff --git a/ios-deploy-tests/ios_deploy_tests.m b/src/ios-deploy-tests/ios_deploy_tests.m similarity index 100% rename from ios-deploy-tests/ios_deploy_tests.m rename to src/ios-deploy-tests/ios_deploy_tests.m diff --git a/src/MobileDevice.h b/src/ios-deploy/MobileDevice.h similarity index 100% rename from src/MobileDevice.h rename to src/ios-deploy/MobileDevice.h diff --git a/src/errors.h b/src/ios-deploy/errors.h similarity index 100% rename from src/errors.h rename to src/ios-deploy/errors.h diff --git a/src/ios-deploy.m b/src/ios-deploy/ios-deploy.m similarity index 100% rename from src/ios-deploy.m rename to src/ios-deploy/ios-deploy.m diff --git a/src/lldb.py.h b/src/ios-deploy/lldb.py.h similarity index 100% rename from src/lldb.py.h rename to src/ios-deploy/lldb.py.h diff --git a/src/version.h b/src/ios-deploy/version.h similarity index 100% rename from src/version.h rename to src/ios-deploy/version.h diff --git a/src/check_reqs.js b/src/scripts/check_reqs.js similarity index 100% rename from src/check_reqs.js rename to src/scripts/check_reqs.js From 3a57b33e8f3d5ee0f8c9da6f695f2289b4e03ead Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 12 Jan 2016 17:42:10 -0800 Subject: [PATCH 215/219] Exported lib-ios-deploy header --- ios-deploy.xcodeproj/project.pbxproj | 20 +++++++++++-------- .../{ios_deploy_lib.h => libios_deploy.h} | 0 .../{ios_deploy_lib.m => libios_deploy.m} | 2 +- 3 files changed, 13 insertions(+), 9 deletions(-) rename src/ios-deploy-lib/{ios_deploy_lib.h => libios_deploy.h} (100%) rename src/ios-deploy-lib/{ios_deploy_lib.m => libios_deploy.m} (58%) diff --git a/ios-deploy.xcodeproj/project.pbxproj b/ios-deploy.xcodeproj/project.pbxproj index a13fe298..0e95458a 100644 --- a/ios-deploy.xcodeproj/project.pbxproj +++ b/ios-deploy.xcodeproj/project.pbxproj @@ -10,8 +10,8 @@ 7E70899E1B587F29004D23AA /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E70899D1B587F29004D23AA /* CoreFoundation.framework */; }; 7E7089A01B58801E004D23AA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E70899F1B58801E004D23AA /* Foundation.framework */; }; 7E8E3A861C45D4CE0017F6C1 /* ios_deploy_tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E8E3A851C45D4CE0017F6C1 /* ios_deploy_tests.m */; }; - 7E8E3A921C45D5380017F6C1 /* ios_deploy_lib.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E8E3A911C45D5380017F6C1 /* ios_deploy_lib.h */; }; - 7E8E3A941C45D5380017F6C1 /* ios_deploy_lib.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E8E3A931C45D5380017F6C1 /* ios_deploy_lib.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 7E8E3A921C45D5380017F6C1 /* libios_deploy.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E8E3A911C45D5380017F6C1 /* libios_deploy.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7E8E3A941C45D5380017F6C1 /* libios_deploy.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E8E3A931C45D5380017F6C1 /* libios_deploy.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 7E8E3A9B1C45D5970017F6C1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E70899F1B58801E004D23AA /* Foundation.framework */; }; 7E8E3A9D1C45D6290017F6C1 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E70899D1B587F29004D23AA /* CoreFoundation.framework */; }; 7EDCC3CD1C45DC94002F9851 /* ios-deploy.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E7089991B587DE4004D23AA /* ios-deploy.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; @@ -48,8 +48,8 @@ 7E8E3A851C45D4CE0017F6C1 /* ios_deploy_tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ios_deploy_tests.m; sourceTree = ""; }; 7E8E3A871C45D4CE0017F6C1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 7E8E3A8F1C45D5380017F6C1 /* libios-deploy.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libios-deploy.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 7E8E3A911C45D5380017F6C1 /* ios_deploy_lib.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ios_deploy_lib.h; sourceTree = ""; }; - 7E8E3A931C45D5380017F6C1 /* ios_deploy_lib.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ios_deploy_lib.m; sourceTree = ""; }; + 7E8E3A911C45D5380017F6C1 /* libios_deploy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = libios_deploy.h; sourceTree = ""; }; + 7E8E3A931C45D5380017F6C1 /* libios_deploy.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = libios_deploy.m; sourceTree = ""; }; 7EDCC3CE1C45DFF0002F9851 /* check_reqs.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = check_reqs.js; sourceTree = ""; }; /* End PBXFileReference section */ @@ -149,8 +149,8 @@ 7E8E3A901C45D5380017F6C1 /* ios-deploy-lib */ = { isa = PBXGroup; children = ( - 7E8E3A911C45D5380017F6C1 /* ios_deploy_lib.h */, - 7E8E3A931C45D5380017F6C1 /* ios_deploy_lib.m */, + 7E8E3A911C45D5380017F6C1 /* libios_deploy.h */, + 7E8E3A931C45D5380017F6C1 /* libios_deploy.m */, ); name = "ios-deploy-lib"; path = "src/ios-deploy-lib"; @@ -163,7 +163,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 7E8E3A921C45D5380017F6C1 /* ios_deploy_lib.h in Headers */, + 7E8E3A921C45D5380017F6C1 /* libios_deploy.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -302,7 +302,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 7E8E3A941C45D5380017F6C1 /* ios_deploy_lib.m in Sources */, + 7E8E3A941C45D5380017F6C1 /* libios_deploy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -463,6 +463,7 @@ buildSettings = { CODE_SIGN_IDENTITY = "-"; EXECUTABLE_PREFIX = lib; + INSTALL_PATH = ""; MACOSX_DEPLOYMENT_TARGET = 10.11; OTHER_LDFLAGS = ( "-framework", @@ -470,6 +471,7 @@ "-F/System/Library/PrivateFrameworks", ); PRODUCT_NAME = "ios-deploy"; + PUBLIC_HEADERS_FOLDER_PATH = ""; }; name = Debug; }; @@ -478,6 +480,7 @@ buildSettings = { CODE_SIGN_IDENTITY = "-"; EXECUTABLE_PREFIX = lib; + INSTALL_PATH = ""; MACOSX_DEPLOYMENT_TARGET = 10.11; OTHER_LDFLAGS = ( "-framework", @@ -485,6 +488,7 @@ "-F/System/Library/PrivateFrameworks", ); PRODUCT_NAME = "ios-deploy"; + PUBLIC_HEADERS_FOLDER_PATH = ""; }; name = Release; }; diff --git a/src/ios-deploy-lib/ios_deploy_lib.h b/src/ios-deploy-lib/libios_deploy.h similarity index 100% rename from src/ios-deploy-lib/ios_deploy_lib.h rename to src/ios-deploy-lib/libios_deploy.h diff --git a/src/ios-deploy-lib/ios_deploy_lib.m b/src/ios-deploy-lib/libios_deploy.m similarity index 58% rename from src/ios-deploy-lib/ios_deploy_lib.m rename to src/ios-deploy-lib/libios_deploy.m index 61a1c18b..5993a9b5 100644 --- a/src/ios-deploy-lib/ios_deploy_lib.m +++ b/src/ios-deploy-lib/libios_deploy.m @@ -1,4 +1,4 @@ -#import "ios_deploy_lib.h" +#import "libios_deploy.h" @implementation ios_deploy_lib From cbba8a4328aeadbea84d987eda19e4119a271821 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 12 Jan 2016 17:49:32 -0800 Subject: [PATCH 216/219] Added npm scripts: test, pycompile --- package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index cf1ea153..af20b26d 100644 --- a/package.json +++ b/package.json @@ -18,8 +18,9 @@ }, "scripts": { "preinstall": "./src/scripts/check_reqs.js && xcodebuild", - "test": "npm run jshint", - "jshint": "node node_modules/jshint/bin/jshint src" + "test": "npm run pycompile && npm run jshint && xcodebuild -scheme ios-deploy-lib && xcodebuild test -scheme ios-deploy-tests", + "jshint": "node node_modules/jshint/bin/jshint src/scripts/*.js", + "pycompile": "python -m py_compile src/scripts/*.py" }, "keywords": [ "ios-deploy", From 0159cfc194966cb44e683de7b178e5967228f610 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Tue, 12 Jan 2016 17:52:11 -0800 Subject: [PATCH 217/219] Added Testing section in the README --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 81c5ae4a..3ceac069 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,13 @@ xcodebuild This will build `ios-deploy` into the `build/Release` folder. +## Testing + +Run: + +``` +npm install && npm test +``` ### OS X 10.11 El Capitan From 2fceef2c75dc3a6613cffe34f839604531a4f434 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Sat, 16 Jan 2016 10:33:11 -0800 Subject: [PATCH 218/219] Updated README to reflect 1.x branch and master (dev) branch expectations. --- README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3ceac069..63a1ce41 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,13 @@ See our [milestones](https://github.com/phonegap/ios-deploy/milestones). Significant changes: - 1.8.0 will use an Xcode project instead of a Makefile (to prepare for 2.0.0) - 2.0.0 will break out the commands into their own files, and create ios-deploy-lib for node.js use + 1.8.0 will use an Xcode project instead of a Makefile (to prepare for 2.0.0) (1.x branch) + 2.0.0 will break out the commands into their own files, and create ios-deploy-lib for node.js use (master branch) + +## Development + +The legacy `1.x` version is under the `1.x` branch. Bug fixes for the `1.x` series will occur under there. +The 'master' branch now contains the `2.x` series, and is the development branch. ## Installation ======= From 9a9c648cdc9d064bab84c5b9e2493c2d222ab9dd Mon Sep 17 00:00:00 2001 From: Shazron Abdullah Date: Sat, 16 Jan 2016 10:35:03 -0800 Subject: [PATCH 219/219] Updated version to 2.0.0 --- package.json | 2 +- src/ios-deploy/version.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index af20b26d..8aa0b049 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ios-deploy", - "version": "1.8.4", + "version": "2.0.0", "os": [ "darwin" ], diff --git a/src/ios-deploy/version.h b/src/ios-deploy/version.h index ec8dea70..27c13522 100644 --- a/src/ios-deploy/version.h +++ b/src/ios-deploy/version.h @@ -1 +1 @@ -"1.8.4" \ No newline at end of file +"2.0.0" \ No newline at end of file