1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2014, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 4 */ 5 #include "array.h" 6 #include <errno.h> 7 #include <fcntl.h> 8 #include <poll.h> 9 #include <stdlib.h> 10 #include <unistd.h> 11 12 void fdarray__init(struct fdarray *fda, int nr_autogrow) 13 { 14 fda->entries = NULL; 15 fda->priv = NULL; 16 fda->nr = fda->nr_alloc = 0; 17 fda->nr_autogrow = nr_autogrow; 18 } 19 20 int fdarray__grow(struct fdarray *fda, int nr) 21 { 22 void *priv; 23 int nr_alloc = fda->nr_alloc + nr; 24 size_t psize = sizeof(fda->priv[0]) * nr_alloc; 25 size_t size = sizeof(struct pollfd) * nr_alloc; 26 struct pollfd *entries = realloc(fda->entries, size); 27 28 if (entries == NULL) 29 return -ENOMEM; 30 31 priv = realloc(fda->priv, psize); 32 if (priv == NULL) { 33 free(entries); 34 return -ENOMEM; 35 } 36 37 fda->nr_alloc = nr_alloc; 38 fda->entries = entries; 39 fda->priv = priv; 40 return 0; 41 } 42 43 struct fdarray *fdarray__new(int nr_alloc, int nr_autogrow) 44 { 45 struct fdarray *fda = calloc(1, sizeof(*fda)); 46 47 if (fda != NULL) { 48 if (fdarray__grow(fda, nr_alloc)) { 49 free(fda); 50 fda = NULL; 51 } else { 52 fda->nr_autogrow = nr_autogrow; 53 } 54 } 55 56 return fda; 57 } 58 59 void fdarray__exit(struct fdarray *fda) 60 { 61 free(fda->entries); 62 free(fda->priv); 63 fdarray__init(fda, 0); 64 } 65 66 void fdarray__delete(struct fdarray *fda) 67 { 68 fdarray__exit(fda); 69 free(fda); 70 } 71 72 int fdarray__add(struct fdarray *fda, int fd, short revents) 73 { 74 int pos = fda->nr; 75 76 if (fda->nr == fda->nr_alloc && 77 fdarray__grow(fda, fda->nr_autogrow) < 0) 78 return -ENOMEM; 79 80 fda->entries[fda->nr].fd = fd; 81 fda->entries[fda->nr].events = revents; 82 fda->nr++; 83 return pos; 84 } 85 86 int fdarray__filter(struct fdarray *fda, short revents, 87 void (*entry_destructor)(struct fdarray *fda, int fd, void *arg), 88 void *arg) 89 { 90 int fd, nr = 0; 91 92 if (fda->nr == 0) 93 return 0; 94 95 for (fd = 0; fd < fda->nr; ++fd) { 96 if (fda->entries[fd].revents & revents) { 97 if (entry_destructor) 98 entry_destructor(fda, fd, arg); 99 100 continue; 101 } 102 103 if (fd != nr) { 104 fda->entries[nr] = fda->entries[fd]; 105 fda->priv[nr] = fda->priv[fd]; 106 } 107 108 ++nr; 109 } 110 111 return fda->nr = nr; 112 } 113 114 int fdarray__poll(struct fdarray *fda, int timeout) 115 { 116 return poll(fda->entries, fda->nr, timeout); 117 } 118 119 int fdarray__fprintf(struct fdarray *fda, FILE *fp) 120 { 121 int fd, printed = fprintf(fp, "%d [ ", fda->nr); 122 123 for (fd = 0; fd < fda->nr; ++fd) 124 printed += fprintf(fp, "%s%d", fd ? ", " : "", fda->entries[fd].fd); 125 126 return printed + fprintf(fp, " ]"); 127 } 128