All pastes #605161 Raw Edit

Anonymous

public text v1 · immutable
·published 2007-07-06 00:07 UTC
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,
        &notif);
    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, &notif);
    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;
}