diff options
Diffstat (limited to 'src/AFC.c')
| -rw-r--r-- | src/AFC.c | 54 |
1 files changed, 47 insertions, 7 deletions
| @@ -26,6 +26,21 @@ const int MAXIMUM_PACKET_SIZE = (2 << 15) - 32; | |||
| 26 | 26 | ||
| 27 | extern int debug; | 27 | extern int debug; |
| 28 | 28 | ||
| 29 | |||
| 30 | /* Locking, for thread-safety (well... kind of, hehe) */ | ||
| 31 | void afc_lock(AFClient *client) { | ||
| 32 | while (client->lock) { | ||
| 33 | sleep(200); | ||
| 34 | } | ||
| 35 | client->lock = 1; | ||
| 36 | } | ||
| 37 | |||
| 38 | void afc_unlock(AFClient *client) { // just to be pretty | ||
| 39 | client->lock = 0; | ||
| 40 | } | ||
| 41 | |||
| 42 | /* main AFC functions */ | ||
| 43 | |||
| 29 | AFClient *afc_connect(iPhone *phone, int s_port, int d_port) { | 44 | AFClient *afc_connect(iPhone *phone, int s_port, int d_port) { |
| 30 | if (!phone) return NULL; | 45 | if (!phone) return NULL; |
| 31 | AFClient *client = (AFClient*)malloc(sizeof(AFClient)); | 46 | AFClient *client = (AFClient*)malloc(sizeof(AFClient)); |
| @@ -39,6 +54,7 @@ AFClient *afc_connect(iPhone *phone, int s_port, int d_port) { | |||
| 39 | client->afc_packet->header1 = 0x36414643; | 54 | client->afc_packet->header1 = 0x36414643; |
| 40 | client->afc_packet->header2 = 0x4141504C; | 55 | client->afc_packet->header2 = 0x4141504C; |
| 41 | client->file_handle = 0; | 56 | client->file_handle = 0; |
| 57 | client->lock = 0; | ||
| 42 | return client; | 58 | return client; |
| 43 | } else { | 59 | } else { |
| 44 | mux_close_connection(client->connection); | 60 | mux_close_connection(client->connection); |
| @@ -184,6 +200,7 @@ int receive_AFC_data(AFClient *client, char **dump_here) { | |||
| 184 | final_buffer = (char*)malloc(sizeof(char) * recv_len); | 200 | final_buffer = (char*)malloc(sizeof(char) * recv_len); |
| 185 | while(current_count < recv_len){ | 201 | while(current_count < recv_len){ |
| 186 | bytes = mux_recv(client->connection, buffer, recv_len-current_count); | 202 | bytes = mux_recv(client->connection, buffer, recv_len-current_count); |
| 203 | if (debug) printf("receive_AFC_data: still collecting packets\n"); | ||
| 187 | if (bytes < 0) | 204 | if (bytes < 0) |
| 188 | { | 205 | { |
| 189 | if(debug) printf("receive_AFC_data: mux_recv failed: %d\n", bytes); | 206 | if(debug) printf("receive_AFC_data: mux_recv failed: %d\n", bytes); |
| @@ -194,6 +211,12 @@ int receive_AFC_data(AFClient *client, char **dump_here) { | |||
| 194 | if(debug) printf("receive_AFC_data: mux_recv delivered too much data\n"); | 211 | if(debug) printf("receive_AFC_data: mux_recv delivered too much data\n"); |
| 195 | break; | 212 | break; |
| 196 | } | 213 | } |
| 214 | if (strstr(buffer, "CFA6LPAA")) { | ||
| 215 | if (debug) printf("receive_AFC_data: WARNING: there is AFC data in this packet at %i\n", strstr(buffer, "CFA6LPAA") - buffer); | ||
| 216 | if (debug) printf("receive_AFC_data: the total packet length is %i\n", bytes); | ||
| 217 | //continue; // but we do need to continue because packets/headers != data | ||
| 218 | } | ||
| 219 | |||
| 197 | memcpy(final_buffer+current_count, buffer, bytes); | 220 | memcpy(final_buffer+current_count, buffer, bytes); |
| 198 | current_count += bytes; | 221 | current_count += bytes; |
| 199 | } | 222 | } |
| @@ -211,18 +234,20 @@ int receive_AFC_data(AFClient *client, char **dump_here) { | |||
| 211 | } | 234 | } |
| 212 | 235 | ||
| 213 | char **afc_get_dir_list(AFClient *client, const char *dir) { | 236 | char **afc_get_dir_list(AFClient *client, const char *dir) { |
| 237 | afc_lock(client); | ||
| 214 | client->afc_packet->operation = AFC_LIST_DIR; | 238 | client->afc_packet->operation = AFC_LIST_DIR; |
| 215 | int bytes = 0; | 239 | int bytes = 0; |
| 216 | char *blah = NULL, **list = NULL; | 240 | char *blah = NULL, **list = NULL; |
| 217 | client->afc_packet->entire_length = client->afc_packet->this_length = 0; | 241 | client->afc_packet->entire_length = client->afc_packet->this_length = 0; |
| 218 | bytes = dispatch_AFC_packet(client, dir, strlen(dir)); | 242 | bytes = dispatch_AFC_packet(client, dir, strlen(dir)); |
| 219 | if (!bytes) return NULL; | 243 | if (!bytes) { afc_unlock(client); return NULL; } |
| 220 | 244 | ||
| 221 | bytes = receive_AFC_data(client, &blah); | 245 | bytes = receive_AFC_data(client, &blah); |
| 222 | if (!bytes && !blah) return NULL; | 246 | if (!bytes && !blah) { afc_unlock(client); return NULL; } |
| 223 | 247 | ||
| 224 | list = make_strings_list(blah, bytes); | 248 | list = make_strings_list(blah, bytes); |
| 225 | free(blah); | 249 | free(blah); |
| 250 | afc_unlock(client); | ||
| 226 | return list; | 251 | return list; |
| 227 | } | 252 | } |
| 228 | 253 | ||
| @@ -243,23 +268,24 @@ char **make_strings_list(char *tokens, int true_length) { | |||
| 243 | 268 | ||
| 244 | int afc_delete_file(AFClient *client, const char *path) { | 269 | int afc_delete_file(AFClient *client, const char *path) { |
| 245 | if (!client || !path || !client->afc_packet || !client->connection) return 0; | 270 | if (!client || !path || !client->afc_packet || !client->connection) return 0; |
| 246 | 271 | afc_lock(client); | |
| 247 | char *receive = NULL; | 272 | char *receive = NULL; |
| 248 | client->afc_packet->this_length = client->afc_packet->entire_length = 0; | 273 | client->afc_packet->this_length = client->afc_packet->entire_length = 0; |
| 249 | client->afc_packet->operation = AFC_DELETE; | 274 | client->afc_packet->operation = AFC_DELETE; |
| 250 | int bytes; | 275 | int bytes; |
| 251 | bytes = dispatch_AFC_packet(client, path, strlen(path)); | 276 | bytes = dispatch_AFC_packet(client, path, strlen(path)); |
| 252 | if (bytes <= 0) return 0; | 277 | if (bytes <= 0) { afc_unlock(client); return 0; } |
| 253 | 278 | ||
| 254 | bytes = receive_AFC_data(client, &receive); | 279 | bytes = receive_AFC_data(client, &receive); |
| 255 | free(receive); | 280 | free(receive); |
| 256 | if (bytes <= 0) return 0; | 281 | afc_unlock(client); |
| 282 | if (bytes <= 0) { return 0; } | ||
| 257 | else return 1; | 283 | else return 1; |
| 258 | } | 284 | } |
| 259 | 285 | ||
| 260 | int afc_rename_file(AFClient *client, const char *from, const char *to) { | 286 | int afc_rename_file(AFClient *client, const char *from, const char *to) { |
| 261 | if (!client || !from || !to || !client->afc_packet || !client->connection) return 0; | 287 | if (!client || !from || !to || !client->afc_packet || !client->connection) return 0; |
| 262 | 288 | afc_lock(client); | |
| 263 | char *receive = NULL; | 289 | char *receive = NULL; |
| 264 | char *send = (char*)malloc(sizeof(char) * (strlen(from) + strlen(to) + 1 + sizeof(uint32))); | 290 | char *send = (char*)malloc(sizeof(char) * (strlen(from) + strlen(to) + 1 + sizeof(uint32))); |
| 265 | int bytes = 0; | 291 | int bytes = 0; |
| @@ -271,10 +297,11 @@ int afc_rename_file(AFClient *client, const char *from, const char *to) { | |||
| 271 | client->afc_packet->entire_length = client->afc_packet->this_length = 0; | 297 | client->afc_packet->entire_length = client->afc_packet->this_length = 0; |
| 272 | client->afc_packet->operation = AFC_RENAME; | 298 | client->afc_packet->operation = AFC_RENAME; |
| 273 | bytes = dispatch_AFC_packet(client, send, strlen(to) + strlen(from) + 2); | 299 | bytes = dispatch_AFC_packet(client, send, strlen(to) + strlen(from) + 2); |
| 274 | if (bytes <= 0) return 0; | 300 | if (bytes <= 0) { afc_unlock(client); return 0; } |
| 275 | 301 | ||
| 276 | bytes = receive_AFC_data(client, &receive); | 302 | bytes = receive_AFC_data(client, &receive); |
| 277 | free(receive); | 303 | free(receive); |
| 304 | afc_unlock(client); | ||
| 278 | if (bytes <= 0) return 0; | 305 | if (bytes <= 0) return 0; |
| 279 | else return 1; | 306 | else return 1; |
| 280 | } | 307 | } |
| @@ -284,6 +311,7 @@ int afc_rename_file(AFClient *client, const char *from, const char *to) { | |||
| 284 | AFCFile *afc_get_file_info(AFClient *client, const char *path) { | 311 | AFCFile *afc_get_file_info(AFClient *client, const char *path) { |
| 285 | client->afc_packet->operation = AFC_GET_INFO; | 312 | client->afc_packet->operation = AFC_GET_INFO; |
| 286 | client->afc_packet->entire_length = client->afc_packet->this_length = 0; | 313 | client->afc_packet->entire_length = client->afc_packet->this_length = 0; |
| 314 | afc_lock(client); | ||
| 287 | dispatch_AFC_packet(client, path, strlen(path)); | 315 | dispatch_AFC_packet(client, path, strlen(path)); |
| 288 | 316 | ||
| 289 | char *received, **list; | 317 | char *received, **list; |
| @@ -293,6 +321,7 @@ AFCFile *afc_get_file_info(AFClient *client, const char *path) { | |||
| 293 | length = receive_AFC_data(client, &received); | 321 | length = receive_AFC_data(client, &received); |
| 294 | list = make_strings_list(received, length); | 322 | list = make_strings_list(received, length); |
| 295 | free(received); | 323 | free(received); |
| 324 | afc_unlock(client); // the rest is just interpretation anyway | ||
| 296 | if (list) { | 325 | if (list) { |
| 297 | my_file = (AFCFile *)malloc(sizeof(AFCFile)); | 326 | my_file = (AFCFile *)malloc(sizeof(AFCFile)); |
| 298 | for (i = 0; strcmp(list[i], ""); i++) { | 327 | for (i = 0; strcmp(list[i], ""); i++) { |
| @@ -323,6 +352,7 @@ AFCFile *afc_get_file_info(AFClient *client, const char *path) { | |||
| 323 | AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode) { | 352 | AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode) { |
| 324 | if (file_mode != AFC_FILE_READ && file_mode != AFC_FILE_WRITE) return NULL; | 353 | if (file_mode != AFC_FILE_READ && file_mode != AFC_FILE_WRITE) return NULL; |
| 325 | if (!client ||!client->connection || !client->afc_packet) return NULL; | 354 | if (!client ||!client->connection || !client->afc_packet) return NULL; |
| 355 | afc_lock(client); | ||
| 326 | char *further_data = (char*)malloc(sizeof(char) * (8 + strlen(filename) + 1)); | 356 | char *further_data = (char*)malloc(sizeof(char) * (8 + strlen(filename) + 1)); |
| 327 | AFCFile *file_infos = NULL; | 357 | AFCFile *file_infos = NULL; |
| 328 | memcpy(further_data, &file_mode, 4); | 358 | memcpy(further_data, &file_mode, 4); |
| @@ -338,10 +368,12 @@ AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode) | |||
| 338 | free(further_data); | 368 | free(further_data); |
| 339 | if (bytes <= 0) { | 369 | if (bytes <= 0) { |
| 340 | if (debug) printf("didn't read enough\n"); | 370 | if (debug) printf("didn't read enough\n"); |
| 371 | afc_unlock(client); | ||
| 341 | return NULL; | 372 | return NULL; |
| 342 | } else { | 373 | } else { |
| 343 | length_thing = receive_AFC_data(client, &further_data); | 374 | length_thing = receive_AFC_data(client, &further_data); |
| 344 | if (length_thing && further_data) { | 375 | if (length_thing && 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. | ||
| 345 | file_infos = afc_get_file_info(client, filename); | 377 | file_infos = afc_get_file_info(client, filename); |
| 346 | memcpy(&file_infos->filehandle, further_data, 4); | 378 | memcpy(&file_infos->filehandle, further_data, 4); |
| 347 | return file_infos; | 379 | return file_infos; |
| @@ -357,6 +389,8 @@ AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode) | |||
| 357 | int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) { | 389 | int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) { |
| 358 | if (!client || !client->afc_packet || !client->connection || !file) return -1; | 390 | if (!client || !client->afc_packet || !client->connection || !file) return -1; |
| 359 | AFCFilePacket *packet = (AFCFilePacket*)malloc(sizeof(AFCFilePacket)); | 391 | AFCFilePacket *packet = (AFCFilePacket*)malloc(sizeof(AFCFilePacket)); |
| 392 | if (debug) printf("afc_read_file called for length %i\n"); | ||
| 393 | afc_lock(client); | ||
| 360 | char *input = NULL; | 394 | char *input = NULL; |
| 361 | packet->unknown1 = packet->unknown2 = 0; | 395 | packet->unknown1 = packet->unknown2 = 0; |
| 362 | packet->filehandle = file->filehandle; | 396 | packet->filehandle = file->filehandle; |
| @@ -369,6 +403,7 @@ int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) { | |||
| 369 | 403 | ||
| 370 | if (bytes > 0) { | 404 | if (bytes > 0) { |
| 371 | bytes = receive_AFC_data(client, &input); | 405 | bytes = receive_AFC_data(client, &input); |
| 406 | afc_unlock(client); | ||
| 372 | if (bytes < 0) { | 407 | if (bytes < 0) { |
| 373 | if (input) free(input); | 408 | if (input) free(input); |
| 374 | return -1; | 409 | return -1; |
| @@ -382,6 +417,7 @@ int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) { | |||
| 382 | return (bytes > length) ? length : bytes; | 417 | return (bytes > length) ? length : bytes; |
| 383 | } | 418 | } |
| 384 | } else { | 419 | } else { |
| 420 | afc_unlock(client); | ||
| 385 | return -1; | 421 | return -1; |
| 386 | } | 422 | } |
| 387 | return 0; | 423 | return 0; |
| @@ -390,6 +426,7 @@ int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) { | |||
| 390 | int afc_write_file(AFClient *client, AFCFile *file, const char *data, int length) { | 426 | int afc_write_file(AFClient *client, AFCFile *file, const char *data, int length) { |
| 391 | char *acknowledgement = NULL; | 427 | char *acknowledgement = NULL; |
| 392 | if (!client ||!client->afc_packet || !client->connection || !file) return -1; | 428 | if (!client ||!client->afc_packet || !client->connection || !file) return -1; |
| 429 | afc_lock(client); | ||
| 393 | client->afc_packet->this_length = sizeof(AFCPacket) + 8; | 430 | client->afc_packet->this_length = sizeof(AFCPacket) + 8; |
| 394 | client->afc_packet->entire_length = client->afc_packet->this_length + length; | 431 | client->afc_packet->entire_length = client->afc_packet->this_length + length; |
| 395 | client->afc_packet->operation = AFC_WRITE; | 432 | client->afc_packet->operation = AFC_WRITE; |
| @@ -407,6 +444,7 @@ int afc_write_file(AFClient *client, AFCFile *file, const char *data, int length | |||
| 407 | 444 | ||
| 408 | zero = bytes; | 445 | zero = bytes; |
| 409 | bytes = receive_AFC_data(client, &acknowledgement); | 446 | bytes = receive_AFC_data(client, &acknowledgement); |
| 447 | afc_unlock(client); | ||
| 410 | if (bytes <= 0) { | 448 | if (bytes <= 0) { |
| 411 | if (debug) printf("afc_write_file: uh oh?\n"); | 449 | if (debug) printf("afc_write_file: uh oh?\n"); |
| 412 | } | 450 | } |
| @@ -418,6 +456,7 @@ void afc_close_file(AFClient *client, AFCFile *file) { | |||
| 418 | char *buffer = malloc(sizeof(char) * 8); | 456 | char *buffer = malloc(sizeof(char) * 8); |
| 419 | uint32 zero = 0; | 457 | uint32 zero = 0; |
| 420 | if (debug) printf("File handle %i\n", file->filehandle); | 458 | if (debug) printf("File handle %i\n", file->filehandle); |
| 459 | afc_lock(client); | ||
| 421 | memcpy(buffer, &file->filehandle, sizeof(uint32)); | 460 | memcpy(buffer, &file->filehandle, sizeof(uint32)); |
| 422 | memcpy(buffer+sizeof(uint32), &zero, sizeof(zero)); | 461 | memcpy(buffer+sizeof(uint32), &zero, sizeof(zero)); |
| 423 | client->afc_packet->operation = AFC_FILE_CLOSE; | 462 | client->afc_packet->operation = AFC_FILE_CLOSE; |
| @@ -430,6 +469,7 @@ void afc_close_file(AFClient *client, AFCFile *file) { | |||
| 430 | if (!bytes) return; | 469 | if (!bytes) return; |
| 431 | 470 | ||
| 432 | bytes = receive_AFC_data(client, &buffer); | 471 | bytes = receive_AFC_data(client, &buffer); |
| 472 | afc_unlock(client); | ||
| 433 | return; | 473 | return; |
| 434 | if (buffer) free(buffer); // we're *SUPPOSED* to get an "error" here. | 474 | if (buffer) free(buffer); // we're *SUPPOSED* to get an "error" here. |
| 435 | } | 475 | } |
