summaryrefslogtreecommitdiffstats
path: root/src/AFC.c
diff options
context:
space:
mode:
authorGravatar Matt Colyer2008-07-29 10:13:37 -0700
committerGravatar Matt Colyer2008-07-29 10:13:37 -0700
commit3dc130f3049e250b2d5c0b48af1995fda2fad3d4 (patch)
tree9d801459ef68e83a0d4ca038c0589d8e4c8aa2b2 /src/AFC.c
parent6039e5bbfc36aa5210295c38f251ed178ce5adbb (diff)
downloadlibimobiledevice-3dc130f3049e250b2d5c0b48af1995fda2fad3d4.tar.gz
libimobiledevice-3dc130f3049e250b2d5c0b48af1995fda2fad3d4.tar.bz2
Autotooled the project with very basic versioning support.
Diffstat (limited to 'src/AFC.c')
-rw-r--r--src/AFC.c381
1 files changed, 381 insertions, 0 deletions
diff --git a/src/AFC.c b/src/AFC.c
new file mode 100644
index 0000000..f3d538e
--- /dev/null
+++ b/src/AFC.c
@@ -0,0 +1,381 @@
1/*
2 * AFC.c -- contains functions for the built-in AFC client.
3 * Written by FxChiP
4 */
5
6#include "AFC.h"
7
8extern int debug;
9
10AFClient *afc_connect(iPhone *phone, int s_port, int d_port) {
11 if (!phone) return NULL;
12 AFClient *client = (AFClient*)malloc(sizeof(AFClient));
13 client->connection = mux_connect(phone, s_port, d_port);
14 if (!client->connection) { free(client); return NULL; }
15 else {
16 client->afc_packet = (AFCPacket*)malloc(sizeof(AFCPacket));
17 if (client->afc_packet) {
18 client->phone = phone;
19 client->afc_packet->packet_num = 0;
20 client->afc_packet->unknown1 = client->afc_packet->unknown2 = client->afc_packet->unknown3 = client->afc_packet->unknown4 = client->afc_packet->entire_length = client->afc_packet->this_length = 0;
21 client->afc_packet->header1 = 0x36414643;
22 client->afc_packet->header2 = 0x4141504C;
23 client->file_handle = 0;
24 return client;
25 } else {
26 mux_close_connection(client->phone, client->connection);
27 free(client);
28 return NULL;
29 }
30 }
31
32 return NULL; // should never get to this point
33}
34
35void afc_disconnect(AFClient *client) {
36 // client and its members should never be NULL is assumed here.
37 if (!client || !client->connection || !client->phone || !client->afc_packet) return;
38 mux_close_connection(client->phone, client->connection);
39 free(client->afc_packet);
40 free(client);
41}
42
43int count_nullspaces(char *string, int number) {
44 int i = 0, nulls = 0;
45 for (i = 0; i < number; i++) {
46 if (string[i] == '\0') nulls++;
47 }
48 return nulls;
49}
50
51int dispatch_AFC_packet(AFClient *client, char *data, int length) {
52 char *buffer;
53 int bytes = 0, offset = 0;
54 if (!client || !client->connection || !client->phone || !client->afc_packet) return 0;
55 if (!data || !length) length = 0;
56
57 client->afc_packet->packet_num++;
58 if (!client->afc_packet->entire_length) client->afc_packet->entire_length = client->afc_packet->this_length = (length) ? sizeof(AFCPacket) + length + 1 : sizeof(AFCPacket);
59 if (!client->afc_packet->this_length) client->afc_packet->this_length = sizeof(AFCPacket);
60
61 if (client->afc_packet->this_length != client->afc_packet->entire_length) {
62 // We want to send two segments; buffer+sizeof(AFCPacket) to this_length is the parameters
63 // And everything beyond that is the next packet. (for writing)
64 char *buffer = (char*)malloc(client->afc_packet->this_length);
65 memcpy(buffer, (char*)client->afc_packet, sizeof(AFCPacket));
66 offset = client->afc_packet->this_length - sizeof(AFCPacket);
67 if (debug) printf("dispatch_AFC_packet: Offset: %i\n", offset);
68 if ((length) < (client->afc_packet->entire_length - client->afc_packet->this_length)) {
69 if (debug) printf("dispatch_AFC_packet: Length did not resemble what it was supposed to based on the packet.\nlength minus offset: %i\nrest of packet: %i\n", length-offset, client->afc_packet->entire_length - client->afc_packet->this_length);
70 free(buffer);
71 return 0;
72 }
73 if (debug) printf("dispatch_AFC_packet: fucked-up packet method (probably a write)\n");
74 memcpy(buffer+sizeof(AFCPacket), data, offset);
75 bytes = mux_send(client->phone, client->connection, buffer, client->afc_packet->this_length);
76 free(buffer);
77 if (bytes <= 0) { return 0; }
78 if (debug) {
79 printf("dispatch_AFC_packet: sent the first now go with the second\n");
80 printf("Length: %i\n", length-offset);
81 printf("Buffer: \n");
82 fwrite(data+offset, 1, length-offset, stdout);
83 }
84
85
86 bytes = mux_send(client->phone, client->connection, data+offset, length-offset);
87 if (bytes <= 0) { return 0; }
88 else { return bytes; }
89 } else {
90 if (debug) printf("dispatch_AFC_packet doin things the old way\n");
91 char *buffer = (char*)malloc(sizeof(char) * client->afc_packet->this_length);
92 if (debug) printf("dispatch_AFC_packet packet length = %i\n", client->afc_packet->this_length);
93 memcpy(buffer, (char*)client->afc_packet, sizeof(AFCPacket));
94 if (debug) printf("dispatch_AFC_packet packet data follows\n");
95 if (length > 0) { memcpy(buffer+sizeof(AFCPacket), data, length); buffer[sizeof(AFCPacket)+length] = '\0'; }
96 if (debug) fwrite(buffer, 1, client->afc_packet->this_length, stdout);
97 if (debug) printf("\n");
98 bytes = mux_send(client->phone, client->connection, buffer, client->afc_packet->this_length);
99 if (bytes <= 0) return 0;
100 else return bytes;
101 }
102 return 0;
103}
104
105int receive_AFC_data(AFClient *client, char **dump_here) {
106 AFCPacket *r_packet;
107 char *buffer = (char*)malloc(sizeof(AFCPacket) * 4);
108 int bytes = 0, recv_len = 0;
109
110 bytes = mux_recv(client->phone, client->connection, buffer, sizeof(AFCPacket) * 4);
111 if (bytes <= 0) {
112 free(buffer);
113 printf("Just didn't get enough.\n");
114 *dump_here = NULL;
115 return 0;
116 }
117
118 r_packet = (AFCPacket*)malloc(sizeof(AFCPacket));
119 memcpy(r_packet, buffer, sizeof(AFCPacket));
120
121 if (r_packet->entire_length == r_packet->this_length && r_packet->entire_length > sizeof(AFCPacket) && r_packet->operation != AFC_ERROR) {
122 *dump_here = (char*)malloc(sizeof(char) * (r_packet->entire_length-sizeof(AFCPacket)));
123 memcpy(*dump_here, buffer+sizeof(AFCPacket), r_packet->entire_length-sizeof(AFCPacket));
124 free(buffer);
125 free(r_packet);
126 return r_packet->entire_length - sizeof(AFCPacket);
127 }
128
129 uint32 param1 = buffer[sizeof(AFCPacket)];
130 free(buffer);
131
132 if (r_packet->operation == 0x01 && !((client->afc_packet->operation == AFC_DELETE && param1 == 7))) {
133 if (debug) printf("Oops? Bad operation code received.\n");
134 if (param1 == 0) {
135 if (debug) printf("... false alarm, but still\n");
136 return 1;
137 }
138 else { if (debug) printf("Errno %i\n", param1); }
139 free(r_packet);
140 *dump_here = NULL;
141 return 0;
142 } else {
143 if (debug) printf("Operation code %x\nFull length %i and this length %i\n", r_packet->operation, r_packet->entire_length, r_packet->this_length);
144 }
145
146 recv_len = r_packet->entire_length - r_packet->this_length;
147 free(r_packet);
148 if (!recv_len) return bytes;
149 buffer = (char*)malloc(sizeof(char) * recv_len);
150 bytes = mux_recv(client->phone, client->connection, buffer, recv_len);
151 if (bytes <= 0) {
152 free(buffer);
153 printf("Didn't get it at the second pass.\n");
154 *dump_here = NULL;
155 return 0;
156 }
157
158 *dump_here = buffer; // what they do beyond this point = not my problem
159 return bytes;
160}
161
162char **afc_get_dir_list(AFClient *client, char *dir) {
163 client->afc_packet->operation = AFC_LIST_DIR;
164 int bytes = 0;
165 char *blah = NULL, **list = NULL;
166 client->afc_packet->entire_length = client->afc_packet->this_length = 0;
167 bytes = dispatch_AFC_packet(client, dir, strlen(dir));
168 if (!bytes) return NULL;
169
170 bytes = receive_AFC_data(client, &blah);
171 if (!bytes && !blah) return NULL;
172
173 list = make_strings_list(blah, bytes);
174 free(blah);
175 return list;
176}
177
178char **make_strings_list(char *tokens, int true_length) {
179 if (!tokens || !true_length) return NULL;
180 int nulls = 0, i = 0, j = 0;
181 char **list = NULL;
182
183 nulls = count_nullspaces(tokens, true_length);
184 list = (char**)malloc(sizeof(char*) * (nulls + 1));
185 for (i = 0; i < nulls; i++) {
186 list[i] = strdup(tokens+j);
187 j += strlen(list[i]) + 1;
188 }
189 list[i] = strdup("");
190 return list;
191}
192
193int afc_delete_file(AFClient *client, const char *path) {
194 if (!client || !path || !client->afc_packet || !client->phone ||!client->connection) return 0;
195
196 char *receive = NULL;
197 client->afc_packet->this_length = client->afc_packet->entire_length = 0;
198 client->afc_packet->operation = AFC_DELETE;
199 int bytes;
200 bytes = dispatch_AFC_packet(client, path, strlen(path));
201 if (bytes <= 0) return 0;
202
203 bytes = receive_AFC_data(client, &receive);
204 free(receive);
205 if (bytes <= 0) return 0;
206 else return 1;
207}
208
209int afc_rename_file(AFClient *client, const char *from, const char *to) {
210 if (!client || !from || !to || !client->afc_packet || !client->phone || !client->connection) return 0;
211
212 char *receive = NULL;
213 char *send = (char*)malloc(sizeof(char) * (strlen(from) + strlen(to) + 1 + sizeof(uint32)));
214 int bytes = 0;
215
216 memcpy(send, from, strlen(from)+1);
217 memcpy(send+strlen(from)+1, to, strlen(to));
218 fwrite(send, 1, strlen(from)+1+strlen(to), stdout);
219 printf("\n");
220 client->afc_packet->entire_length = client->afc_packet->this_length = 0;
221 client->afc_packet->operation = AFC_RENAME;
222 bytes = dispatch_AFC_packet(client, send, strlen(to) + strlen(from) + 2);
223 if (bytes <= 0) return 0;
224
225 bytes = receive_AFC_data(client, &receive);
226 free(receive);
227 if (bytes <= 0) return 0;
228 else return 1;
229}
230
231
232
233AFCFile *afc_get_file_info(AFClient *client, char *path) {
234 client->afc_packet->operation = AFC_GET_INFO;
235 client->afc_packet->entire_length = client->afc_packet->this_length = 0;
236 dispatch_AFC_packet(client, path, strlen(path));
237
238 char *received, **list;
239 AFCFile *my_file;
240 int length, i = 0;
241
242 length = receive_AFC_data(client, &received);
243 list = make_strings_list(received, length);
244 free(received);
245 if (list) {
246 my_file = (AFCFile *)malloc(sizeof(AFCFile));
247 for (i = 0; strcmp(list[i], ""); i++) {
248 if (!strcmp(list[i], "st_size")) {
249 my_file->size = atoi(list[i+1]);
250 }
251
252
253 if (!strcmp(list[i], "st_blocks")) {
254 my_file->blocks = atoi(list[i+1]);
255 }
256
257 if (!strcmp(list[i], "st_ifmt")) {
258 if (!strcmp(list[i+1], "S_IFREG")) {
259 my_file->type = S_IFREG;
260 } else if (!strcmp(list[i+1], "S_IFDIR")) {
261 my_file->type = S_IFDIR;
262 }
263 }
264 }
265 free_dictionary(list);
266 return my_file;
267 } else {
268 return NULL;
269 }
270}
271
272AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode) {
273 if (file_mode != AFC_FILE_READ && file_mode != AFC_FILE_WRITE) return NULL;
274 if (!client ||!client->connection || !client->phone ||!client->afc_packet) return NULL;
275 char *further_data = (char*)malloc(sizeof(char) * (8 + strlen(filename) + 1));
276 AFCFile *file_infos = NULL;
277 memcpy(further_data, &file_mode, 4);
278 uint32 ag = 0;
279 memcpy(further_data+4, &ag, 4);
280 memcpy(further_data+8, filename, strlen(filename));
281 further_data[8+strlen(filename)] = '\0';
282 int bytes = 0, length_thing = 0;
283 client->afc_packet->operation = AFC_FILE_OPEN;
284
285 client->afc_packet->entire_length = client->afc_packet->this_length = 0;
286 bytes = dispatch_AFC_packet(client, further_data, 8+strlen(filename));
287 free(further_data);
288 if (bytes <= 0) {
289 if (debug) printf("didn't read enough\n");
290 return NULL;
291 } else {
292 length_thing = receive_AFC_data(client, &further_data);
293 if (length_thing && further_data) {
294 file_infos = afc_get_file_info(client, filename);
295 memcpy(&file_infos->filehandle, further_data, 4);
296 return file_infos;
297 } else {
298 if (debug) printf("didn't get further data or something\n");
299 return NULL;
300 }
301 }
302 if (debug) printf("what the fuck\n");
303 return NULL;
304}
305
306int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) {
307 if (!client || !client->afc_packet || !client->phone || !client->connection || !file) return -1;
308 AFCFilePacket *packet = (AFCFilePacket*)malloc(sizeof(AFCFilePacket));
309 char *input = NULL;
310 packet->unknown1 = packet->unknown2 = 0;
311 packet->filehandle = file->filehandle;
312 packet->size = length;
313 int bytes = 0;
314
315 client->afc_packet->operation = AFC_READ;
316 client->afc_packet->entire_length = client->afc_packet->this_length = 0;
317 bytes = dispatch_AFC_packet(client, (char*)packet, sizeof(AFCFilePacket));
318
319 if (bytes > 0) {
320 bytes = receive_AFC_data(client, &input);
321 if (bytes <= 0) {
322 if (input) free(input);
323 return -1;
324 } else {
325 memcpy(data, input, (bytes > length) ? length : bytes);
326 free(input);
327 return (bytes > length) ? length : bytes;
328 }
329 } else {
330 return -1;
331 }
332 return 0;
333}
334
335int afc_write_file(AFClient *client, AFCFile *file, char *data, int length) {
336 char *acknowledgement = NULL;
337 if (!client ||!client->afc_packet ||!client->phone || !client->connection || !file) return -1;
338 client->afc_packet->this_length = sizeof(AFCPacket) + 8;
339 client->afc_packet->entire_length = client->afc_packet->this_length + length;
340 client->afc_packet->operation = AFC_WRITE;
341 if (debug) printf("afc_write_file: Write length: %i\n", length);
342 uint32 zero = 0, bytes = 0;
343
344 char *out_buffer = NULL;
345 out_buffer = (char*)malloc(sizeof(char) * client->afc_packet->entire_length - sizeof(AFCPacket));
346 memcpy(out_buffer, (char*)&file->filehandle, sizeof(uint32));
347 memcpy(out_buffer+4, (char*)&zero, sizeof(uint32));
348 memcpy(out_buffer+8, data, length);
349
350 bytes = dispatch_AFC_packet(client, out_buffer, length + 8);
351 if (!bytes) return -1;
352
353 zero = bytes;
354 bytes = receive_AFC_data(client, &acknowledgement);
355 if (bytes <= 0) {
356 if (debug) printf("afc_write_file: uh oh?\n");
357 }
358
359 return zero;
360}
361
362void afc_close_file(AFClient *client, AFCFile *file) {
363 char *buffer = malloc(sizeof(char) * 8);
364 uint32 zero = 0;
365 if (debug) printf("File handle %i\n", file->filehandle);
366 memcpy(buffer, &file->filehandle, sizeof(uint32));
367 memcpy(buffer+sizeof(uint32), &zero, sizeof(zero));
368 client->afc_packet->operation = AFC_FILE_CLOSE;
369 int bytes = 0;
370 client->afc_packet->entire_length = client->afc_packet->this_length = 0;
371 bytes = dispatch_AFC_packet(client, buffer, sizeof(char) * 8);
372
373 free(buffer);
374 client->afc_packet->entire_length = client->afc_packet->this_length = 0;
375 if (!bytes) return;
376
377 bytes = receive_AFC_data(client, &buffer);
378 return;
379 if (buffer) free(buffer); // we're *SUPPOSED* to get an "error" here.
380}
381