static void
g_unix_input_stream_set_property (GObject         *object,
				  guint            prop_id,
				  const GValue    *value,
				  GParamSpec      *pspec)
{
  GUnixInputStream *unix_stream;
  
  unix_stream = G_UNIX_INPUT_STREAM (object);

  switch (prop_id)
    {
    case PROP_FD:
      unix_stream->priv->fd = g_value_get_int (value);
      if (lseek (unix_stream->priv->fd, 0, SEEK_CUR) == -1 && errno == ESPIPE)
	unix_stream->priv->is_pipe_or_socket = TRUE;
      else
	unix_stream->priv->is_pipe_or_socket = FALSE;
      break;
    case PROP_CLOSE_FD:
      unix_stream->priv->close_fd = g_value_get_boolean (value);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}
static gboolean
g_unix_input_stream_close (GInputStream  *stream,
			   GCancellable  *cancellable,
			   GError       **error)
{
  GUnixInputStream *unix_stream;
  int res;

  unix_stream = G_UNIX_INPUT_STREAM (stream);

  if (!unix_stream->priv->close_fd)
    return TRUE;
  
  /* This might block during the close. Doesn't seem to be a way to avoid it though. */
  res = close (unix_stream->priv->fd);
  if (res == -1)
    {
      int errsv = errno;

      g_set_error (error, G_IO_ERROR,
		   g_io_error_from_errno (errsv),
		   _("Error closing file descriptor: %s"),
		   g_strerror (errsv));
    }
  
  return res != -1;
}
static gboolean do_console_raw_local_read(GObject *stream,
                                          gpointer opaque)
{
    GUnixInputStream *localStdin = G_UNIX_INPUT_STREAM(stream);
    GVirSandboxConsoleRaw *console = GVIR_SANDBOX_CONSOLE_RAW(opaque);
    GVirSandboxConsoleRawPrivate *priv = console->priv;
    GError *err = NULL;

    gssize ret = g_pollable_input_stream_read_nonblocking
        (G_POLLABLE_INPUT_STREAM(localStdin),
         priv->localToConsole + priv->localToConsoleOffset,
         priv->localToConsoleLength - priv->localToConsoleOffset,
         NULL, &err);
    if (ret < 0) {
        g_debug("Error from local read %s", err ? err->message : "");
        do_console_raw_close(console, err);
        g_error_free(err);
        goto cleanup;
    }

    if (ret == 0)
        priv->localEOF = TRUE;
    else if (priv->localToConsole[priv->localToConsoleOffset] ==
             CONTROL(gvir_sandbox_console_get_escape(GVIR_SANDBOX_CONSOLE(console)))) {
        do_console_raw_close(console, err);
        goto cleanup;
    }

    priv->localToConsoleOffset += ret;

    priv->localStdinSource = NULL;
    do_console_raw_update_events(console);
 cleanup:
    return FALSE;
}
Example #4
0
static void
g_unix_input_stream_read_async (GInputStream        *stream,
				void                *buffer,
				gsize                count,
				int                  io_priority,
				GCancellable        *cancellable,
				GAsyncReadyCallback  callback,
				gpointer             user_data)
{
  GSource *source;
  GUnixInputStream *unix_stream;
  ReadAsyncData *data;

  unix_stream = G_UNIX_INPUT_STREAM (stream);

  data = g_new0 (ReadAsyncData, 1);
  data->count = count;
  data->buffer = buffer;
  data->callback = callback;
  data->user_data = user_data;
  data->cancellable = cancellable;
  data->stream = unix_stream;

  source = _g_fd_source_new (unix_stream->priv->fd,
			     G_IO_IN,
			     cancellable);
  g_source_set_name (source, "GUnixInputStream");
  
  g_source_set_callback (source, (GSourceFunc)read_async_cb, data, g_free);
  g_source_attach (source, g_main_context_get_thread_default ());
 
  g_source_unref (source);
}
Example #5
0
static gssize
g_unix_input_stream_read (GInputStream  *stream,
			  void          *buffer,
			  gsize          count,
			  GCancellable  *cancellable,
			  GError       **error)
{
  GUnixInputStream *unix_stream;
  gssize res;
  GPollFD poll_fds[2];
  int poll_ret;

  unix_stream = G_UNIX_INPUT_STREAM (stream);

  if (g_cancellable_make_pollfd (cancellable, &poll_fds[1]))
    {
      poll_fds[0].fd = unix_stream->priv->fd;
      poll_fds[0].events = G_IO_IN;
      do
	poll_ret = g_poll (poll_fds, 2, -1);
      while (poll_ret == -1 && errno == EINTR);
      g_cancellable_release_fd (cancellable);

      if (poll_ret == -1)
	{
          int errsv = errno;

	  g_set_error (error, G_IO_ERROR,
		       g_io_error_from_errno (errsv),
		       _("Error reading from unix: %s"),
		       g_strerror (errsv));
	  return -1;
	}
    }

  while (1)
    {
      if (g_cancellable_set_error_if_cancelled (cancellable, error))
	return -1;
      res = read (unix_stream->priv->fd, buffer, count);
      if (res == -1)
	{
          int errsv = errno;

	  if (errsv == EINTR)
	    continue;
	  
	  g_set_error (error, G_IO_ERROR,
		       g_io_error_from_errno (errsv),
		       _("Error reading from unix: %s"),
		       g_strerror (errsv));
	}
      
      break;
    }

  return res;
}
Example #6
0
static gboolean
close_async_cb (CloseAsyncData *data)
{
  GUnixInputStream *unix_stream;
  GSimpleAsyncResult *simple;
  GError *error = NULL;
  gboolean result;
  int res;

  unix_stream = G_UNIX_INPUT_STREAM (data->stream);

  if (!unix_stream->priv->close_fd)
    {
      result = TRUE;
      goto out;
    }
  
  while (1)
    {
      res = close (unix_stream->priv->fd);
      if (res == -1)
        {
          int errsv = errno;

          g_set_error (&error, G_IO_ERROR,
                       g_io_error_from_errno (errsv),
                       _("Error closing unix: %s"),
                       g_strerror (errsv));
        }
      break;
    }
  
  result = res != -1;

 out:
  simple = g_simple_async_result_new (G_OBJECT (data->stream),
				      data->callback,
				      data->user_data,
				      g_unix_input_stream_close_async);

  if (!result)
    {
      g_simple_async_result_set_from_error (simple, error);
      g_error_free (error);
    }

  /* Complete immediately, not in idle, since we're already in a mainloop callout */
  g_simple_async_result_complete (simple);
  g_object_unref (simple);
  
  return FALSE;
}
Example #7
0
static GSource *
g_unix_input_stream_pollable_create_source (GPollableInputStream *stream,
					    GCancellable         *cancellable)
{
  GUnixInputStream *unix_stream = G_UNIX_INPUT_STREAM (stream);
  GSource *inner_source, *pollable_source;

  pollable_source = g_pollable_source_new (G_OBJECT (stream));

  inner_source = _g_fd_source_new (unix_stream->priv->fd, G_IO_IN, cancellable);
  g_source_set_dummy_callback (inner_source);
  g_source_add_child_source (pollable_source, inner_source);
  g_source_unref (inner_source);

  return pollable_source;
}
Example #8
0
static gboolean
g_unix_input_stream_pollable_is_readable (GPollableInputStream *stream)
{
  GUnixInputStream *unix_stream = G_UNIX_INPUT_STREAM (stream);
  GPollFD poll_fd;
  gint result;

  poll_fd.fd = unix_stream->priv->fd;
  poll_fd.events = G_IO_IN;

  do
    result = g_poll (&poll_fd, 1, 0);
  while (result == -1 && errno == EINTR);

  return poll_fd.revents != 0;
}
gboolean gvir_sandbox_console_attach_stdio(GVirSandboxConsole *console_,
                                           GError **error)
{
    GInputStream *localStdin = g_unix_input_stream_new(STDIN_FILENO, FALSE);
    GOutputStream *localStdout = g_unix_output_stream_new(STDOUT_FILENO, FALSE);
    GOutputStream *localStderr = g_unix_output_stream_new(STDERR_FILENO, FALSE);
    gboolean ret;

    ret = gvir_sandbox_console_attach(console_,
                                      G_UNIX_INPUT_STREAM(localStdin),
                                      G_UNIX_OUTPUT_STREAM(localStdout),
                                      G_UNIX_OUTPUT_STREAM(localStderr),
                                      error);

    g_object_unref(localStdin);
    g_object_unref(localStdout);
    g_object_unref(localStderr);

    return ret;
}
Example #10
0
static gssize
g_unix_input_stream_read_finish (GInputStream  *stream,
				 GAsyncResult  *result,
				 GError       **error)
{
  GUnixInputStream *unix_stream = G_UNIX_INPUT_STREAM (stream);
  GSimpleAsyncResult *simple;
  gssize nread;

  if (!unix_stream->priv->is_pipe_or_socket)
    {
      return G_INPUT_STREAM_CLASS (g_unix_input_stream_parent_class)->
	read_finish (stream, result, error);
    }

  simple = G_SIMPLE_ASYNC_RESULT (result);
  g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_unix_input_stream_read_async);
  
  nread = g_simple_async_result_get_op_res_gssize (simple);
  return nread;
}
static void
g_unix_input_stream_get_property (GObject    *object,
				  guint       prop_id,
				  GValue     *value,
				  GParamSpec *pspec)
{
  GUnixInputStream *unix_stream;

  unix_stream = G_UNIX_INPUT_STREAM (object);

  switch (prop_id)
    {
    case PROP_FD:
      g_value_set_int (value, unix_stream->priv->fd);
      break;
    case PROP_CLOSE_FD:
      g_value_set_boolean (value, unix_stream->priv->close_fd);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    }
}
static gboolean
g_unix_input_stream_pollable_can_poll (GPollableInputStream *stream)
{
  return G_UNIX_INPUT_STREAM (stream)->priv->is_pipe_or_socket;
}
static gssize
g_unix_input_stream_read (GInputStream  *stream,
			  void          *buffer,
			  gsize          count,
			  GCancellable  *cancellable,
			  GError       **error)
{
  GUnixInputStream *unix_stream;
  gssize res = -1;
  GPollFD poll_fds[2];
  int nfds;
  int poll_ret;

  unix_stream = G_UNIX_INPUT_STREAM (stream);

  poll_fds[0].fd = unix_stream->priv->fd;
  poll_fds[0].events = G_IO_IN;
  if (unix_stream->priv->is_pipe_or_socket &&
      g_cancellable_make_pollfd (cancellable, &poll_fds[1]))
    nfds = 2;
  else
    nfds = 1;

  while (1)
    {
      poll_fds[0].revents = poll_fds[1].revents = 0;
      do
	poll_ret = g_poll (poll_fds, nfds, -1);
      while (poll_ret == -1 && errno == EINTR);

      if (poll_ret == -1)
	{
          int errsv = errno;

	  g_set_error (error, G_IO_ERROR,
		       g_io_error_from_errno (errsv),
		       _("Error reading from file descriptor: %s"),
		       g_strerror (errsv));
	  break;
	}

      if (g_cancellable_set_error_if_cancelled (cancellable, error))
	break;

      if (!poll_fds[0].revents)
	continue;

      res = read (unix_stream->priv->fd, buffer, count);
      if (res == -1)
	{
          int errsv = errno;

	  if (errsv == EINTR || errsv == EAGAIN)
	    continue;

	  g_set_error (error, G_IO_ERROR,
		       g_io_error_from_errno (errsv),
		       _("Error reading from file descriptor: %s"),
		       g_strerror (errsv));
	}

      break;
    }

  if (nfds == 2)
    g_cancellable_release_fd (cancellable);
  return res;
}
static gboolean gvir_sandbox_console_open_remote(GVirSandboxConsoleRaw *console,
                                                 GError **error)
{
    GVirSandboxConsoleRawPrivate *priv = console->priv;
    GVirConnection *conn = NULL;
    GVirDomain *dom = NULL;
    gchar *devname = NULL;
    gboolean ret = FALSE;
    GVirConfigDomain *conf = NULL;
    GList *devices = NULL, *tmp;

    g_object_get(console,
                 "connection", &conn,
                 "domain", &dom,
                 "devname", &devname,
                 NULL);

    if (!gvir_sandbox_console_get_direct(GVIR_SANDBOX_CONSOLE(console))) {
        priv->console = gvir_connection_get_stream(conn, 0);

        if (!gvir_domain_open_console(dom, priv->console,
                                      devname, 0, error)) {
            g_object_unref(priv->console);
            priv->console = NULL;
            goto cleanup;
        }
    } else {
        const gchar *pty = NULL;

        if (!(conf = gvir_domain_get_config(dom, 0, error)))
            goto cleanup;

        if (!(devices = gvir_config_domain_get_devices(conf))) {
            g_set_error(error, GVIR_SANDBOX_CONSOLE_RAW_ERROR, 0, "%s",
                        _("No devices found for domain"));
            goto cleanup;
        }

        tmp = devices;
        while (tmp && !pty) {
            GVirConfigDomainDevice *dev = tmp->data;
            const gchar *alias = gvir_config_domain_device_get_alias(dev);

            if (alias && g_str_equal(alias, devname) &&
                GVIR_CONFIG_IS_DOMAIN_CHARDEV(dev)) {
                GVirConfigDomainChardev *cdev = GVIR_CONFIG_DOMAIN_CHARDEV(dev);
                GVirConfigDomainChardevSource *csrc =
                    gvir_config_domain_chardev_get_source(cdev);

                if (GVIR_CONFIG_IS_DOMAIN_CHARDEV_SOURCE_PTY(csrc)) {
                    GVirConfigDomainChardevSourcePty *csrcpty =
                        GVIR_CONFIG_DOMAIN_CHARDEV_SOURCE_PTY(csrc);

                    pty = gvir_config_domain_chardev_source_pty_get_path(csrcpty);
                    break;
                }

            }

            tmp = tmp->next;
        }

        if (!pty) {
            g_set_error(error, GVIR_SANDBOX_CONSOLE_RAW_ERROR, 0,
                        _("No device %s found for domain"), devname);
            goto cleanup;
        }

        if ((priv->consolePty = open(pty, O_NOCTTY|O_RDWR)) < 0) {
            g_set_error(error, GVIR_SANDBOX_CONSOLE_RAW_ERROR, 0,
                        _("Unable to open console %s"), pty);
            goto cleanup;
        }

        priv->consoleInput = G_UNIX_INPUT_STREAM(g_unix_input_stream_new(priv->consolePty, FALSE));
        priv->consoleOutput = G_UNIX_OUTPUT_STREAM(g_unix_output_stream_new(priv->consolePty, FALSE));
    }

    ret = TRUE;

 cleanup:
    if (conf)
        g_object_unref(conf);
    if (conn)
        g_object_unref(conn);
    if (dom)
        g_object_unref(dom);
    g_free(devname);

    return ret;
}