io: use qemu_accept to ensure SOCK_CLOEXEC is set
[qemu/rayw.git] / io / channel.c
blob3fc09f887c2c4737c0fbfce1ecd6d43f50b5e52d
1 /*
2 * QEMU I/O channels
4 * Copyright (c) 2015 Red Hat, Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include "qemu/osdep.h"
22 #include "io/channel.h"
23 #include "qemu/coroutine.h"
25 bool qio_channel_has_feature(QIOChannel *ioc,
26 QIOChannelFeature feature)
28 return ioc->features & (1 << feature);
32 ssize_t qio_channel_readv_full(QIOChannel *ioc,
33 const struct iovec *iov,
34 size_t niov,
35 int **fds,
36 size_t *nfds,
37 Error **errp)
39 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
41 if ((fds || nfds) &&
42 !(ioc->features & (1 << QIO_CHANNEL_FEATURE_FD_PASS))) {
43 error_setg_errno(errp, EINVAL,
44 "Channel does not support file descriptor passing");
45 return -1;
48 return klass->io_readv(ioc, iov, niov, fds, nfds, errp);
52 ssize_t qio_channel_writev_full(QIOChannel *ioc,
53 const struct iovec *iov,
54 size_t niov,
55 int *fds,
56 size_t nfds,
57 Error **errp)
59 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
61 if ((fds || nfds) &&
62 !(ioc->features & (1 << QIO_CHANNEL_FEATURE_FD_PASS))) {
63 error_setg_errno(errp, EINVAL,
64 "Channel does not support file descriptor passing");
65 return -1;
68 return klass->io_writev(ioc, iov, niov, fds, nfds, errp);
72 ssize_t qio_channel_readv(QIOChannel *ioc,
73 const struct iovec *iov,
74 size_t niov,
75 Error **errp)
77 return qio_channel_readv_full(ioc, iov, niov, NULL, NULL, errp);
81 ssize_t qio_channel_writev(QIOChannel *ioc,
82 const struct iovec *iov,
83 size_t niov,
84 Error **errp)
86 return qio_channel_writev_full(ioc, iov, niov, NULL, 0, errp);
90 ssize_t qio_channel_read(QIOChannel *ioc,
91 char *buf,
92 size_t buflen,
93 Error **errp)
95 struct iovec iov = { .iov_base = buf, .iov_len = buflen };
96 return qio_channel_readv_full(ioc, &iov, 1, NULL, NULL, errp);
100 ssize_t qio_channel_write(QIOChannel *ioc,
101 const char *buf,
102 size_t buflen,
103 Error **errp)
105 struct iovec iov = { .iov_base = (char *)buf, .iov_len = buflen };
106 return qio_channel_writev_full(ioc, &iov, 1, NULL, 0, errp);
110 int qio_channel_set_blocking(QIOChannel *ioc,
111 bool enabled,
112 Error **errp)
114 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
115 return klass->io_set_blocking(ioc, enabled, errp);
119 int qio_channel_close(QIOChannel *ioc,
120 Error **errp)
122 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
123 return klass->io_close(ioc, errp);
127 GSource *qio_channel_create_watch(QIOChannel *ioc,
128 GIOCondition condition)
130 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
131 return klass->io_create_watch(ioc, condition);
135 guint qio_channel_add_watch(QIOChannel *ioc,
136 GIOCondition condition,
137 QIOChannelFunc func,
138 gpointer user_data,
139 GDestroyNotify notify)
141 GSource *source;
142 guint id;
144 source = qio_channel_create_watch(ioc, condition);
146 g_source_set_callback(source, (GSourceFunc)func, user_data, notify);
148 id = g_source_attach(source, NULL);
149 g_source_unref(source);
151 return id;
155 int qio_channel_shutdown(QIOChannel *ioc,
156 QIOChannelShutdown how,
157 Error **errp)
159 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
161 if (!klass->io_shutdown) {
162 error_setg(errp, "Data path shutdown not supported");
163 return -1;
166 return klass->io_shutdown(ioc, how, errp);
170 void qio_channel_set_delay(QIOChannel *ioc,
171 bool enabled)
173 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
175 if (klass->io_set_delay) {
176 klass->io_set_delay(ioc, enabled);
181 void qio_channel_set_cork(QIOChannel *ioc,
182 bool enabled)
184 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
186 if (klass->io_set_cork) {
187 klass->io_set_cork(ioc, enabled);
192 off_t qio_channel_io_seek(QIOChannel *ioc,
193 off_t offset,
194 int whence,
195 Error **errp)
197 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
199 if (!klass->io_seek) {
200 error_setg(errp, "Channel does not support random access");
201 return -1;
204 return klass->io_seek(ioc, offset, whence, errp);
208 typedef struct QIOChannelYieldData QIOChannelYieldData;
209 struct QIOChannelYieldData {
210 QIOChannel *ioc;
211 Coroutine *co;
215 static gboolean qio_channel_yield_enter(QIOChannel *ioc,
216 GIOCondition condition,
217 gpointer opaque)
219 QIOChannelYieldData *data = opaque;
220 qemu_coroutine_enter(data->co, NULL);
221 return FALSE;
225 void coroutine_fn qio_channel_yield(QIOChannel *ioc,
226 GIOCondition condition)
228 QIOChannelYieldData data;
230 assert(qemu_in_coroutine());
231 data.ioc = ioc;
232 data.co = qemu_coroutine_self();
233 qio_channel_add_watch(ioc,
234 condition,
235 qio_channel_yield_enter,
236 &data,
237 NULL);
238 qemu_coroutine_yield();
242 static gboolean qio_channel_wait_complete(QIOChannel *ioc,
243 GIOCondition condition,
244 gpointer opaque)
246 GMainLoop *loop = opaque;
248 g_main_loop_quit(loop);
249 return FALSE;
253 void qio_channel_wait(QIOChannel *ioc,
254 GIOCondition condition)
256 GMainContext *ctxt = g_main_context_new();
257 GMainLoop *loop = g_main_loop_new(ctxt, TRUE);
258 GSource *source;
260 source = qio_channel_create_watch(ioc, condition);
262 g_source_set_callback(source,
263 (GSourceFunc)qio_channel_wait_complete,
264 loop,
265 NULL);
267 g_source_attach(source, ctxt);
269 g_main_loop_run(loop);
271 g_source_unref(source);
272 g_main_loop_unref(loop);
273 g_main_context_unref(ctxt);
277 static const TypeInfo qio_channel_info = {
278 .parent = TYPE_OBJECT,
279 .name = TYPE_QIO_CHANNEL,
280 .instance_size = sizeof(QIOChannel),
281 .abstract = true,
282 .class_size = sizeof(QIOChannelClass),
286 static void qio_channel_register_types(void)
288 type_register_static(&qio_channel_info);
292 type_init(qio_channel_register_types);