summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2025-06-28 21:01:42 +0200
committerGravatar Nikias Bassen2025-06-28 21:01:42 +0200
commit9049ffb7eaab5a75018bb8fb1a54a9c9903daf00 (patch)
tree2b97019f5bf6e6986ec9a4e377b8de3062c34fc5 /src
parent39357c0eb4122eaf58382e921496984e6d0a7d5d (diff)
downloadlibimobiledevice-9049ffb7eaab5a75018bb8fb1a54a9c9903daf00.tar.gz
libimobiledevice-9049ffb7eaab5a75018bb8fb1a54a9c9903daf00.tar.bz2
afc: Add afc_get_file_info_plist and afc_get_device_info_plist functions
These functions are like afc_get_file_info/afc_get_device_info but the data is returned as a plist_t dictionary instead of a string list.
Diffstat (limited to 'src')
-rw-r--r--src/afc.c118
1 files changed, 116 insertions, 2 deletions
diff --git a/src/afc.c b/src/afc.c
index c0314bc..c7eed5c 100644
--- a/src/afc.c
+++ b/src/afc.c
@@ -402,6 +402,50 @@ static char **make_strings_list(char *tokens, uint32_t length)
402 return list; 402 return list;
403} 403}
404 404
405static plist_t *make_dictionary(char *tokens, size_t length)
406{
407 size_t j = 0;
408 plist_t dict = NULL;
409
410 if (!tokens || !length)
411 return NULL;
412
413 dict = plist_new_dict();
414
415 while (j < length) {
416 size_t key_len = strnlen(tokens + j, length - j);
417 if (j + key_len >= length) {
418 plist_free(dict);
419 return NULL;
420 }
421 char* key = tokens + j;
422 j += key_len + 1;
423
424 if (j >= length) {
425 plist_free(dict);
426 return NULL;
427 }
428
429 size_t val_len = strnlen(tokens + j, length - j);
430 if (j + val_len >= length) {
431 plist_free(dict);
432 return NULL;
433 }
434 char* val = tokens + j;
435 j += val_len + 1;
436
437 char* endp = NULL;
438 unsigned long long u64val = strtoull(val, &endp, 10);
439 if (endp && *endp == '\0') {
440 plist_dict_set_item(dict, key, plist_new_uint(u64val));
441 } else {
442 plist_dict_set_item(dict, key, plist_new_string(val));
443 }
444 }
445
446 return dict;
447}
448
405static int _afc_check_packet_buffer(afc_client_t client, uint32_t data_len) 449static int _afc_check_packet_buffer(afc_client_t client, uint32_t data_len)
406{ 450{
407 if (data_len > client->packet_extra) { 451 if (data_len > client->packet_extra) {
@@ -498,6 +542,40 @@ afc_error_t afc_get_device_info(afc_client_t client, char ***device_information)
498 return ret; 542 return ret;
499} 543}
500 544
545afc_error_t afc_get_device_info_plist(afc_client_t client, plist_t *device_information)
546{
547 uint32_t bytes = 0;
548 char *data = NULL;
549 afc_error_t ret = AFC_E_UNKNOWN_ERROR;
550
551 if (!client || !device_information)
552 return AFC_E_INVALID_ARG;
553
554 afc_lock(client);
555
556 /* Send the command */
557 ret = afc_dispatch_packet(client, AFC_OP_GET_DEVINFO, 0, NULL, 0, &bytes);
558 if (ret != AFC_E_SUCCESS) {
559 afc_unlock(client);
560 return AFC_E_NOT_ENOUGH_DATA;
561 }
562 /* Receive the data */
563 ret = afc_receive_data(client, &data, &bytes);
564 if (ret != AFC_E_SUCCESS) {
565 if (data)
566 free(data);
567 afc_unlock(client);
568 return ret;
569 }
570 /* Parse the data */
571 *device_information = make_dictionary(data, bytes);
572 free(data);
573
574 afc_unlock(client);
575
576 return ret;
577}
578
501afc_error_t afc_get_device_info_key(afc_client_t client, const char *key, char **value) 579afc_error_t afc_get_device_info_key(afc_client_t client, const char *key, char **value)
502{ 580{
503 afc_error_t ret = AFC_E_INTERNAL_ERROR; 581 afc_error_t ret = AFC_E_INTERNAL_ERROR;
@@ -647,8 +725,6 @@ afc_error_t afc_get_file_info(afc_client_t client, const char *path, char ***fil
647 return AFC_E_NO_MEM; 725 return AFC_E_NO_MEM;
648 } 726 }
649 727
650 debug_info("We got %p and %p", client->afc_packet, AFC_PACKET_DATA_PTR);
651
652 /* Send command */ 728 /* Send command */
653 memcpy(AFC_PACKET_DATA_PTR, path, data_len); 729 memcpy(AFC_PACKET_DATA_PTR, path, data_len);
654 ret = afc_dispatch_packet(client, AFC_OP_GET_FILE_INFO, data_len, NULL, 0, &bytes); 730 ret = afc_dispatch_packet(client, AFC_OP_GET_FILE_INFO, data_len, NULL, 0, &bytes);
@@ -669,6 +745,44 @@ afc_error_t afc_get_file_info(afc_client_t client, const char *path, char ***fil
669 return ret; 745 return ret;
670} 746}
671 747
748afc_error_t afc_get_file_info_plist(afc_client_t client, const char *path, plist_t *file_information)
749{
750 char *received = NULL;
751 uint32_t bytes = 0;
752 afc_error_t ret = AFC_E_UNKNOWN_ERROR;
753
754 if (!client || !path || !file_information)
755 return AFC_E_INVALID_ARG;
756
757 afc_lock(client);
758
759 uint32_t data_len = (uint32_t)strlen(path)+1;
760 if (_afc_check_packet_buffer(client, data_len) < 0) {
761 afc_unlock(client);
762 debug_info("Failed to realloc packet buffer");
763 return AFC_E_NO_MEM;
764 }
765
766 /* Send command */
767 memcpy(AFC_PACKET_DATA_PTR, path, data_len);
768 ret = afc_dispatch_packet(client, AFC_OP_GET_FILE_INFO, data_len, NULL, 0, &bytes);
769 if (ret != AFC_E_SUCCESS) {
770 afc_unlock(client);
771 return AFC_E_NOT_ENOUGH_DATA;
772 }
773
774 /* Receive data */
775 ret = afc_receive_data(client, &received, &bytes);
776 if (received) {
777 *file_information = make_dictionary(received, bytes);
778 free(received);
779 }
780
781 afc_unlock(client);
782
783 return ret;
784}
785
672afc_error_t afc_file_open(afc_client_t client, const char *filename, afc_file_mode_t file_mode, uint64_t *handle) 786afc_error_t afc_file_open(afc_client_t client, const char *filename, afc_file_mode_t file_mode, uint64_t *handle)
673{ 787{
674 if (!client || !client->parent || !client->afc_packet) 788 if (!client || !client->parent || !client->afc_packet)