// Opens a session on the iPod. This should be called before starting any // operation to ensure the iPod hasn't been disconnected since the last time, // or simply to initialize the first connection if it hasn't been done before. // // Returns: // IPOD_ERR_OK when successful // IPOD_IPOD_NOT_FOUND if no iPod is connected to any USB port // IPOD_COULD_NOT_CONNECT if the connection could not be established // t_iPodError CiPoTApi::OpenSession() { t_MachError ret; int timeout; CheckConnection(); if (m_ApiState == API_STATE_AVAILABLE) // Session is already open return IPOD_ERR_OK; // Checks if iPod connected for (timeout = 0; (timeout < 200) && (m_iPodState != IPOD_STATE_CONNECTED); timeout++) Sleep(10); if (m_iPodState != IPOD_STATE_CONNECTED) return IPOD_IPOD_NOT_FOUND; // Opens a session for this instance m_pDev = (t_AMDevice *)m_iPodDev; if (AMDeviceStartService(m_pDev, m_iPodAFCName, &m_iPodAFC, NULL)) { // Not jailbroken, tries to connect to the standard name m_iPodAFCName = AMSVC_AFC; ret = AMDeviceStartService(m_pDev, m_iPodAFCName, &m_iPodAFC, NULL); if (ret) return IPOD_COULD_NOT_CONNECT; } lstrcpyn(m_Serial, m_pDev->serial, sizeof(m_Serial)); if (AFCConnectionOpen(m_iPodAFC, 0, &m_iPodConnection)) return IPOD_COULD_NOT_CONNECT; m_ApiState = API_STATE_AVAILABLE; m_ConnectionID = m_GlobalConnectionID; return IPOD_ERR_OK; }
kern_return_t test_apple_AFCOperationCreateGetConnectionInfo(struct am_device *apple, CFTypeRef *response) { kern_return_t apple_return = kAMDUndefinedError; kern_return_t result = AMDeviceConnect(apple); if (SDM_MD_CallSuccessful(result)) { result = AMDeviceStartSession(apple); if (SDM_MD_CallSuccessful(result)) { service_conn_t test_apple_afc_conn; result = AMDeviceStartService(apple, CFSTR(AMSVC_AFC), &test_apple_afc_conn, NULL); if (SDM_MD_CallSuccessful(result)) { struct afc_connection *afc = NULL; result = AFCConnectionOpen(test_apple_afc_conn, 0, &afc); if (afc) { afc_operation conn_info = AFCOperationCreateGetConnectionInfo(kCFAllocatorDefault, NULL); result = AFCConnectionProcessOperation(afc, conn_info, 0); if (SDM_MD_CallSuccessful(result)) { CFTypeRef test = AFCOperationGetResultObject(conn_info); if (test) { *response = test; apple_return = kAMDSuccess; } } AFCConnectionClose(afc); } } AMDeviceStopSession(apple); } AMDeviceDisconnect(apple); } return apple_return; }
/** Connect to an iPhone device, and register callbacks. * Members of the iPhone struct that must be valid: dnc * for device notifications */ BOOL iPhone_Connect(iPhone *iphone) { if(AMDeviceConnect(iphone->handle) == 1) { iPhone_SetLastError("Device is in recovery mode. Must be activated with iTunes."); return FALSE ; } if(AMDeviceIsPaired(iphone->handle) == 0) { iPhone_SetLastError("AMDeviceIsPaired failed."); return FALSE; } if(AMDeviceValidatePairing(iphone->handle) != 0) { iPhone_SetLastError("AMDeviceValidatePairing failed."); return FALSE; } if(AMDeviceStartSession(iphone->handle) == 1) { iPhone_SetLastError("AMDeviceStartSession failed."); return FALSE; } if(AMDeviceStartService(iphone->handle, __CFStringMakeConstantString("com.apple.afc2"), &iphone->hService, NULL) != 0) { if(AMDeviceStartService(iphone->handle, __CFStringMakeConstantString("com.apple.afc"), &iphone->hService, NULL) != 0) return FALSE; } if(AFCConnectionOpen(iphone->hService, 0, &iphone->hAFC) != 0) { iPhone_SetLastError("AFCConnectionOpen failed."); return FALSE; } iphone->connected = TRUE; return TRUE; }
service_conn_t start_afc_service(AMDeviceRef device) { AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); assert(AMDeviceValidatePairing(device) == 0); assert(AMDeviceStartSession(device) == 0); service_conn_t afcFd; assert(AMDeviceStartService(device, AMSVC_AFC, &afcFd, NULL) == 0); assert(AMDeviceStopSession(device) == 0); assert(AMDeviceDisconnect(device) == 0); return afcFd; }
service_conn_t start_install_proxy_service(AMDeviceRef device) { 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); assert(AMDeviceStopSession(device) == 0); assert(AMDeviceDisconnect(device) == 0); return installFd; }
void start_remote_debug_server(AMDeviceRef device) { assert(AMDeviceStartService(device, CFSTR("com.apple.debugserver"), &gdbfd, NULL) == 0); CFSocketRef fdvendor = CFSocketCreate(NULL, AF_UNIX, 0, 0, kCFSocketAcceptCallBack, &fdvendor_callback, NULL); int yes = 1; setsockopt(CFSocketGetNative(fdvendor), SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); struct sockaddr_un address; memset(&address, 0, sizeof(address)); address.sun_family = AF_UNIX; strcpy(address.sun_path, FDVENDOR_PATH); CFDataRef address_data = CFDataCreate(NULL, (const UInt8 *)&address, sizeof(address)); unlink(FDVENDOR_PATH); CFSocketSetAddress(fdvendor, address_data); CFRelease(address_data); CFRunLoopAddSource(CFRunLoopGetMain(), CFSocketCreateRunLoopSource(NULL, fdvendor, 0), kCFRunLoopCommonModes); }
kern_return_t test_apple_AFCConnectionCreate(struct am_device *apple) { kern_return_t apple_return = kAMDUndefinedError; kern_return_t result = AMDeviceConnect(apple); if (SDM_MD_CallSuccessful(result)) { result = AMDeviceStartSession(apple); if (SDM_MD_CallSuccessful(result)) { service_conn_t test_apple_afc_conn; result = AMDeviceStartService(apple, CFSTR(AMSVC_AFC), &test_apple_afc_conn, NULL); if (SDM_MD_CallSuccessful(result)) { struct afc_connection *afc = NULL; result = AFCConnectionOpen(test_apple_afc_conn, 0, &afc); if (afc) { apple_return = kAMDSuccess; AFCConnectionClose(afc); } } AMDeviceStopSession(apple); } AMDeviceDisconnect(apple); } return apple_return; }
static void cb(am_device_notification_callback_info * info, void *foo) { struct am_device *dev; if (info->msg == ADNCI_MSG_CONNECTED) { dev = info->dev; AMDeviceConnect(dev); assert(AMDeviceIsPaired(dev)); assert(!AMDeviceValidatePairing(dev)); assert(!AMDeviceStartSession(dev)); CFStringRef product = AMDeviceCopyValue(dev, 0, CFSTR("ProductVersion")); assert(product); UniChar first = CFStringGetCharacterAtIndex(product, 0); int epoch = first - '0'; Retry: {} printf("Attempting to mount image...\n"); service_conn_t afc_socket = 0; struct afc_connection *afc = NULL; assert(!AMDeviceStartService(dev, CFSTR("com.apple.afc"), &afc_socket, NULL)); assert(!AFCConnectionOpen(afc_socket, 0, &afc)); assert(!AFCDirectoryCreate(afc, "PublicStaging")); AFCRemovePath(afc, "PublicStaging/staging.dimage"); qwrite(afc, real_dmg, "PublicStaging/staging.dimage"); qwrite(afc, ddi_dmg, "PublicStaging/ddi.dimage"); service_conn_t mim_socket1 = 0; service_conn_t mim_socket2 = 0; assert(!AMDeviceStartService(dev, CFSTR("com.apple.mobile.mobile_image_mounter"), &mim_socket1, NULL)); assert(mim_socket1); CFPropertyListRef result = NULL; CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionarySetValue(dict, CFSTR("Command"), CFSTR("MountImage")); CFDictionarySetValue(dict, CFSTR("ImageType"), CFSTR("Developer")); CFDictionarySetValue(dict, CFSTR("ImagePath"), CFSTR("/var/mobile/Media/PublicStaging/staging.dimage")); int fd = open(real_dmg_signature, O_RDONLY); assert(fd != -1); uint8_t sig[128]; assert(read(fd, sig, sizeof(sig)) == sizeof(sig)); close(fd); CFDictionarySetValue(dict, CFSTR("ImageSignature"), CFDataCreateWithBytesNoCopy(NULL, sig, sizeof(sig), kCFAllocatorNull)); send_message(mim_socket1, dict); usleep(timesl); assert(!AFCRenamePath(afc, "PublicStaging/ddi.dimage", "PublicStaging/staging.dimage")); result = receive_message(mim_socket1); int len = CFDataGetLength(CFPropertyListCreateXMLData(NULL, result)); char* bytes = CFDataGetBytePtr(CFPropertyListCreateXMLData(NULL, result)); if(strstr(bytes, "Complete")) { char* the_service = "CopyIt"; service_conn_t socket = 0; sleep(2); printf("Image mounted, running helper...\n"); assert(!AMDeviceStartService(dev, CFStringCreateWithCStringNoCopy(NULL, the_service, kCFStringEncodingUTF8, kCFAllocatorNull), &socket, NULL)); assert(!fcntl(socket, F_SETFL, O_NONBLOCK)); assert(!fcntl(0, F_SETFL, O_NONBLOCK)); } else { printf("Failed to inject image, trying again... (if it fails, try a different time), delay ... %dus\n", timesl); timesl += 1000; goto Retry; } 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) { if(strcmp(device_id, CFStringGetCStringPtr(found_device_id, CFStringGetSystemEncoding())) == 0) { found_device = true; } else { return; } } else { found_device = true; } CFRetain(device); // don't know if this is necessary? 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); CFStringRef path = CFStringCreateWithCString(NULL, app_path, kCFStringEncodingASCII); CFURLRef relative_url = CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, false); CFURLRef url = CFURLCopyAbsoluteURL(relative_url); 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); service_conn_t installFd; assert(AMDeviceStartService(device, CFSTR("com.apple.mobile.installation_proxy"), &installFd, NULL) == 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); printf("[100%%] Installed package %s\n", app_path); if (!debug) exit(0); // no debug phase 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_gdb_prep_cmds(device, url); // dump the necessary gdb commands into a file CFRelease(url); printf("[100%%] Connecting to remote debug server\n"); printf("-------------------------\n"); signal(SIGHUP, gdb_ready_handler); signal(SIGINT, killed); signal(SIGTERM, killed); pid_t parent = getpid(); int pid = fork(); if (pid == 0) { CFStringRef path = copy_xcode_path_for(CFSTR("Platforms/iPhoneOS.platform/Developer/usr/libexec/gdb"), CFSTR("gdb-arm-apple-darwin")); if (path == NULL) { printf("[ !! ] Unable to locate GDB.\n"); kill(parent, SIGHUP); exit(1); } else { CFStringRef gdb_cmd = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ %@ %s"), path, CFSTR(GDB_SHELL), gdb_args); // Convert CFStringRef to char* for system call const char *char_gdb_cmd = CFStringGetCStringPtr(gdb_cmd, kCFStringEncodingMacRoman); system(char_gdb_cmd); // launch gdb } kill(parent, SIGHUP); // "No. I am your father." _exit(0); } }
static void device_notification_callback(am_device_notification_callback_info *info, void *thing) { if (info->msg != ADNCI_MSG_CONNECTED) return; puts("Opened device connection."); am_device *dev = info->dev; AMDeviceConnect(dev); assert(AMDeviceIsPaired(dev)); assert(AMDeviceValidatePairing(dev) == 0); assert(AMDeviceStartSession(dev) == 0); struct afc_connection *afc; service_conn_t afc_conn; assert(AMDeviceStartService(dev, CFSTR("com.apple.afc2"), &afc_conn, NULL) == 0); assert(AFCConnectionOpen(afc_conn, 0, &afc) == 0); char cachepath[63]; const char *caches[3] = {"dyld_shared_cache_armv7s", "dyld_shared_cache_armv7", "dyld_shared_cache_armv6"}; struct afc_dictionary *dict; unsigned int cache_index; char *fullpath; size_t cachesize; for (cache_index=0; cache_index<3; cache_index++) { strcpy(cachepath, "/System/Library/Caches/com.apple.dyld/"); fullpath = strcat(cachepath, caches[cache_index]); if (AFCFileInfoOpen(afc, fullpath, &dict) == 0) { char *key, *value; while (1) { assert(AFCKeyValueRead(dict, &key, &value) == 0); if (key == NULL) break; if (strcmp(key, "st_size") == 0) { cachesize = strtol(value, NULL, 0); break; } } printf("Found cache %s with size %lu\n", fullpath, cachesize); assert(AFCKeyValueClose(dict) == 0); goto _label_hasfile; } } fprintf(stderr, "Could not find cache file.\n"); exit(2); _label_hasfile:; afc_file_ref cache; assert(AFCFileRefOpen(afc, fullpath, 1, &cache) == 0); if (is_cwd) { strcat(outputfile, "/"); strcat(outputfile, caches[cache_index]); gen_path = 1; } puts(outputfile); FILE *output = fopen(outputfile, "w"); assert(output != NULL); printf("Writing cache to %s\n", outputfile); size_t total_bytes = 0; char buffer[65536]; while (1) { unsigned int length = 65536; assert(AFCFileRefRead(afc, cache, buffer, &length) == 0); fwrite(buffer, sizeof(char), length, output); total_bytes += length; float progress = (float)total_bytes/cachesize*100; printf("Progress: %f%%\n\033[F\033[J", progress); if (length < sizeof(buffer)) break; } printf("Successfully wrote cache to %s\n", outputfile); assert(AFCFileRefClose(afc, cache) == 0); CFRunLoopStop(CFRunLoopGetCurrent()); }
static int StartService(void* DeviceHandle, void** OutHandle) { int Result = AMDeviceStartService(DeviceHandle, CFSTR("com.apple.mobile.installation_proxy"), OutHandle, 0); return Result; }
static int StartService(void* DeviceHandle, void** OutHandle) { int Result = AMDeviceStartService(DeviceHandle, CFSTR("com.apple.afc"), OutHandle, 0); return Result; }
void handle_device(AMDeviceRef device) { if (found_device) return; // handle one device only CFStringRef found_device_id = AMDeviceCopyDeviceIdentifier(device); if (device_id != NULL) { if(strcmp(device_id, CFStringGetCStringPtr(found_device_id, kCFStringEncodingMacRoman)) == 0) { found_device = true; } else { return; } } else { found_device = true; } CFRetain(device); // don't know if this is necessary? printf("[ 0%%] Found device (%s), beginning install\n", CFStringGetCStringPtr(found_device_id, kCFStringEncodingMacRoman)); AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); assert(AMDeviceValidatePairing(device) == 0); assert(AMDeviceStartSession(device) == 0); CFStringRef path = CFStringCreateWithCString(NULL, app_path, kCFStringEncodingASCII); CFURLRef relative_url = CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, false); CFURLRef url = CFURLCopyAbsoluteURL(relative_url); CFRelease(relative_url); int 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); int installFd; assert(AMDeviceStartService(device, CFSTR("com.apple.mobile.installation_proxy"), &installFd, NULL) == 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); if (result == -402620388) { printf("Please check code signing or something else your app."); } exit(1); } close(installFd); CFRelease(path); CFRelease(options); printf("[100%%] Installed package %s\n", app_path); if (!debug) exit(0); // no debug phase 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_gdb_prep_cmds(device, url); // dump the necessary gdb commands into a file CFRelease(url); printf("[100%%] Connecting to remote debug server\n"); printf("-------------------------\n"); signal(SIGHUP, gdb_ready_handler); pid_t parent = getpid(); int pid = fork(); if (pid == 0) { system(GDB_SHELL); // launch gdb kill(parent, SIGHUP); // "No. I am your father." _exit(0); } }
static void DeviceNotificationCallback(am_device_notification_callback_info *info, void *unknown) { struct am_device *device = info->dev; switch (info->msg) { case ADNCI_MSG_CONNECTED: { if (debug) { CFStringRef deviceId = AMDeviceCopyDeviceIdentifier(device); CFStringRef str = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("deviceconsole connected: %@"), deviceId); CFRelease(deviceId); CFShow(str); CFRelease(str); } if (requiredDeviceId) { CFStringRef deviceId = AMDeviceCopyDeviceIdentifier(device); Boolean isRequiredDevice = CFEqual(deviceId, requiredDeviceId); CFRelease(deviceId); if (!isRequiredDevice) break; } if (AMDeviceConnect(device) == MDERR_OK) { if (AMDeviceIsPaired(device) && (AMDeviceValidatePairing(device) == MDERR_OK)) { if (AMDeviceStartSession(device) == MDERR_OK) { service_conn_t connection; if (AMDeviceStartService(device, AMSVC_SYSLOG_RELAY, &connection, NULL) == MDERR_OK) { CFSocketRef socket = CFSocketCreateWithNative(kCFAllocatorDefault, connection, kCFSocketDataCallBack, SocketCallback, NULL); if (socket) { CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0); if (source) { CFRunLoopAddSource(CFRunLoopGetMain(), source, kCFRunLoopCommonModes); AMDeviceRetain(device); DeviceConsoleConnection *data = malloc(sizeof *data); data->connection = connection; data->socket = socket; data->source = source; CFDictionarySetValue(liveConnections, device, data); return; } CFRelease(source); } } AMDeviceStopSession(device); } } } AMDeviceDisconnect(device); break; } case ADNCI_MSG_DISCONNECTED: { if (debug) { CFStringRef deviceId = AMDeviceCopyDeviceIdentifier(device); CFStringRef str = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("deviceconsole disconnected: %@"), deviceId); CFRelease(deviceId); CFShow(str); CFRelease(str); } DeviceConsoleConnection *data = (DeviceConsoleConnection *)CFDictionaryGetValue(liveConnections, device); if (data) { CFDictionaryRemoveValue(liveConnections, device); AMDeviceRelease(device); CFRunLoopRemoveSource(CFRunLoopGetMain(), data->source, kCFRunLoopCommonModes); CFRelease(data->source); CFRelease(data->socket); free(data); AMDeviceStopSession(device); AMDeviceDisconnect(device); } break; } default: break; } }
void handle_device(AMDeviceRef device) { if (found_device) return; // handle one device only CFStringRef found_device_id = AMDeviceCopyDeviceIdentifier(device); PRINT ("found device id\n"); if (device_id != NULL) { if(strcmp(device_id, CFStringGetCStringPtr(found_device_id, CFStringGetSystemEncoding())) == 0) { found_device = true; } else { return; } } else { if (operation == OP_LIST_DEVICES) { printf ("%s\n", CFStringGetCStringPtr(found_device_id, CFStringGetSystemEncoding())); CFRetain(device); // don't know if this is necessary? return; } found_device = true; } CFRetain(device); // don't know if this is necessary? PRINT("[ 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); CFStringRef path = CFStringCreateWithCString(NULL, app_path, kCFStringEncodingASCII); CFURLRef relative_url = CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, false); CFURLRef url = CFURLCopyAbsoluteURL(relative_url); CFRelease(relative_url); int afcFd; int startServiceAFCRetval = AMDeviceStartService(device, CFSTR("com.apple.afc"), (service_conn_t *) &afcFd, NULL); printf("trying to start com.apple.afc : %d\n", startServiceAFCRetval); if( startServiceAFCRetval ) { sleep(1); //printf("trying to start com.apple.afc\n"); startServiceAFCRetval = AMDeviceStartService(device, CFSTR("com.apple.afc"), (service_conn_t *) &afcFd, NULL); } printf("trying to start com.apple.afc : %d\n", startServiceAFCRetval); assert(startServiceAFCRetval == 0); assert(AMDeviceStopSession(device) == 0); assert(AMDeviceDisconnect(device) == 0); if (operation == OP_INSTALL) { 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); int installFd; assert(AMDeviceStartService(device, CFSTR("com.apple.mobile.installation_proxy"), (service_conn_t *) &installFd, NULL) == 0); //assert(AMDeviceStopSession(device) == 0); //assert(AMDeviceDisconnect(device) == 0); if (operation == OP_INSTALL) { mach_error_t result = AMDeviceSecureInstallApplication(0, device, url, options, &operation_callback, 0); //mach_error_t result = AMDeviceInstallApplication(installFd, path, options, operation_callback, NULL); if (result != 0) { PRINT("AMDeviceInstallApplication failed: %d\n", result); exit(EXIT_FAILURE); } } else if (operation == OP_UNINSTALL) { mach_error_t result = AMDeviceUninstallApplication (installFd, path, NULL, operation_callback, NULL); if (result != 0) { PRINT("AMDeviceUninstallApplication failed: %d\n", result); exit(EXIT_FAILURE); } } assert(AMDeviceStopSession(device) == 0); assert(AMDeviceDisconnect(device) == 0); close(installFd); CFRelease(path); CFRelease(options); if (operation == OP_INSTALL) PRINT("[100%%] Installed package %s\n", app_path); else if (operation == OP_UNINSTALL) PRINT("[100%%] Uninstalled package %s\n", app_path); if (!debug) exit(EXIT_SUCCESS); // no debug phase AMDeviceConnect(device); assert(AMDeviceIsPaired(device)); assert(AMDeviceValidatePairing(device) == 0); assert(AMDeviceStartSession(device) == 0); PRINT("------ Debug phase ------\n"); 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 CFRelease(url); PRINT("[100%%] Connecting to remote debug server\n"); PRINT("-------------------------\n"); signal(SIGHUP, gdb_ready_handler); pid_t parent = getpid(); int pid = fork(); if (pid == 0) { system(GDB_SHELL); // launch gdb kill(parent, SIGHUP); // "No. I am your father." _exit(EXIT_SUCCESS); } }