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