xref: /kernel/linux/linux-5.10/tools/lib/api/fd/array.c (revision 8c2ecf20)
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