static gboolean ga_channel_open(GAChannel *c, const gchar *path, GAChannelMethod method, int fd) { int ret; c->method = method; switch (c->method) { case GA_CHANNEL_VIRTIO_SERIAL: { assert(fd < 0); fd = qemu_open(path, O_RDWR | O_NONBLOCK #ifndef CONFIG_SOLARIS | O_ASYNC #endif ); if (fd == -1) { g_critical("error opening channel: %s", strerror(errno)); return false; } #ifdef CONFIG_SOLARIS ret = ioctl(fd, I_SETSIG, S_OUTPUT | S_INPUT | S_HIPRI); if (ret == -1) { g_critical("error setting event mask for channel: %s", strerror(errno)); close(fd); return false; } #endif ret = ga_channel_client_add(c, fd); if (ret) { g_critical("error adding channel to main loop"); close(fd); return false; } break; } case GA_CHANNEL_ISA_SERIAL: { struct termios tio; assert(fd < 0); fd = qemu_open(path, O_RDWR | O_NOCTTY | O_NONBLOCK); if (fd == -1) { g_critical("error opening channel: %s", strerror(errno)); return false; } tcgetattr(fd, &tio); /* set up serial port for non-canonical, dumb byte streaming */ tio.c_iflag &= ~(IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF | IXANY | IMAXBEL); tio.c_oflag = 0; tio.c_lflag = 0; tio.c_cflag |= GA_CHANNEL_BAUDRATE_DEFAULT; /* 1 available byte min or reads will block (we'll set non-blocking * elsewhere, else we have to deal with read()=0 instead) */ tio.c_cc[VMIN] = 1; tio.c_cc[VTIME] = 0; /* flush everything waiting for read/xmit, it's garbage at this point */ tcflush(fd, TCIFLUSH); tcsetattr(fd, TCSANOW, &tio); ret = ga_channel_client_add(c, fd); if (ret) { g_critical("error adding channel to main loop"); close(fd); return false; } break; } case GA_CHANNEL_UNIX_LISTEN: { if (fd < 0) { Error *local_err = NULL; fd = unix_listen(path, NULL, strlen(path), &local_err); if (local_err != NULL) { g_critical("%s", error_get_pretty(local_err)); error_free(local_err); return false; } } ga_channel_listen_add(c, fd, true); break; } case GA_CHANNEL_VSOCK_LISTEN: { if (fd < 0) { Error *local_err = NULL; SocketAddress *addr; char *addr_str; addr_str = g_strdup_printf("vsock:%s", path); addr = socket_parse(addr_str, &local_err); g_free(addr_str); if (local_err != NULL) { g_critical("%s", error_get_pretty(local_err)); error_free(local_err); return false; } fd = socket_listen(addr, &local_err); qapi_free_SocketAddress(addr); if (local_err != NULL) { g_critical("%s", error_get_pretty(local_err)); error_free(local_err); return false; } } ga_channel_listen_add(c, fd, true); break; } default: g_critical("error binding/listening to specified socket"); return false; } return true; }