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 28 QIOChannelFile * 29 qio_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 43 QIOChannelFile * 44 qio_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 67 static void qio_channel_file_init(Object *obj) 68 { 69 QIOChannelFile *ioc = QIO_CHANNEL_FILE(obj); 70 ioc->fd = -1; 71 } 72 73 static 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 83 static 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 111 static 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 137 static 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 152 static 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 171 static 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 186 static 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 196 static 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 205 static 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 219 static 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 228 static void qio_channel_file_register_types(void) 229 { 230 type_register_static(&qio_channel_file_info); 231 } 232 233 type_init(qio_channel_file_register_types); 234