sdmmd_return_t SDMMD_mount_image(SDMMD_AMConnectionRef connection, CFStringRef image_type, CFDataRef signature, bool *mounted) { sdmmd_return_t result = kAMDSuccess; CFMutableDictionaryRef mountDict = SDMMD_create_dict(); if (mountDict) { CFDictionarySetValue(mountDict, CFSTR("Command"), CFSTR("MountImage")); CFDictionarySetValue(mountDict, CFSTR("ImageType"), image_type); CFDictionarySetValue(mountDict, CFSTR("ImagePath"), CFSTR("/var/mobile/Media/PublicStaging/staging.dimage")); if (signature) { CFDictionarySetValue(mountDict, CFSTR("ImageSignature"), signature); } result = SDMMD_ServiceSendMessage(SDMMD_TranslateConnectionToSocket(connection), mountDict, kCFPropertyListXMLFormat_v1_0); CFSafeRelease(mountDict); CheckErrorAndReturn(result); CFDictionaryRef response; result = SDMMD_ServiceReceiveMessage(SDMMD_TranslateConnectionToSocket(connection), (CFPropertyListRef *)&response); CheckErrorAndReturn(result); if (response) { result = SDMMD__ErrorHandler(SDMMD_ImageMounterErrorConvert, response); CheckErrorAndReturn(result); CFTypeRef status = CFDictionaryGetValue(response, CFSTR("Status")); if (status) { if (CFEqual(status, CFSTR("Complete"))) { *mounted = true; } else { result = kAMDMissingDigestError; } } } else { result = kAMDReadError; } } else { result = kAMDReadError; } ExitLabelAndReturn(result); }
sdmmd_return_t SDMMD_AMDeviceMountImage(SDMMD_AMDeviceRef device, CFStringRef path, CFDictionaryRef dict, CallBack handle, void *unknown) { sdmmd_return_t result = kAMDSuccess; if (dict) { SDMMD_AMConnectionRef connection = NULL; CFTypeRef digest = NULL; CFTypeRef signature = CFDictionaryGetValue(dict, CFSTR("ImageSignature")); CFStringRef image_type = CFDictionaryGetValue(dict, CFSTR("ImageType")); if (image_type) { unsigned char sum_digest[SHA1_HASH_LENGTH]; result = SDMMD_AMDeviceDigestFile(path, PtrCast(&sum_digest, unsigned char **)); CheckErrorAndReturn(result); SDMMD_AMDeviceRef device_copy = SDMMD_AMDeviceCreateCopy(device); if (SDMMD_AMDeviceIsValid(device_copy)) { result = SDMMD_AMDeviceSecureStartSessionedService(device, CFSTR(AMSVC_MOBILE_IMAGE_MOUNT), &connection); CheckErrorAndReturn(result); SDMMD_fire_callback(handle, unknown, CFSTR("LookingUpImage")); if (connection) { CFMutableDictionaryRef commandDict = SDMMD_create_dict(); if (commandDict) { CFDictionarySetValue(commandDict, CFSTR("Command"), CFSTR("LookupImage")); CFDictionarySetValue(commandDict, CFSTR("ImageType"), image_type); } else { result = kAMDNoResourcesError; } CheckErrorAndReturn(result); result = SDMMD_ServiceSendMessage(SDMMD_TranslateConnectionToSocket(connection), commandDict, kCFPropertyListXMLFormat_v1_0); CFSafeRelease(commandDict); CheckErrorAndReturn(result); CFDictionaryRef response; result = SDMMD_ServiceReceiveMessage(SDMMD_TranslateConnectionToSocket(connection), (CFPropertyListRef *)&response); CheckErrorAndReturn(result); if (response) { result = SDMMD__ErrorHandler(SDMMD__ConvertServiceError, response); CheckErrorAndReturn(result); CFTypeRef image = CFDictionaryGetValue(response, CFSTR("ImagePresent")); if (image) { if (CFEqual(image, kCFBooleanTrue)) { digest = CFDictionaryGetValue(response, CFSTR("ImageDigest")); } else { result = kAMDMissingDigestError; } } } if (!digest) { bool use_stream = SDMMD_device_os_is_at_least(device, CFSTR("7.0")); if (use_stream) { SDMMD_fire_callback(handle, unknown, CFSTR("StreamingImage")); result = SDMMD_stream_image(connection, path, image_type); } else { SDMMD_fire_callback(handle, unknown, CFSTR("CopyingImage")); result = SDMMD_copy_image(device, path); } } CheckErrorAndReturn(result); bool mounted = false; SDMMD_fire_callback(handle, unknown, CFSTR("MountingImage")); result = SDMMD_mount_image(connection, image_type, signature, &mounted); if (mounted) { result = SDMMD__hangup_with_image_mounter_service(connection); } } CFSafeRelease(connection); CFSafeRelease(device_copy); CheckErrorAndReturn(result); } else { result = kAMDUndefinedError; } } else { result = kAMDMissingImageTypeError; } }
sdmmd_return_t SDMMD_stream_image(SDMMD_AMConnectionRef connection, CFStringRef path, CFStringRef image_type) { sdmmd_return_t result = kAMDSuccess; char fspath[0x400] = {0}; Boolean fsRep = CFStringGetFileSystemRepresentation(path, fspath, 0x400); if (fsRep) { struct stat fileStat; lstat(fspath, &fileStat); CFNumberRef size = CFNumberCreate(kCFAllocatorDefault, 0xb, &fileStat.st_size); CFMutableDictionaryRef streamDict = SDMMD_create_dict(); CFDictionarySetValue(streamDict, CFSTR("Command"), CFSTR("ReceiveBytes")); CFDictionarySetValue(streamDict, CFSTR("ImageType"), image_type); CFDictionarySetValue(streamDict, CFSTR("ImageSize"), size); result = SDMMD_ServiceSendMessage(SDMMD_TranslateConnectionToSocket(connection), streamDict, kCFPropertyListXMLFormat_v1_0); CFSafeRelease(streamDict); CFSafeRelease(size); CheckErrorAndReturn(result); CFDictionaryRef response; result = SDMMD_ServiceReceiveMessage(SDMMD_TranslateConnectionToSocket(connection), (CFPropertyListRef *)&response); CheckErrorAndReturn(result); if (response) { result = SDMMD__ErrorHandler(SDMMD_ImageMounterErrorConvert, response); CheckErrorAndReturn(result); CFTypeRef status = CFDictionaryGetValue(response, CFSTR("Status")); if (status) { if (CFStringCompare(status, CFSTR("ReceiveBytesAck"), 0) == 0) { // block code CFDataRef image_file = CFDataCreateFromPath(path); uint64_t offset = 0; uint64_t remainder = 0; while (offset < fileStat.st_size) { remainder = (fileStat.st_size - offset); remainder = (remainder > kDeveloperImageStreamSize ? kDeveloperImageStreamSize : remainder); CFRange current_read = CFRangeMake((CFIndex)offset, (CFIndex)remainder); CFDataRef image_stream = CFDataCreateFromSubrangeOfData(image_file, current_read); result = SDMMD_DirectServiceSend(SDMMD_TranslateConnectionToSocket(connection), image_stream); CheckErrorAndReturn(result); offset += remainder; CFSafeRelease(image_stream); } CFDictionaryRef getStatus; result = SDMMD_ServiceReceiveMessage(SDMMD_TranslateConnectionToSocket(connection), (CFPropertyListRef *)&getStatus); if (result == 0) { result = SDMMD__ErrorHandler(SDMMD_ImageMounterErrorConvert, response); CheckErrorAndReturn(result); CFTypeRef streamStatus = CFDictionaryGetValue(getStatus, CFSTR("Status")); if (streamStatus) { if (CFStringCompare(streamStatus, CFSTR("Complete"), 0x0) == 0) { result = kAMDSuccess; } } } CFSafeRelease(getStatus); CFSafeRelease(image_file); } } else { result = kAMDUndefinedError; } } else { result = kAMDReadError; } } else { result = kAMDNoResourcesError; } ExitLabelAndReturn(result); }
sdmmd_return_t SDMMD_perform_command(SDMMD_AMConnectionRef conn, CFStringRef command, uint64_t code, CallBack handle, uint32_t argsCount, void* paramStart, ...) { sdmmd_return_t result = kAMDSuccess; CFMutableDictionaryRef message = SDMMD_create_dict(); if (message) { va_list args; CFDictionarySetValue(message, CFSTR("Command"), command); va_start(args, paramStart); CFTypeRef key, value; for (uint32_t i = 0; i < argsCount; i++) { key = va_arg(args, CFTypeRef); value = va_arg(args, CFTypeRef); CFDictionarySetValue(message, key, value); i++; } va_end(args); SocketConnection sock = SDMMD_TranslateConnectionToSocket(conn); result = SDMMD_ServiceSendStream(sock, message, kCFPropertyListXMLFormat_v1_0); CFSafeRelease(message); if (result == 0) { CFDictionaryRef response = NULL; result = SDMMD_ServiceReceiveStream(sock, (CFPropertyListRef*)&response); if (result == 0 && response) { while (result == 0) { result = SDMMD__ErrorHandler(SDMMD__ConvertServiceError, response); CheckErrorAndReturn(result); CFTypeRef status = CFDictionaryGetValue(response, CFSTR("Status")); if (status) { if (CFStringCompare(status, CFSTR("Complete"), 0) != 0) { CFArrayRef responses = CFDictionaryGetValue(response, CFSTR("CurrentList")); if (responses) { uint64_t count = CFArrayGetCount(responses); for (uint32_t i = 0; i < count; i++) { CFDictionaryRef value = CFArrayGetValueAtIndex(responses, i); handle(value, paramStart); } } else { handle(response, 0); } } else { break; } } SDMMD_ServiceReceiveStream(sock, (CFPropertyListRef*)&response); } } else { result = kAMDReceiveMessageError; printf("call_and_response: Could not receive response from proxy.\n"); } } else { result = kAMDSendMessageError; printf("call_and_response: Could not send request to proxy.\n"); } } else { result = kAMDUndefinedError; } ExitLabelAndReturn(result); }