/*
 * QEMU I/O channels files driver
 *
 * Copyright (c) 2015 Red Hat, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "qemu/osdep.h"
#include "io/channel-file.h"
#include "io/channel-watch.h"
#include "qapi/error.h"
#include "qemu/module.h"
#include "qemu/sockets.h"
#include "trace.h"

QIOChannelFile *
qio_channel_file_new_fd(int fd)
{
    QIOChannelFile *ioc;

    ioc = QIO_CHANNEL_FILE(object_new(TYPE_QIO_CHANNEL_FILE));

    ioc->fd = fd;

    trace_qio_channel_file_new_fd(ioc, fd);

    return ioc;
}


QIOChannelFile *
qio_channel_file_new_path(const char *path,
                          int flags,
                          mode_t mode,
                          Error **errp)
{
    QIOChannelFile *ioc;

    ioc = QIO_CHANNEL_FILE(object_new(TYPE_QIO_CHANNEL_FILE));

    ioc->fd = qemu_open(path, flags, mode);
    if (ioc->fd < 0) {
        object_unref(OBJECT(ioc));
        error_setg_errno(errp, errno,
                         "Unable to open %s", path);
        return NULL;
    }

    trace_qio_channel_file_new_path(ioc, path, flags, mode, ioc->fd);

    return ioc;
}


static void qio_channel_file_init(Object *obj)
{
    QIOChannelFile *ioc = QIO_CHANNEL_FILE(obj);
    ioc->fd = -1;
}

static void qio_channel_file_finalize(Object *obj)
{
    QIOChannelFile *ioc = QIO_CHANNEL_FILE(obj);
    if (ioc->fd != -1) {
        qemu_close(ioc->fd);
        ioc->fd = -1;
    }
}


static ssize_t qio_channel_file_readv(QIOChannel *ioc,
                                      const struct iovec *iov,
                                      size_t niov,
                                      int **fds,
                                      size_t *nfds,
                                      Error **errp)
{
    QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
    ssize_t ret;

 retry:
    ret = readv(fioc->fd, iov, niov);
    if (ret < 0) {
        if (errno == EAGAIN) {
            return QIO_CHANNEL_ERR_BLOCK;
        }
        if (errno == EINTR) {
            goto retry;
        }

        error_setg_errno(errp, errno,
                         "Unable to read from file");
        return -1;
    }

    return ret;
}

static ssize_t qio_channel_file_writev(QIOChannel *ioc,
                                       const struct iovec *iov,
                                       size_t niov,
                                       int *fds,
                                       size_t nfds,
                                       Error **errp)
{
    QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
    ssize_t ret;

 retry:
    ret = writev(fioc->fd, iov, niov);
    if (ret <= 0) {
        if (errno == EAGAIN) {
            return QIO_CHANNEL_ERR_BLOCK;
        }
        if (errno == EINTR) {
            goto retry;
        }
        error_setg_errno(errp, errno,
                         "Unable to write to file");
        return -1;
    }
    return ret;
}

static int qio_channel_file_set_blocking(QIOChannel *ioc,
                                         bool enabled,
                                         Error **errp)
{
    QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);

    if (enabled) {
        qemu_set_block(fioc->fd);
    } else {
        qemu_set_nonblock(fioc->fd);
    }
    return 0;
}


static off_t qio_channel_file_seek(QIOChannel *ioc,
                                   off_t offset,
                                   int whence,
                                   Error **errp)
{
    QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
    off_t ret;

    ret = lseek(fioc->fd, offset, whence);
    if (ret == (off_t)-1) {
        error_setg_errno(errp, errno,
                         "Unable to seek to offset %lld whence %d in file",
                         (long long int)offset, whence);
        return -1;
    }
    return ret;
}


static int qio_channel_file_close(QIOChannel *ioc,
                                  Error **errp)
{
    QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);

    if (qemu_close(fioc->fd) < 0) {
        error_setg_errno(errp, errno,
                         "Unable to close file");
        return -1;
    }
    fioc->fd = -1;
    return 0;
}


static void qio_channel_file_set_aio_fd_handler(QIOChannel *ioc,
                                                AioContext *ctx,
                                                IOHandler *io_read,
                                                IOHandler *io_write,
                                                void *opaque)
{
    QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
    aio_set_fd_handler(ctx, fioc->fd, false, io_read, io_write, NULL, opaque);
}

static GSource *qio_channel_file_create_watch(QIOChannel *ioc,
                                              GIOCondition condition)
{
    QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
    return qio_channel_create_fd_watch(ioc,
                                       fioc->fd,
                                       condition);
}

static void qio_channel_file_class_init(ObjectClass *klass,
                                        void *class_data G_GNUC_UNUSED)
{
    QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass);

    ioc_klass->io_writev = qio_channel_file_writev;
    ioc_klass->io_readv = qio_channel_file_readv;
    ioc_klass->io_set_blocking = qio_channel_file_set_blocking;
    ioc_klass->io_seek = qio_channel_file_seek;
    ioc_klass->io_close = qio_channel_file_close;
    ioc_klass->io_create_watch = qio_channel_file_create_watch;
    ioc_klass->io_set_aio_fd_handler = qio_channel_file_set_aio_fd_handler;
}

static const TypeInfo qio_channel_file_info = {
    .parent = TYPE_QIO_CHANNEL,
    .name = TYPE_QIO_CHANNEL_FILE,
    .instance_size = sizeof(QIOChannelFile),
    .instance_init = qio_channel_file_init,
    .instance_finalize = qio_channel_file_finalize,
    .class_init = qio_channel_file_class_init,
};

static void qio_channel_file_register_types(void)
{
    type_register_static(&qio_channel_file_info);
}

type_init(qio_channel_file_register_types);
