diff options
Diffstat (limited to 'io/channel-null.c')
-rw-r--r-- | io/channel-null.c | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/io/channel-null.c b/io/channel-null.c new file mode 100644 index 0000000000..75e3781507 --- /dev/null +++ b/io/channel-null.c @@ -0,0 +1,237 @@ +/* + * QEMU I/O channels null driver + * + * Copyright (c) 2022 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + * + */ + +#include "qemu/osdep.h" +#include "io/channel-null.h" +#include "io/channel-watch.h" +#include "qapi/error.h" +#include "trace.h" +#include "qemu/iov.h" + +typedef struct QIOChannelNullSource QIOChannelNullSource; +struct QIOChannelNullSource { + GSource parent; + QIOChannel *ioc; + GIOCondition condition; +}; + + +QIOChannelNull * +qio_channel_null_new(void) +{ + QIOChannelNull *ioc; + + ioc = QIO_CHANNEL_NULL(object_new(TYPE_QIO_CHANNEL_NULL)); + + trace_qio_channel_null_new(ioc); + + return ioc; +} + + +static void +qio_channel_null_init(Object *obj) +{ + QIOChannelNull *ioc = QIO_CHANNEL_NULL(obj); + ioc->closed = false; +} + + +static ssize_t +qio_channel_null_readv(QIOChannel *ioc, + const struct iovec *iov, + size_t niov, + int **fds G_GNUC_UNUSED, + size_t *nfds G_GNUC_UNUSED, + Error **errp) +{ + QIOChannelNull *nioc = QIO_CHANNEL_NULL(ioc); + + if (nioc->closed) { + error_setg_errno(errp, EINVAL, + "Channel is closed"); + return -1; + } + + return 0; +} + + +static ssize_t +qio_channel_null_writev(QIOChannel *ioc, + const struct iovec *iov, + size_t niov, + int *fds G_GNUC_UNUSED, + size_t nfds G_GNUC_UNUSED, + int flags G_GNUC_UNUSED, + Error **errp) +{ + QIOChannelNull *nioc = QIO_CHANNEL_NULL(ioc); + + if (nioc->closed) { + error_setg_errno(errp, EINVAL, + "Channel is closed"); + return -1; + } + + return iov_size(iov, niov); +} + + +static int +qio_channel_null_set_blocking(QIOChannel *ioc G_GNUC_UNUSED, + bool enabled G_GNUC_UNUSED, + Error **errp G_GNUC_UNUSED) +{ + return 0; +} + + +static off_t +qio_channel_null_seek(QIOChannel *ioc G_GNUC_UNUSED, + off_t offset G_GNUC_UNUSED, + int whence G_GNUC_UNUSED, + Error **errp G_GNUC_UNUSED) +{ + return 0; +} + + +static int +qio_channel_null_close(QIOChannel *ioc, + Error **errp G_GNUC_UNUSED) +{ + QIOChannelNull *nioc = QIO_CHANNEL_NULL(ioc); + + nioc->closed = true; + return 0; +} + + +static void +qio_channel_null_set_aio_fd_handler(QIOChannel *ioc G_GNUC_UNUSED, + AioContext *ctx G_GNUC_UNUSED, + IOHandler *io_read G_GNUC_UNUSED, + IOHandler *io_write G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ +} + + +static gboolean +qio_channel_null_source_prepare(GSource *source G_GNUC_UNUSED, + gint *timeout) +{ + *timeout = -1; + + return TRUE; +} + + +static gboolean +qio_channel_null_source_check(GSource *source G_GNUC_UNUSED) +{ + return TRUE; +} + + +static gboolean +qio_channel_null_source_dispatch(GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + QIOChannelFunc func = (QIOChannelFunc)callback; + QIOChannelNullSource *ssource = (QIOChannelNullSource *)source; + + return (*func)(ssource->ioc, + ssource->condition, + user_data); +} + + +static void +qio_channel_null_source_finalize(GSource *source) +{ + QIOChannelNullSource *ssource = (QIOChannelNullSource *)source; + + object_unref(OBJECT(ssource->ioc)); +} + + +GSourceFuncs qio_channel_null_source_funcs = { + qio_channel_null_source_prepare, + qio_channel_null_source_check, + qio_channel_null_source_dispatch, + qio_channel_null_source_finalize +}; + + +static GSource * +qio_channel_null_create_watch(QIOChannel *ioc, + GIOCondition condition) +{ + GSource *source; + QIOChannelNullSource *ssource; + + source = g_source_new(&qio_channel_null_source_funcs, + sizeof(QIOChannelNullSource)); + ssource = (QIOChannelNullSource *)source; + + ssource->ioc = ioc; + object_ref(OBJECT(ioc)); + + ssource->condition = condition; + + return source; +} + + +static void +qio_channel_null_class_init(ObjectClass *klass, + void *class_data G_GNUC_UNUSED) +{ + QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass); + + ioc_klass->io_writev = qio_channel_null_writev; + ioc_klass->io_readv = qio_channel_null_readv; + ioc_klass->io_set_blocking = qio_channel_null_set_blocking; + ioc_klass->io_seek = qio_channel_null_seek; + ioc_klass->io_close = qio_channel_null_close; + ioc_klass->io_create_watch = qio_channel_null_create_watch; + ioc_klass->io_set_aio_fd_handler = qio_channel_null_set_aio_fd_handler; +} + + +static const TypeInfo qio_channel_null_info = { + .parent = TYPE_QIO_CHANNEL, + .name = TYPE_QIO_CHANNEL_NULL, + .instance_size = sizeof(QIOChannelNull), + .instance_init = qio_channel_null_init, + .class_init = qio_channel_null_class_init, +}; + + +static void +qio_channel_null_register_types(void) +{ + type_register_static(&qio_channel_null_info); +} + +type_init(qio_channel_null_register_types); |