rendered paste body#include <stdio.h>
#include <stdlib.h>
#include <readline/history.h>
#include <readline/readline.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <CoreFoundation/CoreFoundation.h>
#include <MobileDevice/MobileDevice.h>
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;
}