1*195e14d0SDaniel P. Berrange /* 2*195e14d0SDaniel P. Berrange * QEMU I/O channels external command driver 3*195e14d0SDaniel P. Berrange * 4*195e14d0SDaniel P. Berrange * Copyright (c) 2015 Red Hat, Inc. 5*195e14d0SDaniel P. Berrange * 6*195e14d0SDaniel P. Berrange * This library is free software; you can redistribute it and/or 7*195e14d0SDaniel P. Berrange * modify it under the terms of the GNU Lesser General Public 8*195e14d0SDaniel P. Berrange * License as published by the Free Software Foundation; either 9*195e14d0SDaniel P. Berrange * version 2 of the License, or (at your option) any later version. 10*195e14d0SDaniel P. Berrange * 11*195e14d0SDaniel P. Berrange * This library is distributed in the hope that it will be useful, 12*195e14d0SDaniel P. Berrange * but WITHOUT ANY WARRANTY; without even the implied warranty of 13*195e14d0SDaniel P. Berrange * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14*195e14d0SDaniel P. Berrange * Lesser General Public License for more details. 15*195e14d0SDaniel P. Berrange * 16*195e14d0SDaniel P. Berrange * You should have received a copy of the GNU Lesser General Public 17*195e14d0SDaniel P. Berrange * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18*195e14d0SDaniel P. Berrange * 19*195e14d0SDaniel P. Berrange */ 20*195e14d0SDaniel P. Berrange 21*195e14d0SDaniel P. Berrange #include "io/channel-command.h" 22*195e14d0SDaniel P. Berrange #include "io/channel-watch.h" 23*195e14d0SDaniel P. Berrange #include "qemu/sockets.h" 24*195e14d0SDaniel P. Berrange #include "trace.h" 25*195e14d0SDaniel P. Berrange 26*195e14d0SDaniel P. Berrange 27*195e14d0SDaniel P. Berrange QIOChannelCommand * 28*195e14d0SDaniel P. Berrange qio_channel_command_new_pid(int writefd, 29*195e14d0SDaniel P. Berrange int readfd, 30*195e14d0SDaniel P. Berrange pid_t pid) 31*195e14d0SDaniel P. Berrange { 32*195e14d0SDaniel P. Berrange QIOChannelCommand *ioc; 33*195e14d0SDaniel P. Berrange 34*195e14d0SDaniel P. Berrange ioc = QIO_CHANNEL_COMMAND(object_new(TYPE_QIO_CHANNEL_COMMAND)); 35*195e14d0SDaniel P. Berrange 36*195e14d0SDaniel P. Berrange ioc->readfd = readfd; 37*195e14d0SDaniel P. Berrange ioc->writefd = writefd; 38*195e14d0SDaniel P. Berrange ioc->pid = pid; 39*195e14d0SDaniel P. Berrange 40*195e14d0SDaniel P. Berrange trace_qio_channel_command_new_pid(ioc, writefd, readfd, pid); 41*195e14d0SDaniel P. Berrange return ioc; 42*195e14d0SDaniel P. Berrange } 43*195e14d0SDaniel P. Berrange 44*195e14d0SDaniel P. Berrange 45*195e14d0SDaniel P. Berrange #ifndef WIN32 46*195e14d0SDaniel P. Berrange QIOChannelCommand * 47*195e14d0SDaniel P. Berrange qio_channel_command_new_spawn(const char *const argv[], 48*195e14d0SDaniel P. Berrange int flags, 49*195e14d0SDaniel P. Berrange Error **errp) 50*195e14d0SDaniel P. Berrange { 51*195e14d0SDaniel P. Berrange pid_t pid = -1; 52*195e14d0SDaniel P. Berrange int stdinfd[2] = { -1, -1 }; 53*195e14d0SDaniel P. Berrange int stdoutfd[2] = { -1, -1 }; 54*195e14d0SDaniel P. Berrange int devnull = -1; 55*195e14d0SDaniel P. Berrange bool stdinnull = false, stdoutnull = false; 56*195e14d0SDaniel P. Berrange QIOChannelCommand *ioc; 57*195e14d0SDaniel P. Berrange 58*195e14d0SDaniel P. Berrange flags = flags & O_ACCMODE; 59*195e14d0SDaniel P. Berrange 60*195e14d0SDaniel P. Berrange if (flags == O_RDONLY) { 61*195e14d0SDaniel P. Berrange stdinnull = true; 62*195e14d0SDaniel P. Berrange } 63*195e14d0SDaniel P. Berrange if (flags == O_WRONLY) { 64*195e14d0SDaniel P. Berrange stdoutnull = true; 65*195e14d0SDaniel P. Berrange } 66*195e14d0SDaniel P. Berrange 67*195e14d0SDaniel P. Berrange if (stdinnull || stdoutnull) { 68*195e14d0SDaniel P. Berrange devnull = open("/dev/null", O_RDWR); 69*195e14d0SDaniel P. Berrange if (!devnull) { 70*195e14d0SDaniel P. Berrange error_setg_errno(errp, errno, 71*195e14d0SDaniel P. Berrange "Unable to open /dev/null"); 72*195e14d0SDaniel P. Berrange goto error; 73*195e14d0SDaniel P. Berrange } 74*195e14d0SDaniel P. Berrange } 75*195e14d0SDaniel P. Berrange 76*195e14d0SDaniel P. Berrange if ((!stdinnull && pipe(stdinfd) < 0) || 77*195e14d0SDaniel P. Berrange (!stdoutnull && pipe(stdoutfd) < 0)) { 78*195e14d0SDaniel P. Berrange error_setg_errno(errp, errno, 79*195e14d0SDaniel P. Berrange "Unable to open pipe"); 80*195e14d0SDaniel P. Berrange goto error; 81*195e14d0SDaniel P. Berrange } 82*195e14d0SDaniel P. Berrange 83*195e14d0SDaniel P. Berrange pid = qemu_fork(errp); 84*195e14d0SDaniel P. Berrange if (pid < 0) { 85*195e14d0SDaniel P. Berrange goto error; 86*195e14d0SDaniel P. Berrange } 87*195e14d0SDaniel P. Berrange 88*195e14d0SDaniel P. Berrange if (pid == 0) { /* child */ 89*195e14d0SDaniel P. Berrange dup2(stdinnull ? devnull : stdinfd[0], STDIN_FILENO); 90*195e14d0SDaniel P. Berrange dup2(stdoutnull ? devnull : stdoutfd[1], STDOUT_FILENO); 91*195e14d0SDaniel P. Berrange /* Leave stderr connected to qemu's stderr */ 92*195e14d0SDaniel P. Berrange 93*195e14d0SDaniel P. Berrange if (!stdinnull) { 94*195e14d0SDaniel P. Berrange close(stdinfd[0]); 95*195e14d0SDaniel P. Berrange close(stdinfd[1]); 96*195e14d0SDaniel P. Berrange } 97*195e14d0SDaniel P. Berrange if (!stdoutnull) { 98*195e14d0SDaniel P. Berrange close(stdoutfd[0]); 99*195e14d0SDaniel P. Berrange close(stdoutfd[1]); 100*195e14d0SDaniel P. Berrange } 101*195e14d0SDaniel P. Berrange 102*195e14d0SDaniel P. Berrange execv(argv[0], (char * const *)argv); 103*195e14d0SDaniel P. Berrange _exit(1); 104*195e14d0SDaniel P. Berrange } 105*195e14d0SDaniel P. Berrange 106*195e14d0SDaniel P. Berrange if (!stdinnull) { 107*195e14d0SDaniel P. Berrange close(stdinfd[0]); 108*195e14d0SDaniel P. Berrange } 109*195e14d0SDaniel P. Berrange if (!stdoutnull) { 110*195e14d0SDaniel P. Berrange close(stdoutfd[1]); 111*195e14d0SDaniel P. Berrange } 112*195e14d0SDaniel P. Berrange 113*195e14d0SDaniel P. Berrange ioc = qio_channel_command_new_pid(stdinnull ? devnull : stdinfd[1], 114*195e14d0SDaniel P. Berrange stdoutnull ? devnull : stdoutfd[0], 115*195e14d0SDaniel P. Berrange pid); 116*195e14d0SDaniel P. Berrange trace_qio_channel_command_new_spawn(ioc, argv[0], flags); 117*195e14d0SDaniel P. Berrange return ioc; 118*195e14d0SDaniel P. Berrange 119*195e14d0SDaniel P. Berrange error: 120*195e14d0SDaniel P. Berrange if (stdinfd[0] != -1) { 121*195e14d0SDaniel P. Berrange close(stdinfd[0]); 122*195e14d0SDaniel P. Berrange } 123*195e14d0SDaniel P. Berrange if (stdinfd[1] != -1) { 124*195e14d0SDaniel P. Berrange close(stdinfd[1]); 125*195e14d0SDaniel P. Berrange } 126*195e14d0SDaniel P. Berrange if (stdoutfd[0] != -1) { 127*195e14d0SDaniel P. Berrange close(stdoutfd[0]); 128*195e14d0SDaniel P. Berrange } 129*195e14d0SDaniel P. Berrange if (stdoutfd[1] != -1) { 130*195e14d0SDaniel P. Berrange close(stdoutfd[1]); 131*195e14d0SDaniel P. Berrange } 132*195e14d0SDaniel P. Berrange return NULL; 133*195e14d0SDaniel P. Berrange } 134*195e14d0SDaniel P. Berrange 135*195e14d0SDaniel P. Berrange #else /* WIN32 */ 136*195e14d0SDaniel P. Berrange QIOChannelCommand * 137*195e14d0SDaniel P. Berrange qio_channel_command_new_spawn(const char *const argv[], 138*195e14d0SDaniel P. Berrange int flags, 139*195e14d0SDaniel P. Berrange Error **errp) 140*195e14d0SDaniel P. Berrange { 141*195e14d0SDaniel P. Berrange error_setg_errno(errp, ENOSYS, 142*195e14d0SDaniel P. Berrange "Command spawn not supported on this platform"); 143*195e14d0SDaniel P. Berrange return NULL; 144*195e14d0SDaniel P. Berrange } 145*195e14d0SDaniel P. Berrange #endif /* WIN32 */ 146*195e14d0SDaniel P. Berrange 147*195e14d0SDaniel P. Berrange #ifndef WIN32 148*195e14d0SDaniel P. Berrange static int qio_channel_command_abort(QIOChannelCommand *ioc, 149*195e14d0SDaniel P. Berrange Error **errp) 150*195e14d0SDaniel P. Berrange { 151*195e14d0SDaniel P. Berrange pid_t ret; 152*195e14d0SDaniel P. Berrange int status; 153*195e14d0SDaniel P. Berrange int step = 0; 154*195e14d0SDaniel P. Berrange 155*195e14d0SDaniel P. Berrange /* See if intermediate process has exited; if not, try a nice 156*195e14d0SDaniel P. Berrange * SIGTERM followed by a more severe SIGKILL. 157*195e14d0SDaniel P. Berrange */ 158*195e14d0SDaniel P. Berrange rewait: 159*195e14d0SDaniel P. Berrange trace_qio_channel_command_abort(ioc, ioc->pid); 160*195e14d0SDaniel P. Berrange ret = waitpid(ioc->pid, &status, WNOHANG); 161*195e14d0SDaniel P. Berrange trace_qio_channel_command_wait(ioc, ioc->pid, ret, status); 162*195e14d0SDaniel P. Berrange if (ret == (pid_t)-1) { 163*195e14d0SDaniel P. Berrange if (errno == EINTR) { 164*195e14d0SDaniel P. Berrange goto rewait; 165*195e14d0SDaniel P. Berrange } else { 166*195e14d0SDaniel P. Berrange error_setg_errno(errp, errno, 167*195e14d0SDaniel P. Berrange "Cannot wait on pid %llu", 168*195e14d0SDaniel P. Berrange (unsigned long long)ioc->pid); 169*195e14d0SDaniel P. Berrange return -1; 170*195e14d0SDaniel P. Berrange } 171*195e14d0SDaniel P. Berrange } else if (ret == 0) { 172*195e14d0SDaniel P. Berrange if (step == 0) { 173*195e14d0SDaniel P. Berrange kill(ioc->pid, SIGTERM); 174*195e14d0SDaniel P. Berrange } else if (step == 1) { 175*195e14d0SDaniel P. Berrange kill(ioc->pid, SIGKILL); 176*195e14d0SDaniel P. Berrange } else { 177*195e14d0SDaniel P. Berrange error_setg(errp, 178*195e14d0SDaniel P. Berrange "Process %llu refused to die", 179*195e14d0SDaniel P. Berrange (unsigned long long)ioc->pid); 180*195e14d0SDaniel P. Berrange return -1; 181*195e14d0SDaniel P. Berrange } 182*195e14d0SDaniel P. Berrange usleep(10 * 1000); 183*195e14d0SDaniel P. Berrange goto rewait; 184*195e14d0SDaniel P. Berrange } 185*195e14d0SDaniel P. Berrange 186*195e14d0SDaniel P. Berrange return 0; 187*195e14d0SDaniel P. Berrange } 188*195e14d0SDaniel P. Berrange #endif /* ! WIN32 */ 189*195e14d0SDaniel P. Berrange 190*195e14d0SDaniel P. Berrange 191*195e14d0SDaniel P. Berrange static void qio_channel_command_init(Object *obj) 192*195e14d0SDaniel P. Berrange { 193*195e14d0SDaniel P. Berrange QIOChannelCommand *ioc = QIO_CHANNEL_COMMAND(obj); 194*195e14d0SDaniel P. Berrange ioc->readfd = -1; 195*195e14d0SDaniel P. Berrange ioc->writefd = -1; 196*195e14d0SDaniel P. Berrange ioc->pid = -1; 197*195e14d0SDaniel P. Berrange } 198*195e14d0SDaniel P. Berrange 199*195e14d0SDaniel P. Berrange static void qio_channel_command_finalize(Object *obj) 200*195e14d0SDaniel P. Berrange { 201*195e14d0SDaniel P. Berrange QIOChannelCommand *ioc = QIO_CHANNEL_COMMAND(obj); 202*195e14d0SDaniel P. Berrange if (ioc->readfd != -1) { 203*195e14d0SDaniel P. Berrange close(ioc->readfd); 204*195e14d0SDaniel P. Berrange ioc->readfd = -1; 205*195e14d0SDaniel P. Berrange } 206*195e14d0SDaniel P. Berrange if (ioc->writefd != -1) { 207*195e14d0SDaniel P. Berrange close(ioc->writefd); 208*195e14d0SDaniel P. Berrange ioc->writefd = -1; 209*195e14d0SDaniel P. Berrange } 210*195e14d0SDaniel P. Berrange if (ioc->pid > 0) { 211*195e14d0SDaniel P. Berrange #ifndef WIN32 212*195e14d0SDaniel P. Berrange qio_channel_command_abort(ioc, NULL); 213*195e14d0SDaniel P. Berrange #endif 214*195e14d0SDaniel P. Berrange } 215*195e14d0SDaniel P. Berrange } 216*195e14d0SDaniel P. Berrange 217*195e14d0SDaniel P. Berrange 218*195e14d0SDaniel P. Berrange static ssize_t qio_channel_command_readv(QIOChannel *ioc, 219*195e14d0SDaniel P. Berrange const struct iovec *iov, 220*195e14d0SDaniel P. Berrange size_t niov, 221*195e14d0SDaniel P. Berrange int **fds, 222*195e14d0SDaniel P. Berrange size_t *nfds, 223*195e14d0SDaniel P. Berrange Error **errp) 224*195e14d0SDaniel P. Berrange { 225*195e14d0SDaniel P. Berrange QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc); 226*195e14d0SDaniel P. Berrange ssize_t ret; 227*195e14d0SDaniel P. Berrange 228*195e14d0SDaniel P. Berrange retry: 229*195e14d0SDaniel P. Berrange ret = readv(cioc->readfd, iov, niov); 230*195e14d0SDaniel P. Berrange if (ret < 0) { 231*195e14d0SDaniel P. Berrange if (errno == EAGAIN || 232*195e14d0SDaniel P. Berrange errno == EWOULDBLOCK) { 233*195e14d0SDaniel P. Berrange return QIO_CHANNEL_ERR_BLOCK; 234*195e14d0SDaniel P. Berrange } 235*195e14d0SDaniel P. Berrange if (errno == EINTR) { 236*195e14d0SDaniel P. Berrange goto retry; 237*195e14d0SDaniel P. Berrange } 238*195e14d0SDaniel P. Berrange 239*195e14d0SDaniel P. Berrange error_setg_errno(errp, errno, 240*195e14d0SDaniel P. Berrange "Unable to read from command"); 241*195e14d0SDaniel P. Berrange return -1; 242*195e14d0SDaniel P. Berrange } 243*195e14d0SDaniel P. Berrange 244*195e14d0SDaniel P. Berrange return ret; 245*195e14d0SDaniel P. Berrange } 246*195e14d0SDaniel P. Berrange 247*195e14d0SDaniel P. Berrange static ssize_t qio_channel_command_writev(QIOChannel *ioc, 248*195e14d0SDaniel P. Berrange const struct iovec *iov, 249*195e14d0SDaniel P. Berrange size_t niov, 250*195e14d0SDaniel P. Berrange int *fds, 251*195e14d0SDaniel P. Berrange size_t nfds, 252*195e14d0SDaniel P. Berrange Error **errp) 253*195e14d0SDaniel P. Berrange { 254*195e14d0SDaniel P. Berrange QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc); 255*195e14d0SDaniel P. Berrange ssize_t ret; 256*195e14d0SDaniel P. Berrange 257*195e14d0SDaniel P. Berrange retry: 258*195e14d0SDaniel P. Berrange ret = writev(cioc->writefd, iov, niov); 259*195e14d0SDaniel P. Berrange if (ret <= 0) { 260*195e14d0SDaniel P. Berrange if (errno == EAGAIN || 261*195e14d0SDaniel P. Berrange errno == EWOULDBLOCK) { 262*195e14d0SDaniel P. Berrange return QIO_CHANNEL_ERR_BLOCK; 263*195e14d0SDaniel P. Berrange } 264*195e14d0SDaniel P. Berrange if (errno == EINTR) { 265*195e14d0SDaniel P. Berrange goto retry; 266*195e14d0SDaniel P. Berrange } 267*195e14d0SDaniel P. Berrange error_setg_errno(errp, errno, "%s", 268*195e14d0SDaniel P. Berrange "Unable to write to command"); 269*195e14d0SDaniel P. Berrange return -1; 270*195e14d0SDaniel P. Berrange } 271*195e14d0SDaniel P. Berrange return ret; 272*195e14d0SDaniel P. Berrange } 273*195e14d0SDaniel P. Berrange 274*195e14d0SDaniel P. Berrange static int qio_channel_command_set_blocking(QIOChannel *ioc, 275*195e14d0SDaniel P. Berrange bool enabled, 276*195e14d0SDaniel P. Berrange Error **errp) 277*195e14d0SDaniel P. Berrange { 278*195e14d0SDaniel P. Berrange QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc); 279*195e14d0SDaniel P. Berrange 280*195e14d0SDaniel P. Berrange if (enabled) { 281*195e14d0SDaniel P. Berrange qemu_set_block(cioc->writefd); 282*195e14d0SDaniel P. Berrange qemu_set_block(cioc->readfd); 283*195e14d0SDaniel P. Berrange } else { 284*195e14d0SDaniel P. Berrange qemu_set_nonblock(cioc->writefd); 285*195e14d0SDaniel P. Berrange qemu_set_nonblock(cioc->readfd); 286*195e14d0SDaniel P. Berrange } 287*195e14d0SDaniel P. Berrange 288*195e14d0SDaniel P. Berrange return 0; 289*195e14d0SDaniel P. Berrange } 290*195e14d0SDaniel P. Berrange 291*195e14d0SDaniel P. Berrange 292*195e14d0SDaniel P. Berrange static int qio_channel_command_close(QIOChannel *ioc, 293*195e14d0SDaniel P. Berrange Error **errp) 294*195e14d0SDaniel P. Berrange { 295*195e14d0SDaniel P. Berrange QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc); 296*195e14d0SDaniel P. Berrange int rv = 0; 297*195e14d0SDaniel P. Berrange 298*195e14d0SDaniel P. Berrange /* We close FDs before killing, because that 299*195e14d0SDaniel P. Berrange * gives a better chance of clean shutdown 300*195e14d0SDaniel P. Berrange */ 301*195e14d0SDaniel P. Berrange if (close(cioc->writefd) < 0) { 302*195e14d0SDaniel P. Berrange rv = -1; 303*195e14d0SDaniel P. Berrange } 304*195e14d0SDaniel P. Berrange if (close(cioc->readfd) < 0) { 305*195e14d0SDaniel P. Berrange rv = -1; 306*195e14d0SDaniel P. Berrange } 307*195e14d0SDaniel P. Berrange #ifndef WIN32 308*195e14d0SDaniel P. Berrange if (qio_channel_command_abort(cioc, errp) < 0) { 309*195e14d0SDaniel P. Berrange return -1; 310*195e14d0SDaniel P. Berrange } 311*195e14d0SDaniel P. Berrange #endif 312*195e14d0SDaniel P. Berrange if (rv < 0) { 313*195e14d0SDaniel P. Berrange error_setg_errno(errp, errno, "%s", 314*195e14d0SDaniel P. Berrange "Unable to close command"); 315*195e14d0SDaniel P. Berrange } 316*195e14d0SDaniel P. Berrange return rv; 317*195e14d0SDaniel P. Berrange } 318*195e14d0SDaniel P. Berrange 319*195e14d0SDaniel P. Berrange 320*195e14d0SDaniel P. Berrange static GSource *qio_channel_command_create_watch(QIOChannel *ioc, 321*195e14d0SDaniel P. Berrange GIOCondition condition) 322*195e14d0SDaniel P. Berrange { 323*195e14d0SDaniel P. Berrange QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc); 324*195e14d0SDaniel P. Berrange return qio_channel_create_fd_pair_watch(ioc, 325*195e14d0SDaniel P. Berrange cioc->readfd, 326*195e14d0SDaniel P. Berrange cioc->writefd, 327*195e14d0SDaniel P. Berrange condition); 328*195e14d0SDaniel P. Berrange } 329*195e14d0SDaniel P. Berrange 330*195e14d0SDaniel P. Berrange 331*195e14d0SDaniel P. Berrange static void qio_channel_command_class_init(ObjectClass *klass, 332*195e14d0SDaniel P. Berrange void *class_data G_GNUC_UNUSED) 333*195e14d0SDaniel P. Berrange { 334*195e14d0SDaniel P. Berrange QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass); 335*195e14d0SDaniel P. Berrange 336*195e14d0SDaniel P. Berrange ioc_klass->io_writev = qio_channel_command_writev; 337*195e14d0SDaniel P. Berrange ioc_klass->io_readv = qio_channel_command_readv; 338*195e14d0SDaniel P. Berrange ioc_klass->io_set_blocking = qio_channel_command_set_blocking; 339*195e14d0SDaniel P. Berrange ioc_klass->io_close = qio_channel_command_close; 340*195e14d0SDaniel P. Berrange ioc_klass->io_create_watch = qio_channel_command_create_watch; 341*195e14d0SDaniel P. Berrange } 342*195e14d0SDaniel P. Berrange 343*195e14d0SDaniel P. Berrange static const TypeInfo qio_channel_command_info = { 344*195e14d0SDaniel P. Berrange .parent = TYPE_QIO_CHANNEL, 345*195e14d0SDaniel P. Berrange .name = TYPE_QIO_CHANNEL_COMMAND, 346*195e14d0SDaniel P. Berrange .instance_size = sizeof(QIOChannelCommand), 347*195e14d0SDaniel P. Berrange .instance_init = qio_channel_command_init, 348*195e14d0SDaniel P. Berrange .instance_finalize = qio_channel_command_finalize, 349*195e14d0SDaniel P. Berrange .class_init = qio_channel_command_class_init, 350*195e14d0SDaniel P. Berrange }; 351*195e14d0SDaniel P. Berrange 352*195e14d0SDaniel P. Berrange static void qio_channel_command_register_types(void) 353*195e14d0SDaniel P. Berrange { 354*195e14d0SDaniel P. Berrange type_register_static(&qio_channel_command_info); 355*195e14d0SDaniel P. Berrange } 356*195e14d0SDaniel P. Berrange 357*195e14d0SDaniel P. Berrange type_init(qio_channel_command_register_types); 358