summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Matt Colyer2008-08-06 23:47:20 -0700
committerGravatar Matt Colyer2008-08-06 23:47:20 -0700
commit1c6aa3dd8aa8cd985a63ccbfa3848ebbe52715e1 (patch)
tree0ddd4df6e0022683d3cbc01d18d1ac7ad9d47ee2 /src
parentbef655966045af34e1f20a7211f0cab2e7e79001 (diff)
downloadlibimobiledevice-1c6aa3dd8aa8cd985a63ccbfa3848ebbe52715e1.tar.gz
libimobiledevice-1c6aa3dd8aa8cd985a63ccbfa3848ebbe52715e1.tar.bz2
Fixed the data corruption, it turns out that there is a maximum length
that you can request in an AFC packet 2^16.
Diffstat (limited to 'src')
-rw-r--r--src/AFC.c82
-rw-r--r--src/ifuse.c3
2 files changed, 55 insertions, 30 deletions
diff --git a/src/AFC.c b/src/AFC.c
index d7a4dda..680a08f 100644
--- a/src/AFC.c
+++ b/src/AFC.c
@@ -141,7 +141,7 @@ int receive_AFC_data(AFClient *client, char **dump_here) {
char *buffer = (char*)malloc(sizeof(AFCPacket) * 4);
char *final_buffer = NULL;
int bytes = 0, recv_len = 0, current_count=0;
- int retval = 0;
+ int retval = 0;
bytes = mux_recv(client->connection, buffer, sizeof(AFCPacket) * 4);
if (bytes <= 0) {
@@ -386,41 +386,63 @@ AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode)
return NULL;
}
+/** Attempts to the read the given number of bytes from the given file.
+ *
+ * @param client The relevant AFC client
+ * @param file The AFCFile to read from
+ * @param data The pointer to the memory region to store the read data
+ * @param length The number of bytes to read
+ *
+ * @return The number of bytes read if successful. If there was an error
+ */
int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) {
if (!client || !client->afc_packet || !client->connection || !file) return -1;
- AFCFilePacket *packet = (AFCFilePacket*)malloc(sizeof(AFCFilePacket));
- if (debug) printf("afc_read_file called for length %i\n");
- afc_lock(client);
+ if (debug) printf("afc_read_file called for length %i\n", length);
+
char *input = NULL;
- packet->unknown1 = packet->unknown2 = 0;
- packet->filehandle = file->filehandle;
- packet->size = length;
- int bytes = 0;
-
- client->afc_packet->operation = AFC_READ;
- client->afc_packet->entire_length = client->afc_packet->this_length = 0;
- bytes = dispatch_AFC_packet(client, (char*)packet, sizeof(AFCFilePacket));
-
- if (bytes > 0) {
- bytes = receive_AFC_data(client, &input);
- afc_unlock(client);
- if (bytes < 0) {
- if (input) free(input);
- return -1;
- } else if (bytes == 0) {
- if (input) free(input);
- return 0;
+ int current_count = 0, bytes = 0;
+ const int MAXIMUM_READ_SIZE = 1 << 16;
+
+ afc_lock(client);
+
+
+ // Looping here to get around the maximum amount of data that recieve_AFC_data can handle
+ while (current_count < length){
+
+ // Send the read command
+ AFCFilePacket *packet = (AFCFilePacket*)malloc(sizeof(AFCFilePacket));
+ packet->unknown1 = packet->unknown2 = 0;
+ packet->filehandle = file->filehandle;
+ packet->size = ((length - current_count) < MAXIMUM_READ_SIZE) ? (length - current_count) : MAXIMUM_READ_SIZE;
+ client->afc_packet->operation = AFC_READ;
+ client->afc_packet->entire_length = client->afc_packet->this_length = 0;
+ bytes = dispatch_AFC_packet(client, (char*)packet, sizeof(AFCFilePacket));
+
+ // If we get a positive reponse to the command gather the data
+ if (bytes > 0) {
+ bytes = receive_AFC_data(client, &input);
+ if (bytes < 0) {
+ if (input) free(input);
+ return -1;
+ } else if (bytes == 0) {
+ if (input) free(input);
+ return current_count;
+ } else {
+ if (input) {
+ printf("afc_read_file: %d\n", bytes);
+ memcpy(data+current_count, input, (bytes > length) ? length : bytes);
+ free(input);
+ input = NULL;
+ current_count += (bytes > length) ? length : bytes;
+ }
+ }
} else {
- if (input)
- memcpy(data, input, (bytes > length) ? length : bytes);
- free(input);
- return (bytes > length) ? length : bytes;
+ afc_unlock(client);
+ return -1;
}
- } else {
- afc_unlock(client);
- return -1;
}
- return 0;
+ afc_unlock(client);
+ return current_count;
}
int afc_write_file(AFClient *client, AFCFile *file, const char *data, int length) {
diff --git a/src/ifuse.c b/src/ifuse.c
index 7d6f72a..a56289d 100644
--- a/src/ifuse.c
+++ b/src/ifuse.c
@@ -103,6 +103,9 @@ static int ifuse_read(const char *path, char *buf, size_t size, off_t offset,
AFCFile *file;
AFClient *afc = fuse_get_context()->private_data;
+ if (size == 0)
+ return 0;
+
file = g_hash_table_lookup(file_handles, &(fi->fh));
if (!file){
return -ENOENT;