qemu/io/channel-file.c
<<
>>
Prefs
   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-watch.h"
  24#include "qapi/error.h"
  25#include "qemu/module.h"
  26#include "qemu/sockets.h"
  27#include "trace.h"
  28
  29QIOChannelFile *
  30qio_channel_file_new_fd(int fd)
  31{
  32    QIOChannelFile *ioc;
  33
  34    ioc = QIO_CHANNEL_FILE(object_new(TYPE_QIO_CHANNEL_FILE));
  35
  36    ioc->fd = fd;
  37
  38    trace_qio_channel_file_new_fd(ioc, fd);
  39
  40    return ioc;
  41}
  42
  43
  44QIOChannelFile *
  45qio_channel_file_new_path(const char *path,
  46                          int flags,
  47                          mode_t mode,
  48                          Error **errp)
  49{
  50    QIOChannelFile *ioc;
  51
  52    ioc = QIO_CHANNEL_FILE(object_new(TYPE_QIO_CHANNEL_FILE));
  53
  54    ioc->fd = qemu_open_old(path, flags, mode);
  55    if (ioc->fd < 0) {
  56        object_unref(OBJECT(ioc));
  57        error_setg_errno(errp, errno,
  58                         "Unable to open %s", path);
  59        return NULL;
  60    }
  61
  62    trace_qio_channel_file_new_path(ioc, path, flags, mode, ioc->fd);
  63
  64    return ioc;
  65}
  66
  67
  68static void qio_channel_file_init(Object *obj)
  69{
  70    QIOChannelFile *ioc = QIO_CHANNEL_FILE(obj);
  71    ioc->fd = -1;
  72}
  73
  74static void qio_channel_file_finalize(Object *obj)
  75{
  76    QIOChannelFile *ioc = QIO_CHANNEL_FILE(obj);
  77    if (ioc->fd != -1) {
  78        qemu_close(ioc->fd);
  79        ioc->fd = -1;
  80    }
  81}
  82
  83
  84static ssize_t qio_channel_file_readv(QIOChannel *ioc,
  85                                      const struct iovec *iov,
  86                                      size_t niov,
  87                                      int **fds,
  88                                      size_t *nfds,
  89                                      Error **errp)
  90{
  91    QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
  92    ssize_t ret;
  93
  94 retry:
  95    ret = readv(fioc->fd, iov, niov);
  96    if (ret < 0) {
  97        if (errno == EAGAIN) {
  98            return QIO_CHANNEL_ERR_BLOCK;
  99        }
 100        if (errno == EINTR) {
 101            goto retry;
 102        }
 103
 104        error_setg_errno(errp, errno,
 105                         "Unable to read from file");
 106        return -1;
 107    }
 108
 109    return ret;
 110}
 111
 112static ssize_t qio_channel_file_writev(QIOChannel *ioc,
 113                                       const struct iovec *iov,
 114                                       size_t niov,
 115                                       int *fds,
 116                                       size_t nfds,
 117                                       Error **errp)
 118{
 119    QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
 120    ssize_t ret;
 121
 122 retry:
 123    ret = writev(fioc->fd, iov, niov);
 124    if (ret <= 0) {
 125        if (errno == EAGAIN) {
 126            return QIO_CHANNEL_ERR_BLOCK;
 127        }
 128        if (errno == EINTR) {
 129            goto retry;
 130        }
 131        error_setg_errno(errp, errno,
 132                         "Unable to write to file");
 133        return -1;
 134    }
 135    return ret;
 136}
 137
 138static int qio_channel_file_set_blocking(QIOChannel *ioc,
 139                                         bool enabled,
 140                                         Error **errp)
 141{
 142    QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
 143
 144    if (enabled) {
 145        qemu_set_block(fioc->fd);
 146    } else {
 147        qemu_set_nonblock(fioc->fd);
 148    }
 149    return 0;
 150}
 151
 152
 153static off_t qio_channel_file_seek(QIOChannel *ioc,
 154                                   off_t offset,
 155                                   int whence,
 156                                   Error **errp)
 157{
 158    QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
 159    off_t ret;
 160
 161    ret = lseek(fioc->fd, offset, whence);
 162    if (ret == (off_t)-1) {
 163        error_setg_errno(errp, errno,
 164                         "Unable to seek to offset %lld whence %d in file",
 165                         (long long int)offset, whence);
 166        return -1;
 167    }
 168    return ret;
 169}
 170
 171
 172static int qio_channel_file_close(QIOChannel *ioc,
 173                                  Error **errp)
 174{
 175    QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
 176
 177    if (qemu_close(fioc->fd) < 0) {
 178        error_setg_errno(errp, errno,
 179                         "Unable to close file");
 180        return -1;
 181    }
 182    fioc->fd = -1;
 183    return 0;
 184}
 185
 186
 187static void qio_channel_file_set_aio_fd_handler(QIOChannel *ioc,
 188                                                AioContext *ctx,
 189                                                IOHandler *io_read,
 190                                                IOHandler *io_write,
 191                                                void *opaque)
 192{
 193    QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
 194    aio_set_fd_handler(ctx, fioc->fd, false, io_read, io_write,
 195                       NULL, NULL, opaque);
 196}
 197
 198static GSource *qio_channel_file_create_watch(QIOChannel *ioc,
 199                                              GIOCondition condition)
 200{
 201    QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
 202    return qio_channel_create_fd_watch(ioc,
 203                                       fioc->fd,
 204                                       condition);
 205}
 206
 207static void qio_channel_file_class_init(ObjectClass *klass,
 208                                        void *class_data G_GNUC_UNUSED)
 209{
 210    QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass);
 211
 212    ioc_klass->io_writev = qio_channel_file_writev;
 213    ioc_klass->io_readv = qio_channel_file_readv;
 214    ioc_klass->io_set_blocking = qio_channel_file_set_blocking;
 215    ioc_klass->io_seek = qio_channel_file_seek;
 216    ioc_klass->io_close = qio_channel_file_close;
 217    ioc_klass->io_create_watch = qio_channel_file_create_watch;
 218    ioc_klass->io_set_aio_fd_handler = qio_channel_file_set_aio_fd_handler;
 219}
 220
 221static const TypeInfo qio_channel_file_info = {
 222    .parent = TYPE_QIO_CHANNEL,
 223    .name = TYPE_QIO_CHANNEL_FILE,
 224    .instance_size = sizeof(QIOChannelFile),
 225    .instance_init = qio_channel_file_init,
 226    .instance_finalize = qio_channel_file_finalize,
 227    .class_init = qio_channel_file_class_init,
 228};
 229
 230static void qio_channel_file_register_types(void)
 231{
 232    type_register_static(&qio_channel_file_info);
 233}
 234
 235type_init(qio_channel_file_register_types);
 236