xref: /openbmc/qemu/io/channel-file.c (revision ee48fef0)
1 /*
2  * QEMU I/O channels files driver
3  *
4  * Copyright (c) 2015 Red Hat, Inc.
5  *
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.1 of the License, or (at your option) any later version.
10  *
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.
15  *
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/>.
18  *
19  */
20 
21 #include "qemu/osdep.h"
22 #include "io/channel-file.h"
23 #include "io/channel-util.h"
24 #include "io/channel-watch.h"
25 #include "qapi/error.h"
26 #include "qemu/module.h"
27 #include "qemu/sockets.h"
28 #include "trace.h"
29 
30 QIOChannelFile *
31 qio_channel_file_new_fd(int fd)
32 {
33     QIOChannelFile *ioc;
34 
35     ioc = QIO_CHANNEL_FILE(object_new(TYPE_QIO_CHANNEL_FILE));
36 
37     ioc->fd = fd;
38 
39     if (lseek(fd, 0, SEEK_CUR) != (off_t)-1) {
40         qio_channel_set_feature(QIO_CHANNEL(ioc), QIO_CHANNEL_FEATURE_SEEKABLE);
41     }
42 
43     trace_qio_channel_file_new_fd(ioc, fd);
44 
45     return ioc;
46 }
47 
48 QIOChannelFile *
49 qio_channel_file_new_dupfd(int fd, Error **errp)
50 {
51     int newfd = dup(fd);
52 
53     if (newfd < 0) {
54         error_setg_errno(errp, errno, "Could not dup FD %d", fd);
55         return NULL;
56     }
57 
58     return qio_channel_file_new_fd(newfd);
59 }
60 
61 QIOChannelFile *
62 qio_channel_file_new_path(const char *path,
63                           int flags,
64                           mode_t mode,
65                           Error **errp)
66 {
67     QIOChannelFile *ioc;
68 
69     ioc = QIO_CHANNEL_FILE(object_new(TYPE_QIO_CHANNEL_FILE));
70 
71     ioc->fd = qemu_open_old(path, flags, mode);
72     if (ioc->fd < 0) {
73         object_unref(OBJECT(ioc));
74         error_setg_errno(errp, errno,
75                          "Unable to open %s", path);
76         return NULL;
77     }
78 
79     if (lseek(ioc->fd, 0, SEEK_CUR) != (off_t)-1) {
80         qio_channel_set_feature(QIO_CHANNEL(ioc), QIO_CHANNEL_FEATURE_SEEKABLE);
81     }
82 
83     trace_qio_channel_file_new_path(ioc, path, flags, mode, ioc->fd);
84 
85     return ioc;
86 }
87 
88 
89 static void qio_channel_file_init(Object *obj)
90 {
91     QIOChannelFile *ioc = QIO_CHANNEL_FILE(obj);
92     ioc->fd = -1;
93 }
94 
95 static void qio_channel_file_finalize(Object *obj)
96 {
97     QIOChannelFile *ioc = QIO_CHANNEL_FILE(obj);
98     if (ioc->fd != -1) {
99         qemu_close(ioc->fd);
100         ioc->fd = -1;
101     }
102 }
103 
104 
105 static ssize_t qio_channel_file_readv(QIOChannel *ioc,
106                                       const struct iovec *iov,
107                                       size_t niov,
108                                       int **fds,
109                                       size_t *nfds,
110                                       int flags,
111                                       Error **errp)
112 {
113     QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
114     ssize_t ret;
115 
116  retry:
117     ret = readv(fioc->fd, iov, niov);
118     if (ret < 0) {
119         if (errno == EAGAIN) {
120             return QIO_CHANNEL_ERR_BLOCK;
121         }
122         if (errno == EINTR) {
123             goto retry;
124         }
125 
126         error_setg_errno(errp, errno,
127                          "Unable to read from file");
128         return -1;
129     }
130 
131     return ret;
132 }
133 
134 static ssize_t qio_channel_file_writev(QIOChannel *ioc,
135                                        const struct iovec *iov,
136                                        size_t niov,
137                                        int *fds,
138                                        size_t nfds,
139                                        int flags,
140                                        Error **errp)
141 {
142     QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
143     ssize_t ret;
144 
145  retry:
146     ret = writev(fioc->fd, iov, niov);
147     if (ret <= 0) {
148         if (errno == EAGAIN) {
149             return QIO_CHANNEL_ERR_BLOCK;
150         }
151         if (errno == EINTR) {
152             goto retry;
153         }
154         error_setg_errno(errp, errno,
155                          "Unable to write to file");
156         return -1;
157     }
158     return ret;
159 }
160 
161 #ifdef CONFIG_PREADV
162 static ssize_t qio_channel_file_preadv(QIOChannel *ioc,
163                                        const struct iovec *iov,
164                                        size_t niov,
165                                        off_t offset,
166                                        Error **errp)
167 {
168     QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
169     ssize_t ret;
170 
171  retry:
172     ret = preadv(fioc->fd, iov, niov, offset);
173     if (ret < 0) {
174         if (errno == EAGAIN) {
175             return QIO_CHANNEL_ERR_BLOCK;
176         }
177         if (errno == EINTR) {
178             goto retry;
179         }
180 
181         error_setg_errno(errp, errno, "Unable to read from file");
182         return -1;
183     }
184 
185     return ret;
186 }
187 
188 static ssize_t qio_channel_file_pwritev(QIOChannel *ioc,
189                                         const struct iovec *iov,
190                                         size_t niov,
191                                         off_t offset,
192                                         Error **errp)
193 {
194     QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
195     ssize_t ret;
196 
197  retry:
198     ret = pwritev(fioc->fd, iov, niov, offset);
199     if (ret <= 0) {
200         if (errno == EAGAIN) {
201             return QIO_CHANNEL_ERR_BLOCK;
202         }
203         if (errno == EINTR) {
204             goto retry;
205         }
206         error_setg_errno(errp, errno, "Unable to write to file");
207         return -1;
208     }
209     return ret;
210 }
211 #endif /* CONFIG_PREADV */
212 
213 static int qio_channel_file_set_blocking(QIOChannel *ioc,
214                                          bool enabled,
215                                          Error **errp)
216 {
217 #ifdef WIN32
218     /* not implemented */
219     error_setg_errno(errp, errno, "Failed to set FD nonblocking");
220     return -1;
221 #else
222     QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
223 
224     if (!g_unix_set_fd_nonblocking(fioc->fd, !enabled, NULL)) {
225         error_setg_errno(errp, errno, "Failed to set FD nonblocking");
226         return -1;
227     }
228     return 0;
229 #endif
230 }
231 
232 
233 static off_t qio_channel_file_seek(QIOChannel *ioc,
234                                    off_t offset,
235                                    int whence,
236                                    Error **errp)
237 {
238     QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
239     off_t ret;
240 
241     ret = lseek(fioc->fd, offset, whence);
242     if (ret == (off_t)-1) {
243         error_setg_errno(errp, errno,
244                          "Unable to seek to offset %lld whence %d in file",
245                          (long long int)offset, whence);
246         return -1;
247     }
248     return ret;
249 }
250 
251 
252 static int qio_channel_file_close(QIOChannel *ioc,
253                                   Error **errp)
254 {
255     QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
256 
257     if (qemu_close(fioc->fd) < 0) {
258         error_setg_errno(errp, errno,
259                          "Unable to close file");
260         return -1;
261     }
262     fioc->fd = -1;
263     return 0;
264 }
265 
266 
267 static void qio_channel_file_set_aio_fd_handler(QIOChannel *ioc,
268                                                 AioContext *read_ctx,
269                                                 IOHandler *io_read,
270                                                 AioContext *write_ctx,
271                                                 IOHandler *io_write,
272                                                 void *opaque)
273 {
274     QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
275 
276     qio_channel_util_set_aio_fd_handler(fioc->fd, read_ctx, io_read,
277                                         fioc->fd, write_ctx, io_write,
278                                         opaque);
279 }
280 
281 static GSource *qio_channel_file_create_watch(QIOChannel *ioc,
282                                               GIOCondition condition)
283 {
284     QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
285     return qio_channel_create_fd_watch(ioc,
286                                        fioc->fd,
287                                        condition);
288 }
289 
290 static void qio_channel_file_class_init(ObjectClass *klass,
291                                         void *class_data G_GNUC_UNUSED)
292 {
293     QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass);
294 
295     ioc_klass->io_writev = qio_channel_file_writev;
296     ioc_klass->io_readv = qio_channel_file_readv;
297     ioc_klass->io_set_blocking = qio_channel_file_set_blocking;
298 #ifdef CONFIG_PREADV
299     ioc_klass->io_pwritev = qio_channel_file_pwritev;
300     ioc_klass->io_preadv = qio_channel_file_preadv;
301 #endif
302     ioc_klass->io_seek = qio_channel_file_seek;
303     ioc_klass->io_close = qio_channel_file_close;
304     ioc_klass->io_create_watch = qio_channel_file_create_watch;
305     ioc_klass->io_set_aio_fd_handler = qio_channel_file_set_aio_fd_handler;
306 }
307 
308 static const TypeInfo qio_channel_file_info = {
309     .parent = TYPE_QIO_CHANNEL,
310     .name = TYPE_QIO_CHANNEL_FILE,
311     .instance_size = sizeof(QIOChannelFile),
312     .instance_init = qio_channel_file_init,
313     .instance_finalize = qio_channel_file_finalize,
314     .class_init = qio_channel_file_class_init,
315 };
316 
317 static void qio_channel_file_register_types(void)
318 {
319     type_register_static(&qio_channel_file_info);
320 }
321 
322 type_init(qio_channel_file_register_types);
323