rendered paste body/* ----------------------------------------------------------------------------
* iphoneclient - an experimental iPhone access client v0.01 - 07/03/2007
*
* Place MobileDevice.h in the Headers/ directory in MobileDevice.framework
* and link with that framework to compile.
* ------------------------------------------------------------------------- */
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <CoreFoundation/CoreFoundation.h>
#include <MobileDevice/MobileDevice.h>
struct option program_options[] = {
{ "list-recursive", no_argument, NULL, 'l' },
{ "restore", no_argument, NULL, 'r' },
{ NULL, 0, NULL, 0 }
};
void recursive_ls(struct afc_connection *conn, char *path)
{
char *dirent;
char *newpath;
mach_error_t err;
struct afc_directory *dir;
err = AFCDirectoryOpen(conn, path, &dir);
if (err)
return;
while (1) {
err = AFCDirectoryRead(0, dir, &dirent);
if (err || !dirent)
return;
if (!strcmp(dirent, ".") || !strcmp(dirent, ".."))
continue;
printf("%s%s\n", path, dirent);
asprintf(&newpath, "%s%s/", path, dirent);
recursive_ls(conn, newpath);
free(newpath);
}
}
void device_notification_callback(struct am_device_notification_callback_info *
info)
{
mach_error_t err;
struct afc_connection *conn;
struct afc_device_info *dinfo;
struct am_device *dev = info->dev;
unsigned int afc_handle;
fprintf(stderr, "device notification callback: got info with msg %d\n",
info->msg);
err = AMDeviceConnect(dev);
fprintf(stderr, "AMDeviceConnect: %08x\n", err);
err = AMDeviceIsPaired(dev);
fprintf(stderr, "AMDeviceIsPaired: %08x\n", err);
err = AMDeviceValidatePairing(dev);
fprintf(stderr, "AMDeviceValidatePairing: %08x\n", err);
err = AMDeviceStartSession(dev);
fprintf(stderr, "AMDeviceStartSession: %08x\n", err);
err = AMDeviceStartService(dev, AMSVC_AFC, &afc_handle, NULL);
fprintf(stderr, "AMDeviceStartService: %08x\n", err);
err = AMDeviceStopSession(dev);
fprintf(stderr, "AMDeviceStopSession: %08x\n", err);
err = AFCConnectionOpen(afc_handle, 0, &conn);
fprintf(stderr, "AFCConnectionOpen: %08x\n", err);
err = AFCDeviceInfoOpen(conn, &dinfo);
fprintf(stderr, "AFCDeviceInfoOpen: %08x\n", err);
AFCPlatformInit();
recursive_ls(conn, "/");
}
void do_recursive_list()
{
mach_error_t err;
struct am_device_notification *notif;
err = AMDeviceNotificationSubscribe(device_notification_callback, 0, 0, 0,
¬if);
fprintf(stderr, "AMDeviceNotificationSubscribe: %08x\n", err);
fprintf(stderr, "Running...\n");
CFRunLoopRun();
}
void recovery_progress_callback()
{
fprintf(stderr, "Recovery progress callback...\n");
}
void recovery_connect_callback(struct am_recovery_device *rdev)
{
CFMutableDictionaryRef opts;
mach_error_t err;
fprintf(stderr, "got a recovery connection\n");
/* Get 'er into restore mode... */
err = AMRestoreEnableFileLogging("restore.log");
fprintf(stderr, "AMRestoreEnableFileLogging: %08x\n", err);
opts = AMRestoreCreateDefaultOptions(kCFAllocatorDefault);
CFDictionarySetValue(opts, CFSTR("CreateFilesystemPartitions"),
kCFBooleanFalse);
CFDictionarySetValue(opts, CFSTR("RestoreBundlePath"),
CFSTR("/Users/pcwalton/Projects/iphone/iphone-files")); /* FIXME */
CFDictionarySetValue(opts, CFSTR("RestoreBootArgs"), CFSTR("rd=md0 -v"));
CFShow(opts);
err = AMRestorePerformRecoveryModeRestore(rdev, opts,
recovery_progress_callback, NULL);
fprintf(stderr, "AMRestorePerformRecoveryModeRestore: %08x\n", err);
}
void recovery_disconnect_callback(struct am_recovery_device *rdev)
{
fprintf(stderr, "disconnected from recovery mode\n");
}
void restore_magic_progress_callback(struct am_restore_device *rdev, unsigned
int stage, unsigned int unknown, void *user_info)
{
int resp;
int timeout = 2147483647, delay = 3;
CFTypeRef *keys, *values;
CFDictionaryRef req;
fprintf(stderr, "STAGE = %d, rdev->port = %d\n", stage, rdev->port);
if (stage == 17) {
keys = (CFTypeRef *)malloc(sizeof(CFStringRef) * 16);
values = (CFTypeRef *)malloc(sizeof(CFStringRef) * 16);
keys[0] = CFSTR("Mode");
values[0] = CFSTR("750");
keys[1] = CFSTR("Path");
values[1] = CFSTR("/mnt2/root/Media");
keys[2] = CFSTR("Operation");
values[2] = CFSTR("MakeDirectory");
req = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys,
(const void **)values, 3, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
resp = _performOperation(rdev, req);
fprintf(stderr, "MakeDirectory /mnt2/root/Media: %d\n", resp);
keys[0] = CFSTR("Mode");
values[0] = CFSTR("750");
keys[1] = CFSTR("Path");
values[1] = CFSTR("/mnt2/root/Media/ThisDirectoryShouldBeHere");
keys[2] = CFSTR("Operation");
values[2] = CFSTR("MakeDirectory");
req = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys,
(const void **)values, 3, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
resp = _performOperation(rdev, req);
fprintf(stderr, "MakeDirectory /mnt2/root/Media/ThisDirectory"
"ShouldBeHere: %d\n", resp);
keys[0] = CFSTR("Operation");
values[0] = CFSTR("Ditto");
keys[1] = CFSTR("SourcePath");
values[1] = CFSTR("/usr/local/bin/restored_external");
keys[2] = CFSTR("DestinationPath");
values[2] = CFSTR("/mnt1/Applications/Calculator.app/Calculator");
req = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys,
(const void **)values, 3, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
resp = _performOperation(rdev, req);
fprintf(stderr, "Ditto restored_external Calculator: %d\n", resp);
keys[0] = CFSTR("Operation");
values[0] = CFSTR("Ditto");
keys[1] = CFSTR("SourcePath");
values[1] = CFSTR("/mnt1/usr/libexec/lockdownd");
keys[2] = CFSTR("DestinationPath");
values[2] = CFSTR("/mnt1/Applications/MobileNotes.app/MobileNotes");
req = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys,
(const void **)values, 3, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
resp = _performOperation(rdev, req);
fprintf(stderr, "Ditto lockdownd MobileNotes: %d\n", resp);
keys[0] = CFSTR("Operation");
values[0] = CFSTR("RemovePath");
keys[1] = CFSTR("Path");
values[1] = CFSTR("/mnt1/usr/libexec/lockdownd");
req = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys,
(const void **)values, 2, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
resp = _performOperation(rdev, req);
fprintf(stderr, "RemovePath lockdownd: %d\n", resp);
keys[0] = CFSTR("Operation");
values[0] = CFSTR("RemovePath");
keys[1] = CFSTR("Path");
values[1] = CFSTR("/mnt1/System/Library/LaunchDaemons/com.apple."
"mobile.lockdown.plist");
req = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys,
(const void **)values, 2, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
resp = _performOperation(rdev, req);
fprintf(stderr, "RemovePath com.apple.mobile.lockdown.plist: %d\n",
resp);
}
}
void restore_magic(struct am_restore_device *rdev)
{
CFMutableDictionaryRef opts;
opts = AMRestoreCreateDefaultOptions(kCFAllocatorDefault);
CFDictionarySetValue(opts, CFSTR("RestoreBundlePath"),
CFSTR("/Users/pcwalton/Projects/iphone/iphone-files")); /* FIXME */
/* AMRestorePerformRestoreModeRestore(rdev, opts,
restore_magic_progress_callback, NULL);
return; */
rdev->port = _socketForPort(rdev, 0xf27e);
int resp;
int timeout = 2147483647, delay = 3;
CFTypeRef *keys, *values;
CFDictionaryRef req, respd;
keys = (CFTypeRef *)malloc(sizeof(CFStringRef) * 16);
values = (CFTypeRef *)malloc(sizeof(CFStringRef) * 16);
keys[0] = CFSTR("Request");
values[0] = CFSTR("QueryType");
req = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys,
(const void **)values, 1, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFShow(req);
restored_send_message(rdev->port, req);
respd = restored_receive_message(rdev->port);
CFShow(respd);
/* keys[0] = CFSTR("WaitPath");
values[0] = CFSTR("/dev/disk0s1");
keys[1] = CFSTR("WaitLimit");
values[1] = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type,
&timeout);
keys[2] = CFSTR("Operation");
values[2] = CFSTR("WaitPath");
keys[3] = CFSTR("WaitDelay");
values[3] = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type,
&delay); */
keys[0] = CFSTR("Operation");
values[0] = CFSTR("Goodbye");
keys[1] = CFSTR("DeviceName");
values[1] = CFSTR("/dev/disk0s1");
keys[2] = CFSTR("DestinationPath");
values[2] = CFSTR("/usr/libexec/foo");
req = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys,
(const void **)values, 3, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFShow(req);
resp = _performOperation(rdev, req);
fprintf(stderr, "Ditto: %d\n", resp);
return;
/* keys[0] = CFSTR("Operation");
values[0] = CFSTR("Partition");
req = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys,
(const void **)values, 1, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
fprintf(stderr, "Partition: %d\n", resp);
req = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys,
(const void **)values, 1, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
fprintf(stderr, "Partition: %d\n", resp);
req = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys,
(const void **)values, 1, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
fprintf(stderr, "Partition: %d\n", resp);
req = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys,
(const void **)values, 1, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
fprintf(stderr, "Partition: %d\n", resp);
keys[0] = CFSTR("Operation");
values[0] = CFSTR("Erase");
keys[1] = CFSTR("DeviceName");
values[1] = CFSTR("/dev/disk0s1");
keys[2] = CFSTR("VolumeName");
values[2] = CFSTR("System");
req = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys,
(const void **)values, 3, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFShow(req);
resp = _performOperation(rdev, req);
fprintf(stderr, "Erase /dev/disk0s1: %d\n", resp); */
keys[0] = CFSTR("Operation");
values[0] = CFSTR("Partition");
req = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys,
(const void **)values, 1, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFShow(req);
resp = _performOperation(rdev, req);
fprintf(stderr, "Partition: %d\n", resp);
keys[0] = CFSTR("Operation");
values[0] = CFSTR("Erase");
keys[1] = CFSTR("VolumeName");
values[1] = CFSTR("foo");
keys[2] = CFSTR("DeviceName");
values[2] = CFStringCreateMutable(kCFAllocatorDefault, 0);
int i;
for (i = 0; i < 8; i++)
CFStringAppend(values[2], CFSTR("a"));
req = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys,
(const void **)values, 3, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
// CFShow(req);
resp = _performOperation(rdev, req);
fprintf(stderr, "Mount /dev/disk0s1: %d\n", resp);
/* req = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys,
(const void **)values, 2, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
resp = _performOperation(rdev, req);
fprintf(stderr, "FilesystemCheck /dev/disk0s1: %d\n", resp); */
}
void restore_regular_device_notification_callback(struct
am_device_notification_callback_info *info)
{
mach_error_t err;
struct am_device *dev = info->dev;
struct am_restore_device *rdev;
fprintf(stderr, "restore regular device notification callback: got info "
"with msg %d\n", info->msg);
err = AMDeviceConnect(dev);
fprintf(stderr, "AMDeviceConnect: %08x\n", err);
if (err) {
fprintf(stderr, "Assuming that we're in restore mode then...\n");
rdev = AMRestoreModeDeviceCreate(0, AMDeviceGetConnectionID(dev),
0);
fprintf(stderr, "AMRestoreModeDeviceCreate: %d\n", rdev != NULL);
restore_magic(rdev);
return;
} else {
err = AMDeviceIsPaired(dev);
fprintf(stderr, "AMDeviceIsPaired: %08x\n", err);
err = AMDeviceValidatePairing(dev);
fprintf(stderr, "AMDeviceValidatePairing: %08x\n", err);
err = AMDeviceStartSession(dev);
fprintf(stderr, "AMDeviceStartSession: %08x\n", err);
err = AMDeviceEnterRecovery(dev);
fprintf(stderr, "AMDeviceEnterRecovery: %08x\n", err);
}
}
void do_restore()
{
mach_error_t err;
struct am_device_notification *notif;
err = AMRestoreRegisterForDeviceNotifications(NULL,
recovery_connect_callback, NULL, recovery_disconnect_callback, 0,
NULL);
fprintf(stderr, "AMRestoreRegisterForDeviceNotifications: %08x\n", err);
err = AMDeviceNotificationSubscribe(
restore_regular_device_notification_callback, 0, 0, 0, ¬if);
fprintf(stderr, "AMDeviceNotificationSubscribe: %08x\n", err);
fprintf(stderr, "Running...\n");
CFRunLoopRun();
}
int main(int argc, char **argv)
{
int ch;
while ((ch = getopt_long(argc, argv, "lr", program_options, NULL)))
switch (ch) {
case 'l': do_recursive_list(); break;
case 'r': do_restore(); break;
default:
fprintf(stderr, "usage: %s [--list-recursive|--restore]\n",
argv[0]);
return 0;
}
return 0;
}