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