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