summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/AFC.c180
-rw-r--r--src/AFC.h13
-rw-r--r--src/ifuse.c131
-rw-r--r--src/main.c24
4 files changed, 306 insertions, 42 deletions
diff --git a/src/AFC.c b/src/AFC.c
index 6fb5a9e..6a0df50 100644
--- a/src/AFC.c
+++ b/src/AFC.c
@@ -29,13 +29,15 @@ extern int debug;
29 29
30/* Locking, for thread-safety (well... kind of, hehe) */ 30/* Locking, for thread-safety (well... kind of, hehe) */
31void afc_lock(AFClient *client) { 31void afc_lock(AFClient *client) {
32 if (debug) printf("In the midst of a lock...\n");
32 while (client->lock) { 33 while (client->lock) {
33 sleep(200); 34 usleep(500); // they say it's obsolete, but whatever
34 } 35 }
35 client->lock = 1; 36 client->lock = 1;
36} 37}
37 38
38void afc_unlock(AFClient *client) { // just to be pretty 39void afc_unlock(AFClient *client) { // just to be pretty
40 if (debug) printf("Unlock!\n");
39 client->lock = 0; 41 client->lock = 0;
40} 42}
41 43
@@ -102,13 +104,13 @@ int dispatch_AFC_packet(AFClient *client, const char *data, int length) {
102 if ((length) < (client->afc_packet->entire_length - client->afc_packet->this_length)) { 104 if ((length) < (client->afc_packet->entire_length - client->afc_packet->this_length)) {
103 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); 105 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);
104 free(buffer); 106 free(buffer);
105 return 0; 107 return -1;
106 } 108 }
107 if (debug) printf("dispatch_AFC_packet: fucked-up packet method (probably a write)\n"); 109 if (debug) printf("dispatch_AFC_packet: fucked-up packet method (probably a write)\n");
108 memcpy(buffer+sizeof(AFCPacket), data, offset); 110 memcpy(buffer+sizeof(AFCPacket), data, offset);
109 bytes = mux_send(client->connection, buffer, client->afc_packet->this_length); 111 bytes = mux_send(client->connection, buffer, client->afc_packet->this_length);
110 free(buffer); 112 free(buffer);
111 if (bytes <= 0) { return 0; } 113 if (bytes <= 0) { return bytes; }
112 if (debug) { 114 if (debug) {
113 printf("dispatch_AFC_packet: sent the first now go with the second\n"); 115 printf("dispatch_AFC_packet: sent the first now go with the second\n");
114 printf("Length: %i\n", length-offset); 116 printf("Length: %i\n", length-offset);
@@ -118,8 +120,7 @@ int dispatch_AFC_packet(AFClient *client, const char *data, int length) {
118 120
119 121
120 bytes = mux_send(client->connection, data+offset, length-offset); 122 bytes = mux_send(client->connection, data+offset, length-offset);
121 if (bytes <= 0) { return 0; } 123 return bytes;
122 else { return bytes; }
123 } else { 124 } else {
124 if (debug) printf("dispatch_AFC_packet doin things the old way\n"); 125 if (debug) printf("dispatch_AFC_packet doin things the old way\n");
125 char *buffer = (char*)malloc(sizeof(char) * client->afc_packet->this_length); 126 char *buffer = (char*)malloc(sizeof(char) * client->afc_packet->this_length);
@@ -130,10 +131,9 @@ int dispatch_AFC_packet(AFClient *client, const char *data, int length) {
130 if (debug) fwrite(buffer, 1, client->afc_packet->this_length, stdout); 131 if (debug) fwrite(buffer, 1, client->afc_packet->this_length, stdout);
131 if (debug) printf("\n"); 132 if (debug) printf("\n");
132 bytes = mux_send(client->connection, buffer, client->afc_packet->this_length); 133 bytes = mux_send(client->connection, buffer, client->afc_packet->this_length);
133 if (bytes <= 0) return 0; 134 return bytes;
134 else return bytes;
135 } 135 }
136 return 0; 136 return -1;
137} 137}
138 138
139int receive_AFC_data(AFClient *client, char **dump_here) { 139int receive_AFC_data(AFClient *client, char **dump_here) {
@@ -148,7 +148,7 @@ int receive_AFC_data(AFClient *client, char **dump_here) {
148 free(buffer); 148 free(buffer);
149 printf("Just didn't get enough.\n"); 149 printf("Just didn't get enough.\n");
150 *dump_here = NULL; 150 *dump_here = NULL;
151 return 0; 151 return -1;
152 } 152 }
153 153
154 r_packet = (AFCPacket*)malloc(sizeof(AFCPacket)); 154 r_packet = (AFCPacket*)malloc(sizeof(AFCPacket));
@@ -177,19 +177,19 @@ int receive_AFC_data(AFClient *client, char **dump_here) {
177 if(param1 == 0) { 177 if(param1 == 0) {
178 if (debug) printf("... false alarm, but still\n"); 178 if (debug) printf("... false alarm, but still\n");
179 *dump_here = NULL; 179 *dump_here = NULL;
180 return 1; 180 return 0;
181 } 181 }
182 else { if (debug) printf("Errno %i\n", param1); } 182 else { if (debug) printf("Errno %i\n", param1); }
183 free(r_packet); 183 free(r_packet);
184 *dump_here = NULL; 184 *dump_here = NULL;
185 return 0; 185 return -1;
186 } else { 186 } else {
187 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); 187 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);
188 } 188 }
189 189
190 recv_len = r_packet->entire_length - r_packet->this_length; 190 recv_len = r_packet->entire_length - r_packet->this_length;
191 free(r_packet); 191 free(r_packet);
192 if (!recv_len) 192 if (!recv_len && r_packet->operation == AFC_SUCCESS_RESPONSE)
193 { 193 {
194 *dump_here = NULL; 194 *dump_here = NULL;
195 return 0; 195 return 0;
@@ -240,10 +240,28 @@ char **afc_get_dir_list(AFClient *client, const char *dir) {
240 char *blah = NULL, **list = NULL; 240 char *blah = NULL, **list = NULL;
241 client->afc_packet->entire_length = client->afc_packet->this_length = 0; 241 client->afc_packet->entire_length = client->afc_packet->this_length = 0;
242 bytes = dispatch_AFC_packet(client, dir, strlen(dir)); 242 bytes = dispatch_AFC_packet(client, dir, strlen(dir));
243 if (!bytes) { afc_unlock(client); return NULL; } 243 if (bytes <= 0) { afc_unlock(client); return NULL; }
244
245 bytes = receive_AFC_data(client, &blah);
246 if (bytes < 0 && !blah) { afc_unlock(client); return NULL; }
247
248 list = make_strings_list(blah, bytes);
249 free(blah);
250 afc_unlock(client);
251 return list;
252}
253
254char **afc_get_devinfo(AFClient *client) {
255 afc_lock(client);
256 client->afc_packet->operation = AFC_GET_DEVINFO;
257 int bytes = 0;
258 char *blah = NULL, **list = NULL;
259 client->afc_packet->entire_length = client->afc_packet->this_length = 0;
260 bytes = dispatch_AFC_packet(client, NULL, 0);
261 if (bytes < 0) { afc_unlock(client); return NULL; }
244 262
245 bytes = receive_AFC_data(client, &blah); 263 bytes = receive_AFC_data(client, &blah);
246 if (!bytes && !blah) { afc_unlock(client); return NULL; } 264 if (bytes < 0 && !blah) { afc_unlock(client); return NULL; }
247 265
248 list = make_strings_list(blah, bytes); 266 list = make_strings_list(blah, bytes);
249 free(blah); 267 free(blah);
@@ -251,6 +269,7 @@ char **afc_get_dir_list(AFClient *client, const char *dir) {
251 return list; 269 return list;
252} 270}
253 271
272
254char **make_strings_list(char *tokens, int true_length) { 273char **make_strings_list(char *tokens, int true_length) {
255 if (!tokens || !true_length) return NULL; 274 if (!tokens || !true_length) return NULL;
256 int nulls = 0, i = 0, j = 0; 275 int nulls = 0, i = 0, j = 0;
@@ -279,7 +298,7 @@ int afc_delete_file(AFClient *client, const char *path) {
279 bytes = receive_AFC_data(client, &receive); 298 bytes = receive_AFC_data(client, &receive);
280 free(receive); 299 free(receive);
281 afc_unlock(client); 300 afc_unlock(client);
282 if (bytes <= 0) { return 0; } 301 if (bytes < 0) { return 0; }
283 else return 1; 302 else return 1;
284} 303}
285 304
@@ -302,12 +321,28 @@ int afc_rename_file(AFClient *client, const char *from, const char *to) {
302 bytes = receive_AFC_data(client, &receive); 321 bytes = receive_AFC_data(client, &receive);
303 free(receive); 322 free(receive);
304 afc_unlock(client); 323 afc_unlock(client);
305 if (bytes <= 0) return 0; 324 if (bytes < 0) return 0;
306 else return 1; 325 else return 1;
307} 326}
308 327
328int afc_mkdir(AFClient *client, const char *dir) {
329 if (!client) return 0;
330 afc_lock(client);
331 int bytes = 0;
332 char *recvd = NULL;
309 333
334 client->afc_packet->operation = AFC_MAKE_DIR;
335 client->afc_packet->this_length = client->afc_packet->entire_length = 0;
336 bytes = dispatch_AFC_packet(client, dir, strlen(dir));
337 if (bytes <= 0) { afc_unlock(client); return 0; }
310 338
339 bytes = receive_AFC_data(client, &recvd);
340 afc_unlock(client);
341 if (recvd) { free(recvd); recvd = NULL; }
342 if (bytes == 0) return 1;
343 else return 0;
344}
345
311AFCFile *afc_get_file_info(AFClient *client, const char *path) { 346AFCFile *afc_get_file_info(AFClient *client, const char *path) {
312 client->afc_packet->operation = AFC_GET_INFO; 347 client->afc_packet->operation = AFC_GET_INFO;
313 client->afc_packet->entire_length = client->afc_packet->this_length = 0; 348 client->afc_packet->entire_length = client->afc_packet->this_length = 0;
@@ -350,7 +385,7 @@ AFCFile *afc_get_file_info(AFClient *client, const char *path) {
350} 385}
351 386
352AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode) { 387AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode) {
353 if (file_mode != AFC_FILE_READ && file_mode != AFC_FILE_WRITE) return NULL; 388 //if (file_mode != AFC_FILE_READ && file_mode != AFC_FILE_WRITE) return NULL;
354 if (!client ||!client->connection || !client->afc_packet) return NULL; 389 if (!client ||!client->connection || !client->afc_packet) return NULL;
355 afc_lock(client); 390 afc_lock(client);
356 char *further_data = (char*)malloc(sizeof(char) * (8 + strlen(filename) + 1)); 391 char *further_data = (char*)malloc(sizeof(char) * (8 + strlen(filename) + 1));
@@ -372,17 +407,19 @@ AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode)
372 return NULL; 407 return NULL;
373 } else { 408 } else {
374 length_thing = receive_AFC_data(client, &further_data); 409 length_thing = receive_AFC_data(client, &further_data);
375 if (length_thing && further_data) { 410 if (length_thing > 0 && further_data) {
376 afc_unlock(client); // don't want to hang on the next call... and besides, it'll re-lock, do its thing, and unlock again anyway. 411 afc_unlock(client); // don't want to hang on the next call... and besides, it'll re-lock, do its thing, and unlock again anyway.
377 file_infos = afc_get_file_info(client, filename); 412 file_infos = afc_get_file_info(client, filename);
378 memcpy(&file_infos->filehandle, further_data, 4); 413 memcpy(&file_infos->filehandle, further_data, 4);
379 return file_infos; 414 return file_infos;
380 } else { 415 } else {
381 if (debug) printf("didn't get further data or something\n"); 416 if (debug) printf("didn't get further data or something\n");
417 afc_unlock(client);
382 return NULL; 418 return NULL;
383 } 419 }
384 } 420 }
385 if (debug) printf("what the fuck\n"); 421 if (debug) printf("what the fuck\n");
422 afc_unlock(client);
386 return NULL; 423 return NULL;
387} 424}
388 425
@@ -408,7 +445,8 @@ int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) {
408 445
409 // Looping here to get around the maximum amount of data that recieve_AFC_data can handle 446 // Looping here to get around the maximum amount of data that recieve_AFC_data can handle
410 while (current_count < length){ 447 while (current_count < length){
411 448 if (debug) printf("afc_read_file: current count is %i but length is %i\n", current_count, length);
449
412 // Send the read command 450 // Send the read command
413 AFCFilePacket *packet = (AFCFilePacket*)malloc(sizeof(AFCFilePacket)); 451 AFCFilePacket *packet = (AFCFilePacket*)malloc(sizeof(AFCFilePacket));
414 packet->unknown1 = packet->unknown2 = 0; 452 packet->unknown1 = packet->unknown2 = 0;
@@ -421,6 +459,7 @@ int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) {
421 // If we get a positive reponse to the command gather the data 459 // If we get a positive reponse to the command gather the data
422 if (bytes > 0) { 460 if (bytes > 0) {
423 bytes = receive_AFC_data(client, &input); 461 bytes = receive_AFC_data(client, &input);
462 if (debug) printf("afc_read_file: bytes returned: %i\n", bytes);
424 if (bytes < 0) { 463 if (bytes < 0) {
425 if (input) free(input); 464 if (input) free(input);
426 afc_unlock(client); 465 afc_unlock(client);
@@ -431,7 +470,7 @@ int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) {
431 return current_count; 470 return current_count;
432 } else { 471 } else {
433 if (input) { 472 if (input) {
434 printf("afc_read_file: %d\n", bytes); 473 if (debug) printf("afc_read_file: %d\n", bytes);
435 memcpy(data+current_count, input, (bytes > length) ? length : bytes); 474 memcpy(data+current_count, input, (bytes > length) ? length : bytes);
436 free(input); 475 free(input);
437 input = NULL; 476 input = NULL;
@@ -444,6 +483,7 @@ int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) {
444 } 483 }
445 } 484 }
446 afc_unlock(client); 485 afc_unlock(client);
486 if (debug) printf("afc_read_file: returning current_count as %i\n", current_count);
447 return current_count; 487 return current_count;
448} 488}
449 489
@@ -451,29 +491,53 @@ int afc_write_file(AFClient *client, AFCFile *file, const char *data, int length
451 char *acknowledgement = NULL; 491 char *acknowledgement = NULL;
452 if (!client ||!client->afc_packet || !client->connection || !file) return -1; 492 if (!client ||!client->afc_packet || !client->connection || !file) return -1;
453 afc_lock(client); 493 afc_lock(client);
454 client->afc_packet->this_length = sizeof(AFCPacket) + 8;
455 client->afc_packet->entire_length = client->afc_packet->this_length + length;
456 client->afc_packet->operation = AFC_WRITE;
457 if (debug) printf("afc_write_file: Write length: %i\n", length); 494 if (debug) printf("afc_write_file: Write length: %i\n", length);
458 uint32 zero = 0, bytes = 0; 495 const int MAXIMUM_WRITE_SIZE = 1 << 16;
459 496 uint32 zero = 0, bytes = 0, segments = (length / MAXIMUM_WRITE_SIZE), current_count = 0, i = 0;
460 char *out_buffer = NULL; 497 char *out_buffer = NULL;
498
499 for (i = 0; i < segments; i++) { // Essentially, yeah, divide it into segments.
500 client->afc_packet->this_length = sizeof(AFCPacket) + 8;
501 //client->afc_packet->entire_length = client->afc_packet->this_length + length;
502 client->afc_packet->entire_length = client->afc_packet->this_length + MAXIMUM_WRITE_SIZE;
503 client->afc_packet->operation = AFC_WRITE;
504 out_buffer = (char*)malloc(sizeof(char) * client->afc_packet->entire_length - sizeof(AFCPacket));
505 memcpy(out_buffer, (char*)&file->filehandle, sizeof(uint32));
506 memcpy(out_buffer+4, (char*)&zero, sizeof(uint32));
507 memcpy(out_buffer+8, data+current_count, MAXIMUM_WRITE_SIZE);
508
509 bytes = dispatch_AFC_packet(client, out_buffer, MAXIMUM_WRITE_SIZE + 8);
510 if (bytes < 0) { afc_unlock(client); return bytes; }
511 free(out_buffer); out_buffer = NULL; // cleanup and hope it works
512 current_count += bytes;
513 bytes = receive_AFC_data(client, &acknowledgement);
514 if (bytes < 0) { afc_unlock(client); return current_count; }
515 }
516
517 // By this point, we should be at the end. i.e. the last segment that didn't get sent in the for loop
518 // this length is fine because it's always sizeof(AFCPacket) + 8, but to be sure we do it again
519 if (current_count == length) { afc_unlock(client); return current_count; }
520 client->afc_packet->this_length = sizeof(AFCPacket) + 8;
521 client->afc_packet->entire_length = client->afc_packet->this_length + (length - current_count);
522 // operation is already AFC_WRITE, but set again to be sure
523 client->afc_packet->operation = AFC_WRITE;
461 out_buffer = (char*)malloc(sizeof(char) * client->afc_packet->entire_length - sizeof(AFCPacket)); 524 out_buffer = (char*)malloc(sizeof(char) * client->afc_packet->entire_length - sizeof(AFCPacket));
462 memcpy(out_buffer, (char*)&file->filehandle, sizeof(uint32)); 525 memcpy(out_buffer, (char*)&file->filehandle, sizeof(uint32));
463 memcpy(out_buffer+4, (char*)&zero, sizeof(uint32)); 526 memcpy(out_buffer+4, (char*)&zero, sizeof(uint32));
464 memcpy(out_buffer+8, data, length); 527 memcpy(out_buffer+8, data+current_count, (length - current_count));
465 528 bytes = dispatch_AFC_packet(client, out_buffer, (length - current_count) + 8);
466 bytes = dispatch_AFC_packet(client, out_buffer, length + 8); 529 free(out_buffer); out_buffer = NULL;
467 if (!bytes) return -1; 530 current_count += bytes;
531 if (bytes <= 0) { afc_unlock(client); return current_count; }
468 532
469 zero = bytes; 533 zero = bytes;
470 bytes = receive_AFC_data(client, &acknowledgement); 534 bytes = receive_AFC_data(client, &acknowledgement);
471 afc_unlock(client); 535 afc_unlock(client);
472 if (bytes <= 0) { 536 if (bytes < 0) {
473 if (debug) printf("afc_write_file: uh oh?\n"); 537 if (debug) printf("afc_write_file: uh oh?\n");
474 } 538 }
475 539
476 return zero; 540 return current_count;
477} 541}
478 542
479void afc_close_file(AFClient *client, AFCFile *file) { 543void afc_close_file(AFClient *client, AFCFile *file) {
@@ -490,9 +554,61 @@ void afc_close_file(AFClient *client, AFCFile *file) {
490 554
491 free(buffer); 555 free(buffer);
492 client->afc_packet->entire_length = client->afc_packet->this_length = 0; 556 client->afc_packet->entire_length = client->afc_packet->this_length = 0;
493 if (!bytes) return; 557 if (bytes <= 0) { afc_unlock(client); return; }
494 558
495 bytes = receive_AFC_data(client, &buffer); 559 bytes = receive_AFC_data(client, &buffer);
496 afc_unlock(client); 560 afc_unlock(client);
561 if (buffer) { free(buffer); }
497 return; 562 return;
498} 563}
564
565int afc_seek_file(AFClient *client, AFCFile *file, int seekpos) {
566 afc_lock(client);
567
568 char *buffer = (char*)malloc(sizeof(char) * 24);
569 uint32 seekto = 0, bytes = 0, zero = 0;
570 if (seekpos < 0) seekpos = file->size - abs(seekpos);
571 seekto = seekpos;
572
573 memcpy(buffer, &file->filehandle, sizeof(uint32)); // handle
574 memcpy(buffer+4, &zero, sizeof(uint32)); // pad
575 memcpy(buffer+8, &zero, sizeof(uint32)); // fromwhere
576 memcpy(buffer+12, &zero, sizeof(uint32)); // pad
577 memcpy(buffer+16, &seekto, sizeof(uint32)); // offset
578 memcpy(buffer+20, &zero, sizeof(uint32)); // pad
579 client->afc_packet->operation = AFC_FILE_SEEK;
580 client->afc_packet->this_length = client->afc_packet->entire_length = 0;
581 bytes = dispatch_AFC_packet(client, buffer, 23);
582 free(buffer); buffer = NULL;
583 if (bytes <= 0) { afc_unlock(client); return -1; }
584
585 bytes = receive_AFC_data(client, &buffer);
586 if (buffer) free(buffer);
587 afc_unlock(client);
588 if (bytes >= 0) return 0;
589 else return -1;
590}
591
592int afc_truncate_file(AFClient *client, AFCFile *file, uint32 newsize) {
593 afc_lock(client);
594
595 char *buffer = (char*)malloc(sizeof(char) * 16);
596 uint32 bytes = 0, zero = 0;
597
598 memcpy(buffer, &file->filehandle, sizeof(uint32)); // handle
599 memcpy(buffer+4, &zero, sizeof(uint32)); // pad
600 memcpy(buffer+8, &newsize, sizeof(uint32)); // newsize
601 memcpy(buffer+12, &zero, 3); // pad
602 client->afc_packet->operation = AFC_FILE_TRUNCATE;
603 client->afc_packet->this_length = client->afc_packet->entire_length = 0;
604 bytes = dispatch_AFC_packet(client, buffer, 15);
605 free(buffer); buffer = NULL;
606 if (bytes <= 0) { afc_unlock(client); return -1; }
607
608 bytes = receive_AFC_data(client, &buffer);
609 if (buffer) free(buffer);
610 afc_unlock(client);
611 if (bytes >= 0) return 0;
612 else return -1;
613}
614
diff --git a/src/AFC.h b/src/AFC.h
index 32defbe..39ada91 100644
--- a/src/AFC.h
+++ b/src/AFC.h
@@ -56,8 +56,14 @@ typedef struct __AFCToken {
56 56
57 57
58enum { 58enum {
59 AFC_FILE_READ = 0x00000002, 59 AFC_FILE_READ = 0x00000002, // seems to be able to read and write files
60 AFC_FILE_WRITE = 0x00000003 60 AFC_FILE_WRITE = 0x00000003, // writes and creates a file, blanks it out, etc.
61 AFC_FILE_RW = 0x00000005, // seems to do the same as 2. Might even create the file.
62 AFC_FILE_OP4 = 0x00000004, // no idea -- appears to be "write" -- clears file beforehand like 3
63 AFC_FILE_OP6 = 0x00000006, // no idea yet -- appears to be the same as 5.
64 AFC_FILE_OP1 = 0x00000001, // no idea juuust yet... probably read.
65 AFC_FILE_OP0 = 0x00000000,
66 AFC_FILE_OP10 = 0x0000000a
61}; 67};
62 68
63enum { 69enum {
@@ -65,11 +71,14 @@ enum {
65 AFC_GET_INFO = 0x0000000a, 71 AFC_GET_INFO = 0x0000000a,
66 AFC_GET_DEVINFO = 0x0000000b, 72 AFC_GET_DEVINFO = 0x0000000b,
67 AFC_LIST_DIR = 0x00000003, 73 AFC_LIST_DIR = 0x00000003,
74 AFC_MAKE_DIR = 0x00000009,
68 AFC_DELETE = 0x00000008, 75 AFC_DELETE = 0x00000008,
69 AFC_RENAME = 0x00000018, 76 AFC_RENAME = 0x00000018,
70 AFC_SUCCESS_RESPONSE = 0x00000002, 77 AFC_SUCCESS_RESPONSE = 0x00000002,
71 AFC_FILE_OPEN = 0x0000000d, 78 AFC_FILE_OPEN = 0x0000000d,
72 AFC_FILE_CLOSE = 0x00000014, 79 AFC_FILE_CLOSE = 0x00000014,
80 AFC_FILE_SEEK = 0x00000011,
81 AFC_FILE_TRUNCATE = 0x00000015,
73 AFC_FILE_HANDLE = 0x0000000e, 82 AFC_FILE_HANDLE = 0x0000000e,
74 AFC_READ = 0x0000000f, 83 AFC_READ = 0x0000000f,
75 AFC_WRITE = 0x00000010 84 AFC_WRITE = 0x00000010
diff --git a/src/ifuse.c b/src/ifuse.c
index 3d921fd..9fc1ad8 100644
--- a/src/ifuse.c
+++ b/src/ifuse.c
@@ -41,7 +41,7 @@
41GHashTable *file_handles; 41GHashTable *file_handles;
42int fh_index = 0; 42int fh_index = 0;
43 43
44int debug = 1; 44int debug = 0;
45 45
46static int ifuse_getattr(const char *path, struct stat *stbuf) { 46static int ifuse_getattr(const char *path, struct stat *stbuf) {
47 int res = 0; 47 int res = 0;
@@ -53,7 +53,8 @@ static int ifuse_getattr(const char *path, struct stat *stbuf) {
53 if (!file){ 53 if (!file){
54 res = -ENOENT; 54 res = -ENOENT;
55 } else { 55 } else {
56 stbuf->st_mode = file->type | 0444; 56 //stbuf->st_mode = file->type | 0444; // testing write access too now
57 stbuf->st_mode = file->type | 0644; // but we don't want anything on the iPhone executable, like, ever
57 stbuf->st_size = file->size; 58 stbuf->st_size = file->size;
58 //stbuf->st_nlink = 2; 59 //stbuf->st_nlink = 2;
59 } 60 }
@@ -81,14 +82,34 @@ static int ifuse_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
81 return 0; 82 return 0;
82} 83}
83 84
84static int ifuse_open(const char *path, struct fuse_file_info *fi) { 85static int ifuse_create(const char *path, mode_t mode, struct fuse_file_info *fi) {
86 // exactly the same as open but using a different mode
85 AFCFile *file; 87 AFCFile *file;
86 AFClient *afc = fuse_get_context()->private_data; 88 AFClient *afc = fuse_get_context()->private_data;
89
90 file = afc_open_file(afc, path, AFC_FILE_WRITE);
91 fh_index++;
92 fi->fh = fh_index;
93 g_hash_table_insert(file_handles, &fh_index, file);
94 return 0;
95}
87 96
88 if((fi->flags & 3) != O_RDONLY) 97static int ifuse_open(const char *path, struct fuse_file_info *fi) {
89 return -EACCES; 98 AFCFile *file;
99 AFClient *afc = fuse_get_context()->private_data;
100 uint32 mode = 0;
101 /*if((fi->flags & 3) != O_RDONLY)
102 return -EACCES;*/ // trying to test write access here
103
104 if ((fi->flags & 3) == O_RDWR || (fi->flags & 3) == O_WRONLY) {
105 mode = AFC_FILE_READ;
106 } else if ((fi->flags & 3) == O_RDONLY) {
107 mode = AFC_FILE_READ;
108 } else {
109 mode = AFC_FILE_READ;
110 }
90 111
91 file = afc_open_file(afc, path, AFC_FILE_READ); 112 file = afc_open_file(afc, path, mode);
92 113
93 fh_index++; 114 fh_index++;
94 fi->fh = fh_index; 115 fi->fh = fh_index;
@@ -111,10 +132,30 @@ static int ifuse_read(const char *path, char *buf, size_t size, off_t offset,
111 return -ENOENT; 132 return -ENOENT;
112 } 133 }
113 134
135 bytes = afc_seek_file(afc, file, offset);
114 bytes = afc_read_file(afc, file, buf, size); 136 bytes = afc_read_file(afc, file, buf, size);
115 return bytes; 137 return bytes;
116} 138}
117 139
140static int ifuse_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) {
141 int bytes = 0;
142 AFCFile *file = NULL;
143 AFClient *afc = fuse_get_context()->private_data;
144
145 if (size == 0) return 0;
146
147 file = g_hash_table_lookup(file_handles, &(fi->fh));
148 if (!file) return -ENOENT;
149
150 bytes = afc_seek_file(afc, file, offset);
151 bytes = afc_write_file(afc, file, buf, size);
152 return bytes;
153}
154
155static int ifuse_fsync(const char *path, int datasync, struct fuse_file_info *fi) {
156 return 0;
157}
158
118static int ifuse_release(const char *path, struct fuse_file_info *fi){ 159static int ifuse_release(const char *path, struct fuse_file_info *fi){
119 AFCFile *file; 160 AFCFile *file;
120 AFClient *afc = fuse_get_context()->private_data; 161 AFClient *afc = fuse_get_context()->private_data;
@@ -181,11 +222,89 @@ void ifuse_cleanup(void *data) {
181 } 222 }
182} 223}
183 224
225int ifuse_flush(const char *path, struct fuse_file_info *fi) {
226 return 0;
227}
228
229int ifuse_statfs(const char *path, struct statvfs *stats) {
230 AFClient *afc = fuse_get_context()->private_data;
231 char **info_raw = afc_get_devinfo(afc);
232 uint32 totalspace = 0, freespace = 0, blocksize = 0, i = 0;
233
234 if (!info_raw) return -ENOENT;
235
236 for (i = 0; strcmp(info_raw[i], ""); i++) {
237 if (!strcmp(info_raw[i], "FSTotalBytes")) {
238 totalspace = atoi(info_raw[i+1]);
239 } else if (!strcmp(info_raw[i], "FSFreeBytes")) {
240 freespace = atoi(info_raw[i+1]);
241 } else if (!strcmp(info_raw[i], "FSBlockSize")) {
242 blocksize = atoi(info_raw[i+1]);
243 }
244 }
245
246 // Now to fill the struct.
247 stats->f_bsize = stats->f_frsize = blocksize;
248 stats->f_blocks = totalspace / blocksize; // gets the blocks by dividing bytes by blocksize
249 stats->f_bfree = stats->f_bavail = freespace / blocksize; // all bytes are free to everyone, I guess.
250 stats->f_namemax = 255; // blah
251 stats->f_files = stats->f_ffree = 1000000000; // make up any old thing, I guess
252 return 0;
253}
254
255int ifuse_truncate(const char *path, off_t size) {
256 int result = 0;
257 AFClient *afc = fuse_get_context()->private_data;
258 AFCFile *tfile = afc_open_file(afc, path, AFC_FILE_READ);
259 if (!tfile) return -1;
260
261 result = afc_truncate_file(afc, tfile, size);
262 afc_close_file(afc, tfile);
263 return result;
264}
265
266int ifuse_ftruncate(const char *path, off_t size, struct fuse_file_info *fi) {
267 int result = 0;
268 AFClient *afc = fuse_get_context()->private_data;
269 AFCFile *file = g_hash_table_lookup(file_handles, &fi->fh);
270 if (!file) return -ENOENT;
271
272 return afc_truncate_file(afc, file, size);
273}
274
275int ifuse_unlink(const char *path) {
276 AFClient *afc = fuse_get_context()->private_data;
277 if (afc_delete_file(afc, path)) return 0;
278 else return -1;
279}
280
281int ifuse_rename(const char *from, const char *to) {
282 AFClient *afc = fuse_get_context()->private_data;
283 if (afc_rename_file(afc, from, to)) return 0;
284 else return -1;
285}
286
287int ifuse_mkdir(const char *dir, mode_t ignored) {
288 AFClient *afc = fuse_get_context()->private_data;
289 if (afc_mkdir(afc, dir)) return 0;
290 else return -1;
291}
292
184static struct fuse_operations ifuse_oper = { 293static struct fuse_operations ifuse_oper = {
185 .getattr = ifuse_getattr, 294 .getattr = ifuse_getattr,
295 .statfs = ifuse_statfs,
186 .readdir = ifuse_readdir, 296 .readdir = ifuse_readdir,
297 .mkdir = ifuse_mkdir,
298 .rmdir = ifuse_unlink, // AFC uses the same op for both.
299 .create = ifuse_create,
187 .open = ifuse_open, 300 .open = ifuse_open,
188 .read = ifuse_read, 301 .read = ifuse_read,
302 .write = ifuse_write,
303 .truncate = ifuse_truncate,
304 .ftruncate = ifuse_ftruncate,
305 .unlink = ifuse_unlink,
306 .rename = ifuse_rename,
307 .fsync = ifuse_fsync,
189 .release = ifuse_release, 308 .release = ifuse_release,
190 .init = ifuse_init, 309 .init = ifuse_init,
191 .destroy = ifuse_cleanup 310 .destroy = ifuse_cleanup
diff --git a/src/main.c b/src/main.c
index fd2a0d4..91bb48c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -80,6 +80,13 @@ int main(int argc, char *argv[]) {
80 } 80 }
81 81
82 free_dictionary(dirs); 82 free_dictionary(dirs);
83 dirs = afc_get_devinfo(afc);
84 if (dirs) {
85 for (i = 0; strcmp(dirs[i], ""); i+=2) {
86 printf("%s: %s\n", dirs[i], dirs[i+1]);
87 }
88 }
89
83 AFCFile *my_file = afc_open_file(afc, "/iTunesOnTheGoPlaylist.plist", AFC_FILE_READ); 90 AFCFile *my_file = afc_open_file(afc, "/iTunesOnTheGoPlaylist.plist", AFC_FILE_READ);
84 if (my_file) { 91 if (my_file) {
85 printf("A file size: %i\n", my_file->size); 92 printf("A file size: %i\n", my_file->size);
@@ -108,12 +115,25 @@ int main(int argc, char *argv[]) {
108 printf("Deleting a file...\n"); 115 printf("Deleting a file...\n");
109 bytes = afc_delete_file(afc, "/delme"); 116 bytes = afc_delete_file(afc, "/delme");
110 if (bytes) printf("Success.\n"); 117 if (bytes) printf("Success.\n");
111 else printf("Failure.\n"); 118 else printf("Failure. (expected unless you have a /delme file on your phone)\n");
112 119
113 printf("Renaming a file...\n"); 120 printf("Renaming a file...\n");
114 bytes = afc_rename_file(afc, "/renme", "/renme2"); 121 bytes = afc_rename_file(afc, "/renme", "/renme2");
115 if (bytes > 0) printf("Success.\n"); 122 if (bytes > 0) printf("Success.\n");
116 else printf("Failure.\n"); 123 else printf("Failure. (expected unless you have a /renme file on your phone)\n");
124
125 printf("Seek & read\n");
126 my_file = afc_open_file(afc, "/readme.libiphone.fx", AFC_FILE_READ);
127 bytes = afc_seek_file(afc, my_file, 5);
128 if (!bytes) printf("WARN: SEEK DID NOT WORK\n");
129 char *threeletterword = (char*)malloc(sizeof(char) * 5);
130 bytes = afc_read_file(afc, my_file, threeletterword, 3);
131 threeletterword[3] = '\0';
132 if (bytes > 0) printf("Result: %s\n", threeletterword);
133 else printf("Couldn't read!\n");
134 free(threeletterword);
135 afc_close_file(afc, my_file);
136
117 } 137 }
118 afc_disconnect(afc); 138 afc_disconnect(afc);
119 } else { 139 } else {