#include #include #include #include #include #include #include #include void put_file(struct afc_connection *conn, char *local_path, char *remote_path) { FILE *f; struct stat sb; unsigned char *buf; unsigned int size; afc_file_ref ref; f = fopen(local_path, "r"); if (!f) { printf("failed to open local file\n"); return; } size = fstat(fileno(f), &sb); buf = (unsigned char *)malloc(sb.st_size); fread(buf, sb.st_size, 1, f); fclose(f); if (AFCFileRefOpen(conn, remote_path, 3, 0, &ref)) { printf("failed to open remote file\n"); return; } if (AFCFileRefWrite(conn, ref, buf, sb.st_size)) { printf("failed to write to remote file\n"); return; } if (AFCFileRefClose(conn, ref)) { printf("failed to close remote file\n"); return; } free(buf); printf("put command successful\n"); } unsigned int get_file_size(struct afc_connection *conn, char *path) { char *key, *val; unsigned int size; struct afc_dictionary *info; if (AFCFileInfoOpen(conn, path, &info)) return 0; while (1) { AFCKeyValueRead(info, &key, &val); if (!key || !val) break; if (!strcmp(key, "st_size")) { sscanf(val, "%u", &size); AFCKeyValueClose(info); return size; } } AFCKeyValueClose(info); return 0; } void get_file(struct afc_connection *conn, char *local_path, char *remote_path) { FILE *f; unsigned char *buf; unsigned int size = get_file_size(conn, remote_path); afc_file_ref ref; if (AFCFileRefOpen(conn, remote_path, 2, 0, &ref)) { printf("failed to open remote file\n"); return; } buf = (unsigned char *)malloc(size); if (AFCFileRefRead(conn, ref, buf, &size)) { printf("failed to read from file\n"); return; } if (AFCFileRefClose(conn, ref)) { printf("failed to close remote file\n"); return; } f = fopen(local_path, "w"); if (!f) { printf("failed to open local file\n"); return; } fwrite(buf, size, 1, f); fclose(f); free(buf); printf("transfer successful\n"); } void run_afc(struct am_device *dev, unsigned int afch) { char *line, *path, *tok, *dirent; struct afc_connection *conn; struct afc_directory *dir; AFCConnectionOpen(afch, 0, &conn); AFCPlatformInit(); fprintf(stderr, "done.\n"); path = strdup("/"); while (1) { line = readline("(afc) "); if (!line) break; if (!(line[0])) continue; add_history(line); tok = strsep(&line, " "); if (!strcmp(tok, "pwd")) printf("%s\n", path); else if (!strcmp(tok, "cd")) { if (AFCDirectoryOpen(conn, line, &dir)) printf("Failed.\n"); free(path); path = strdup(line); } else if (!strcmp(tok, "ls")) { if (AFCDirectoryOpen(conn, path, &dir)) { printf("Failed.\n"); continue; } while (1) { AFCDirectoryRead(0, dir, &dirent); if (!dirent) break; printf("%s\n", dirent); } AFCDirectoryClose(0, dir); } else if (!strcmp(tok, "exit")) { AFCConnectionClose(conn); exit(0); } else if (!strcmp(tok, "put")) { tok = strsep(&line, " "); put_file(conn, tok, line); } else if (!strcmp(tok, "get")) { tok = strsep(&line, " "); get_file(conn, line, tok); } else if (!strcmp(tok, "size")) { printf("%u\n", get_file_size(conn, line)); } else printf("Unknown command '%s'.\n", tok); } } void notification(struct am_device_notification_callback_info *info) { struct am_device *dev = info->dev; unsigned int afch; unsigned int msg = info->msg; if (msg != 1) return; fprintf(stderr, "iPhone attached. Connecting...\n"); AMDeviceConnect(dev); AMDeviceIsPaired(dev); AMDeviceValidatePairing(dev); AMDeviceStartSession(dev); AMDeviceStartService(dev, AMSVC_AFC, &afch, NULL); AMDeviceStopSession(dev); run_afc(dev, afch); } int main() { struct am_device_notification *notif; AMDeviceNotificationSubscribe(notification, 0, 0, 0, ¬if); fprintf(stderr, "Please connect an iPhone in normal mode.\n"); CFRunLoopRun(); return 0; }