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 static int qio_channel_file_set_blocking(QIOChannel *ioc, 150 bool enabled, 151 Error **errp) 152 { 153 #ifdef WIN32 154 /* not implemented */ 155 error_setg_errno(errp, errno, "Failed to set FD nonblocking"); 156 return -1; 157 #else 158 QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc); 159 160 if (!g_unix_set_fd_nonblocking(fioc->fd, !enabled, NULL)) { 161 error_setg_errno(errp, errno, "Failed to set FD nonblocking"); 162 return -1; 163 } 164 return 0; 165 #endif 166 } 167 168 169 static off_t qio_channel_file_seek(QIOChannel *ioc, 170 off_t offset, 171 int whence, 172 Error **errp) 173 { 174 QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc); 175 off_t ret; 176 177 ret = lseek(fioc->fd, offset, whence); 178 if (ret == (off_t)-1) { 179 error_setg_errno(errp, errno, 180 "Unable to seek to offset %lld whence %d in file", 181 (long long int)offset, whence); 182 return -1; 183 } 184 return ret; 185 } 186 187 188 static int qio_channel_file_close(QIOChannel *ioc, 189 Error **errp) 190 { 191 QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc); 192 193 if (qemu_close(fioc->fd) < 0) { 194 error_setg_errno(errp, errno, 195 "Unable to close file"); 196 return -1; 197 } 198 fioc->fd = -1; 199 return 0; 200 } 201 202 203 static void qio_channel_file_set_aio_fd_handler(QIOChannel *ioc, 204 AioContext *read_ctx, 205 IOHandler *io_read, 206 AioContext *write_ctx, 207 IOHandler *io_write, 208 void *opaque) 209 { 210 QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc); 211 212 qio_channel_util_set_aio_fd_handler(fioc->fd, read_ctx, io_read, 213 fioc->fd, write_ctx, io_write, 214 opaque); 215 } 216 217 static GSource *qio_channel_file_create_watch(QIOChannel *ioc, 218 GIOCondition condition) 219 { 220 QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc); 221 return qio_channel_create_fd_watch(ioc, 222 fioc->fd, 223 condition); 224 } 225 226 static void qio_channel_file_class_init(ObjectClass *klass, 227 void *class_data G_GNUC_UNUSED) 228 { 229 QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass); 230 231 ioc_klass->io_writev = qio_channel_file_writev; 232 ioc_klass->io_readv = qio_channel_file_readv; 233 ioc_klass->io_set_blocking = qio_channel_file_set_blocking; 234 ioc_klass->io_seek = qio_channel_file_seek; 235 ioc_klass->io_close = qio_channel_file_close; 236 ioc_klass->io_create_watch = qio_channel_file_create_watch; 237 ioc_klass->io_set_aio_fd_handler = qio_channel_file_set_aio_fd_handler; 238 } 239 240 static const TypeInfo qio_channel_file_info = { 241 .parent = TYPE_QIO_CHANNEL, 242 .name = TYPE_QIO_CHANNEL_FILE, 243 .instance_size = sizeof(QIOChannelFile), 244 .instance_init = qio_channel_file_init, 245 .instance_finalize = qio_channel_file_finalize, 246 .class_init = qio_channel_file_class_init, 247 }; 248 249 static void qio_channel_file_register_types(void) 250 { 251 type_register_static(&qio_channel_file_info); 252 } 253 254 type_init(qio_channel_file_register_types); 255