1d6e48869SDaniel P. Berrange /*
2d6e48869SDaniel P. Berrange * QEMU I/O channels files driver
3d6e48869SDaniel P. Berrange *
4d6e48869SDaniel P. Berrange * Copyright (c) 2015 Red Hat, Inc.
5d6e48869SDaniel P. Berrange *
6d6e48869SDaniel P. Berrange * This library is free software; you can redistribute it and/or
7d6e48869SDaniel P. Berrange * modify it under the terms of the GNU Lesser General Public
8d6e48869SDaniel P. Berrange * License as published by the Free Software Foundation; either
9c8198bd5SChetan Pant * version 2.1 of the License, or (at your option) any later version.
10d6e48869SDaniel P. Berrange *
11d6e48869SDaniel P. Berrange * This library is distributed in the hope that it will be useful,
12d6e48869SDaniel P. Berrange * but WITHOUT ANY WARRANTY; without even the implied warranty of
13d6e48869SDaniel P. Berrange * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14d6e48869SDaniel P. Berrange * Lesser General Public License for more details.
15d6e48869SDaniel P. Berrange *
16d6e48869SDaniel P. Berrange * You should have received a copy of the GNU Lesser General Public
17d6e48869SDaniel P. Berrange * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18d6e48869SDaniel P. Berrange *
19d6e48869SDaniel P. Berrange */
20d6e48869SDaniel P. Berrange
21cae9fc56SPeter Maydell #include "qemu/osdep.h"
22d6e48869SDaniel P. Berrange #include "io/channel-file.h"
2306e0f098SStefan Hajnoczi #include "io/channel-util.h"
24d6e48869SDaniel P. Berrange #include "io/channel-watch.h"
25da34e65cSMarkus Armbruster #include "qapi/error.h"
260b8fa32fSMarkus Armbruster #include "qemu/module.h"
27d6e48869SDaniel P. Berrange #include "qemu/sockets.h"
28d6e48869SDaniel P. Berrange #include "trace.h"
29d6e48869SDaniel P. Berrange
30d6e48869SDaniel P. Berrange QIOChannelFile *
qio_channel_file_new_fd(int fd)31d6e48869SDaniel P. Berrange qio_channel_file_new_fd(int fd)
32d6e48869SDaniel P. Berrange {
33d6e48869SDaniel P. Berrange QIOChannelFile *ioc;
34d6e48869SDaniel P. Berrange
35d6e48869SDaniel P. Berrange ioc = QIO_CHANNEL_FILE(object_new(TYPE_QIO_CHANNEL_FILE));
36d6e48869SDaniel P. Berrange
37d6e48869SDaniel P. Berrange ioc->fd = fd;
38d6e48869SDaniel P. Berrange
39401e311fSNikolay Borisov if (lseek(fd, 0, SEEK_CUR) != (off_t)-1) {
40401e311fSNikolay Borisov qio_channel_set_feature(QIO_CHANNEL(ioc), QIO_CHANNEL_FEATURE_SEEKABLE);
41401e311fSNikolay Borisov }
42401e311fSNikolay Borisov
43d6e48869SDaniel P. Berrange trace_qio_channel_file_new_fd(ioc, fd);
44d6e48869SDaniel P. Berrange
45d6e48869SDaniel P. Berrange return ioc;
46d6e48869SDaniel P. Berrange }
47d6e48869SDaniel P. Berrange
484760cedcSFabiano Rosas QIOChannelFile *
qio_channel_file_new_dupfd(int fd,Error ** errp)494760cedcSFabiano Rosas qio_channel_file_new_dupfd(int fd, Error **errp)
504760cedcSFabiano Rosas {
514760cedcSFabiano Rosas int newfd = dup(fd);
524760cedcSFabiano Rosas
534760cedcSFabiano Rosas if (newfd < 0) {
544760cedcSFabiano Rosas error_setg_errno(errp, errno, "Could not dup FD %d", fd);
554760cedcSFabiano Rosas return NULL;
564760cedcSFabiano Rosas }
574760cedcSFabiano Rosas
584760cedcSFabiano Rosas return qio_channel_file_new_fd(newfd);
594760cedcSFabiano Rosas }
60d6e48869SDaniel P. Berrange
61d6e48869SDaniel P. Berrange QIOChannelFile *
qio_channel_file_new_path(const char * path,int flags,mode_t mode,Error ** errp)62d6e48869SDaniel P. Berrange qio_channel_file_new_path(const char *path,
63d6e48869SDaniel P. Berrange int flags,
64d6e48869SDaniel P. Berrange mode_t mode,
65d6e48869SDaniel P. Berrange Error **errp)
66d6e48869SDaniel P. Berrange {
67d6e48869SDaniel P. Berrange QIOChannelFile *ioc;
68d6e48869SDaniel P. Berrange
69d6e48869SDaniel P. Berrange ioc = QIO_CHANNEL_FILE(object_new(TYPE_QIO_CHANNEL_FILE));
70d6e48869SDaniel P. Berrange
71*46cec74cSFabiano Rosas if (flags & O_CREAT) {
72*46cec74cSFabiano Rosas ioc->fd = qemu_create(path, flags & ~O_CREAT, mode, errp);
73*46cec74cSFabiano Rosas } else {
74*46cec74cSFabiano Rosas ioc->fd = qemu_open(path, flags, errp);
75*46cec74cSFabiano Rosas }
76d6e48869SDaniel P. Berrange if (ioc->fd < 0) {
77d6e48869SDaniel P. Berrange object_unref(OBJECT(ioc));
78d6e48869SDaniel P. Berrange return NULL;
79d6e48869SDaniel P. Berrange }
80d6e48869SDaniel P. Berrange
81401e311fSNikolay Borisov if (lseek(ioc->fd, 0, SEEK_CUR) != (off_t)-1) {
82401e311fSNikolay Borisov qio_channel_set_feature(QIO_CHANNEL(ioc), QIO_CHANNEL_FEATURE_SEEKABLE);
83401e311fSNikolay Borisov }
84401e311fSNikolay Borisov
85d6e48869SDaniel P. Berrange trace_qio_channel_file_new_path(ioc, path, flags, mode, ioc->fd);
86d6e48869SDaniel P. Berrange
87d6e48869SDaniel P. Berrange return ioc;
88d6e48869SDaniel P. Berrange }
89d6e48869SDaniel P. Berrange
90d6e48869SDaniel P. Berrange
qio_channel_file_init(Object * obj)91d6e48869SDaniel P. Berrange static void qio_channel_file_init(Object *obj)
92d6e48869SDaniel P. Berrange {
93d6e48869SDaniel P. Berrange QIOChannelFile *ioc = QIO_CHANNEL_FILE(obj);
94d6e48869SDaniel P. Berrange ioc->fd = -1;
95d6e48869SDaniel P. Berrange }
96d6e48869SDaniel P. Berrange
qio_channel_file_finalize(Object * obj)97d6e48869SDaniel P. Berrange static void qio_channel_file_finalize(Object *obj)
98d6e48869SDaniel P. Berrange {
99d6e48869SDaniel P. Berrange QIOChannelFile *ioc = QIO_CHANNEL_FILE(obj);
100d6e48869SDaniel P. Berrange if (ioc->fd != -1) {
101b8f244b1SRoss Lagerwall qemu_close(ioc->fd);
102d6e48869SDaniel P. Berrange ioc->fd = -1;
103d6e48869SDaniel P. Berrange }
104d6e48869SDaniel P. Berrange }
105d6e48869SDaniel P. Berrange
106d6e48869SDaniel P. Berrange
qio_channel_file_readv(QIOChannel * ioc,const struct iovec * iov,size_t niov,int ** fds,size_t * nfds,int flags,Error ** errp)107d6e48869SDaniel P. Berrange static ssize_t qio_channel_file_readv(QIOChannel *ioc,
108d6e48869SDaniel P. Berrange const struct iovec *iov,
109d6e48869SDaniel P. Berrange size_t niov,
110d6e48869SDaniel P. Berrange int **fds,
111d6e48869SDaniel P. Berrange size_t *nfds,
11284615a19Smanish.mishra int flags,
113d6e48869SDaniel P. Berrange Error **errp)
114d6e48869SDaniel P. Berrange {
115d6e48869SDaniel P. Berrange QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
116d6e48869SDaniel P. Berrange ssize_t ret;
117d6e48869SDaniel P. Berrange
118d6e48869SDaniel P. Berrange retry:
119d6e48869SDaniel P. Berrange ret = readv(fioc->fd, iov, niov);
120d6e48869SDaniel P. Berrange if (ret < 0) {
12130fd3e27SDaniel P. Berrange if (errno == EAGAIN) {
122d6e48869SDaniel P. Berrange return QIO_CHANNEL_ERR_BLOCK;
123d6e48869SDaniel P. Berrange }
124d6e48869SDaniel P. Berrange if (errno == EINTR) {
125d6e48869SDaniel P. Berrange goto retry;
126d6e48869SDaniel P. Berrange }
127d6e48869SDaniel P. Berrange
128d6e48869SDaniel P. Berrange error_setg_errno(errp, errno,
129d6e48869SDaniel P. Berrange "Unable to read from file");
130d6e48869SDaniel P. Berrange return -1;
131d6e48869SDaniel P. Berrange }
132d6e48869SDaniel P. Berrange
133d6e48869SDaniel P. Berrange return ret;
134d6e48869SDaniel P. Berrange }
135d6e48869SDaniel P. Berrange
qio_channel_file_writev(QIOChannel * ioc,const struct iovec * iov,size_t niov,int * fds,size_t nfds,int flags,Error ** errp)136d6e48869SDaniel P. Berrange static ssize_t qio_channel_file_writev(QIOChannel *ioc,
137d6e48869SDaniel P. Berrange const struct iovec *iov,
138d6e48869SDaniel P. Berrange size_t niov,
139d6e48869SDaniel P. Berrange int *fds,
140d6e48869SDaniel P. Berrange size_t nfds,
141b88651cbSLeonardo Bras int flags,
142d6e48869SDaniel P. Berrange Error **errp)
143d6e48869SDaniel P. Berrange {
144d6e48869SDaniel P. Berrange QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
145d6e48869SDaniel P. Berrange ssize_t ret;
146d6e48869SDaniel P. Berrange
147d6e48869SDaniel P. Berrange retry:
148d6e48869SDaniel P. Berrange ret = writev(fioc->fd, iov, niov);
149d6e48869SDaniel P. Berrange if (ret <= 0) {
15030fd3e27SDaniel P. Berrange if (errno == EAGAIN) {
151d6e48869SDaniel P. Berrange return QIO_CHANNEL_ERR_BLOCK;
152d6e48869SDaniel P. Berrange }
153d6e48869SDaniel P. Berrange if (errno == EINTR) {
154d6e48869SDaniel P. Berrange goto retry;
155d6e48869SDaniel P. Berrange }
156d6e48869SDaniel P. Berrange error_setg_errno(errp, errno,
157d6e48869SDaniel P. Berrange "Unable to write to file");
158d6e48869SDaniel P. Berrange return -1;
159d6e48869SDaniel P. Berrange }
160d6e48869SDaniel P. Berrange return ret;
161d6e48869SDaniel P. Berrange }
162d6e48869SDaniel P. Berrange
1630478b030SNikolay Borisov #ifdef CONFIG_PREADV
qio_channel_file_preadv(QIOChannel * ioc,const struct iovec * iov,size_t niov,off_t offset,Error ** errp)1640478b030SNikolay Borisov static ssize_t qio_channel_file_preadv(QIOChannel *ioc,
1650478b030SNikolay Borisov const struct iovec *iov,
1660478b030SNikolay Borisov size_t niov,
1670478b030SNikolay Borisov off_t offset,
1680478b030SNikolay Borisov Error **errp)
1690478b030SNikolay Borisov {
1700478b030SNikolay Borisov QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
1710478b030SNikolay Borisov ssize_t ret;
1720478b030SNikolay Borisov
1730478b030SNikolay Borisov retry:
1740478b030SNikolay Borisov ret = preadv(fioc->fd, iov, niov, offset);
1750478b030SNikolay Borisov if (ret < 0) {
1760478b030SNikolay Borisov if (errno == EAGAIN) {
1770478b030SNikolay Borisov return QIO_CHANNEL_ERR_BLOCK;
1780478b030SNikolay Borisov }
1790478b030SNikolay Borisov if (errno == EINTR) {
1800478b030SNikolay Borisov goto retry;
1810478b030SNikolay Borisov }
1820478b030SNikolay Borisov
1830478b030SNikolay Borisov error_setg_errno(errp, errno, "Unable to read from file");
1840478b030SNikolay Borisov return -1;
1850478b030SNikolay Borisov }
1860478b030SNikolay Borisov
1870478b030SNikolay Borisov return ret;
1880478b030SNikolay Borisov }
1890478b030SNikolay Borisov
qio_channel_file_pwritev(QIOChannel * ioc,const struct iovec * iov,size_t niov,off_t offset,Error ** errp)1900478b030SNikolay Borisov static ssize_t qio_channel_file_pwritev(QIOChannel *ioc,
1910478b030SNikolay Borisov const struct iovec *iov,
1920478b030SNikolay Borisov size_t niov,
1930478b030SNikolay Borisov off_t offset,
1940478b030SNikolay Borisov Error **errp)
1950478b030SNikolay Borisov {
1960478b030SNikolay Borisov QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
1970478b030SNikolay Borisov ssize_t ret;
1980478b030SNikolay Borisov
1990478b030SNikolay Borisov retry:
2000478b030SNikolay Borisov ret = pwritev(fioc->fd, iov, niov, offset);
2010478b030SNikolay Borisov if (ret <= 0) {
2020478b030SNikolay Borisov if (errno == EAGAIN) {
2030478b030SNikolay Borisov return QIO_CHANNEL_ERR_BLOCK;
2040478b030SNikolay Borisov }
2050478b030SNikolay Borisov if (errno == EINTR) {
2060478b030SNikolay Borisov goto retry;
2070478b030SNikolay Borisov }
2080478b030SNikolay Borisov error_setg_errno(errp, errno, "Unable to write to file");
2090478b030SNikolay Borisov return -1;
2100478b030SNikolay Borisov }
2110478b030SNikolay Borisov return ret;
2120478b030SNikolay Borisov }
2130478b030SNikolay Borisov #endif /* CONFIG_PREADV */
2140478b030SNikolay Borisov
qio_channel_file_set_blocking(QIOChannel * ioc,bool enabled,Error ** errp)215d6e48869SDaniel P. Berrange static int qio_channel_file_set_blocking(QIOChannel *ioc,
216d6e48869SDaniel P. Berrange bool enabled,
217d6e48869SDaniel P. Berrange Error **errp)
218d6e48869SDaniel P. Berrange {
21917fc1245SMarc-André Lureau #ifdef WIN32
22017fc1245SMarc-André Lureau /* not implemented */
22117fc1245SMarc-André Lureau error_setg_errno(errp, errno, "Failed to set FD nonblocking");
22217fc1245SMarc-André Lureau return -1;
22317fc1245SMarc-André Lureau #else
224d6e48869SDaniel P. Berrange QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
225d6e48869SDaniel P. Berrange
22617fc1245SMarc-André Lureau if (!g_unix_set_fd_nonblocking(fioc->fd, !enabled, NULL)) {
22717fc1245SMarc-André Lureau error_setg_errno(errp, errno, "Failed to set FD nonblocking");
22817fc1245SMarc-André Lureau return -1;
229d6e48869SDaniel P. Berrange }
230d6e48869SDaniel P. Berrange return 0;
23117fc1245SMarc-André Lureau #endif
232d6e48869SDaniel P. Berrange }
233d6e48869SDaniel P. Berrange
234d6e48869SDaniel P. Berrange
qio_channel_file_seek(QIOChannel * ioc,off_t offset,int whence,Error ** errp)235d6e48869SDaniel P. Berrange static off_t qio_channel_file_seek(QIOChannel *ioc,
236d6e48869SDaniel P. Berrange off_t offset,
237d6e48869SDaniel P. Berrange int whence,
238d6e48869SDaniel P. Berrange Error **errp)
239d6e48869SDaniel P. Berrange {
240d6e48869SDaniel P. Berrange QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
241d6e48869SDaniel P. Berrange off_t ret;
242d6e48869SDaniel P. Berrange
243d6e48869SDaniel P. Berrange ret = lseek(fioc->fd, offset, whence);
244d6e48869SDaniel P. Berrange if (ret == (off_t)-1) {
245d6e48869SDaniel P. Berrange error_setg_errno(errp, errno,
246d6e48869SDaniel P. Berrange "Unable to seek to offset %lld whence %d in file",
247d6e48869SDaniel P. Berrange (long long int)offset, whence);
248d6e48869SDaniel P. Berrange return -1;
249d6e48869SDaniel P. Berrange }
250d6e48869SDaniel P. Berrange return ret;
251d6e48869SDaniel P. Berrange }
252d6e48869SDaniel P. Berrange
253d6e48869SDaniel P. Berrange
qio_channel_file_close(QIOChannel * ioc,Error ** errp)254d6e48869SDaniel P. Berrange static int qio_channel_file_close(QIOChannel *ioc,
255d6e48869SDaniel P. Berrange Error **errp)
256d6e48869SDaniel P. Berrange {
257d6e48869SDaniel P. Berrange QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
258d6e48869SDaniel P. Berrange
259b8f244b1SRoss Lagerwall if (qemu_close(fioc->fd) < 0) {
260d6e48869SDaniel P. Berrange error_setg_errno(errp, errno,
261d6e48869SDaniel P. Berrange "Unable to close file");
262d6e48869SDaniel P. Berrange return -1;
263d6e48869SDaniel P. Berrange }
264a2565df1SRoss Lagerwall fioc->fd = -1;
265d6e48869SDaniel P. Berrange return 0;
266d6e48869SDaniel P. Berrange }
267d6e48869SDaniel P. Berrange
268d6e48869SDaniel P. Berrange
qio_channel_file_set_aio_fd_handler(QIOChannel * ioc,AioContext * read_ctx,IOHandler * io_read,AioContext * write_ctx,IOHandler * io_write,void * opaque)269bf88c124SPaolo Bonzini static void qio_channel_file_set_aio_fd_handler(QIOChannel *ioc,
27006e0f098SStefan Hajnoczi AioContext *read_ctx,
271bf88c124SPaolo Bonzini IOHandler *io_read,
27206e0f098SStefan Hajnoczi AioContext *write_ctx,
273bf88c124SPaolo Bonzini IOHandler *io_write,
274bf88c124SPaolo Bonzini void *opaque)
275bf88c124SPaolo Bonzini {
276bf88c124SPaolo Bonzini QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
27706e0f098SStefan Hajnoczi
27806e0f098SStefan Hajnoczi qio_channel_util_set_aio_fd_handler(fioc->fd, read_ctx, io_read,
27906e0f098SStefan Hajnoczi fioc->fd, write_ctx, io_write,
28006e0f098SStefan Hajnoczi opaque);
281bf88c124SPaolo Bonzini }
282bf88c124SPaolo Bonzini
qio_channel_file_create_watch(QIOChannel * ioc,GIOCondition condition)283d6e48869SDaniel P. Berrange static GSource *qio_channel_file_create_watch(QIOChannel *ioc,
284d6e48869SDaniel P. Berrange GIOCondition condition)
285d6e48869SDaniel P. Berrange {
286d6e48869SDaniel P. Berrange QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
287d6e48869SDaniel P. Berrange return qio_channel_create_fd_watch(ioc,
288d6e48869SDaniel P. Berrange fioc->fd,
289d6e48869SDaniel P. Berrange condition);
290d6e48869SDaniel P. Berrange }
291d6e48869SDaniel P. Berrange
qio_channel_file_class_init(ObjectClass * klass,void * class_data G_GNUC_UNUSED)292d6e48869SDaniel P. Berrange static void qio_channel_file_class_init(ObjectClass *klass,
293d6e48869SDaniel P. Berrange void *class_data G_GNUC_UNUSED)
294d6e48869SDaniel P. Berrange {
295d6e48869SDaniel P. Berrange QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass);
296d6e48869SDaniel P. Berrange
297d6e48869SDaniel P. Berrange ioc_klass->io_writev = qio_channel_file_writev;
298d6e48869SDaniel P. Berrange ioc_klass->io_readv = qio_channel_file_readv;
299d6e48869SDaniel P. Berrange ioc_klass->io_set_blocking = qio_channel_file_set_blocking;
3000478b030SNikolay Borisov #ifdef CONFIG_PREADV
3010478b030SNikolay Borisov ioc_klass->io_pwritev = qio_channel_file_pwritev;
3020478b030SNikolay Borisov ioc_klass->io_preadv = qio_channel_file_preadv;
3030478b030SNikolay Borisov #endif
304d6e48869SDaniel P. Berrange ioc_klass->io_seek = qio_channel_file_seek;
305d6e48869SDaniel P. Berrange ioc_klass->io_close = qio_channel_file_close;
306d6e48869SDaniel P. Berrange ioc_klass->io_create_watch = qio_channel_file_create_watch;
307bf88c124SPaolo Bonzini ioc_klass->io_set_aio_fd_handler = qio_channel_file_set_aio_fd_handler;
308d6e48869SDaniel P. Berrange }
309d6e48869SDaniel P. Berrange
310d6e48869SDaniel P. Berrange static const TypeInfo qio_channel_file_info = {
311d6e48869SDaniel P. Berrange .parent = TYPE_QIO_CHANNEL,
312d6e48869SDaniel P. Berrange .name = TYPE_QIO_CHANNEL_FILE,
313d6e48869SDaniel P. Berrange .instance_size = sizeof(QIOChannelFile),
314d6e48869SDaniel P. Berrange .instance_init = qio_channel_file_init,
315d6e48869SDaniel P. Berrange .instance_finalize = qio_channel_file_finalize,
316d6e48869SDaniel P. Berrange .class_init = qio_channel_file_class_init,
317d6e48869SDaniel P. Berrange };
318d6e48869SDaniel P. Berrange
qio_channel_file_register_types(void)319d6e48869SDaniel P. Berrange static void qio_channel_file_register_types(void)
320d6e48869SDaniel P. Berrange {
321d6e48869SDaniel P. Berrange type_register_static(&qio_channel_file_info);
322d6e48869SDaniel P. Berrange }
323d6e48869SDaniel P. Berrange
324d6e48869SDaniel P. Berrange type_init(qio_channel_file_register_types);
325