summaryrefslogtreecommitdiffstats
path: root/src/afc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/afc.c')
-rw-r--r--src/afc.c485
1 files changed, 322 insertions, 163 deletions
diff --git a/src/afc.c b/src/afc.c
index d83b50d..1b4070b 100644
--- a/src/afc.c
+++ b/src/afc.c
@@ -29,8 +29,8 @@
#include <unistd.h>
#include <string.h>
-#include "afc.h"
#include "idevice.h"
+#include "afc.h"
#include "common/debug.h"
#include "endianness.h"
@@ -68,7 +68,7 @@ static void afc_unlock(afc_client_t client)
* invalid, or AFC_E_NO_MEM if there is a memory allocation problem.
*/
-LIBIMOBILEDEVICE_API afc_error_t afc_client_new_with_service_client(service_client_t service_client, afc_client_t *client)
+afc_error_t afc_client_new_with_service_client(service_client_t service_client, afc_client_t *client)
{
if (!service_client)
return AFC_E_INVALID_ARG;
@@ -78,25 +78,23 @@ LIBIMOBILEDEVICE_API afc_error_t afc_client_new_with_service_client(service_clie
client_loc->free_parent = 0;
/* allocate a packet */
- client_loc->afc_packet = (AFCPacket *) malloc(sizeof(AFCPacket));
+ client_loc->packet_extra = 1024;
+ client_loc->afc_packet = (AFCPacket *) malloc(sizeof(AFCPacket) + client_loc->packet_extra);
if (!client_loc->afc_packet) {
free(client_loc);
return AFC_E_NO_MEM;
}
-
client_loc->afc_packet->packet_num = 0;
client_loc->afc_packet->entire_length = 0;
client_loc->afc_packet->this_length = 0;
memcpy(client_loc->afc_packet->magic, AFC_MAGIC, AFC_MAGIC_LEN);
- client_loc->file_handle = 0;
- client_loc->lock = 0;
mutex_init(&client_loc->mutex);
*client = client_loc;
return AFC_E_SUCCESS;
}
-LIBIMOBILEDEVICE_API afc_error_t afc_client_new(idevice_t device, lockdownd_service_descriptor_t service, afc_client_t * client)
+afc_error_t afc_client_new(idevice_t device, lockdownd_service_descriptor_t service, afc_client_t * client)
{
if (!device || !service || service->port == 0)
return AFC_E_INVALID_ARG;
@@ -115,14 +113,14 @@ LIBIMOBILEDEVICE_API afc_error_t afc_client_new(idevice_t device, lockdownd_serv
return err;
}
-LIBIMOBILEDEVICE_API afc_error_t afc_client_start_service(idevice_t device, afc_client_t * client, const char* label)
+afc_error_t afc_client_start_service(idevice_t device, afc_client_t * client, const char* label)
{
afc_error_t err = AFC_E_UNKNOWN_ERROR;
service_client_factory_start_service(device, AFC_SERVICE_NAME, (void**)client, label, SERVICE_CONSTRUCTOR(afc_client_new), &err);
return err;
}
-LIBIMOBILEDEVICE_API afc_error_t afc_client_free(afc_client_t client)
+afc_error_t afc_client_free(afc_client_t client)
{
if (!client || !client->afc_packet)
return AFC_E_INVALID_ARG;
@@ -150,7 +148,7 @@ LIBIMOBILEDEVICE_API afc_error_t afc_client_free(afc_client_t client)
*
* @return AFC_E_SUCCESS on success or an AFC_E_* error value.
*/
-static afc_error_t afc_dispatch_packet(afc_client_t client, uint64_t operation, const char *data, uint32_t data_length, const char* payload, uint32_t payload_length, uint32_t *bytes_sent)
+static afc_error_t afc_dispatch_packet(afc_client_t client, uint64_t operation, uint32_t data_length, const char* payload, uint32_t payload_length, uint32_t *bytes_sent)
{
uint32_t sent = 0;
@@ -159,8 +157,6 @@ static afc_error_t afc_dispatch_packet(afc_client_t client, uint64_t operation,
*bytes_sent = 0;
- if (!data || !data_length)
- data_length = 0;
if (!payload || !payload_length)
payload_length = 0;
@@ -171,34 +167,26 @@ static afc_error_t afc_dispatch_packet(afc_client_t client, uint64_t operation,
debug_info("packet length = %i", client->afc_packet->this_length);
- debug_buffer((char*)client->afc_packet, sizeof(AFCPacket));
-
- /* send AFC packet header */
+ /* send AFC packet header and data */
AFCPacket_to_LE(client->afc_packet);
+ debug_buffer((char*)client->afc_packet, sizeof(AFCPacket) + data_length);
sent = 0;
- service_send(client->parent, (void*)client->afc_packet, sizeof(AFCPacket), &sent);
+ service_send(client->parent, (void*)client->afc_packet, sizeof(AFCPacket) + data_length, &sent);
AFCPacket_from_LE(client->afc_packet);
*bytes_sent += sent;
- if (sent < sizeof(AFCPacket)) {
- return AFC_E_SUCCESS;
- }
-
- /* send AFC packet data (if there's data to send) */
- sent = 0;
- if (data_length > 0) {
- debug_info("packet data follows");
- debug_buffer(data, data_length);
- service_send(client->parent, data, data_length, &sent);
- }
- *bytes_sent += sent;
- if (sent < data_length) {
+ if (sent < sizeof(AFCPacket) + data_length) {
return AFC_E_SUCCESS;
}
sent = 0;
if (payload_length > 0) {
- debug_info("packet payload follows");
- debug_buffer(payload, payload_length);
+ if (payload_length > 256) {
+ debug_info("packet payload follows (256/%u)", payload_length);
+ debug_buffer(payload, 256);
+ } else {
+ debug_info("packet payload follows");
+ debug_buffer(payload, payload_length);
+ }
service_send(client->parent, payload, payload_length, &sent);
}
*bytes_sent += sent;
@@ -225,7 +213,8 @@ static afc_error_t afc_receive_data(afc_client_t client, char **bytes, uint32_t
uint32_t this_len = 0;
uint32_t current_count = 0;
uint64_t param1 = -1;
- char* dump_here = NULL;
+ char *buf = NULL;
+ uint32_t recv_len = 0;
if (bytes_recv) {
*bytes_recv = 0;
@@ -235,18 +224,20 @@ static afc_error_t afc_receive_data(afc_client_t client, char **bytes, uint32_t
}
/* first, read the AFC header */
- service_receive(client->parent, (char*)&header, sizeof(AFCPacket), bytes_recv);
+ service_receive(client->parent, (char*)&header, sizeof(AFCPacket), &recv_len);
AFCPacket_from_LE(&header);
- if (*bytes_recv == 0) {
+ if (recv_len == 0) {
debug_info("Just didn't get enough.");
return AFC_E_MUX_ERROR;
- } else if (*bytes_recv < sizeof(AFCPacket)) {
+ }
+
+ if (recv_len < sizeof(AFCPacket)) {
debug_info("Did not even get the AFCPacket header");
return AFC_E_MUX_ERROR;
}
/* check if it's a valid AFC header */
- if (strncmp(header.magic, AFC_MAGIC, AFC_MAGIC_LEN)) {
+ if (strncmp(header.magic, AFC_MAGIC, AFC_MAGIC_LEN) != 0) {
debug_info("Invalid AFC packet received (magic != " AFC_MAGIC ")!");
}
@@ -261,15 +252,14 @@ static afc_error_t afc_receive_data(afc_client_t client, char **bytes, uint32_t
if (header.this_length < sizeof(AFCPacket)) {
debug_info("Invalid AFCPacket header received!");
return AFC_E_OP_HEADER_INVALID;
- } else if ((header.this_length == header.entire_length)
- && header.entire_length == sizeof(AFCPacket)) {
+ }
+ if ((header.this_length == header.entire_length)
+ && header.entire_length == sizeof(AFCPacket)) {
debug_info("Empty AFCPacket received!");
- *bytes_recv = 0;
if (header.operation == AFC_OP_DATA) {
return AFC_E_SUCCESS;
- } else {
- return AFC_E_IO_ERROR;
}
+ return AFC_E_IO_ERROR;
}
debug_info("received AFC packet, full len=%lld, this len=%lld, operation=0x%llx", header.entire_length, header.this_length, header.operation);
@@ -277,15 +267,17 @@ static afc_error_t afc_receive_data(afc_client_t client, char **bytes, uint32_t
entire_len = (uint32_t)header.entire_length - sizeof(AFCPacket);
this_len = (uint32_t)header.this_length - sizeof(AFCPacket);
- dump_here = (char*)malloc(entire_len);
+ buf = (char*)malloc(entire_len);
if (this_len > 0) {
- service_receive(client->parent, dump_here, this_len, bytes_recv);
- if (*bytes_recv <= 0) {
- free(dump_here);
+ recv_len = 0;
+ service_receive(client->parent, buf, this_len, &recv_len);
+ if (recv_len <= 0) {
+ free(buf);
debug_info("Did not get packet contents!");
return AFC_E_NOT_ENOUGH_DATA;
- } else if (*bytes_recv < this_len) {
- free(dump_here);
+ }
+ if (recv_len < this_len) {
+ free(buf);
debug_info("Could not receive this_len=%d bytes", this_len);
return AFC_E_NOT_ENOUGH_DATA;
}
@@ -295,12 +287,13 @@ static afc_error_t afc_receive_data(afc_client_t client, char **bytes, uint32_t
if (entire_len > this_len) {
while (current_count < entire_len) {
- service_receive(client->parent, dump_here+current_count, entire_len - current_count, bytes_recv);
- if (*bytes_recv <= 0) {
- debug_info("Error receiving data (recv returned %d)", *bytes_recv);
+ recv_len = 0;
+ service_receive(client->parent, buf+current_count, entire_len - current_count, &recv_len);
+ if (recv_len <= 0) {
+ debug_info("Error receiving data (recv returned %d)", recv_len);
break;
}
- current_count += *bytes_recv;
+ current_count += recv_len;
}
if (current_count < entire_len) {
debug_info("WARNING: could not receive full packet (read %s, size %d)", current_count, entire_len);
@@ -308,12 +301,17 @@ static afc_error_t afc_receive_data(afc_client_t client, char **bytes, uint32_t
}
if (current_count >= sizeof(uint64_t)) {
- param1 = le64toh(*(uint64_t*)(dump_here));
+ param1 = le64toh(*(uint64_t*)(buf));
}
debug_info("packet data size = %i", current_count);
- debug_info("packet data follows");
- debug_buffer(dump_here, current_count);
+ if (current_count > 256) {
+ debug_info("packet data follows (256/%u)", current_count);
+ debug_buffer(buf, 256);
+ } else {
+ debug_info("packet data follows");
+ debug_buffer(buf, current_count);
+ }
/* check operation types */
if (header.operation == AFC_OP_STATUS) {
@@ -323,7 +321,7 @@ static afc_error_t afc_receive_data(afc_client_t client, char **bytes, uint32_t
if (param1 != AFC_E_SUCCESS) {
/* error status */
/* free buffer */
- free(dump_here);
+ free(buf);
return (afc_error_t)param1;
}
} else if (header.operation == AFC_OP_DATA) {
@@ -337,8 +335,7 @@ static afc_error_t afc_receive_data(afc_client_t client, char **bytes, uint32_t
debug_info("got a tell response, position=%lld", param1);
} else {
/* unknown operation code received */
- free(dump_here);
- *bytes_recv = 0;
+ free(buf);
debug_info("WARNING: Unknown operation code received 0x%llx param1=%lld", header.operation, param1);
#ifndef WIN32
@@ -349,9 +346,9 @@ static afc_error_t afc_receive_data(afc_client_t client, char **bytes, uint32_t
}
if (bytes) {
- *bytes = dump_here;
+ *bytes = buf;
} else {
- free(dump_here);
+ free(buf);
}
*bytes_recv = current_count;
@@ -361,7 +358,7 @@ static afc_error_t afc_receive_data(afc_client_t client, char **bytes, uint32_t
/**
* Returns counts of null characters within a string.
*/
-static uint32_t count_nullspaces(char *string, uint32_t number)
+static uint32_t count_nullspaces(const char *string, uint32_t number)
{
uint32_t i = 0, nulls = 0;
@@ -402,7 +399,22 @@ static char **make_strings_list(char *tokens, uint32_t length)
return list;
}
-LIBIMOBILEDEVICE_API afc_error_t afc_read_directory(afc_client_t client, const char *path, char ***directory_information)
+static int _afc_check_packet_buffer(afc_client_t client, uint32_t data_len)
+{
+ if (data_len > client->packet_extra) {
+ client->packet_extra = (data_len & ~8) + 8;
+ AFCPacket* newpkt = (AFCPacket*)realloc(client->afc_packet, sizeof(AFCPacket) + client->packet_extra);
+ if (!newpkt) {
+ return -1;
+ }
+ client->afc_packet = newpkt;
+ }
+ return 0;
+}
+
+#define AFC_PACKET_DATA_PTR ((char*)client->afc_packet + sizeof(AFCPacket))
+
+afc_error_t afc_read_directory(afc_client_t client, const char *path, char ***directory_information)
{
uint32_t bytes = 0;
char *data = NULL, **list_loc = NULL;
@@ -413,8 +425,16 @@ LIBIMOBILEDEVICE_API afc_error_t afc_read_directory(afc_client_t client, const c
afc_lock(client);
+ uint32_t data_len = (uint32_t)strlen(path)+1;
+ if (_afc_check_packet_buffer(client, data_len) < 0) {
+ afc_unlock(client);
+ debug_info("Failed to realloc packet buffer");
+ return AFC_E_NO_MEM;
+ }
+
/* Send the command */
- ret = afc_dispatch_packet(client, AFC_OP_READ_DIR, path, strlen(path)+1, NULL, 0, &bytes);
+ memcpy(AFC_PACKET_DATA_PTR, path, data_len);
+ ret = afc_dispatch_packet(client, AFC_OP_READ_DIR, data_len, NULL, 0, &bytes);
if (ret != AFC_E_SUCCESS) {
afc_unlock(client);
return AFC_E_NOT_ENOUGH_DATA;
@@ -438,7 +458,7 @@ LIBIMOBILEDEVICE_API afc_error_t afc_read_directory(afc_client_t client, const c
return ret;
}
-LIBIMOBILEDEVICE_API afc_error_t afc_get_device_info(afc_client_t client, char ***device_information)
+afc_error_t afc_get_device_info(afc_client_t client, char ***device_information)
{
uint32_t bytes = 0;
char *data = NULL, **list = NULL;
@@ -450,7 +470,7 @@ LIBIMOBILEDEVICE_API afc_error_t afc_get_device_info(afc_client_t client, char *
afc_lock(client);
/* Send the command */
- ret = afc_dispatch_packet(client, AFC_OP_GET_DEVINFO, NULL, 0, NULL, 0, &bytes);
+ ret = afc_dispatch_packet(client, AFC_OP_GET_DEVINFO, 0, NULL, 0, &bytes);
if (ret != AFC_E_SUCCESS) {
afc_unlock(client);
return AFC_E_NOT_ENOUGH_DATA;
@@ -475,7 +495,7 @@ LIBIMOBILEDEVICE_API afc_error_t afc_get_device_info(afc_client_t client, char *
return ret;
}
-LIBIMOBILEDEVICE_API afc_error_t afc_get_device_info_key(afc_client_t client, const char *key, char **value)
+afc_error_t afc_get_device_info_key(afc_client_t client, const char *key, char **value)
{
afc_error_t ret = AFC_E_INTERNAL_ERROR;
char **kvps, **ptr;
@@ -502,7 +522,7 @@ LIBIMOBILEDEVICE_API afc_error_t afc_get_device_info_key(afc_client_t client, co
return ret;
}
-LIBIMOBILEDEVICE_API afc_error_t afc_remove_path(afc_client_t client, const char *path)
+afc_error_t afc_remove_path(afc_client_t client, const char *path)
{
uint32_t bytes = 0;
afc_error_t ret = AFC_E_UNKNOWN_ERROR;
@@ -512,8 +532,16 @@ LIBIMOBILEDEVICE_API afc_error_t afc_remove_path(afc_client_t client, const char
afc_lock(client);
+ uint32_t data_len = (uint32_t)strlen(path)+1;
+ if (_afc_check_packet_buffer(client, data_len) < 0) {
+ afc_unlock(client);
+ debug_info("Failed to realloc packet buffer");
+ return AFC_E_NO_MEM;
+ }
+
/* Send command */
- ret = afc_dispatch_packet(client, AFC_OP_REMOVE_PATH, path, strlen(path)+1, NULL, 0, &bytes);
+ memcpy(AFC_PACKET_DATA_PTR, path, data_len);
+ ret = afc_dispatch_packet(client, AFC_OP_REMOVE_PATH, data_len, NULL, 0, &bytes);
if (ret != AFC_E_SUCCESS) {
afc_unlock(client);
return AFC_E_NOT_ENOUGH_DATA;
@@ -530,23 +558,30 @@ LIBIMOBILEDEVICE_API afc_error_t afc_remove_path(afc_client_t client, const char
return ret;
}
-LIBIMOBILEDEVICE_API afc_error_t afc_rename_path(afc_client_t client, const char *from, const char *to)
+afc_error_t afc_rename_path(afc_client_t client, const char *from, const char *to)
{
if (!client || !from || !to || !client->afc_packet || !client->parent)
return AFC_E_INVALID_ARG;
- char *buffer = (char *) malloc(sizeof(char) * (strlen(from) + strlen(to) + 1 + sizeof(uint32_t)));
uint32_t bytes = 0;
afc_error_t ret = AFC_E_UNKNOWN_ERROR;
+ size_t from_len = strlen(from);
+ size_t to_len = strlen(to);
+
afc_lock(client);
- /* Send command */
- memcpy(buffer, from, strlen(from) + 1);
- memcpy(buffer + strlen(from) + 1, to, strlen(to) + 1);
- ret = afc_dispatch_packet(client, AFC_OP_RENAME_PATH, buffer, strlen(to)+1 + strlen(from)+1, NULL, 0, &bytes);
- free(buffer);
+ uint32_t data_len = (uint32_t)(from_len+1 + to_len+1);
+ if (_afc_check_packet_buffer(client, data_len) < 0) {
+ afc_unlock(client);
+ debug_info("Failed to realloc packet buffer");
+ return AFC_E_NO_MEM;
+ }
+ /* Send command */
+ memcpy(AFC_PACKET_DATA_PTR, from, from_len+1);
+ memcpy(AFC_PACKET_DATA_PTR + from_len+1, to, to_len+1);
+ ret = afc_dispatch_packet(client, AFC_OP_RENAME_PATH, data_len, NULL, 0, &bytes);
if (ret != AFC_E_SUCCESS) {
afc_unlock(client);
return AFC_E_NOT_ENOUGH_DATA;
@@ -559,7 +594,7 @@ LIBIMOBILEDEVICE_API afc_error_t afc_rename_path(afc_client_t client, const char
return ret;
}
-LIBIMOBILEDEVICE_API afc_error_t afc_make_directory(afc_client_t client, const char *path)
+afc_error_t afc_make_directory(afc_client_t client, const char *path)
{
uint32_t bytes = 0;
afc_error_t ret = AFC_E_UNKNOWN_ERROR;
@@ -569,8 +604,16 @@ LIBIMOBILEDEVICE_API afc_error_t afc_make_directory(afc_client_t client, const c
afc_lock(client);
+ uint32_t data_len = (uint32_t)strlen(path)+1;
+ if (_afc_check_packet_buffer(client, data_len) < 0) {
+ afc_unlock(client);
+ debug_info("Failed to realloc packet buffer");
+ return AFC_E_NO_MEM;
+ }
+
/* Send command */
- ret = afc_dispatch_packet(client, AFC_OP_MAKE_DIR, path, strlen(path)+1, NULL, 0, &bytes);
+ memcpy(AFC_PACKET_DATA_PTR, path, data_len);
+ ret = afc_dispatch_packet(client, AFC_OP_MAKE_DIR, data_len, NULL, 0, &bytes);
if (ret != AFC_E_SUCCESS) {
afc_unlock(client);
return AFC_E_NOT_ENOUGH_DATA;
@@ -583,7 +626,7 @@ LIBIMOBILEDEVICE_API afc_error_t afc_make_directory(afc_client_t client, const c
return ret;
}
-LIBIMOBILEDEVICE_API afc_error_t afc_get_file_info(afc_client_t client, const char *path, char ***file_information)
+afc_error_t afc_get_file_info(afc_client_t client, const char *path, char ***file_information)
{
char *received = NULL;
uint32_t bytes = 0;
@@ -594,8 +637,18 @@ LIBIMOBILEDEVICE_API afc_error_t afc_get_file_info(afc_client_t client, const ch
afc_lock(client);
+ uint32_t data_len = (uint32_t)strlen(path)+1;
+ if (_afc_check_packet_buffer(client, data_len) < 0) {
+ afc_unlock(client);
+ debug_info("Failed to realloc packet buffer");
+ return AFC_E_NO_MEM;
+ }
+
+ debug_info("We got %p and %p", client->afc_packet, AFC_PACKET_DATA_PTR);
+
/* Send command */
- ret = afc_dispatch_packet(client, AFC_OP_GET_FILE_INFO, path, strlen(path)+1, NULL, 0, &bytes);
+ memcpy(AFC_PACKET_DATA_PTR, path, data_len);
+ ret = afc_dispatch_packet(client, AFC_OP_GET_FILE_INFO, data_len, NULL, 0, &bytes);
if (ret != AFC_E_SUCCESS) {
afc_unlock(client);
return AFC_E_NOT_ENOUGH_DATA;
@@ -613,14 +666,13 @@ LIBIMOBILEDEVICE_API afc_error_t afc_get_file_info(afc_client_t client, const ch
return ret;
}
-LIBIMOBILEDEVICE_API afc_error_t afc_file_open(afc_client_t client, const char *filename, afc_file_mode_t file_mode, uint64_t *handle)
+afc_error_t afc_file_open(afc_client_t client, const char *filename, afc_file_mode_t file_mode, uint64_t *handle)
{
if (!client || !client->parent || !client->afc_packet)
return AFC_E_INVALID_ARG;
- uint64_t file_mode_loc = htole64(file_mode);
+ //uint64_t file_mode_loc = htole64(file_mode);
uint32_t bytes = 0;
- char *data = (char *) malloc(sizeof(char) * (8 + strlen(filename) + 1));
afc_error_t ret = AFC_E_UNKNOWN_ERROR;
/* set handle to 0 so in case an error occurs, the handle is invalid */
@@ -628,20 +680,25 @@ LIBIMOBILEDEVICE_API afc_error_t afc_file_open(afc_client_t client, const char *
afc_lock(client);
- /* Send command */
- memcpy(data, &file_mode_loc, 8);
- memcpy(data + 8, filename, strlen(filename));
- data[8 + strlen(filename)] = '\0';
- ret = afc_dispatch_packet(client, AFC_OP_FILE_OPEN, data, 8 + strlen(filename) + 1, NULL, 0, &bytes);
- free(data);
+ uint32_t data_len = (uint32_t)(strlen(filename)+1 + 8);
+ if (_afc_check_packet_buffer(client, data_len) < 0) {
+ afc_unlock(client);
+ debug_info("Failed to realloc packet buffer");
+ return AFC_E_NO_MEM;
+ }
+ /* Send command */
+ //memcpy(AFC_PACKET_DATA_PTR, &file_mode_loc, 8);
+ *(uint64_t*)(AFC_PACKET_DATA_PTR) = htole64(file_mode);
+ memcpy(AFC_PACKET_DATA_PTR + 8, filename, data_len-8);
+ ret = afc_dispatch_packet(client, AFC_OP_FILE_OPEN, data_len, NULL, 0, &bytes);
if (ret != AFC_E_SUCCESS) {
debug_info("Didn't receive a response to the command");
afc_unlock(client);
return AFC_E_NOT_ENOUGH_DATA;
}
/* Receive the data */
- data = NULL;
+ char* data = NULL;
ret = afc_receive_data(client, &data, &bytes);
if ((ret == AFC_E_SUCCESS) && (bytes > 0) && data) {
afc_unlock(client);
@@ -661,27 +718,29 @@ LIBIMOBILEDEVICE_API afc_error_t afc_file_open(afc_client_t client, const char *
return ret;
}
-LIBIMOBILEDEVICE_API afc_error_t afc_file_read(afc_client_t client, uint64_t handle, char *data, uint32_t length, uint32_t *bytes_read)
+afc_error_t afc_file_read(afc_client_t client, uint64_t handle, char *data, uint32_t length, uint32_t *bytes_read)
{
char *input = NULL;
uint32_t current_count = 0, bytes_loc = 0;
+ struct readinfo {
+ uint64_t handle;
+ uint64_t size;
+ };
afc_error_t ret = AFC_E_SUCCESS;
if (!client || !client->afc_packet || !client->parent || handle == 0)
return AFC_E_INVALID_ARG;
debug_info("called for length %i", length);
+ //uint32_t data_len = 8 + 8;
+
afc_lock(client);
/* Send the read command */
- struct {
- uint64_t handle;
- uint64_t size;
- } readinfo;
- readinfo.handle = handle;
- readinfo.size = htole64(length);
- ret = afc_dispatch_packet(client, AFC_OP_FILE_READ, (const char*)&readinfo, sizeof(readinfo), NULL, 0, &bytes_loc);
-
+ struct readinfo* readinfo = (struct readinfo*)(AFC_PACKET_DATA_PTR);
+ readinfo->handle = handle;
+ readinfo->size = htole64(length);
+ ret = afc_dispatch_packet(client, AFC_OP_FILE_READ, sizeof(struct readinfo), NULL, 0, &bytes_loc);
if (ret != AFC_E_SUCCESS) {
afc_unlock(client);
return AFC_E_NOT_ENOUGH_DATA;
@@ -693,28 +752,29 @@ LIBIMOBILEDEVICE_API afc_error_t afc_file_read(afc_client_t client, uint64_t han
if (ret != AFC_E_SUCCESS) {
afc_unlock(client);
return ret;
- } else if (bytes_loc == 0) {
+ }
+ if (bytes_loc == 0) {
if (input)
free(input);
afc_unlock(client);
*bytes_read = current_count;
/* FIXME: check that's actually a success */
return ret;
- } else {
- if (input) {
- debug_info("%d", bytes_loc);
- memcpy(data + current_count, input, (bytes_loc > length) ? length : bytes_loc);
- free(input);
- input = NULL;
- current_count += (bytes_loc > length) ? length : bytes_loc;
- }
}
+ if (input) {
+ debug_info("%d", bytes_loc);
+ memcpy(data + current_count, input, (bytes_loc > length) ? length : bytes_loc);
+ free(input);
+ input = NULL;
+ current_count += (bytes_loc > length) ? length : bytes_loc;
+ }
+
afc_unlock(client);
*bytes_read = current_count;
return ret;
}
-LIBIMOBILEDEVICE_API afc_error_t afc_file_write(afc_client_t client, uint64_t handle, const char *data, uint32_t length, uint32_t *bytes_written)
+afc_error_t afc_file_write(afc_client_t client, uint64_t handle, const char *data, uint32_t length, uint32_t *bytes_written)
{
uint32_t current_count = 0;
uint32_t bytes_loc = 0;
@@ -723,11 +783,14 @@ LIBIMOBILEDEVICE_API afc_error_t afc_file_write(afc_client_t client, uint64_t ha
if (!client || !client->afc_packet || !client->parent || !bytes_written || (handle == 0))
return AFC_E_INVALID_ARG;
+ uint32_t data_len = 8;
+
afc_lock(client);
debug_info("Write length: %i", length);
- ret = afc_dispatch_packet(client, AFC_OP_FILE_WRITE, (const char*)&handle, 8, data, length, &bytes_loc);
+ *(uint64_t*)(AFC_PACKET_DATA_PTR) = handle;
+ ret = afc_dispatch_packet(client, AFC_OP_FILE_WRITE, data_len, data, length, &bytes_loc);
current_count += bytes_loc - (sizeof(AFCPacket) + 8);
@@ -740,13 +803,13 @@ LIBIMOBILEDEVICE_API afc_error_t afc_file_write(afc_client_t client, uint64_t ha
ret = afc_receive_data(client, NULL, &bytes_loc);
afc_unlock(client);
if (ret != AFC_E_SUCCESS) {
- debug_info("uh oh?");
+ debug_info("Failed to receive reply (%d)", ret);
}
*bytes_written = current_count;
return ret;
}
-LIBIMOBILEDEVICE_API afc_error_t afc_file_close(afc_client_t client, uint64_t handle)
+afc_error_t afc_file_close(afc_client_t client, uint64_t handle)
{
uint32_t bytes = 0;
afc_error_t ret = AFC_E_UNKNOWN_ERROR;
@@ -754,12 +817,15 @@ LIBIMOBILEDEVICE_API afc_error_t afc_file_close(afc_client_t client, uint64_t ha
if (!client || (handle == 0))
return AFC_E_INVALID_ARG;
+ uint32_t data_len = 8;
+
afc_lock(client);
debug_info("File handle %i", handle);
/* Send command */
- ret = afc_dispatch_packet(client, AFC_OP_FILE_CLOSE, (const char*)&handle, 8, NULL, 0, &bytes);
+ *(uint64_t*)(AFC_PACKET_DATA_PTR) = handle;
+ ret = afc_dispatch_packet(client, AFC_OP_FILE_CLOSE, data_len, NULL, 0, &bytes);
if (ret != AFC_E_SUCCESS) {
afc_unlock(client);
@@ -774,13 +840,13 @@ LIBIMOBILEDEVICE_API afc_error_t afc_file_close(afc_client_t client, uint64_t ha
return ret;
}
-LIBIMOBILEDEVICE_API afc_error_t afc_file_lock(afc_client_t client, uint64_t handle, afc_lock_op_t operation)
+afc_error_t afc_file_lock(afc_client_t client, uint64_t handle, afc_lock_op_t operation)
{
uint32_t bytes = 0;
- struct {
+ struct lockinfo {
uint64_t handle;
uint64_t op;
- } lockinfo;
+ };
afc_error_t ret = AFC_E_UNKNOWN_ERROR;
if (!client || (handle == 0))
@@ -791,10 +857,10 @@ LIBIMOBILEDEVICE_API afc_error_t afc_file_lock(afc_client_t client, uint64_t han
debug_info("file handle %i", handle);
/* Send command */
- lockinfo.handle = handle;
- lockinfo.op = htole64(operation);
- ret = afc_dispatch_packet(client, AFC_OP_FILE_LOCK, (const char*)&lockinfo, sizeof(lockinfo), NULL, 0, &bytes);
-
+ struct lockinfo* lockinfo = (struct lockinfo*)(AFC_PACKET_DATA_PTR);
+ lockinfo->handle = handle;
+ lockinfo->op = htole64(operation);
+ ret = afc_dispatch_packet(client, AFC_OP_FILE_LOCK, sizeof(struct lockinfo), NULL, 0, &bytes);
if (ret != AFC_E_SUCCESS) {
afc_unlock(client);
debug_info("could not send lock command");
@@ -808,14 +874,14 @@ LIBIMOBILEDEVICE_API afc_error_t afc_file_lock(afc_client_t client, uint64_t han
return ret;
}
-LIBIMOBILEDEVICE_API afc_error_t afc_file_seek(afc_client_t client, uint64_t handle, int64_t offset, int whence)
+afc_error_t afc_file_seek(afc_client_t client, uint64_t handle, int64_t offset, int whence)
{
uint32_t bytes = 0;
- struct {
+ struct seekinfo {
uint64_t handle;
uint64_t whence;
int64_t offset;
- } seekinfo;
+ };
afc_error_t ret = AFC_E_UNKNOWN_ERROR;
if (!client || (handle == 0))
@@ -824,10 +890,11 @@ LIBIMOBILEDEVICE_API afc_error_t afc_file_seek(afc_client_t client, uint64_t han
afc_lock(client);
/* Send the command */
- seekinfo.handle = handle;
- seekinfo.whence = htole64(whence);
- seekinfo.offset = (int64_t)htole64(offset);
- ret = afc_dispatch_packet(client, AFC_OP_FILE_SEEK, (const char*)&seekinfo, sizeof(seekinfo), NULL, 0, &bytes);
+ struct seekinfo* seekinfo = (struct seekinfo*)(AFC_PACKET_DATA_PTR);
+ seekinfo->handle = handle;
+ seekinfo->whence = htole64(whence);
+ seekinfo->offset = (int64_t)htole64(offset);
+ ret = afc_dispatch_packet(client, AFC_OP_FILE_SEEK, sizeof(struct seekinfo), NULL, 0, &bytes);
if (ret != AFC_E_SUCCESS) {
afc_unlock(client);
@@ -841,7 +908,7 @@ LIBIMOBILEDEVICE_API afc_error_t afc_file_seek(afc_client_t client, uint64_t han
return ret;
}
-LIBIMOBILEDEVICE_API afc_error_t afc_file_tell(afc_client_t client, uint64_t handle, uint64_t *position)
+afc_error_t afc_file_tell(afc_client_t client, uint64_t handle, uint64_t *position)
{
char *buffer = NULL;
uint32_t bytes = 0;
@@ -850,11 +917,13 @@ LIBIMOBILEDEVICE_API afc_error_t afc_file_tell(afc_client_t client, uint64_t han
if (!client || (handle == 0))
return AFC_E_INVALID_ARG;
+ uint32_t data_len = 8;
+
afc_lock(client);
/* Send the command */
- ret = afc_dispatch_packet(client, AFC_OP_FILE_TELL, (const char*)&handle, 8, NULL, 0, &bytes);
-
+ *(uint64_t*)(AFC_PACKET_DATA_PTR) = handle;
+ ret = afc_dispatch_packet(client, AFC_OP_FILE_TELL, data_len, NULL, 0, &bytes);
if (ret != AFC_E_SUCCESS) {
afc_unlock(client);
return AFC_E_NOT_ENOUGH_DATA;
@@ -874,13 +943,13 @@ LIBIMOBILEDEVICE_API afc_error_t afc_file_tell(afc_client_t client, uint64_t han
return ret;
}
-LIBIMOBILEDEVICE_API afc_error_t afc_file_truncate(afc_client_t client, uint64_t handle, uint64_t newsize)
+afc_error_t afc_file_truncate(afc_client_t client, uint64_t handle, uint64_t newsize)
{
uint32_t bytes = 0;
- struct {
+ struct truncinfo {
uint64_t handle;
uint64_t newsize;
- } truncinfo;
+ };
afc_error_t ret = AFC_E_UNKNOWN_ERROR;
if (!client || (handle == 0))
@@ -889,9 +958,10 @@ LIBIMOBILEDEVICE_API afc_error_t afc_file_truncate(afc_client_t client, uint64_t
afc_lock(client);
/* Send command */
- truncinfo.handle = handle;
- truncinfo.newsize = htole64(newsize);
- ret = afc_dispatch_packet(client, AFC_OP_FILE_SET_SIZE, (const char*)&truncinfo, sizeof(truncinfo), NULL, 0, &bytes);
+ struct truncinfo* truncinfo = (struct truncinfo*)(AFC_PACKET_DATA_PTR);
+ truncinfo->handle = handle;
+ truncinfo->newsize = htole64(newsize);
+ ret = afc_dispatch_packet(client, AFC_OP_FILE_SET_SIZE, sizeof(struct truncinfo), NULL, 0, &bytes);
if (ret != AFC_E_SUCCESS) {
afc_unlock(client);
@@ -905,24 +975,27 @@ LIBIMOBILEDEVICE_API afc_error_t afc_file_truncate(afc_client_t client, uint64_t
return ret;
}
-LIBIMOBILEDEVICE_API afc_error_t afc_truncate(afc_client_t client, const char *path, uint64_t newsize)
+afc_error_t afc_truncate(afc_client_t client, const char *path, uint64_t newsize)
{
if (!client || !path || !client->afc_packet || !client->parent)
return AFC_E_INVALID_ARG;
- char *buffer = (char *) malloc(sizeof(char) * (strlen(path) + 1 + 8));
uint32_t bytes = 0;
- uint64_t size_requested = htole64(newsize);
afc_error_t ret = AFC_E_UNKNOWN_ERROR;
afc_lock(client);
- /* Send command */
- memcpy(buffer, &size_requested, 8);
- memcpy(buffer + 8, path, strlen(path) + 1);
- ret = afc_dispatch_packet(client, AFC_OP_TRUNCATE, buffer, 8 + strlen(path) + 1, NULL, 0, &bytes);
- free(buffer);
+ uint32_t data_len = 8 + (uint32_t)(strlen(path)+1);
+ if (_afc_check_packet_buffer(client, data_len) < 0) {
+ afc_unlock(client);
+ debug_info("Failed to realloc packet buffer");
+ return AFC_E_NO_MEM;
+ }
+ /* Send command */
+ *(uint64_t*)(AFC_PACKET_DATA_PTR) = htole64(newsize);
+ memcpy(AFC_PACKET_DATA_PTR + 8, path, data_len-8);
+ ret = afc_dispatch_packet(client, AFC_OP_TRUNCATE, data_len, NULL, 0, &bytes);
if (ret != AFC_E_SUCCESS) {
afc_unlock(client);
return AFC_E_NOT_ENOUGH_DATA;
@@ -935,28 +1008,35 @@ LIBIMOBILEDEVICE_API afc_error_t afc_truncate(afc_client_t client, const char *p
return ret;
}
-LIBIMOBILEDEVICE_API afc_error_t afc_make_link(afc_client_t client, afc_link_type_t linktype, const char *target, const char *linkname)
+afc_error_t afc_make_link(afc_client_t client, afc_link_type_t linktype, const char *target, const char *linkname)
{
if (!client || !target || !linkname || !client->afc_packet || !client->parent)
return AFC_E_INVALID_ARG;
- char *buffer = (char *) malloc(sizeof(char) * (strlen(target)+1 + strlen(linkname)+1 + 8));
uint32_t bytes = 0;
- uint64_t type = htole64(linktype);
afc_error_t ret = AFC_E_UNKNOWN_ERROR;
+ size_t target_len = strlen(target);
+ size_t link_len = strlen(linkname);
+
afc_lock(client);
- debug_info("link type: %lld", type);
- debug_info("target: %s, length:%d", target, strlen(target));
- debug_info("linkname: %s, length:%d", linkname, strlen(linkname));
+ uint32_t data_len = 8 + target_len + 1 + link_len + 1;
+ if (_afc_check_packet_buffer(client, data_len) < 0) {
+ afc_unlock(client);
+ debug_info("Failed to realloc packet buffer");
+ return AFC_E_NO_MEM;
+ }
+
+ debug_info("link type: %lld", htole64(linktype));
+ debug_info("target: %s, length:%d", target, target_len);
+ debug_info("linkname: %s, length:%d", linkname, link_len);
/* Send command */
- memcpy(buffer, &type, 8);
- memcpy(buffer + 8, target, strlen(target) + 1);
- memcpy(buffer + 8 + strlen(target) + 1, linkname, strlen(linkname) + 1);
- ret = afc_dispatch_packet(client, AFC_OP_MAKE_LINK, buffer, 8 + strlen(linkname) + 1 + strlen(target) + 1, NULL, 0, &bytes);
- free(buffer);
+ *(uint64_t*)(AFC_PACKET_DATA_PTR) = htole64(linktype);
+ memcpy(AFC_PACKET_DATA_PTR + 8, target, target_len + 1);
+ memcpy(AFC_PACKET_DATA_PTR + 8 + target_len + 1, linkname, link_len + 1);
+ ret = afc_dispatch_packet(client, AFC_OP_MAKE_LINK, data_len, NULL, 0, &bytes);
if (ret != AFC_E_SUCCESS) {
afc_unlock(client);
return AFC_E_NOT_ENOUGH_DATA;
@@ -969,23 +1049,27 @@ LIBIMOBILEDEVICE_API afc_error_t afc_make_link(afc_client_t client, afc_link_typ
return ret;
}
-LIBIMOBILEDEVICE_API afc_error_t afc_set_file_time(afc_client_t client, const char *path, uint64_t mtime)
+afc_error_t afc_set_file_time(afc_client_t client, const char *path, uint64_t mtime)
{
if (!client || !path || !client->afc_packet || !client->parent)
return AFC_E_INVALID_ARG;
- char *buffer = (char *) malloc(sizeof(char) * (strlen(path) + 1 + 8));
uint32_t bytes = 0;
- uint64_t mtime_loc = htole64(mtime);
afc_error_t ret = AFC_E_UNKNOWN_ERROR;
afc_lock(client);
+ uint32_t data_len = 8 + strlen(path) + 1;
+ if (_afc_check_packet_buffer(client, data_len) < 0) {
+ afc_unlock(client);
+ debug_info("Failed to realloc packet buffer");
+ return AFC_E_NO_MEM;
+ }
+
/* Send command */
- memcpy(buffer, &mtime_loc, 8);
- memcpy(buffer + 8, path, strlen(path) + 1);
- ret = afc_dispatch_packet(client, AFC_OP_SET_FILE_MOD_TIME, buffer, 8 + strlen(path) + 1, NULL, 0, &bytes);
- free(buffer);
+ *(uint64_t*)(AFC_PACKET_DATA_PTR) = htole64(mtime);
+ memcpy(AFC_PACKET_DATA_PTR + 8, path, data_len-8);
+ ret = afc_dispatch_packet(client, AFC_OP_SET_FILE_MOD_TIME, data_len, NULL, 0, &bytes);
if (ret != AFC_E_SUCCESS) {
afc_unlock(client);
return AFC_E_NOT_ENOUGH_DATA;
@@ -998,7 +1082,7 @@ LIBIMOBILEDEVICE_API afc_error_t afc_set_file_time(afc_client_t client, const ch
return ret;
}
-LIBIMOBILEDEVICE_API afc_error_t afc_remove_path_and_contents(afc_client_t client, const char *path)
+afc_error_t afc_remove_path_and_contents(afc_client_t client, const char *path)
{
uint32_t bytes = 0;
afc_error_t ret = AFC_E_UNKNOWN_ERROR;
@@ -1008,8 +1092,16 @@ LIBIMOBILEDEVICE_API afc_error_t afc_remove_path_and_contents(afc_client_t clien
afc_lock(client);
+ uint32_t data_len = strlen(path) + 1;
+ if (_afc_check_packet_buffer(client, data_len) < 0) {
+ afc_unlock(client);
+ debug_info("Failed to realloc packet buffer");
+ return AFC_E_NO_MEM;
+ }
+
/* Send command */
- ret = afc_dispatch_packet(client, AFC_OP_REMOVE_PATH_AND_CONTENTS, path, strlen(path)+1, NULL, 0, &bytes);
+ memcpy(AFC_PACKET_DATA_PTR, path, data_len);
+ ret = afc_dispatch_packet(client, AFC_OP_REMOVE_PATH_AND_CONTENTS, data_len, NULL, 0, &bytes);
if (ret != AFC_E_SUCCESS) {
afc_unlock(client);
return AFC_E_NOT_ENOUGH_DATA;
@@ -1022,7 +1114,7 @@ LIBIMOBILEDEVICE_API afc_error_t afc_remove_path_and_contents(afc_client_t clien
return ret;
}
-LIBIMOBILEDEVICE_API afc_error_t afc_dictionary_free(char **dictionary)
+afc_error_t afc_dictionary_free(char **dictionary)
{
int i = 0;
@@ -1036,3 +1128,70 @@ LIBIMOBILEDEVICE_API afc_error_t afc_dictionary_free(char **dictionary)
return AFC_E_SUCCESS;
}
+
+const char* afc_strerror(afc_error_t err)
+{
+ switch (err) {
+ case AFC_E_SUCCESS:
+ return "Success";
+ case AFC_E_UNKNOWN_ERROR:
+ return "Unknown Error";
+ case AFC_E_OP_HEADER_INVALID:
+ return "Operation header invalid";
+ case AFC_E_NO_RESOURCES:
+ return "No resources";
+ case AFC_E_READ_ERROR:
+ return "Read error";
+ case AFC_E_WRITE_ERROR:
+ return "Write error";
+ case AFC_E_UNKNOWN_PACKET_TYPE:
+ return "Unknown packet type";
+ case AFC_E_INVALID_ARG:
+ return "Invalid argument";
+ case AFC_E_OBJECT_NOT_FOUND:
+ return "Not found";
+ case AFC_E_OBJECT_IS_DIR:
+ return "Object is a directory";
+ case AFC_E_PERM_DENIED:
+ return "Permission denied";
+ case AFC_E_SERVICE_NOT_CONNECTED:
+ return "Service not connected";
+ case AFC_E_OP_TIMEOUT:
+ return "Timeout";
+ case AFC_E_TOO_MUCH_DATA:
+ return "Too much data";
+ case AFC_E_END_OF_DATA:
+ return "End of data";
+ case AFC_E_OP_NOT_SUPPORTED:
+ return "Operation not supported";
+ case AFC_E_OBJECT_EXISTS:
+ return "Object exists";
+ case AFC_E_OBJECT_BUSY:
+ return "Object busy";
+ case AFC_E_NO_SPACE_LEFT:
+ return "No space left on device";
+ case AFC_E_OP_WOULD_BLOCK:
+ return "Operation would block";
+ case AFC_E_IO_ERROR:
+ return "I/O error";
+ case AFC_E_OP_INTERRUPTED:
+ return "Operation interrupted";
+ case AFC_E_OP_IN_PROGRESS:
+ return "Operation on progress";
+ case AFC_E_INTERNAL_ERROR:
+ return "Internal error";
+ case AFC_E_MUX_ERROR:
+ return "MUX error";
+ case AFC_E_NO_MEM:
+ return "Out of memory";
+ case AFC_E_NOT_ENOUGH_DATA:
+ return "Not enough data";
+ case AFC_E_DIR_NOT_EMPTY:
+ return "Directory not empty";
+ case AFC_E_FORCE_SIGNED_TYPE:
+ return "Force signed type";
+ default:
+ break;
+ }
+ return "Unknown Error";
+}