18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2014, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci#include "array.h" 68c2ecf20Sopenharmony_ci#include <errno.h> 78c2ecf20Sopenharmony_ci#include <fcntl.h> 88c2ecf20Sopenharmony_ci#include <poll.h> 98c2ecf20Sopenharmony_ci#include <stdlib.h> 108c2ecf20Sopenharmony_ci#include <unistd.h> 118c2ecf20Sopenharmony_ci#include <string.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_civoid fdarray__init(struct fdarray *fda, int nr_autogrow) 148c2ecf20Sopenharmony_ci{ 158c2ecf20Sopenharmony_ci fda->entries = NULL; 168c2ecf20Sopenharmony_ci fda->priv = NULL; 178c2ecf20Sopenharmony_ci fda->nr = fda->nr_alloc = 0; 188c2ecf20Sopenharmony_ci fda->nr_autogrow = nr_autogrow; 198c2ecf20Sopenharmony_ci} 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ciint fdarray__grow(struct fdarray *fda, int nr) 228c2ecf20Sopenharmony_ci{ 238c2ecf20Sopenharmony_ci struct priv *priv; 248c2ecf20Sopenharmony_ci int nr_alloc = fda->nr_alloc + nr; 258c2ecf20Sopenharmony_ci size_t psize = sizeof(fda->priv[0]) * nr_alloc; 268c2ecf20Sopenharmony_ci size_t size = sizeof(struct pollfd) * nr_alloc; 278c2ecf20Sopenharmony_ci struct pollfd *entries = realloc(fda->entries, size); 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci if (entries == NULL) 308c2ecf20Sopenharmony_ci return -ENOMEM; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci priv = realloc(fda->priv, psize); 338c2ecf20Sopenharmony_ci if (priv == NULL) { 348c2ecf20Sopenharmony_ci free(entries); 358c2ecf20Sopenharmony_ci return -ENOMEM; 368c2ecf20Sopenharmony_ci } 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci memset(&entries[fda->nr_alloc], 0, sizeof(struct pollfd) * nr); 398c2ecf20Sopenharmony_ci memset(&priv[fda->nr_alloc], 0, sizeof(fda->priv[0]) * nr); 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci fda->nr_alloc = nr_alloc; 428c2ecf20Sopenharmony_ci fda->entries = entries; 438c2ecf20Sopenharmony_ci fda->priv = priv; 448c2ecf20Sopenharmony_ci return 0; 458c2ecf20Sopenharmony_ci} 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_cistruct fdarray *fdarray__new(int nr_alloc, int nr_autogrow) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci struct fdarray *fda = calloc(1, sizeof(*fda)); 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci if (fda != NULL) { 528c2ecf20Sopenharmony_ci if (fdarray__grow(fda, nr_alloc)) { 538c2ecf20Sopenharmony_ci free(fda); 548c2ecf20Sopenharmony_ci fda = NULL; 558c2ecf20Sopenharmony_ci } else { 568c2ecf20Sopenharmony_ci fda->nr_autogrow = nr_autogrow; 578c2ecf20Sopenharmony_ci } 588c2ecf20Sopenharmony_ci } 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci return fda; 618c2ecf20Sopenharmony_ci} 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_civoid fdarray__exit(struct fdarray *fda) 648c2ecf20Sopenharmony_ci{ 658c2ecf20Sopenharmony_ci free(fda->entries); 668c2ecf20Sopenharmony_ci free(fda->priv); 678c2ecf20Sopenharmony_ci fdarray__init(fda, 0); 688c2ecf20Sopenharmony_ci} 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_civoid fdarray__delete(struct fdarray *fda) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci fdarray__exit(fda); 738c2ecf20Sopenharmony_ci free(fda); 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ciint fdarray__add(struct fdarray *fda, int fd, short revents, enum fdarray_flags flags) 778c2ecf20Sopenharmony_ci{ 788c2ecf20Sopenharmony_ci int pos = fda->nr; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci if (fda->nr == fda->nr_alloc && 818c2ecf20Sopenharmony_ci fdarray__grow(fda, fda->nr_autogrow) < 0) 828c2ecf20Sopenharmony_ci return -ENOMEM; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci fda->entries[fda->nr].fd = fd; 858c2ecf20Sopenharmony_ci fda->entries[fda->nr].events = revents; 868c2ecf20Sopenharmony_ci fda->priv[fda->nr].flags = flags; 878c2ecf20Sopenharmony_ci fda->nr++; 888c2ecf20Sopenharmony_ci return pos; 898c2ecf20Sopenharmony_ci} 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ciint fdarray__filter(struct fdarray *fda, short revents, 928c2ecf20Sopenharmony_ci void (*entry_destructor)(struct fdarray *fda, int fd, void *arg), 938c2ecf20Sopenharmony_ci void *arg) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci int fd, nr = 0; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci if (fda->nr == 0) 988c2ecf20Sopenharmony_ci return 0; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci for (fd = 0; fd < fda->nr; ++fd) { 1018c2ecf20Sopenharmony_ci if (!fda->entries[fd].events) 1028c2ecf20Sopenharmony_ci continue; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci if (fda->entries[fd].revents & revents) { 1058c2ecf20Sopenharmony_ci if (entry_destructor) 1068c2ecf20Sopenharmony_ci entry_destructor(fda, fd, arg); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci fda->entries[fd].revents = fda->entries[fd].events = 0; 1098c2ecf20Sopenharmony_ci continue; 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci if (!(fda->priv[fd].flags & fdarray_flag__nonfilterable)) 1138c2ecf20Sopenharmony_ci ++nr; 1148c2ecf20Sopenharmony_ci } 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci return nr; 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ciint fdarray__poll(struct fdarray *fda, int timeout) 1208c2ecf20Sopenharmony_ci{ 1218c2ecf20Sopenharmony_ci return poll(fda->entries, fda->nr, timeout); 1228c2ecf20Sopenharmony_ci} 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ciint fdarray__fprintf(struct fdarray *fda, FILE *fp) 1258c2ecf20Sopenharmony_ci{ 1268c2ecf20Sopenharmony_ci int fd, printed = fprintf(fp, "%d [ ", fda->nr); 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci for (fd = 0; fd < fda->nr; ++fd) 1298c2ecf20Sopenharmony_ci printed += fprintf(fp, "%s%d", fd ? ", " : "", fda->entries[fd].fd); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci return printed + fprintf(fp, " ]"); 1328c2ecf20Sopenharmony_ci} 133