int main(int argc, char **argv) {
    const char *pty_path;
    int pty_in_fd, pty_out_fd;
    GInputStream *stdin, *instream;
    GOutputStream *stdout, *outstream;
    GMainLoop *loop;
    GError *error = NULL;

    if (argc != 2) {
        g_printerr("Usage: gnome-hwtest-terminal-splice <pty>\n");
        exit(1);
    }

    pty_path = argv[1];

    pty_in_fd = open(pty_path, O_RDONLY);
    if (pty_in_fd == -1)
        die_errno("Opening PTY for reading");

    pty_out_fd = open(pty_path, O_WRONLY);
    if (pty_out_fd == -1)
        die_errno("Opening PTY for writing");

    make_raw (0);
    make_raw (pty_in_fd);

    stdin = g_unix_input_stream_new(0, FALSE);
    stdout = g_unix_output_stream_new(1, FALSE);
    instream = g_unix_input_stream_new(pty_in_fd, FALSE);
    outstream = g_unix_output_stream_new(pty_out_fd, FALSE);

    loop = g_main_loop_new (NULL, FALSE);

    g_output_stream_splice_async(stdout, instream,
                                 G_OUTPUT_STREAM_SPLICE_NONE,
                                 G_PRIORITY_DEFAULT, NULL,
                                 on_eof, loop);
    check_error("Splicing stdout to PTY", error);

    g_output_stream_splice_async(outstream, stdin,
                                 G_OUTPUT_STREAM_SPLICE_NONE,
                                 G_PRIORITY_DEFAULT, NULL,
                                 on_eof, loop);
    check_error("Splicing stdin from PTY", error);

    g_main_loop_run (loop);

    return 0;
}
Beispiel #2
0
/**
 * test_pipe:
 * @is: (out) (allow-none): used to return a #GInputStream
 * @os: (out) (allow-none): used to return a #GOutputStream
 * @error: used to raise an error
 *
 * Return a "pipe to self" connecting @is to @os. This can be used
 * as a unidirectional pipe to or from a child process, for instance.
 *
 * See test_bidi_pipe() if you want to emulate a bidirectional pipe
 * via a pair of unidirectional pipes.
 *
 * Returns: %TRUE on success
 */
gboolean
test_pipe (GInputStream  **is,
           GOutputStream **os,
           GError        **error)
{
    int pipefd[2];
    int ret;

    ret = pipe (pipefd);

    if (ret != 0)
    {
        int e = errno;

        g_set_error (error, G_IO_ERROR, g_io_error_from_errno (e),
                     "%s", g_strerror (e));
        return FALSE;
    }

    if (is != NULL)
        *is = g_unix_input_stream_new (pipefd[0], TRUE);
    else
        close (pipefd[0]);

    if (os != NULL)
        *os = g_unix_output_stream_new (pipefd[1], TRUE);
    else
        close (pipefd[1]);

    return TRUE;
}
static gboolean
convert_var_to_tmpfiles_d (int            src_rootfs_dfd,
                           int            dest_rootfs_dfd,
                           GCancellable  *cancellable,
                           GError       **error)
{
    gboolean ret = FALSE;
    g_autoptr(GString) prefix = g_string_new ("/var");
    glnx_fd_close int tmpfiles_fd = -1;

    /* Append to an existing one for package layering */
    if ((tmpfiles_fd = TEMP_FAILURE_RETRY (openat (dest_rootfs_dfd, "usr/lib/tmpfiles.d/rpm-ostree-autovar.conf",
                                           O_WRONLY | O_CREAT | O_APPEND | O_NOCTTY, 0644))) == -1)
    {
        glnx_set_error_from_errno (error);
        goto out;
    }

    {   glnx_unref_object GOutputStream *tmpfiles_out =
            g_unix_output_stream_new (tmpfiles_fd, FALSE);

        if (!tmpfiles_out)
            goto out;

        if (!convert_var_to_tmpfiles_d_recurse (tmpfiles_out, src_rootfs_dfd, prefix, cancellable, error))
            goto out;

        if (!g_output_stream_close (tmpfiles_out, cancellable, error))
            goto out;
    }

    ret = TRUE;
out:
    return ret;
}
Beispiel #4
0
/**
 * gs_file_create:
 * @file: Path to non-existent file
 * @mode: Unix access permissions
 * @out_stream: (out) (transfer full) (allow-none): Newly created output, or %NULL
 * @cancellable: a #GCancellable
 * @error: a #GError
 *
 * Like g_file_create(), except this function allows specifying the
 * access mode.  This allows atomically creating private files.
 */
gboolean
gs_file_create (GFile          *file,
                int             mode,
                GOutputStream **out_stream,
                GCancellable   *cancellable,
                GError        **error)
{
    gboolean ret = FALSE;
    int fd;
    GOutputStream *ret_stream = NULL;

    fd = open_nointr (gs_file_get_path_cached (file), O_WRONLY | O_CREAT | O_EXCL, mode);
    if (fd < 0)
    {
        gs_set_prefix_error_from_errno (error, errno, "open");
        goto out;
    }

    if (fchmod (fd, mode) < 0)
    {
        close (fd);
        gs_set_prefix_error_from_errno (error, errno, "fchmod");
        goto out;
    }

    ret_stream = g_unix_output_stream_new (fd, TRUE);

    ret = TRUE;
    gs_transfer_out_value (out_stream, &ret_stream);
out:
    g_clear_object (&ret_stream);
    return ret;
}
Beispiel #5
0
static void
uri_resolved (YelpUri *uri, gchar *orig)
{
    GOutputStream *stream = g_unix_output_stream_new (1, FALSE);
    print_uri (orig, uri, stream);
    g_object_unref (uri);
    g_main_loop_quit (loop);
}
static gboolean
sysroot_setup_stdout_redirect (RpmostreedSysroot *self,
                               GError **error)
{
  g_autoptr(GInputStream) stream = NULL;
  g_autoptr(GSource) source = NULL;
  StdoutClosure *closure;
  gint pipefd[2];
  gboolean ret = FALSE;

  /* XXX libostree logs messages to systemd's journal and also to stdout.
   *     Redirect our own stdout back to ourselves so we can capture those
   *     messages and pass them on to clients.  Admittedly hokey but avoids
   *     hacking libostree directly (for now). */

  closure = g_slice_new0 (StdoutClosure);
  g_weak_ref_set (&closure->sysroot, self);

  /* Save the real stdout before overwriting its file descriptor. */
  closure->real_stdout = g_unix_output_stream_new (dup (STDOUT_FILENO), FALSE);

  if (pipe (pipefd) < 0)
    {
      glnx_set_prefix_error_from_errno (error, "%s", "pipe() failed");
      goto out;
    }

  if (dup2 (pipefd[1], STDOUT_FILENO) < 0)
    {
      glnx_set_prefix_error_from_errno (error, "%s", "dup2() failed");
      goto out;
    }

  stream = g_memory_input_stream_new ();
  closure->data_stream = g_data_input_stream_new (stream);
  g_clear_object (&stream);

  stream = g_unix_input_stream_new (pipefd[0], FALSE);

  source = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (stream),
                                                  NULL);
  /* Transfer ownership of the StdoutClosure. */
  g_source_set_callback (source,
                         (GSourceFunc) sysroot_stdout_ready_cb,
                         closure,
                         (GDestroyNotify) stdout_closure_free);
  closure = NULL;

  self->stdout_source_id = g_source_attach (source, NULL);

  ret = TRUE;

out:
  if (closure != NULL)
    stdout_closure_free (closure);

  return ret;
}
gint
main (gint argc,
      gchar *argv[])
{
  g_autoptr(GDBusConnection) connection = NULL;
  g_autoptr(IpcGitService) service = NULL;
  g_autoptr(GOutputStream) stdout_stream = NULL;
  g_autoptr(GInputStream) stdin_stream = NULL;
  g_autoptr(GIOStream) stream = NULL;
  g_autoptr(GMainLoop) main_loop = NULL;
  g_autoptr(GError) error = NULL;

  g_set_prgname ("gnome-builder-git");
  g_set_application_name ("gnome-builder-git");

  prctl (PR_SET_PDEATHSIG, SIGTERM);

  signal (SIGPIPE, SIG_IGN);

  ggit_init ();

  g_log_set_handler (NULL, G_LOG_LEVEL_MASK, log_func, NULL);

  if (!g_unix_set_fd_nonblocking (STDIN_FILENO, TRUE, &error) ||
      !g_unix_set_fd_nonblocking (STDOUT_FILENO, TRUE, &error))
    goto error;

  main_loop = g_main_loop_new (NULL, FALSE);
  stdin_stream = g_unix_input_stream_new (STDIN_FILENO, FALSE);
  stdout_stream = g_unix_output_stream_new (STDOUT_FILENO, FALSE);
  stream = g_simple_io_stream_new (stdin_stream, stdout_stream);

  if (!(connection = create_connection (stream, main_loop, &error)))
    goto error;

  service = ipc_git_service_impl_new ();

  if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (service),
                                         connection,
                                         "/org/gnome/Builder/Git",
                                         &error))
    goto error;

  g_dbus_connection_start_message_processing (connection);
  g_main_loop_run (main_loop);

  return EXIT_SUCCESS;

error:
  if (error != NULL)
    g_printerr ("%s\n", error->message);

  return EXIT_FAILURE;
}
static gboolean
handle_userdata_script (MinCloudAgentApp      *self,
                        GInputStream               *instream,
                        GCancellable               *cancellable,
                        GError                    **error)
{
  gboolean ret = FALSE;
  gs_free char *tmppath = g_strdup ("/var/tmp/userdata-script.XXXXXX");
  gs_unref_object GOutputStream *outstream = NULL;
  int fd;

  fd = g_mkstemp_full (tmppath, O_WRONLY, 0700);
  if (fd == -1)
    {
      int errsv = errno;
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Failed to create temporary userdata script: %s",
                   g_strerror (errsv));
      goto out;
    }
  outstream = g_unix_output_stream_new (fd, TRUE);

  if (0 > g_output_stream_splice ((GOutputStream*)outstream, instream,
                                  G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET |
                                  G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE,
                                  self->cancellable, error))
    goto out;

  gs_log_structured_print_id_v (MCA_USERDATA_EXECUTING_ID,
                                "Executing user data script");

  if (!gs_subprocess_simple_run_sync (NULL, GS_SUBPROCESS_STREAM_DISPOSITION_NULL,
                                      cancellable, error,
                                      tmppath,
                                      NULL))
    {
      gs_log_structured_print_id_v (MCA_USERDATA_FAILED_ID,
                                    "User data script failed");
      goto out;
    }

  gs_log_structured_print_id_v (MCA_USERDATA_SUCCESS_ID,
                                "User data script suceeded");
  
  if (!g_file_replace_contents (self->userdata_done_stamp, "done\n", 5,
                                NULL, FALSE, 0,
                                NULL, cancellable, error))
    goto out;

  ret = TRUE;
 out:
  (void) unlink (tmppath);
  return ret;
}
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;
}
Beispiel #10
0
static AsyncWriteData *
async_write_data_new (GdkWaylandSelection *selection)
{
  AsyncWriteData *write_data;

  write_data = g_slice_new0 (AsyncWriteData);
  write_data->selection = selection;
  write_data->stream =
    g_unix_output_stream_new (selection->stored_selection.fd, TRUE);

  return write_data;
}
Beispiel #11
0
gboolean
gimp_config_dump (GObject              *gimp,
                  GimpConfigDumpFormat  format)
{
  GOutputStream    *output;
  GimpConfigWriter *writer;
  GimpConfig       *rc;

  g_return_val_if_fail (G_IS_OBJECT (gimp), FALSE);

  rc = g_object_new (GIMP_TYPE_RC,
                     "gimp", gimp,
                     NULL);

#ifdef G_OS_WIN32
  output = g_win32_output_stream_new ((gpointer) 1, FALSE);
#else
  output = g_unix_output_stream_new (1, FALSE);
#endif

  writer = gimp_config_writer_new_stream (output, NULL, NULL);

  switch (format)
    {
    case GIMP_CONFIG_DUMP_NONE:
      break;

    case GIMP_CONFIG_DUMP_GIMPRC:
      gimp_config_writer_comment (writer,
                                  "Dump of the GIMP default configuration");
      gimp_config_writer_linefeed (writer);
      gimp_config_serialize_properties (rc, writer);
      gimp_config_writer_linefeed (writer);
      break;

    case GIMP_CONFIG_DUMP_GIMPRC_SYSTEM:
      dump_gimprc_system (rc, writer, output);
      break;

    case GIMP_CONFIG_DUMP_GIMPRC_MANPAGE:
      dump_gimprc_manpage (rc, writer, output);
      break;
    }

  gimp_config_writer_finish (writer, NULL, NULL);
  g_object_unref (output);
  g_object_unref (rc);

  return TRUE;
}
Beispiel #12
0
/**
 * gs_console_get_stderr:
 *
 * Returns: (transfer none): The singleton stream connected to standard error
 */
GOutputStream *
gs_console_get_stderr (void)
{
#ifdef G_OS_UNIX
  static gsize instance = 0;

  if (g_once_init_enter (&instance))
    g_once_init_leave (&instance, (gsize) g_unix_output_stream_new (2, FALSE));
  
  return (GOutputStream*) instance;
#else
  g_error ("not implemented");
#endif
}
gboolean gvir_sandbox_console_attach_stderr(GVirSandboxConsole *console_,
                                           GError **error)
{
    GOutputStream *localStderr = g_unix_output_stream_new(STDERR_FILENO, FALSE);
    gboolean ret;

    ret = gvir_sandbox_console_attach(console_,
                                      NULL, NULL,
                                      G_UNIX_OUTPUT_STREAM(localStderr),
                                      error);

    g_object_unref(localStderr);

    return ret;
}
Beispiel #14
0
/**
 * gs_file_open_in_tmpdir_at:
 * @tmpdir_fd: Directory to place temporary file
 * @mode: Default mode (will be affected by umask)
 * @out_name: (out) (transfer full): Newly created file name
 * @out_stream: (out) (transfer full) (allow-none): Newly created output stream
 * @cancellable:
 * @error:
 *
 * Like g_file_open_tmp(), except the file will be created in the
 * provided @tmpdir, and allows specification of the Unix @mode, which
 * means private files may be created.  Return values will be stored
 * in @out_name, and optionally @out_stream.
 */
gboolean
gs_file_open_in_tmpdir_at (int                tmpdir_fd,
                           int                mode,
                           char             **out_name,
                           GOutputStream    **out_stream,
                           GCancellable      *cancellable,
                           GError           **error)
{
    gboolean ret = FALSE;
    const int max_attempts = 128;
    int i;
    char *tmp_name = NULL;
    int fd;

    /* 128 attempts seems reasonable... */
    for (i = 0; i < max_attempts; i++)
    {
        g_free (tmp_name);
        tmp_name = gs_fileutil_gen_tmp_name (NULL, NULL);

        do
            fd = openat (tmpdir_fd, tmp_name, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode);
        while (fd == -1 && errno == EINTR);
        if (fd < 0 && errno != EEXIST)
        {
            gs_set_prefix_error_from_errno (error, errno, "openat");
            goto out;
        }
        else if (fd != -1)
            break;
    }
    if (i == max_attempts)
    {
        g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                     "Exhausted attempts to open temporary file");
        goto out;
    }

    ret = TRUE;
    gs_transfer_out_value (out_name, &tmp_name);
    if (out_stream)
        *out_stream = g_unix_output_stream_new (fd, TRUE);
    else
        (void) close (fd);
out:
    g_free (tmp_name);
    return ret;
}
GSignondPipeStream *
gsignond_pipe_stream_new (
        gint in_fd,
        gint out_fd,
        gboolean close_fds)
{
    GSignondPipeStream *stream = GSIGNOND_PIPE_STREAM (g_object_new (
            GSIGNOND_TYPE_PIPE_STREAM, NULL));
    if (stream) {
        stream->priv->input_stream = G_INPUT_STREAM (
                g_unix_input_stream_new (in_fd, close_fds));
        stream->priv->output_stream = G_OUTPUT_STREAM (
                g_unix_output_stream_new (out_fd, close_fds));
    }
    return stream;
}
Beispiel #16
0
gboolean
ostree_builtin_cat (int argc, char **argv, GCancellable *cancellable, GError **error)
{
  GOptionContext *context;
  gs_unref_object OstreeRepo *repo = NULL;
  gboolean ret = FALSE;
  int i;
  const char *rev;
  gs_unref_object GOutputStream *stdout_stream = NULL;
  gs_unref_object GFile *root = NULL;
  gs_unref_object GFile *f = NULL;

  context = g_option_context_new ("COMMIT PATH... - Concatenate contents of files");

  if (!ostree_option_context_parse (context, options, &argc, &argv, OSTREE_BUILTIN_FLAG_NONE, &repo, cancellable, error))
    goto out;

  if (argc <= 2)
    {
      ot_util_usage_error (context, "A COMMIT and at least one PATH argument are required", error);
      goto out;
    }
  rev = argv[1];

  if (!ostree_repo_read_commit (repo, rev, &root, NULL, NULL, error))
    goto out;

  stdout_stream = g_unix_output_stream_new (1, FALSE);

  for (i = 2; i < argc; i++)
    {
      g_clear_object (&f);
      f = g_file_resolve_relative_path (root, argv[i]);

      if (!cat_one_file (f, stdout_stream, cancellable, error))
        goto out;
    }
 
  ret = TRUE;
 out:
  if (context)
    g_option_context_free (context);
  return ret;
}
Beispiel #17
0
/**
 * gimp_config_writer_new_fd:
 * @fd:
 *
 * Return value: a new #GimpConfigWriter or %NULL in case of an error
 *
 * Since: GIMP 2.4
 **/
GimpConfigWriter *
gimp_config_writer_new_fd (gint fd)
{
  GimpConfigWriter *writer;

  g_return_val_if_fail (fd > 0, NULL);

  writer = g_slice_new0 (GimpConfigWriter);

#ifdef G_OS_WIN32
  writer->output = g_win32_output_stream_new ((gpointer) fd, FALSE);
#else
  writer->output = g_unix_output_stream_new (fd, FALSE);
#endif

  writer->buffer = g_string_new (NULL);

  return writer;
}
Beispiel #18
0
static GIOStream *
my_io_stream_new_for_fds (gint fd_in, gint fd_out)
{
  GIOStream *stream;
  GInputStream *input_stream;
  GOutputStream *real_output_stream;
  GOutputStream *output_stream;

  input_stream = g_unix_input_stream_new (fd_in, TRUE);
  real_output_stream = g_unix_output_stream_new (fd_out, TRUE);
  output_stream = g_object_new (MY_TYPE_SLOW_CLOSE_OUTPUT_STREAM,
                                "base-stream", real_output_stream,
                                NULL);
  stream = my_io_stream_new (input_stream, output_stream);
  g_object_unref (input_stream);
  g_object_unref (output_stream);
  g_object_unref (real_output_stream);
  return stream;
}
int main(int argc, char *argv[])
{
  gint ret, fds[2];
  GInputStream *input;
  GOutputStream *output;

  g_type_init();
  ret = pipe(fds);

  if (ret < 0)
    {
      g_error("pipe() failed, ret = %d", ret);
		  exit(EXIT_FAILURE);
    }

  input = g_unix_input_stream_new(fds[0], TRUE);
  output = g_unix_output_stream_new(fds[1], TRUE);

  receiver = sockmux_receiver_new(input, SOCKMUX_PROTOCOL_MAGIC);
  if (receiver == NULL)
    {
      g_error("sockmux_receiver_new() failed");
		  exit(EXIT_FAILURE);
    }

  sender = sockmux_sender_new(output, SOCKMUX_PROTOCOL_MAGIC);
  if (sender == NULL)
    {
      g_error("sockmux_sender_new() failed");
		  exit(EXIT_FAILURE);
    }

  g_signal_connect(receiver, "protocol-error",
                   G_CALLBACK(receiver_protocol_error), NULL);

  loop = g_main_loop_new(NULL, FALSE);
  checksum = g_checksum_new(G_CHECKSUM_SHA1);
  trigger();
  g_main_loop_run(loop);

  return EXIT_SUCCESS;
}
void
set_user_icon_data (ActUser   *user,
                    GdkPixbuf *pixbuf)
{
        gchar *path;
        gint fd;
        GOutputStream *stream;
        GError *error;

        path = g_build_filename (g_get_tmp_dir (), "gnome-control-center-user-icon-XXXXXX", NULL);
        fd = g_mkstemp (path);

        if (fd == -1) {
                g_warning ("failed to create temporary file for image data");
                g_free (path);
                return;
        }

        stream = g_unix_output_stream_new (fd, TRUE);

        error = NULL;
        if (!gdk_pixbuf_save_to_stream (pixbuf, stream, "png", NULL, &error, NULL)) {
                g_warning ("failed to save image: %s", error->message);
                g_error_free (error);
                g_object_unref (stream);
                return;
        }

        g_object_unref (stream);

        act_user_set_icon_file (user, path);

        /* if we ever make the dbus call async, the g_remove call needs
         * to wait for its completion
         */
        g_remove (path);

        g_free (path);
}
Beispiel #21
0
static void
extract_content_child_process (PopplerDocument *document,
                               gsize            n_bytes,
                               int              fd[2])
{
	GString *str;
	gint64 size;
	GOutputStream *output_stream;
	GDataOutputStream *dataout_stream;

	/* This is the child extracting the content, hopefully in time */

	output_stream = g_unix_output_stream_new (fd[1], FALSE);
	dataout_stream = g_data_output_stream_new (output_stream);
	str = extract_content_text (document, n_bytes);
	size = (gint64) str->len;

	/* Write the results to the pipe */
	if (g_data_output_stream_put_int64 (dataout_stream, size, NULL, NULL)) {
		g_output_stream_write_all (output_stream,
		                           str->str,
		                           str->len,
		                           NULL,
		                           NULL,
		                           NULL);
	}

	g_debug ("Child: Content extraction now finished in child process, "
	         "written %" G_GSIZE_FORMAT " bytes to parent process",
	         size);

	g_string_free (str, TRUE);
	g_object_unref (dataout_stream);
	g_object_unref (output_stream);

	close (fd[1]);

	exit (0);
}
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;
}
gboolean
_ostree_bootloader_grub2_generate_config (OstreeSysroot                 *sysroot,
                                          int                            bootversion,
                                          int                            target_fd,
                                          GCancellable                  *cancellable,
                                          GError                       **error)
{
  gboolean ret = FALSE;
  GString *output = g_string_new ("");
  gs_unref_object GOutputStream *out_stream = NULL;
  gs_unref_ptrarray GPtrArray *loader_configs = NULL;
  guint i;
  gsize bytes_written;
  gboolean is_efi;
  /* So... yeah.  Just going to hardcode these. */
  static const char hardcoded_video[] = "load_video\n"
    "set gfxpayload=keep\n";
  static const char hardcoded_insmods[] = "insmod gzio\n";
  const char *grub2_boot_device_id =
    g_getenv ("GRUB2_BOOT_DEVICE_ID");
  const char *grub2_prepare_root_cache =
    g_getenv ("GRUB2_PREPARE_ROOT_CACHE");

  /* We must have been called via the wrapper script */
  g_assert (grub2_boot_device_id != NULL);
  g_assert (grub2_prepare_root_cache != NULL);

  /* Passed from the parent */
  is_efi = g_getenv ("_OSTREE_GRUB2_IS_EFI") != NULL;

  out_stream = g_unix_output_stream_new (target_fd, FALSE);

  if (!_ostree_sysroot_read_boot_loader_configs (sysroot, bootversion,
                                                 &loader_configs,
                                                 cancellable, error))
    goto out;

  for (i = 0; i < loader_configs->len; i++)
    {
      OstreeBootconfigParser *config = loader_configs->pdata[i];
      const char *title;
      const char *options;
      const char *kernel;
      const char *initrd;
      char *quoted_title = NULL;
      char *uuid = NULL;
      char *quoted_uuid = NULL;

      title = ostree_bootconfig_parser_get (config, "title");
      if (!title)
        title = "(Untitled)";

      kernel = ostree_bootconfig_parser_get (config, "linux");

      quoted_title = g_shell_quote (title);
      uuid = g_strdup_printf ("ostree-%u-%s", (guint)i, grub2_boot_device_id);
      quoted_uuid = g_shell_quote (uuid);
      g_string_append_printf (output, "menuentry %s --class gnu-linux --class gnu --class os --unrestricted %s {\n", quoted_title, quoted_uuid);
      g_free (uuid);
      g_free (quoted_title);
      g_free (quoted_uuid);

      /* Hardcoded sections */
      g_string_append (output, hardcoded_video);
      g_string_append (output, hardcoded_insmods);
      g_string_append (output, grub2_prepare_root_cache);
      g_string_append_c (output, '\n');
      
      if (!kernel)
        {
          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                       "No \"linux\" key in bootloader config");
          goto out;
        }
      if (is_efi)
        g_string_append (output, "linuxefi ");
      else
        g_string_append (output, "linux16 ");
      g_string_append (output, kernel);

      options = ostree_bootconfig_parser_get (config, "options");
      if (options)
        {
          g_string_append_c (output, ' ');
          g_string_append (output, options);
        }
      g_string_append_c (output, '\n');

      initrd = ostree_bootconfig_parser_get (config, "initrd");
      if (initrd)
        {
          if (is_efi)
            g_string_append (output, "initrdefi ");
          else
            g_string_append (output, "initrd16 ");
          g_string_append (output, initrd);
          g_string_append_c (output, '\n');
        }

      g_string_append (output, "}\n");
    }

  if (!g_output_stream_write_all (out_stream, output->str, output->len,
                                  &bytes_written, cancellable, error))
    goto out;

  ret = TRUE;
 out:
  if (output)
    g_string_free (output, TRUE);
  return ret;
}
Beispiel #24
0
static void
_j4status_io_add_stream(J4statusIOContext *self, const gchar *stream_desc)
{
    J4statusIOStream *stream;
    if ( g_strcmp0(stream_desc, "std") == 0 )
    {
        GOutputStream *out;
        GInputStream *in;
#ifdef G_OS_UNIX
        out = g_unix_output_stream_new(1, FALSE);
        in = g_unix_input_stream_new(0, FALSE);
#else /* ! G_OS_UNIX */
        return;
#endif /* ! G_OS_UNIX */

        stream = _j4status_io_stream_new(self);

        stream->out = g_data_output_stream_new(out);
        stream->in = g_data_input_stream_new(in);
        g_object_unref(out);
        g_object_unref(in);

        _j4status_io_stream_put_header(stream, self->header);
        g_data_input_stream_read_line_async(stream->in, G_PRIORITY_DEFAULT, NULL, _j4status_io_stream_read_callback, stream);

        goto end;
    }

    GSocketAddress *address = NULL;

    if ( g_str_has_prefix(stream_desc, "tcp:") )
    {
        const gchar *uri = stream_desc + strlen("tcp:");
        gchar *port_str = g_utf8_strrchr(uri, -1, ':');
        if ( port_str == NULL )
            /* No port, illegal stream description */
            return;

        *port_str = '\0';
        ++port_str;

        guint64 port;
        port = g_ascii_strtoull(port_str, NULL, 10);
        if ( port > 65535 )
            return;

        GInetAddress *inet_address;
        inet_address = g_inet_address_new_from_string(uri);

        address = g_inet_socket_address_new(inet_address, port);
    }

#ifdef G_OS_UNIX
    if ( g_str_has_prefix(stream_desc, "unix:") )
    {
        const gchar *path = stream_desc + strlen("unix:");

        address = g_unix_socket_address_new(path);
    }
#endif /* G_OS_UNIX */

    if ( address == NULL )
        return;

    stream = _j4status_io_stream_new(self);
    stream->address = address;

    _j4status_io_stream_connect(stream);

end:
    self->streams = g_list_prepend(self->streams, stream);
}
static void
tp_file_start_transfer (EmpathyTpFile *self)
{
  gint fd, domain, res = 0;
  GError *error = NULL;
  struct sockaddr *my_addr = NULL;
  size_t my_size = 0;

  if (self->priv->socket_address_type == TP_SOCKET_ADDRESS_TYPE_UNIX)
    {
      domain = AF_UNIX;
    }
  else if (self->priv->socket_address_type == TP_SOCKET_ADDRESS_TYPE_IPV4)
    {
      domain = AF_INET;
    }
  else
    {
      error = g_error_new_literal (EMPATHY_FT_ERROR_QUARK,
          EMPATHY_FT_ERROR_NOT_SUPPORTED, _("Socket type not supported"));

      DEBUG ("Socket not supported, closing channel");

      ft_operation_close_with_error (self, error);
      g_clear_error (&error);

      return;
    }

  fd = socket (domain, SOCK_STREAM, 0);

  if (fd < 0)
    {
      int code = errno;

      error = g_error_new_literal (EMPATHY_FT_ERROR_QUARK,
          EMPATHY_FT_ERROR_SOCKET, g_strerror (code));

      DEBUG ("Failed to create socket, closing channel");

      ft_operation_close_with_error (self, error);
      g_clear_error (&error);

      return;
    }

  if (self->priv->socket_address_type == TP_SOCKET_ADDRESS_TYPE_UNIX)
    {
      struct sockaddr_un addr;

      memset (&addr, 0, sizeof (addr));
      addr.sun_family = domain;
      strncpy (addr.sun_path, self->priv->socket_address->data,
          self->priv->socket_address->len);

      my_addr = (struct sockaddr *) &addr;
      my_size = sizeof (addr);
    }
  else if (self->priv->socket_address_type == TP_SOCKET_ADDRESS_TYPE_IPV4)
    {
      struct sockaddr_in addr;

      memset (&addr, 0, sizeof (addr));
      addr.sin_family = domain;
      inet_pton (AF_INET, self->priv->socket_address->data, &addr.sin_addr);
      addr.sin_port = htons (self->priv->port);

      my_addr = (struct sockaddr *) &addr;
      my_size = sizeof (addr);
    }

  res = connect (fd, my_addr, my_size);

  if (res < 0)
    {
      int code = errno;

      error = g_error_new_literal (EMPATHY_FT_ERROR_QUARK,
          EMPATHY_FT_ERROR_SOCKET, g_strerror (code));

      DEBUG ("Failed to connect socket, closing channel");

      ft_operation_close_with_error (self, error);
      close (fd);
      g_clear_error (&error);

      return;
    }

  DEBUG ("Start the transfer");

  self->priv->start_time = empathy_time_get_current ();

  /* notify we're starting a transfer */
  if (self->priv->progress_callback != NULL)
    self->priv->progress_callback (self, 0, self->priv->progress_user_data);

  if (self->priv->incoming)
    {
      GInputStream *socket_stream;

      socket_stream = g_unix_input_stream_new (fd, TRUE);

      g_output_stream_splice_async (self->priv->out_stream, socket_stream,
          G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE |
          G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
          G_PRIORITY_DEFAULT, self->priv->cancellable,
          splice_stream_ready_cb, self);

      g_object_unref (socket_stream);
    }
  else
    {
      GOutputStream *socket_stream;

      socket_stream = g_unix_output_stream_new (fd, TRUE);

      g_output_stream_splice_async (socket_stream, self->priv->in_stream,
          G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE |
          G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
          G_PRIORITY_DEFAULT, self->priv->cancellable,
          splice_stream_ready_cb, self);

      g_object_unref (socket_stream);
    }
}
gboolean
_ostree_static_delta_part_open (GInputStream   *part_in,
                                GBytes         *inline_part_bytes,
                                OstreeStaticDeltaOpenFlags flags,
                                const char     *expected_checksum,
                                GVariant    **out_part,
                                GCancellable *cancellable,
                                GError      **error)
{
  gboolean ret = FALSE;
  const gboolean trusted = (flags & OSTREE_STATIC_DELTA_OPEN_FLAGS_VARIANT_TRUSTED) > 0;
  const gboolean skip_checksum = (flags & OSTREE_STATIC_DELTA_OPEN_FLAGS_SKIP_CHECKSUM) > 0;
  gsize bytes_read;
  guint8 comptype;
  g_autoptr(GChecksum) checksum = NULL;
  g_autoptr(GInputStream) checksum_in = NULL;
  g_autoptr(GVariant) ret_part = NULL;
  GInputStream *source_in;

  /* We either take a fd or a GBytes reference */
  g_return_val_if_fail (G_IS_FILE_DESCRIPTOR_BASED (part_in) || inline_part_bytes != NULL, FALSE);
  g_return_val_if_fail (skip_checksum || expected_checksum != NULL, FALSE);

  if (!skip_checksum)
    {
      checksum = g_checksum_new (G_CHECKSUM_SHA256);
      checksum_in = (GInputStream*)ostree_checksum_input_stream_new (part_in, checksum);
      source_in = checksum_in;
    }
  else
    {
      source_in = part_in;
    }

  { guint8 buf[1];
    /* First byte is compression type */
    if (!g_input_stream_read_all (source_in, buf, sizeof(buf), &bytes_read,
                                  cancellable, error))
      {
        g_prefix_error (error, "Reading initial compression flag byte: ");
      goto out;
      }
    comptype = buf[0];
  }

  switch (comptype)
    {
    case 0:
      if (!inline_part_bytes)
        {
          int part_fd = g_file_descriptor_based_get_fd ((GFileDescriptorBased*)part_in);

          /* No compression, no checksums - a fast path */
          if (!ot_util_variant_map_fd (part_fd, 1, G_VARIANT_TYPE (OSTREE_STATIC_DELTA_PART_PAYLOAD_FORMAT_V0),
                                       trusted, &ret_part, error))
            goto out;
        }
      else
        {
          g_autoptr(GBytes) content_bytes = g_bytes_new_from_bytes (inline_part_bytes, 1,
                                                                    g_bytes_get_size (inline_part_bytes) - 1);
          ret_part = g_variant_new_from_bytes (G_VARIANT_TYPE (OSTREE_STATIC_DELTA_PART_PAYLOAD_FORMAT_V0),
                                               content_bytes, trusted);
          g_variant_ref_sink (ret_part);
        }

      if (!skip_checksum)
        g_checksum_update (checksum, g_variant_get_data (ret_part),
                           g_variant_get_size (ret_part));
      
      break;
    case 'x':
      {
        g_autofree char *tmppath = g_strdup ("/var/tmp/ostree-delta-XXXXXX");
        g_autoptr(GConverter) decomp = (GConverter*) _ostree_lzma_decompressor_new ();
        g_autoptr(GInputStream) convin = g_converter_input_stream_new (source_in, decomp);
        g_autoptr(GOutputStream) unpacked_out = NULL;
        glnx_fd_close int unpacked_fd = -1;
        gssize n_bytes_written;

        unpacked_fd = g_mkstemp_full (tmppath, O_RDWR | O_CLOEXEC, 0640);
        if (unpacked_fd < 0)
          {
            glnx_set_error_from_errno (error);
            goto out;
          }
        
        /* Now make it autocleanup on process exit - in the future, we
         * should consider caching unpacked deltas as well.
         */
        if (unlink (tmppath) < 0)
          {
            glnx_set_error_from_errno (error);
            goto out;
          }
        
        unpacked_out = g_unix_output_stream_new (unpacked_fd, FALSE);

        n_bytes_written = g_output_stream_splice (unpacked_out, convin,
                                                  G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE |
                                                  G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
                                                  cancellable, error);
        if (n_bytes_written < 0)
          goto out;

        if (!ot_util_variant_map_fd (unpacked_fd, 0, G_VARIANT_TYPE (OSTREE_STATIC_DELTA_PART_PAYLOAD_FORMAT_V0),
                                     trusted, &ret_part, error))
          goto out;
      }
      break;
    default:
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Invalid compression type '%u'", comptype);
      goto out;
    }

  if (checksum)
    {
      const char *actual_checksum = g_checksum_get_string (checksum);
      g_assert (expected_checksum != NULL);
      if (strcmp (actual_checksum, expected_checksum) != 0)
        {
          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                       "Checksum mismatch in static delta part; expected=%s actual=%s",
                       expected_checksum, actual_checksum);
          goto out;
        }
    }
        
  ret = TRUE;
  *out_part = g_steal_pointer (&ret_part);
 out:
  return ret;
}
Beispiel #27
0
/*
 * This function creates a file under a temporary name, then rename()s
 * it into place.  This implements union-like behavior.
 */
static gboolean
checkout_file_unioning_from_input_at (OstreeRepo     *repo,
                                      OstreeRepoCheckoutAtOptions  *options,
                                      GFileInfo      *file_info,
                                      GVariant       *xattrs,
                                      GInputStream   *input,
                                      int             destination_dfd,
                                      const char     *destination_name,
                                      GCancellable   *cancellable,
                                      GError        **error)
{
  gboolean ret = FALSE;
  g_autofree char *temp_filename = NULL;

  if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_SYMBOLIC_LINK)
    {
      if (!_ostree_make_temporary_symlink_at (destination_dfd,
                                              g_file_info_get_symlink_target (file_info),
                                              &temp_filename,
                                              cancellable, error))
        goto out;
          
      if (xattrs)
        {
          if (!glnx_dfd_name_set_all_xattrs (destination_dfd, temp_filename,
                                               xattrs, cancellable, error))
            goto out;
        }
      if (G_UNLIKELY (renameat (destination_dfd, temp_filename,
                                destination_dfd, destination_name) == -1))
        {
          glnx_set_error_from_errno (error);
          goto out;
        }
    }
  else if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR)
    {
      glnx_fd_close int temp_fd = -1;
      g_autoptr(GOutputStream) temp_out = NULL;
      guint32 file_mode;

      file_mode = g_file_info_get_attribute_uint32 (file_info, "unix::mode");
      /* Don't make setuid files on checkout when we're doing --user */
      if (options->mode == OSTREE_REPO_CHECKOUT_MODE_USER)
        file_mode &= ~(S_ISUID|S_ISGID);

      if (!glnx_open_tmpfile_linkable_at (destination_dfd, ".", O_WRONLY | O_CLOEXEC,
                                          &temp_fd, &temp_filename,
                                          error))
        goto out;
      temp_out = g_unix_output_stream_new (temp_fd, FALSE);

      if (!write_regular_file_content (repo, options, temp_out, file_info, xattrs, input,
                                       cancellable, error))
        goto out;

      if (!glnx_link_tmpfile_at (destination_dfd, GLNX_LINK_TMPFILE_REPLACE,
                                 temp_fd, temp_filename, destination_dfd,
                                 destination_name,
                                 error))
        goto out;
    }
  else
    g_assert_not_reached ();

  ret = TRUE;
 out:
  return ret;
}
static gboolean
run (int argc, char **argv, GCancellable *cancellable, GError **error)
{
  gboolean ret = FALSE;
  g_autoptr(GOptionContext) context = NULL;
  const char *dirpath;
  OtTrivialHttpd appstruct = { 0, };
  OtTrivialHttpd *app = &appstruct;
  glnx_unref_object SoupServer *server = NULL;
  g_autoptr(GFileMonitor) dirmon = NULL;

  context = g_option_context_new ("[DIR] - Simple webserver");
  g_option_context_add_main_entries (context, options, NULL);

  app->root_dfd = -1;

  if (!g_option_context_parse (context, &argc, &argv, error))
    goto out;

  if (argc > 1)
    dirpath = argv[1];
  else
    dirpath = ".";

  if (!glnx_opendirat (AT_FDCWD, dirpath, TRUE, &app->root_dfd, error))
    goto out;

  if (!(opt_random_500s_percentage >= 0 && opt_random_500s_percentage <= 99))
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Invalid --random-500s=%u", opt_random_500s_percentage);
      goto out;
    }

  if (opt_log)
    {
      GOutputStream *stream = NULL;

      if (g_strcmp0 (opt_log, "-") == 0)
        {
          if (opt_daemonize)
            {
              ot_util_usage_error (context, "Cannot use --log-file=- and --daemonize at the same time", error);
              goto out;
            }
          stream = G_OUTPUT_STREAM (g_unix_output_stream_new (STDOUT_FILENO, FALSE));
        }
      else
        {
          g_autoptr(GFile) log_file = NULL;
          GFileOutputStream* log_stream;

          log_file = g_file_new_for_path (opt_log);
          log_stream = g_file_create (log_file,
                                      G_FILE_CREATE_PRIVATE,
                                      cancellable,
                                      error);
          if (!log_stream)
            goto out;
          stream = G_OUTPUT_STREAM (log_stream);
        }

      app->log = stream;
    }

#if SOUP_CHECK_VERSION(2, 48, 0)
  server = soup_server_new (SOUP_SERVER_SERVER_HEADER, "ostree-httpd ", NULL);
  if (!soup_server_listen_all (server, opt_port, 0, error))
    goto out;
#else
  server = soup_server_new (SOUP_SERVER_PORT, opt_port,
                            SOUP_SERVER_SERVER_HEADER, "ostree-httpd ",
                            NULL);
#endif

  soup_server_add_handler (server, NULL, httpd_callback, app, NULL);
  if (opt_port_file)
    {
      g_autofree char *portstr = NULL;
#if SOUP_CHECK_VERSION(2, 48, 0)
      GSList *listeners = soup_server_get_listeners (server);
      g_autoptr(GSocket) listener = NULL;
      g_autoptr(GSocketAddress) addr = NULL;
      
      g_assert (listeners);
      listener = g_object_ref (listeners->data);
      g_slist_free (listeners);
      listeners = NULL;
      addr = g_socket_get_local_address (listener, error);
      if (!addr)
        goto out;

      g_assert (G_IS_INET_SOCKET_ADDRESS (addr));
      
      portstr = g_strdup_printf ("%u\n", g_inet_socket_address_get_port ((GInetSocketAddress*)addr));
#else
      portstr = g_strdup_printf ("%u\n", soup_server_get_port (server));
#endif

      if (g_strcmp0 ("-", opt_port_file) == 0)
        {
          fputs (portstr, stdout); // not g_print - this must go to stdout, not a handler
          fflush (stdout);
        }
      else if (!g_file_set_contents (opt_port_file, portstr, strlen (portstr), error))
        goto out;
    }
#if !SOUP_CHECK_VERSION(2, 48, 0)
  soup_server_run_async (server);
#endif
  
  if (opt_daemonize)
    {
      pid_t pid = fork();
      if (pid == -1)
        {
          int errsv = errno;
          g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errsv),
                               g_strerror (errsv));
          goto out;
        }
      else if (pid > 0)
        {
          ret = TRUE;
          goto out;
        }
      /* Child, continue */
      if (setsid () < 0)
        err (1, "setsid");
      /* Daemonising: close stdout/stderr so $() et al work on us */
      if (freopen("/dev/null", "r", stdin) == NULL)
        err (1, "freopen");
      if (freopen("/dev/null", "w", stdout) == NULL)
        err (1, "freopen");
      if (freopen("/dev/null", "w", stderr) == NULL)
        err (1, "freopen");
    }
  else
    {
      /* Since we're used for testing purposes, let's just do this by
       * default.  This ensures we exit when our parent does.
       */
      if (prctl (PR_SET_PDEATHSIG, SIGTERM) != 0)
        {
          if (errno != ENOSYS)
            {
              glnx_set_error_from_errno (error);
              goto out;
            }
        }
    }

  app->running = TRUE;
  if (opt_autoexit)
    {
      gboolean is_symlink = FALSE;
      g_autoptr(GFile) root = NULL;
      g_autoptr(GFileInfo) info = NULL;

      root = g_file_new_for_path (dirpath);
      info = g_file_query_info (root,
                                G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK,
                                G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                cancellable, error);
      if (!info)
        goto out;

      is_symlink = g_file_info_get_is_symlink (info);

      if (is_symlink)
        dirmon = g_file_monitor_file (root, 0, cancellable, error);
      else
        dirmon = g_file_monitor_directory (root, 0, cancellable, error);

      if (!dirmon)
        goto out;
      g_signal_connect (dirmon, "changed", G_CALLBACK (on_dir_changed), app);
    }
  httpd_log (app, "serving at root %s\n", dirpath);
  while (app->running)
    g_main_context_iteration (NULL, TRUE);

  ret = TRUE;
 out:
  if (app->root_dfd != -1)
    (void) close (app->root_dfd);
  g_clear_object (&app->log);
  return ret;
}
static gboolean
checkout_file_from_input_at (OstreeRepo     *self,
                             OstreeRepoCheckoutOptions *options,
                             GFileInfo      *file_info,
                             GVariant       *xattrs,
                             GInputStream   *input,
                             int             destination_dfd,
                             const char     *destination_name,
                             GCancellable   *cancellable,
                             GError        **error)
{
  gboolean ret = FALSE;
  int res;

  if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_SYMBOLIC_LINK)
    {
      do
        res = symlinkat (g_file_info_get_symlink_target (file_info),
                         destination_dfd, destination_name);
      while (G_UNLIKELY (res == -1 && errno == EINTR));
      if (res == -1)
        {
          glnx_set_error_from_errno (error);
          goto out;
        }

      if (options->mode != OSTREE_REPO_CHECKOUT_MODE_USER)
        {
          if (G_UNLIKELY (fchownat (destination_dfd, destination_name,
                                    g_file_info_get_attribute_uint32 (file_info, "unix::uid"),
                                    g_file_info_get_attribute_uint32 (file_info, "unix::gid"),
                                    AT_SYMLINK_NOFOLLOW) == -1))
            {
              glnx_set_error_from_errno (error);
              goto out;
            }

          if (xattrs)
            {
              if (!glnx_dfd_name_set_all_xattrs (destination_dfd, destination_name,
                                                   xattrs, cancellable, error))
                goto out;
            }
        }
    }
  else if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR)
    {
      g_autoptr(GOutputStream) temp_out = NULL;
      int fd;
      guint32 file_mode;

      file_mode = g_file_info_get_attribute_uint32 (file_info, "unix::mode");
      /* Don't make setuid files on checkout when we're doing --user */
      if (options->mode == OSTREE_REPO_CHECKOUT_MODE_USER)
        file_mode &= ~(S_ISUID|S_ISGID);

      do
        fd = openat (destination_dfd, destination_name, O_WRONLY | O_CREAT | O_EXCL, file_mode);
      while (G_UNLIKELY (fd == -1 && errno == EINTR));
      if (fd == -1)
        {
          glnx_set_error_from_errno (error);
          goto out;
        }
      temp_out = g_unix_output_stream_new (fd, TRUE);
      fd = -1; /* Transfer ownership */

      if (!write_regular_file_content (self, options, temp_out, file_info, xattrs, input,
                                       cancellable, error))
        goto out;
    }
  else
    g_assert_not_reached ();
  
  ret = TRUE;
 out:
  return ret;
}
Beispiel #30
0
static gboolean
checkout_object_for_uncompressed_cache (OstreeRepo      *self,
                                        const char      *loose_path,
                                        GFileInfo       *src_info,
                                        GInputStream    *content,
                                        GCancellable    *cancellable,
                                        GError         **error)
{
  gboolean ret = FALSE;
  g_autofree char *temp_filename = NULL;
  g_autoptr(GOutputStream) temp_out = NULL;
  glnx_fd_close int fd = -1;
  int res;
  guint32 file_mode;

  /* Don't make setuid files in uncompressed cache */
  file_mode = g_file_info_get_attribute_uint32 (src_info, "unix::mode");
  file_mode &= ~(S_ISUID|S_ISGID);

  if (!glnx_open_tmpfile_linkable_at (self->tmp_dir_fd, ".", O_WRONLY | O_CLOEXEC,
                                      &fd, &temp_filename,
                                      error))
    goto out;
  temp_out = g_unix_output_stream_new (fd, FALSE);

  if (g_output_stream_splice (temp_out, content, 0, cancellable, error) < 0)
    goto out;

  if (!g_output_stream_flush (temp_out, cancellable, error))
    goto out;

  if (!self->disable_fsync)
    {
      do
        res = fsync (fd);
      while (G_UNLIKELY (res == -1 && errno == EINTR));
      if (G_UNLIKELY (res == -1))
        {
          glnx_set_error_from_errno (error);
          goto out;
        }
    }

  if (!g_output_stream_close (temp_out, cancellable, error))
    goto out;

  if (fchmod (fd, file_mode) < 0)
    {
      glnx_set_error_from_errno (error);
      goto out;
    }

  if (!_ostree_repo_ensure_loose_objdir_at (self->uncompressed_objects_dir_fd,
                                            loose_path,
                                            cancellable, error))
    goto out;

  if (!glnx_link_tmpfile_at (self->tmp_dir_fd, GLNX_LINK_TMPFILE_NOREPLACE_IGNORE_EXIST,
                             fd, temp_filename,
                             self->uncompressed_objects_dir_fd, loose_path,
                             error))
    goto out;

  ret = TRUE;
 out:
  return ret;
}