diff options
| author | 2021-09-01 15:54:53 +0200 | |
|---|---|---|
| committer | 2021-09-01 15:54:53 +0200 | |
| commit | 32a8ebedc695dfae21497977bf2f77a3d5b50f91 (patch) | |
| tree | 0cfd7f83c4d49ee4a20ecdc249167f6dc084396d /src | |
| parent | c3a16f3e4968f38aa8813ad0c0731bdb5aa745fb (diff) | |
| download | usbmuxd-32a8ebedc695dfae21497977bf2f77a3d5b50f91.tar.gz usbmuxd-32a8ebedc695dfae21497977bf2f77a3d5b50f91.tar.bz2 | |
Remove common code in favor of new libimobiledevice-glue
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.am | 2 | ||||
| -rw-r--r-- | src/client.c | 43 | ||||
| -rw-r--r-- | src/conf.c | 2 | ||||
| -rw-r--r-- | src/device.c | 69 | ||||
| -rw-r--r-- | src/preflight.c | 15 | ||||
| -rw-r--r-- | src/usb.c | 2 | ||||
| -rw-r--r-- | src/utils.c | 248 | ||||
| -rw-r--r-- | src/utils.h | 43 |
8 files changed, 70 insertions, 354 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 328b700..8a96e46 100644 --- a/src/Makefile.am +++ b/src/Makefile.am | |||
| @@ -6,11 +6,13 @@ AM_CFLAGS = \ | |||
| 6 | $(GLOBAL_CFLAGS) \ | 6 | $(GLOBAL_CFLAGS) \ |
| 7 | $(libplist_CFLAGS) \ | 7 | $(libplist_CFLAGS) \ |
| 8 | $(libusb_CFLAGS) \ | 8 | $(libusb_CFLAGS) \ |
| 9 | $(limd_glue_CFLAGS) \ | ||
| 9 | $(libimobiledevice_CFLAGS) | 10 | $(libimobiledevice_CFLAGS) |
| 10 | 11 | ||
| 11 | AM_LDFLAGS = \ | 12 | AM_LDFLAGS = \ |
| 12 | $(libplist_LIBS) \ | 13 | $(libplist_LIBS) \ |
| 13 | $(libusb_LIBS) \ | 14 | $(libusb_LIBS) \ |
| 15 | $(limd_glue_LIBS) \ | ||
| 14 | $(libimobiledevice_LIBS) \ | 16 | $(libimobiledevice_LIBS) \ |
| 15 | $(libpthread_LIBS) | 17 | $(libpthread_LIBS) |
| 16 | 18 | ||
diff --git a/src/client.c b/src/client.c index 7395046..75a526d 100644 --- a/src/client.c +++ b/src/client.c | |||
| @@ -34,10 +34,11 @@ | |||
| 34 | #include <netinet/tcp.h> | 34 | #include <netinet/tcp.h> |
| 35 | #include <sys/un.h> | 35 | #include <sys/un.h> |
| 36 | #include <arpa/inet.h> | 36 | #include <arpa/inet.h> |
| 37 | #include <pthread.h> | ||
| 38 | #include <fcntl.h> | 37 | #include <fcntl.h> |
| 39 | 38 | ||
| 40 | #include <plist/plist.h> | 39 | #include <plist/plist.h> |
| 40 | #include <libimobiledevice-glue/collection.h> | ||
| 41 | #include <libimobiledevice-glue/thread.h> | ||
| 41 | 42 | ||
| 42 | #include "log.h" | 43 | #include "log.h" |
| 43 | #include "usb.h" | 44 | #include "usb.h" |
| @@ -75,7 +76,7 @@ struct mux_client { | |||
| 75 | }; | 76 | }; |
| 76 | 77 | ||
| 77 | static struct collection client_list; | 78 | static struct collection client_list; |
| 78 | pthread_mutex_t client_list_mutex; | 79 | mutex_t client_list_mutex; |
| 79 | static uint32_t client_number = 0; | 80 | static uint32_t client_number = 0; |
| 80 | 81 | ||
| 81 | #ifdef SO_PEERCRED | 82 | #ifdef SO_PEERCRED |
| @@ -224,10 +225,10 @@ int client_accept(int listenfd) | |||
| 224 | client->events = POLLIN; | 225 | client->events = POLLIN; |
| 225 | client->info = NULL; | 226 | client->info = NULL; |
| 226 | 227 | ||
| 227 | pthread_mutex_lock(&client_list_mutex); | 228 | mutex_lock(&client_list_mutex); |
| 228 | client->number = client_number++; | 229 | client->number = client_number++; |
| 229 | collection_add(&client_list, client); | 230 | collection_add(&client_list, client); |
| 230 | pthread_mutex_unlock(&client_list_mutex); | 231 | mutex_unlock(&client_list_mutex); |
| 231 | 232 | ||
| 232 | #ifdef SO_PEERCRED | 233 | #ifdef SO_PEERCRED |
| 233 | if (log_level >= LL_INFO) { | 234 | if (log_level >= LL_INFO) { |
| @@ -252,7 +253,7 @@ int client_accept(int listenfd) | |||
| 252 | void client_close(struct mux_client *client) | 253 | void client_close(struct mux_client *client) |
| 253 | { | 254 | { |
| 254 | int found = 0; | 255 | int found = 0; |
| 255 | pthread_mutex_lock(&client_list_mutex); | 256 | mutex_lock(&client_list_mutex); |
| 256 | FOREACH(struct mux_client *lc, &client_list) { | 257 | FOREACH(struct mux_client *lc, &client_list) { |
| 257 | if (client == lc) { | 258 | if (client == lc) { |
| 258 | found = 1; | 259 | found = 1; |
| @@ -262,7 +263,7 @@ void client_close(struct mux_client *client) | |||
| 262 | if (!found) { | 263 | if (!found) { |
| 263 | // in case we get called again but client was already freed | 264 | // in case we get called again but client was already freed |
| 264 | usbmuxd_log(LL_DEBUG, "%s: ignoring for non-existing client %p", __func__, client); | 265 | usbmuxd_log(LL_DEBUG, "%s: ignoring for non-existing client %p", __func__, client); |
| 265 | pthread_mutex_unlock(&client_list_mutex); | 266 | mutex_unlock(&client_list_mutex); |
| 266 | return; | 267 | return; |
| 267 | } | 268 | } |
| 268 | #ifdef SO_PEERCRED | 269 | #ifdef SO_PEERCRED |
| @@ -293,17 +294,17 @@ void client_close(struct mux_client *client) | |||
| 293 | plist_free(client->info); | 294 | plist_free(client->info); |
| 294 | 295 | ||
| 295 | collection_remove(&client_list, client); | 296 | collection_remove(&client_list, client); |
| 296 | pthread_mutex_unlock(&client_list_mutex); | 297 | mutex_unlock(&client_list_mutex); |
| 297 | free(client); | 298 | free(client); |
| 298 | } | 299 | } |
| 299 | 300 | ||
| 300 | void client_get_fds(struct fdlist *list) | 301 | void client_get_fds(struct fdlist *list) |
| 301 | { | 302 | { |
| 302 | pthread_mutex_lock(&client_list_mutex); | 303 | mutex_lock(&client_list_mutex); |
| 303 | FOREACH(struct mux_client *client, &client_list) { | 304 | FOREACH(struct mux_client *client, &client_list) { |
| 304 | fdlist_add(list, FD_CLIENT, client->fd, client->events); | 305 | fdlist_add(list, FD_CLIENT, client->fd, client->events); |
| 305 | } ENDFOREACH | 306 | } ENDFOREACH |
| 306 | pthread_mutex_unlock(&client_list_mutex); | 307 | mutex_unlock(&client_list_mutex); |
| 307 | } | 308 | } |
| 308 | 309 | ||
| 309 | static int output_buffer_add_message(struct mux_client *client, uint32_t tag, enum usbmuxd_msgtype msg, void *payload, int payload_length) | 310 | static int output_buffer_add_message(struct mux_client *client, uint32_t tag, enum usbmuxd_msgtype msg, void *payload, int payload_length) |
| @@ -442,7 +443,7 @@ static int send_listener_list(struct mux_client *client, uint32_t tag) | |||
| 442 | plist_t dict = plist_new_dict(); | 443 | plist_t dict = plist_new_dict(); |
| 443 | plist_t listeners = plist_new_array(); | 444 | plist_t listeners = plist_new_array(); |
| 444 | 445 | ||
| 445 | pthread_mutex_lock(&client_list_mutex); | 446 | mutex_lock(&client_list_mutex); |
| 446 | FOREACH(struct mux_client *lc, &client_list) { | 447 | FOREACH(struct mux_client *lc, &client_list) { |
| 447 | if (lc->state == CLIENT_LISTEN) { | 448 | if (lc->state == CLIENT_LISTEN) { |
| 448 | plist_t n = NULL; | 449 | plist_t n = NULL; |
| @@ -489,7 +490,7 @@ static int send_listener_list(struct mux_client *client, uint32_t tag) | |||
| 489 | plist_array_append_item(listeners, l); | 490 | plist_array_append_item(listeners, l); |
| 490 | } | 491 | } |
| 491 | } ENDFOREACH | 492 | } ENDFOREACH |
| 492 | pthread_mutex_unlock(&client_list_mutex); | 493 | mutex_unlock(&client_list_mutex); |
| 493 | 494 | ||
| 494 | plist_dict_set_item(dict, "ListenerList", listeners); | 495 | plist_dict_set_item(dict, "ListenerList", listeners); |
| 495 | res = send_plist(client, tag, dict); | 496 | res = send_plist(client, tag, dict); |
| @@ -975,14 +976,14 @@ static void input_buffer_process(struct mux_client *client) | |||
| 975 | void client_process(int fd, short events) | 976 | void client_process(int fd, short events) |
| 976 | { | 977 | { |
| 977 | struct mux_client *client = NULL; | 978 | struct mux_client *client = NULL; |
| 978 | pthread_mutex_lock(&client_list_mutex); | 979 | mutex_lock(&client_list_mutex); |
| 979 | FOREACH(struct mux_client *lc, &client_list) { | 980 | FOREACH(struct mux_client *lc, &client_list) { |
| 980 | if(lc->fd == fd) { | 981 | if(lc->fd == fd) { |
| 981 | client = lc; | 982 | client = lc; |
| 982 | break; | 983 | break; |
| 983 | } | 984 | } |
| 984 | } ENDFOREACH | 985 | } ENDFOREACH |
| 985 | pthread_mutex_unlock(&client_list_mutex); | 986 | mutex_unlock(&client_list_mutex); |
| 986 | 987 | ||
| 987 | if(!client) { | 988 | if(!client) { |
| 988 | usbmuxd_log(LL_INFO, "client_process: fd %d not found in client list", fd); | 989 | usbmuxd_log(LL_INFO, "client_process: fd %d not found in client list", fd); |
| @@ -1004,45 +1005,45 @@ void client_process(int fd, short events) | |||
| 1004 | 1005 | ||
| 1005 | void client_device_add(struct device_info *dev) | 1006 | void client_device_add(struct device_info *dev) |
| 1006 | { | 1007 | { |
| 1007 | pthread_mutex_lock(&client_list_mutex); | 1008 | mutex_lock(&client_list_mutex); |
| 1008 | usbmuxd_log(LL_DEBUG, "client_device_add: id %d, location 0x%x, serial %s", dev->id, dev->location, dev->serial); | 1009 | usbmuxd_log(LL_DEBUG, "client_device_add: id %d, location 0x%x, serial %s", dev->id, dev->location, dev->serial); |
| 1009 | device_set_visible(dev->id); | 1010 | device_set_visible(dev->id); |
| 1010 | FOREACH(struct mux_client *client, &client_list) { | 1011 | FOREACH(struct mux_client *client, &client_list) { |
| 1011 | if(client->state == CLIENT_LISTEN) | 1012 | if(client->state == CLIENT_LISTEN) |
| 1012 | send_device_add(client, dev); | 1013 | send_device_add(client, dev); |
| 1013 | } ENDFOREACH | 1014 | } ENDFOREACH |
| 1014 | pthread_mutex_unlock(&client_list_mutex); | 1015 | mutex_unlock(&client_list_mutex); |
| 1015 | } | 1016 | } |
| 1016 | 1017 | ||
| 1017 | void client_device_remove(int device_id) | 1018 | void client_device_remove(int device_id) |
| 1018 | { | 1019 | { |
| 1019 | pthread_mutex_lock(&client_list_mutex); | 1020 | mutex_lock(&client_list_mutex); |
| 1020 | uint32_t id = device_id; | 1021 | uint32_t id = device_id; |
| 1021 | usbmuxd_log(LL_DEBUG, "client_device_remove: id %d", device_id); | 1022 | usbmuxd_log(LL_DEBUG, "client_device_remove: id %d", device_id); |
| 1022 | FOREACH(struct mux_client *client, &client_list) { | 1023 | FOREACH(struct mux_client *client, &client_list) { |
| 1023 | if(client->state == CLIENT_LISTEN) | 1024 | if(client->state == CLIENT_LISTEN) |
| 1024 | send_device_remove(client, id); | 1025 | send_device_remove(client, id); |
| 1025 | } ENDFOREACH | 1026 | } ENDFOREACH |
| 1026 | pthread_mutex_unlock(&client_list_mutex); | 1027 | mutex_unlock(&client_list_mutex); |
| 1027 | } | 1028 | } |
| 1028 | 1029 | ||
| 1029 | void client_device_paired(int device_id) | 1030 | void client_device_paired(int device_id) |
| 1030 | { | 1031 | { |
| 1031 | pthread_mutex_lock(&client_list_mutex); | 1032 | mutex_lock(&client_list_mutex); |
| 1032 | uint32_t id = device_id; | 1033 | uint32_t id = device_id; |
| 1033 | usbmuxd_log(LL_DEBUG, "client_device_paired: id %d", device_id); | 1034 | usbmuxd_log(LL_DEBUG, "client_device_paired: id %d", device_id); |
| 1034 | FOREACH(struct mux_client *client, &client_list) { | 1035 | FOREACH(struct mux_client *client, &client_list) { |
| 1035 | if (client->state == CLIENT_LISTEN) | 1036 | if (client->state == CLIENT_LISTEN) |
| 1036 | send_device_paired(client, id); | 1037 | send_device_paired(client, id); |
| 1037 | } ENDFOREACH | 1038 | } ENDFOREACH |
| 1038 | pthread_mutex_unlock(&client_list_mutex); | 1039 | mutex_unlock(&client_list_mutex); |
| 1039 | } | 1040 | } |
| 1040 | 1041 | ||
| 1041 | void client_init(void) | 1042 | void client_init(void) |
| 1042 | { | 1043 | { |
| 1043 | usbmuxd_log(LL_DEBUG, "client_init"); | 1044 | usbmuxd_log(LL_DEBUG, "client_init"); |
| 1044 | collection_init(&client_list); | 1045 | collection_init(&client_list); |
| 1045 | pthread_mutex_init(&client_list_mutex, NULL); | 1046 | mutex_init(&client_list_mutex); |
| 1046 | } | 1047 | } |
| 1047 | 1048 | ||
| 1048 | void client_shutdown(void) | 1049 | void client_shutdown(void) |
| @@ -1051,6 +1052,6 @@ void client_shutdown(void) | |||
| 1051 | FOREACH(struct mux_client *client, &client_list) { | 1052 | FOREACH(struct mux_client *client, &client_list) { |
| 1052 | client_close(client); | 1053 | client_close(client); |
| 1053 | } ENDFOREACH | 1054 | } ENDFOREACH |
| 1054 | pthread_mutex_destroy(&client_list_mutex); | 1055 | mutex_destroy(&client_list_mutex); |
| 1055 | collection_free(&client_list); | 1056 | collection_free(&client_list); |
| 1056 | } | 1057 | } |
| @@ -39,6 +39,8 @@ | |||
| 39 | #include <shlobj.h> | 39 | #include <shlobj.h> |
| 40 | #endif | 40 | #endif |
| 41 | 41 | ||
| 42 | #include <libimobiledevice-glue/utils.h> | ||
| 43 | |||
| 42 | #include "conf.h" | 44 | #include "conf.h" |
| 43 | #include "utils.h" | 45 | #include "utils.h" |
| 44 | #include "log.h" | 46 | #include "log.h" |
diff --git a/src/device.c b/src/device.c index aac40b1..0928021 100644 --- a/src/device.c +++ b/src/device.c | |||
| @@ -32,8 +32,11 @@ | |||
| 32 | #include <string.h> | 32 | #include <string.h> |
| 33 | #include <stdint.h> | 33 | #include <stdint.h> |
| 34 | #include <inttypes.h> | 34 | #include <inttypes.h> |
| 35 | #include <pthread.h> | ||
| 36 | #include <unistd.h> | 35 | #include <unistd.h> |
| 36 | |||
| 37 | #include <libimobiledevice-glue/collection.h> | ||
| 38 | #include <libimobiledevice-glue/thread.h> | ||
| 39 | |||
| 37 | #include "device.h" | 40 | #include "device.h" |
| 38 | #include "client.h" | 41 | #include "client.h" |
| 39 | #include "preflight.h" | 42 | #include "preflight.h" |
| @@ -127,19 +130,19 @@ struct mux_device | |||
| 127 | }; | 130 | }; |
| 128 | 131 | ||
| 129 | static struct collection device_list; | 132 | static struct collection device_list; |
| 130 | pthread_mutex_t device_list_mutex; | 133 | mutex_t device_list_mutex; |
| 131 | 134 | ||
| 132 | static struct mux_device* get_mux_device_for_id(int device_id) | 135 | static struct mux_device* get_mux_device_for_id(int device_id) |
| 133 | { | 136 | { |
| 134 | struct mux_device *dev = NULL; | 137 | struct mux_device *dev = NULL; |
| 135 | pthread_mutex_lock(&device_list_mutex); | 138 | mutex_lock(&device_list_mutex); |
| 136 | FOREACH(struct mux_device *cdev, &device_list) { | 139 | FOREACH(struct mux_device *cdev, &device_list) { |
| 137 | if(cdev->id == device_id) { | 140 | if(cdev->id == device_id) { |
| 138 | dev = cdev; | 141 | dev = cdev; |
| 139 | break; | 142 | break; |
| 140 | } | 143 | } |
| 141 | } ENDFOREACH | 144 | } ENDFOREACH |
| 142 | pthread_mutex_unlock(&device_list_mutex); | 145 | mutex_unlock(&device_list_mutex); |
| 143 | 146 | ||
| 144 | return dev; | 147 | return dev; |
| 145 | } | 148 | } |
| @@ -166,7 +169,7 @@ static int get_next_device_id(void) | |||
| 166 | { | 169 | { |
| 167 | while(1) { | 170 | while(1) { |
| 168 | int ok = 1; | 171 | int ok = 1; |
| 169 | pthread_mutex_lock(&device_list_mutex); | 172 | mutex_lock(&device_list_mutex); |
| 170 | FOREACH(struct mux_device *dev, &device_list) { | 173 | FOREACH(struct mux_device *dev, &device_list) { |
| 171 | if(dev->id == next_device_id) { | 174 | if(dev->id == next_device_id) { |
| 172 | next_device_id++; | 175 | next_device_id++; |
| @@ -174,7 +177,7 @@ static int get_next_device_id(void) | |||
| 174 | break; | 177 | break; |
| 175 | } | 178 | } |
| 176 | } ENDFOREACH | 179 | } ENDFOREACH |
| 177 | pthread_mutex_unlock(&device_list_mutex); | 180 | mutex_unlock(&device_list_mutex); |
| 178 | if(ok) | 181 | if(ok) |
| 179 | return next_device_id++; | 182 | return next_device_id++; |
| 180 | } | 183 | } |
| @@ -464,9 +467,9 @@ static int send_tcp_ack(struct mux_connection *conn) | |||
| 464 | */ | 467 | */ |
| 465 | void device_client_process(int device_id, struct mux_client *client, short events) | 468 | void device_client_process(int device_id, struct mux_client *client, short events) |
| 466 | { | 469 | { |
| 467 | pthread_mutex_lock(&device_list_mutex); | 470 | mutex_lock(&device_list_mutex); |
| 468 | struct mux_connection *conn = get_mux_connection(device_id, client); | 471 | struct mux_connection *conn = get_mux_connection(device_id, client); |
| 469 | pthread_mutex_unlock(&device_list_mutex); | 472 | mutex_unlock(&device_list_mutex); |
| 470 | if(!conn) { | 473 | if(!conn) { |
| 471 | usbmuxd_log(LL_WARNING, "Could not find connection for device %d client %p", device_id, client); | 474 | usbmuxd_log(LL_WARNING, "Could not find connection for device %d client %p", device_id, client); |
| 472 | return; | 475 | return; |
| @@ -566,9 +569,9 @@ static void device_version_input(struct mux_device *dev, struct version_header * | |||
| 566 | vh->minor = ntohl(vh->minor); | 569 | vh->minor = ntohl(vh->minor); |
| 567 | if(vh->major != 2 && vh->major != 1) { | 570 | if(vh->major != 2 && vh->major != 1) { |
| 568 | usbmuxd_log(LL_ERROR, "Device %d has unknown version %d.%d", dev->id, vh->major, vh->minor); | 571 | usbmuxd_log(LL_ERROR, "Device %d has unknown version %d.%d", dev->id, vh->major, vh->minor); |
| 569 | pthread_mutex_lock(&device_list_mutex); | 572 | mutex_lock(&device_list_mutex); |
| 570 | collection_remove(&device_list, dev); | 573 | collection_remove(&device_list, dev); |
| 571 | pthread_mutex_unlock(&device_list_mutex); | 574 | mutex_unlock(&device_list_mutex); |
| 572 | free(dev); | 575 | free(dev); |
| 573 | return; | 576 | return; |
| 574 | } | 577 | } |
| @@ -726,14 +729,14 @@ static void device_tcp_input(struct mux_device *dev, struct tcphdr *th, unsigned | |||
| 726 | void device_data_input(struct usb_device *usbdev, unsigned char *buffer, uint32_t length) | 729 | void device_data_input(struct usb_device *usbdev, unsigned char *buffer, uint32_t length) |
| 727 | { | 730 | { |
| 728 | struct mux_device *dev = NULL; | 731 | struct mux_device *dev = NULL; |
| 729 | pthread_mutex_lock(&device_list_mutex); | 732 | mutex_lock(&device_list_mutex); |
| 730 | FOREACH(struct mux_device *tdev, &device_list) { | 733 | FOREACH(struct mux_device *tdev, &device_list) { |
| 731 | if(tdev->usbdev == usbdev) { | 734 | if(tdev->usbdev == usbdev) { |
| 732 | dev = tdev; | 735 | dev = tdev; |
| 733 | break; | 736 | break; |
| 734 | } | 737 | } |
| 735 | } ENDFOREACH | 738 | } ENDFOREACH |
| 736 | pthread_mutex_unlock(&device_list_mutex); | 739 | mutex_unlock(&device_list_mutex); |
| 737 | if(!dev) { | 740 | if(!dev) { |
| 738 | usbmuxd_log(LL_WARNING, "Cannot find device entry for RX input from USB device %p on location 0x%x", usbdev, usb_get_location(usbdev)); | 741 | usbmuxd_log(LL_WARNING, "Cannot find device entry for RX input from USB device %p on location 0x%x", usbdev, usb_get_location(usbdev)); |
| 739 | return; | 742 | return; |
| @@ -850,15 +853,15 @@ int device_add(struct usb_device *usbdev) | |||
| 850 | free(dev); | 853 | free(dev); |
| 851 | return res; | 854 | return res; |
| 852 | } | 855 | } |
| 853 | pthread_mutex_lock(&device_list_mutex); | 856 | mutex_lock(&device_list_mutex); |
| 854 | collection_add(&device_list, dev); | 857 | collection_add(&device_list, dev); |
| 855 | pthread_mutex_unlock(&device_list_mutex); | 858 | mutex_unlock(&device_list_mutex); |
| 856 | return 0; | 859 | return 0; |
| 857 | } | 860 | } |
| 858 | 861 | ||
| 859 | void device_remove(struct usb_device *usbdev) | 862 | void device_remove(struct usb_device *usbdev) |
| 860 | { | 863 | { |
| 861 | pthread_mutex_lock(&device_list_mutex); | 864 | mutex_lock(&device_list_mutex); |
| 862 | FOREACH(struct mux_device *dev, &device_list) { | 865 | FOREACH(struct mux_device *dev, &device_list) { |
| 863 | if(dev->usbdev == usbdev) { | 866 | if(dev->usbdev == usbdev) { |
| 864 | usbmuxd_log(LL_NOTICE, "Removed device %d on location 0x%x", dev->id, usb_get_location(usbdev)); | 867 | usbmuxd_log(LL_NOTICE, "Removed device %d on location 0x%x", dev->id, usb_get_location(usbdev)); |
| @@ -874,48 +877,48 @@ void device_remove(struct usb_device *usbdev) | |||
| 874 | preflight_device_remove_cb(dev->preflight_cb_data); | 877 | preflight_device_remove_cb(dev->preflight_cb_data); |
| 875 | } | 878 | } |
| 876 | collection_remove(&device_list, dev); | 879 | collection_remove(&device_list, dev); |
| 877 | pthread_mutex_unlock(&device_list_mutex); | 880 | mutex_unlock(&device_list_mutex); |
| 878 | free(dev->pktbuf); | 881 | free(dev->pktbuf); |
| 879 | free(dev); | 882 | free(dev); |
| 880 | return; | 883 | return; |
| 881 | } | 884 | } |
| 882 | } ENDFOREACH | 885 | } ENDFOREACH |
| 883 | pthread_mutex_unlock(&device_list_mutex); | 886 | mutex_unlock(&device_list_mutex); |
| 884 | 887 | ||
| 885 | usbmuxd_log(LL_WARNING, "Cannot find device entry while removing USB device %p on location 0x%x", usbdev, usb_get_location(usbdev)); | 888 | usbmuxd_log(LL_WARNING, "Cannot find device entry while removing USB device %p on location 0x%x", usbdev, usb_get_location(usbdev)); |
| 886 | } | 889 | } |
| 887 | 890 | ||
| 888 | void device_set_visible(int device_id) | 891 | void device_set_visible(int device_id) |
| 889 | { | 892 | { |
| 890 | pthread_mutex_lock(&device_list_mutex); | 893 | mutex_lock(&device_list_mutex); |
| 891 | FOREACH(struct mux_device *dev, &device_list) { | 894 | FOREACH(struct mux_device *dev, &device_list) { |
| 892 | if(dev->id == device_id) { | 895 | if(dev->id == device_id) { |
| 893 | dev->visible = 1; | 896 | dev->visible = 1; |
| 894 | break; | 897 | break; |
| 895 | } | 898 | } |
| 896 | } ENDFOREACH | 899 | } ENDFOREACH |
| 897 | pthread_mutex_unlock(&device_list_mutex); | 900 | mutex_unlock(&device_list_mutex); |
| 898 | } | 901 | } |
| 899 | 902 | ||
| 900 | void device_set_preflight_cb_data(int device_id, void* data) | 903 | void device_set_preflight_cb_data(int device_id, void* data) |
| 901 | { | 904 | { |
| 902 | pthread_mutex_lock(&device_list_mutex); | 905 | mutex_lock(&device_list_mutex); |
| 903 | FOREACH(struct mux_device *dev, &device_list) { | 906 | FOREACH(struct mux_device *dev, &device_list) { |
| 904 | if(dev->id == device_id) { | 907 | if(dev->id == device_id) { |
| 905 | dev->preflight_cb_data = data; | 908 | dev->preflight_cb_data = data; |
| 906 | break; | 909 | break; |
| 907 | } | 910 | } |
| 908 | } ENDFOREACH | 911 | } ENDFOREACH |
| 909 | pthread_mutex_unlock(&device_list_mutex); | 912 | mutex_unlock(&device_list_mutex); |
| 910 | } | 913 | } |
| 911 | 914 | ||
| 912 | int device_get_count(int include_hidden) | 915 | int device_get_count(int include_hidden) |
| 913 | { | 916 | { |
| 914 | int count = 0; | 917 | int count = 0; |
| 915 | struct collection dev_list = {NULL, 0}; | 918 | struct collection dev_list = {NULL, 0}; |
| 916 | pthread_mutex_lock(&device_list_mutex); | 919 | mutex_lock(&device_list_mutex); |
| 917 | collection_copy(&dev_list, &device_list); | 920 | collection_copy(&dev_list, &device_list); |
| 918 | pthread_mutex_unlock(&device_list_mutex); | 921 | mutex_unlock(&device_list_mutex); |
| 919 | 922 | ||
| 920 | FOREACH(struct mux_device *dev, &dev_list) { | 923 | FOREACH(struct mux_device *dev, &dev_list) { |
| 921 | if((dev->state == MUXDEV_ACTIVE) && (include_hidden || dev->visible)) | 924 | if((dev->state == MUXDEV_ACTIVE) && (include_hidden || dev->visible)) |
| @@ -930,9 +933,9 @@ int device_get_list(int include_hidden, struct device_info **devices) | |||
| 930 | { | 933 | { |
| 931 | int count = 0; | 934 | int count = 0; |
| 932 | struct collection dev_list = {NULL, 0}; | 935 | struct collection dev_list = {NULL, 0}; |
| 933 | pthread_mutex_lock(&device_list_mutex); | 936 | mutex_lock(&device_list_mutex); |
| 934 | collection_copy(&dev_list, &device_list); | 937 | collection_copy(&dev_list, &device_list); |
| 935 | pthread_mutex_unlock(&device_list_mutex); | 938 | mutex_unlock(&device_list_mutex); |
| 936 | 939 | ||
| 937 | *devices = malloc(sizeof(struct device_info) * dev_list.capacity); | 940 | *devices = malloc(sizeof(struct device_info) * dev_list.capacity); |
| 938 | struct device_info *p = *devices; | 941 | struct device_info *p = *devices; |
| @@ -957,7 +960,7 @@ int device_get_list(int include_hidden, struct device_info **devices) | |||
| 957 | int device_get_timeout(void) | 960 | int device_get_timeout(void) |
| 958 | { | 961 | { |
| 959 | uint64_t oldest = (uint64_t)-1LL; | 962 | uint64_t oldest = (uint64_t)-1LL; |
| 960 | pthread_mutex_lock(&device_list_mutex); | 963 | mutex_lock(&device_list_mutex); |
| 961 | FOREACH(struct mux_device *dev, &device_list) { | 964 | FOREACH(struct mux_device *dev, &device_list) { |
| 962 | if(dev->state == MUXDEV_ACTIVE) { | 965 | if(dev->state == MUXDEV_ACTIVE) { |
| 963 | FOREACH(struct mux_connection *conn, &dev->connections) { | 966 | FOREACH(struct mux_connection *conn, &dev->connections) { |
| @@ -966,7 +969,7 @@ int device_get_timeout(void) | |||
| 966 | } ENDFOREACH | 969 | } ENDFOREACH |
| 967 | } | 970 | } |
| 968 | } ENDFOREACH | 971 | } ENDFOREACH |
| 969 | pthread_mutex_unlock(&device_list_mutex); | 972 | mutex_unlock(&device_list_mutex); |
| 970 | uint64_t ct = mstime64(); | 973 | uint64_t ct = mstime64(); |
| 971 | if((int64_t)oldest == -1LL) | 974 | if((int64_t)oldest == -1LL) |
| 972 | return 100000; //meh | 975 | return 100000; //meh |
| @@ -978,7 +981,7 @@ int device_get_timeout(void) | |||
| 978 | void device_check_timeouts(void) | 981 | void device_check_timeouts(void) |
| 979 | { | 982 | { |
| 980 | uint64_t ct = mstime64(); | 983 | uint64_t ct = mstime64(); |
| 981 | pthread_mutex_lock(&device_list_mutex); | 984 | mutex_lock(&device_list_mutex); |
| 982 | FOREACH(struct mux_device *dev, &device_list) { | 985 | FOREACH(struct mux_device *dev, &device_list) { |
| 983 | if(dev->state == MUXDEV_ACTIVE) { | 986 | if(dev->state == MUXDEV_ACTIVE) { |
| 984 | FOREACH(struct mux_connection *conn, &dev->connections) { | 987 | FOREACH(struct mux_connection *conn, &dev->connections) { |
| @@ -991,14 +994,14 @@ void device_check_timeouts(void) | |||
| 991 | } ENDFOREACH | 994 | } ENDFOREACH |
| 992 | } | 995 | } |
| 993 | } ENDFOREACH | 996 | } ENDFOREACH |
| 994 | pthread_mutex_unlock(&device_list_mutex); | 997 | mutex_unlock(&device_list_mutex); |
| 995 | } | 998 | } |
| 996 | 999 | ||
| 997 | void device_init(void) | 1000 | void device_init(void) |
| 998 | { | 1001 | { |
| 999 | usbmuxd_log(LL_DEBUG, "device_init"); | 1002 | usbmuxd_log(LL_DEBUG, "device_init"); |
| 1000 | collection_init(&device_list); | 1003 | collection_init(&device_list); |
| 1001 | pthread_mutex_init(&device_list_mutex, NULL); | 1004 | mutex_init(&device_list_mutex); |
| 1002 | next_device_id = 1; | 1005 | next_device_id = 1; |
| 1003 | } | 1006 | } |
| 1004 | 1007 | ||
| @@ -1019,7 +1022,7 @@ void device_kill_connections(void) | |||
| 1019 | void device_shutdown(void) | 1022 | void device_shutdown(void) |
| 1020 | { | 1023 | { |
| 1021 | usbmuxd_log(LL_DEBUG, "device_shutdown"); | 1024 | usbmuxd_log(LL_DEBUG, "device_shutdown"); |
| 1022 | pthread_mutex_lock(&device_list_mutex); | 1025 | mutex_lock(&device_list_mutex); |
| 1023 | FOREACH(struct mux_device *dev, &device_list) { | 1026 | FOREACH(struct mux_device *dev, &device_list) { |
| 1024 | FOREACH(struct mux_connection *conn, &dev->connections) { | 1027 | FOREACH(struct mux_connection *conn, &dev->connections) { |
| 1025 | connection_teardown(conn); | 1028 | connection_teardown(conn); |
| @@ -1028,7 +1031,7 @@ void device_shutdown(void) | |||
| 1028 | collection_remove(&device_list, dev); | 1031 | collection_remove(&device_list, dev); |
| 1029 | free(dev); | 1032 | free(dev); |
| 1030 | } ENDFOREACH | 1033 | } ENDFOREACH |
| 1031 | pthread_mutex_unlock(&device_list_mutex); | 1034 | mutex_unlock(&device_list_mutex); |
| 1032 | pthread_mutex_destroy(&device_list_mutex); | 1035 | mutex_destroy(&device_list_mutex); |
| 1033 | collection_free(&device_list); | 1036 | collection_free(&device_list); |
| 1034 | } | 1037 | } |
diff --git a/src/preflight.c b/src/preflight.c index 6a303c2..5902f5d 100644 --- a/src/preflight.c +++ b/src/preflight.c | |||
| @@ -26,8 +26,6 @@ | |||
| 26 | #include <unistd.h> | 26 | #include <unistd.h> |
| 27 | #include <errno.h> | 27 | #include <errno.h> |
| 28 | 28 | ||
| 29 | #include <pthread.h> | ||
| 30 | |||
| 31 | #include <sys/time.h> | 29 | #include <sys/time.h> |
| 32 | 30 | ||
| 33 | #ifdef HAVE_LIBIMOBILEDEVICE | 31 | #ifdef HAVE_LIBIMOBILEDEVICE |
| @@ -36,6 +34,8 @@ | |||
| 36 | #include <libimobiledevice/notification_proxy.h> | 34 | #include <libimobiledevice/notification_proxy.h> |
| 37 | #endif | 35 | #endif |
| 38 | 36 | ||
| 37 | #include <libimobiledevice-glue/thread.h> | ||
| 38 | |||
| 39 | #include "preflight.h" | 39 | #include "preflight.h" |
| 40 | #include "device.h" | 40 | #include "device.h" |
| 41 | #include "client.h" | 41 | #include "client.h" |
| @@ -389,18 +389,15 @@ void preflight_worker_device_add(struct device_info* info) | |||
| 389 | infocopy->serial = strdup(info->serial); | 389 | infocopy->serial = strdup(info->serial); |
| 390 | } | 390 | } |
| 391 | 391 | ||
| 392 | pthread_t th; | 392 | THREAD_T th; |
| 393 | pthread_attr_t attr; | 393 | int perr = thread_new(&th, preflight_worker_handle_device_add, infocopy); |
| 394 | |||
| 395 | pthread_attr_init(&attr); | ||
| 396 | pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); | ||
| 397 | |||
| 398 | int perr = pthread_create(&th, &attr, preflight_worker_handle_device_add, infocopy); | ||
| 399 | if (perr != 0) { | 394 | if (perr != 0) { |
| 400 | free((char*)infocopy->serial); | 395 | free((char*)infocopy->serial); |
| 401 | free(infocopy); | 396 | free(infocopy); |
| 402 | usbmuxd_log(LL_ERROR, "ERROR: failed to start preflight worker thread for device %s: %s (%d). Invoking client_device_add() directly but things might not work as expected.", info->serial, strerror(perr), perr); | 397 | usbmuxd_log(LL_ERROR, "ERROR: failed to start preflight worker thread for device %s: %s (%d). Invoking client_device_add() directly but things might not work as expected.", info->serial, strerror(perr), perr); |
| 403 | client_device_add(info); | 398 | client_device_add(info); |
| 399 | } else { | ||
| 400 | thread_detach(th); | ||
| 404 | } | 401 | } |
| 405 | #else | 402 | #else |
| 406 | client_device_add(info); | 403 | client_device_add(info); |
| @@ -31,6 +31,8 @@ | |||
| 31 | 31 | ||
| 32 | #include <libusb.h> | 32 | #include <libusb.h> |
| 33 | 33 | ||
| 34 | #include <libimobiledevice-glue/collection.h> | ||
| 35 | |||
| 34 | #include "usb.h" | 36 | #include "usb.h" |
| 35 | #include "log.h" | 37 | #include "log.h" |
| 36 | #include "device.h" | 38 | #include "device.h" |
diff --git a/src/utils.c b/src/utils.c index 206c684..2cc5675 100644 --- a/src/utils.c +++ b/src/utils.c | |||
| @@ -76,254 +76,6 @@ void fdlist_reset(struct fdlist *list) | |||
| 76 | list->count = 0; | 76 | list->count = 0; |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | #define CAPACITY_STEP 8 | ||
| 80 | |||
| 81 | void collection_init(struct collection *col) | ||
| 82 | { | ||
| 83 | col->list = malloc(sizeof(void *) * CAPACITY_STEP); | ||
| 84 | memset(col->list, 0, sizeof(void *) * CAPACITY_STEP); | ||
| 85 | col->capacity = CAPACITY_STEP; | ||
| 86 | } | ||
| 87 | |||
| 88 | void collection_free(struct collection *col) | ||
| 89 | { | ||
| 90 | free(col->list); | ||
| 91 | col->list = NULL; | ||
| 92 | col->capacity = 0; | ||
| 93 | } | ||
| 94 | |||
| 95 | void collection_add(struct collection *col, void *element) | ||
| 96 | { | ||
| 97 | int i; | ||
| 98 | for(i=0; i<col->capacity; i++) { | ||
| 99 | if(!col->list[i]) { | ||
| 100 | col->list[i] = element; | ||
| 101 | return; | ||
| 102 | } | ||
| 103 | } | ||
| 104 | col->list = realloc(col->list, sizeof(void*) * (col->capacity + CAPACITY_STEP)); | ||
| 105 | memset(&col->list[col->capacity], 0, sizeof(void *) * CAPACITY_STEP); | ||
| 106 | col->list[col->capacity] = element; | ||
| 107 | col->capacity += CAPACITY_STEP; | ||
| 108 | } | ||
| 109 | |||
| 110 | void collection_remove(struct collection *col, void *element) | ||
| 111 | { | ||
| 112 | int i; | ||
| 113 | for(i=0; i<col->capacity; i++) { | ||
| 114 | if(col->list[i] == element) { | ||
| 115 | col->list[i] = NULL; | ||
| 116 | return; | ||
| 117 | } | ||
| 118 | } | ||
| 119 | util_error("collection_remove: element %p not present in collection %p (cap %d)", element, col, col->capacity); | ||
| 120 | } | ||
| 121 | |||
| 122 | int collection_count(struct collection *col) | ||
| 123 | { | ||
| 124 | int i, cnt = 0; | ||
| 125 | for(i=0; i<col->capacity; i++) { | ||
| 126 | if(col->list[i]) | ||
| 127 | cnt++; | ||
| 128 | } | ||
| 129 | return cnt; | ||
| 130 | } | ||
| 131 | |||
| 132 | void collection_copy(struct collection *dest, struct collection *src) | ||
| 133 | { | ||
| 134 | if (!dest || !src) return; | ||
| 135 | dest->capacity = src->capacity; | ||
| 136 | dest->list = malloc(sizeof(void*) * src->capacity); | ||
| 137 | memcpy(dest->list, src->list, sizeof(void*) * src->capacity); | ||
| 138 | } | ||
| 139 | |||
| 140 | #ifndef HAVE_STPCPY | ||
| 141 | /** | ||
| 142 | * Copy characters from one string into another | ||
| 143 | * | ||
| 144 | * @note: The strings should not overlap, as the behavior is undefined. | ||
| 145 | * | ||
| 146 | * @s1: The source string. | ||
| 147 | * @s2: The destination string. | ||
| 148 | * | ||
| 149 | * @return a pointer to the terminating `\0' character of @s1, | ||
| 150 | * or NULL if @s1 or @s2 is NULL. | ||
| 151 | */ | ||
| 152 | char *stpcpy(char * s1, const char * s2) | ||
| 153 | { | ||
| 154 | if (s1 == NULL || s2 == NULL) | ||
| 155 | return NULL; | ||
| 156 | |||
| 157 | strcpy(s1, s2); | ||
| 158 | |||
| 159 | return s1 + strlen(s2); | ||
| 160 | } | ||
| 161 | #endif | ||
| 162 | |||
| 163 | /** | ||
| 164 | * Concatenate strings into a newly allocated string | ||
| 165 | * | ||
| 166 | * @note: Specify NULL for the last string in the varargs list | ||
| 167 | * | ||
| 168 | * @str: The first string in the list | ||
| 169 | * @...: Subsequent strings. Use NULL for the last item. | ||
| 170 | * | ||
| 171 | * @return a newly allocated string, or NULL if @str is NULL. This will also | ||
| 172 | * return NULL and set errno to ENOMEM if memory is exhausted. | ||
| 173 | */ | ||
| 174 | char *string_concat(const char *str, ...) | ||
| 175 | { | ||
| 176 | size_t len; | ||
| 177 | va_list args; | ||
| 178 | char *s; | ||
| 179 | char *result; | ||
| 180 | char *dest; | ||
| 181 | |||
| 182 | if (!str) | ||
| 183 | return NULL; | ||
| 184 | |||
| 185 | /* Compute final length */ | ||
| 186 | |||
| 187 | len = strlen(str) + 1; /* plus 1 for the null terminator */ | ||
| 188 | |||
| 189 | va_start(args, str); | ||
| 190 | s = va_arg(args, char *); | ||
| 191 | while (s) { | ||
| 192 | len += strlen(s); | ||
| 193 | s = va_arg(args, char*); | ||
| 194 | } | ||
| 195 | va_end(args); | ||
| 196 | |||
| 197 | /* Concat each string */ | ||
| 198 | |||
| 199 | result = malloc(len); | ||
| 200 | if (!result) | ||
| 201 | return NULL; /* errno remains set */ | ||
| 202 | |||
| 203 | dest = result; | ||
| 204 | |||
| 205 | dest = stpcpy(dest, str); | ||
| 206 | |||
| 207 | va_start(args, str); | ||
| 208 | s = va_arg(args, char *); | ||
| 209 | while (s) { | ||
| 210 | dest = stpcpy(dest, s); | ||
| 211 | s = va_arg(args, char *); | ||
| 212 | } | ||
| 213 | va_end(args); | ||
| 214 | |||
| 215 | return result; | ||
| 216 | } | ||
| 217 | |||
| 218 | int buffer_read_from_filename(const char *filename, char **buffer, uint64_t *length) | ||
| 219 | { | ||
| 220 | FILE *f; | ||
| 221 | uint64_t size; | ||
| 222 | |||
| 223 | *length = 0; | ||
| 224 | |||
| 225 | f = fopen(filename, "rb"); | ||
| 226 | if (!f) { | ||
| 227 | return 0; | ||
| 228 | } | ||
| 229 | |||
| 230 | fseek(f, 0, SEEK_END); | ||
| 231 | size = ftell(f); | ||
| 232 | rewind(f); | ||
| 233 | |||
| 234 | if (size == 0) { | ||
| 235 | fclose(f); | ||
| 236 | return 0; | ||
| 237 | } | ||
| 238 | |||
| 239 | *buffer = (char*)malloc(sizeof(char)*(size+1)); | ||
| 240 | |||
| 241 | if (!buffer) { | ||
| 242 | return 0; | ||
| 243 | } | ||
| 244 | |||
| 245 | int ret = 1; | ||
| 246 | if (fread(*buffer, sizeof(char), size, f) != size) { | ||
| 247 | usbmuxd_log(LL_ERROR, "%s: ERROR: couldn't read %d bytes from %s", __func__, (int)size, filename); | ||
| 248 | free(*buffer); | ||
| 249 | ret = 0; | ||
| 250 | errno = EIO; | ||
| 251 | } | ||
| 252 | fclose(f); | ||
| 253 | |||
| 254 | *length = size; | ||
| 255 | return ret; | ||
| 256 | } | ||
| 257 | |||
| 258 | int buffer_write_to_filename(const char *filename, const char *buffer, uint64_t length) | ||
| 259 | { | ||
| 260 | FILE *f; | ||
| 261 | |||
| 262 | f = fopen(filename, "wb"); | ||
| 263 | if (f) { | ||
| 264 | size_t written = fwrite(buffer, sizeof(char), length, f); | ||
| 265 | fclose(f); | ||
| 266 | |||
| 267 | if (written == length) { | ||
| 268 | return 1; | ||
| 269 | } | ||
| 270 | else { | ||
| 271 | // Not all data could be written. | ||
| 272 | errno = EIO; | ||
| 273 | return 0; | ||
| 274 | } | ||
| 275 | } | ||
| 276 | else { | ||
| 277 | // Failed to open the file, let the caller know. | ||
| 278 | return 0; | ||
| 279 | } | ||
| 280 | } | ||
| 281 | |||
| 282 | int plist_read_from_filename(plist_t *plist, const char *filename) | ||
| 283 | { | ||
| 284 | char *buffer = NULL; | ||
| 285 | uint64_t length; | ||
| 286 | |||
| 287 | if (!filename) | ||
| 288 | return 0; | ||
| 289 | |||
| 290 | if (!buffer_read_from_filename(filename, &buffer, &length)) { | ||
| 291 | return 0; | ||
| 292 | } | ||
| 293 | |||
| 294 | if ((length > 8) && (memcmp(buffer, "bplist00", 8) == 0)) { | ||
| 295 | plist_from_bin(buffer, length, plist); | ||
| 296 | } else { | ||
| 297 | plist_from_xml(buffer, length, plist); | ||
| 298 | } | ||
| 299 | |||
| 300 | free(buffer); | ||
| 301 | |||
| 302 | return 1; | ||
| 303 | } | ||
| 304 | |||
| 305 | int plist_write_to_filename(plist_t plist, const char *filename, enum plist_format_t format) | ||
| 306 | { | ||
| 307 | char *buffer = NULL; | ||
| 308 | uint32_t length; | ||
| 309 | |||
| 310 | if (!plist || !filename) | ||
| 311 | return 0; | ||
| 312 | |||
| 313 | if (format == PLIST_FORMAT_XML) | ||
| 314 | plist_to_xml(plist, &buffer, &length); | ||
| 315 | else if (format == PLIST_FORMAT_BINARY) | ||
| 316 | plist_to_bin(plist, &buffer, &length); | ||
| 317 | else | ||
| 318 | return 0; | ||
| 319 | |||
| 320 | int res = buffer_write_to_filename(filename, buffer, length); | ||
| 321 | |||
| 322 | free(buffer); | ||
| 323 | |||
| 324 | return res; | ||
| 325 | } | ||
| 326 | |||
| 327 | #ifndef HAVE_CLOCK_GETTIME | 79 | #ifndef HAVE_CLOCK_GETTIME |
| 328 | typedef int clockid_t; | 80 | typedef int clockid_t; |
| 329 | #define CLOCK_MONOTONIC 1 | 81 | #define CLOCK_MONOTONIC 1 |
diff --git a/src/utils.h b/src/utils.h index b5cab3f..ce3b2e0 100644 --- a/src/utils.h +++ b/src/utils.h | |||
| @@ -43,49 +43,6 @@ void fdlist_add(struct fdlist *list, enum fdowner owner, int fd, short events); | |||
| 43 | void fdlist_free(struct fdlist *list); | 43 | void fdlist_free(struct fdlist *list); |
| 44 | void fdlist_reset(struct fdlist *list); | 44 | void fdlist_reset(struct fdlist *list); |
| 45 | 45 | ||
| 46 | struct collection { | ||
| 47 | void **list; | ||
| 48 | int capacity; | ||
| 49 | }; | ||
| 50 | |||
| 51 | void collection_init(struct collection *col); | ||
| 52 | void collection_add(struct collection *col, void *element); | ||
| 53 | void collection_remove(struct collection *col, void *element); | ||
| 54 | int collection_count(struct collection *col); | ||
| 55 | void collection_free(struct collection *col); | ||
| 56 | void collection_copy(struct collection *dest, struct collection *src); | ||
| 57 | |||
| 58 | #define MERGE_(a,b) a ## _ ## b | ||
| 59 | #define LABEL_(a,b) MERGE_(a, b) | ||
| 60 | #define UNIQUE_VAR(a) LABEL_(a, __LINE__) | ||
| 61 | |||
| 62 | #define FOREACH(var, col) \ | ||
| 63 | do { \ | ||
| 64 | int UNIQUE_VAR(_iter); \ | ||
| 65 | for(UNIQUE_VAR(_iter)=0; UNIQUE_VAR(_iter)<(col)->capacity; UNIQUE_VAR(_iter)++) { \ | ||
| 66 | if(!(col)->list[UNIQUE_VAR(_iter)]) continue; \ | ||
| 67 | var = (col)->list[UNIQUE_VAR(_iter)]; | ||
| 68 | |||
| 69 | #define ENDFOREACH \ | ||
| 70 | } \ | ||
| 71 | } while(0); | ||
| 72 | |||
| 73 | #ifndef HAVE_STPCPY | ||
| 74 | char *stpcpy(char * s1, const char * s2); | ||
| 75 | #endif | ||
| 76 | char *string_concat(const char *str, ...); | ||
| 77 | |||
| 78 | int buffer_read_from_filename(const char *filename, char **buffer, uint64_t *length); | ||
| 79 | int buffer_write_to_filename(const char *filename, const char *buffer, uint64_t length); | ||
| 80 | |||
| 81 | enum plist_format_t { | ||
| 82 | PLIST_FORMAT_XML, | ||
| 83 | PLIST_FORMAT_BINARY | ||
| 84 | }; | ||
| 85 | |||
| 86 | int plist_read_from_filename(plist_t *plist, const char *filename); | ||
| 87 | int plist_write_to_filename(plist_t plist, const char *filename, enum plist_format_t format); | ||
| 88 | |||
| 89 | uint64_t mstime64(void); | 46 | uint64_t mstime64(void); |
| 90 | void get_tick_count(struct timeval * tv); | 47 | void get_tick_count(struct timeval * tv); |
| 91 | 48 | ||
