static gboolean
relabel_one_path (OstreeSePolicy *sepolicy,
                  GFile          *path,
                  GFileInfo      *info,
                  GPtrArray      *path_parts,
                  GCancellable   *cancellable,
                  GError        **error)
{
  gboolean ret = FALSE;
  g_autofree char *relpath = NULL;
  g_autofree char *new_label = NULL;

  relpath = ptrarray_path_join (path_parts);
  if (!ostree_sepolicy_restorecon (sepolicy, relpath,
                                   info, path,
                                   OSTREE_SEPOLICY_RESTORECON_FLAGS_ALLOW_NOLABEL |
                                   OSTREE_SEPOLICY_RESTORECON_FLAGS_KEEP_EXISTING,
                                   &new_label,
                                   cancellable, error))
    {
      g_prefix_error (error, "Setting context of %s: ", gs_file_get_path_cached (path));
      goto out;
    }

  if (new_label)
    g_print ("Set label of '%s' (as '%s') to '%s'\n",
             gs_file_get_path_cached (path),
             relpath,
             new_label);

  ret = TRUE;
 out:
  return ret;
}
Пример #2
0
static gboolean
chown_internal (GFile          *path,
                gboolean        dereference_links,
                guint32         owner,
                guint32         group,
                GCancellable   *cancellable,
                GError        **error)
{
    gboolean ret = FALSE;
    int res;

    if (g_cancellable_set_error_if_cancelled (cancellable, error))
        return FALSE;

    do
        if (dereference_links)
            res = chown (gs_file_get_path_cached (path), owner, group);
        else
            res = lchown (gs_file_get_path_cached (path), owner, group);
    while (G_UNLIKELY (res != 0 && errno == EINTR));

    if (res < 0)
    {
        gs_set_prefix_error_from_errno (error, errno, "chown");
        goto out;
    }

    ret = TRUE;
out:
    return ret;
}
Пример #3
0
/**
 * rpmostree_prepare_rootfs_for_commit:
 *
 * Walk over the root filesystem and perform some core conversions
 * from RPM conventions to OSTree conventions.  For example:
 *
 *  * Move /etc to /usr/etc
 *  * Checksum the kernel in /boot
 *  * Migrate content in /var to systemd-tmpfiles
 */
gboolean
rpmostree_prepare_rootfs_for_commit (GFile         *rootfs,
                                     JsonObject    *treefile,
                                     GCancellable  *cancellable,
                                     GError       **error)
{
    gboolean ret = FALSE;
    gs_free char *dest_rootfs_path = NULL;

    dest_rootfs_path = g_strconcat (gs_file_get_path_cached (rootfs), ".post", NULL);

    if (!glnx_shutil_rm_rf_at (AT_FDCWD, dest_rootfs_path, cancellable, error))
        goto out;

    {
        gs_unref_object GFile *dest_rootfs = g_file_new_for_path (dest_rootfs_path);
        if (!create_rootfs_from_yumroot_content (dest_rootfs, rootfs, treefile,
                cancellable, error))
            goto out;
    }

    if (!glnx_shutil_rm_rf_at (AT_FDCWD, gs_file_get_path_cached (rootfs), cancellable, error))
        goto out;

    if (TEMP_FAILURE_RETRY (renameat (AT_FDCWD, dest_rootfs_path,
                                      AT_FDCWD, gs_file_get_path_cached (rootfs))) != 0)
    {
        glnx_set_error_from_errno (error);
        goto out;
    }

    ret = TRUE;
out:
    return ret;
}
Пример #4
0
char *
ot_editor_prompt (OstreeRepo *repo,
                  const char *input,
                  GCancellable *cancellable,
                  GError **error)
{
  glnx_unref_object GSubprocess *proc = NULL;
  g_autoptr(GFile) file = NULL;
  g_autoptr(GFileIOStream) io = NULL;
  GOutputStream *output;
  const char *editor;
  char *ret = NULL;
  g_autofree char *args = NULL;

  editor = get_editor ();
  if (editor == NULL)
    {
      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                           "Terminal is dumb, but EDITOR unset");
      goto out;
    }

  file = g_file_new_tmp (NULL, &io, error);
  if (file == NULL)
    goto out;

  output = g_io_stream_get_output_stream (G_IO_STREAM (io));
  if (!g_output_stream_write_all (output, input, strlen (input), NULL, cancellable, error) ||
      !g_io_stream_close (G_IO_STREAM (io), cancellable, error))
    goto out;

  {
    g_autofree char *quoted_file = g_shell_quote (gs_file_get_path_cached (file));
    args = g_strconcat (editor, " ", quoted_file, NULL);
  }

  proc = g_subprocess_new (G_SUBPROCESS_FLAGS_STDIN_INHERIT, error, 
                           "/bin/sh", "-c", args, NULL);

  if (!g_subprocess_wait_check (proc, cancellable, error))
    {
      g_prefix_error (error, "There was a problem with the editor '%s'", editor);
      goto out;
    }

  ret = glnx_file_get_contents_utf8_at (AT_FDCWD, gs_file_get_path_cached (file), NULL,
                                        cancellable, error);

out:
  if (file)
    (void )g_file_delete (file, NULL, NULL);
  return ret;
}
Пример #5
0
/**
 * rpmostree_prepare_rootfs_for_commit:
 *
 * Walk over the root filesystem and perform some core conversions
 * from RPM conventions to OSTree conventions.  For example:
 *
 *  * Move /etc to /usr/etc
 *  * Checksum the kernel in /boot
 *  * Migrate content in /var to systemd-tmpfiles
 */
gboolean
rpmostree_prepare_rootfs_for_commit (GFile         *rootfs,
                                     JsonObject    *treefile,
                                     GCancellable  *cancellable,
                                     GError       **error)
{
  gboolean ret = FALSE;
  gs_unref_object GFile *rootfs_tmp = NULL;
  gs_free char *rootfs_tmp_path = NULL;

  rootfs_tmp_path = g_strconcat (gs_file_get_path_cached (rootfs), ".tmp", NULL);
  rootfs_tmp = g_file_new_for_path (rootfs_tmp_path);

  if (!gs_shutil_rm_rf (rootfs_tmp, cancellable, error))
    goto out;

  if (!create_rootfs_from_yumroot_content (rootfs_tmp, rootfs, treefile,
                                           cancellable, error))
    goto out;

  if (!gs_shutil_rm_rf (rootfs, cancellable, error))
    goto out;
  if (!gs_file_rename (rootfs_tmp, rootfs, cancellable, error))
    goto out;

  ret = TRUE;
 out:
  return ret;
}
Пример #6
0
/**
 * gs_file_read_noatime:
 * @file: a #GFile
 * @cancellable: a #GCancellable
 * @error: a #GError
 *
 * Like g_file_read(), but try to avoid updating the file's
 * access time.  This should be used by background scanning
 * components such as search indexers, antivirus programs, etc.
 *
 * Returns: (transfer full): A new input stream, or %NULL on error
 */
GInputStream *
gs_file_read_noatime (GFile         *file,
                      GCancellable  *cancellable,
                      GError       **error)
{
    const char *path = NULL;
    int fd;

    if (g_cancellable_set_error_if_cancelled (cancellable, error))
        return NULL;

    path = gs_file_get_path_cached (file);
    if (path == NULL)
    {
        char *uri;
        uri = g_file_get_uri (file);
        g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT,
                     "%s has no associated path", uri);
        g_free (uri);
        return NULL;
    }

    if (!gs_file_openat_noatime (AT_FDCWD, path, &fd, cancellable, error))
        return NULL;

    return g_unix_input_stream_new (fd, TRUE);
}
Пример #7
0
static gboolean
prepare_root_ssh (GCancellable   *cancellable,
                  GError        **error)
{
  gboolean ret = FALSE;
  GFile *root_ssh_path = g_file_new_for_path ("/root/.ssh");

  if (!g_file_query_exists (root_ssh_path, NULL))
    {
      if (!g_file_make_directory (root_ssh_path, cancellable, error))
        goto out;

      if (!gs_file_chmod (root_ssh_path, 0700, cancellable, error))
        goto out;

      /* Ignore errors here to be simple, otherwise we'd have to link
       * to libselinux etc.
       */
      (void) gs_subprocess_simple_run_sync (NULL, GS_SUBPROCESS_STREAM_DISPOSITION_NULL,
                                            cancellable, error,
                                            "restorecon",
                                            gs_file_get_path_cached (root_ssh_path),
                                            NULL);
    }

  ret = TRUE;
 out:
  return ret;
}
Пример #8
0
/**
 * gs_file_chmod:
 * @path: Path to file
 * @mode: UNIX mode
 * @cancellable: a #GCancellable
 * @error: a #GError
 *
 * Merely wraps UNIX chmod().
 *
 * Returns: %TRUE on success, %FALSE on error
 */
gboolean
gs_file_chmod (GFile          *path,
               guint           mode,
               GCancellable   *cancellable,
               GError        **error)
{
    gboolean ret = FALSE;
    int res;

    if (g_cancellable_set_error_if_cancelled (cancellable, error))
        return FALSE;

    do
        res = chmod (gs_file_get_path_cached (path), mode);
    while (G_UNLIKELY (res != 0 && errno == EINTR));

    if (res < 0)
    {
        gs_set_prefix_error_from_errno (error, errno, "chmod");
        goto out;
    }

    ret = TRUE;
out:
    return ret;
}
Пример #9
0
/**
 * gs_shutil_rm_rf:
 * @path: A file or directory
 * @cancellable:
 * @error:
 *
 * Recursively delete the filename referenced by @path; it may be a
 * file or directory.  No error is thrown if @path does not exist.
 */
gboolean
gs_shutil_rm_rf (GFile        *path,
                 GCancellable *cancellable,
                 GError      **error)
{
  return gs_shutil_rm_rf_at (-1, gs_file_get_path_cached (path), cancellable, error);
}
Пример #10
0
/**
 * ot_gfile_replace_contents_fsync:
 * 
 * Like g_file_replace_contents(), except always uses fdatasync().
 */
gboolean
ot_gfile_replace_contents_fsync (GFile          *path,
                                 GBytes         *contents,
                                 GCancellable   *cancellable,
                                 GError        **error)
{
  gboolean ret = FALSE;
  int parent_dfd;
  const char *target_basename = gs_file_get_basename_cached (path);
  g_autoptr(GFile) parent = NULL;

  parent = g_file_get_parent (path);

  if (!glnx_opendirat (AT_FDCWD, gs_file_get_path_cached (parent), TRUE,
                       &parent_dfd, error))
    goto out;

  if (!ot_file_replace_contents_at (parent_dfd, target_basename,
                                    contents, TRUE,
                                    cancellable, error))
    goto out;

  ret = TRUE;
 out:
  if (parent_dfd != -1)
    (void) close (parent_dfd);
  return ret;
}
Пример #11
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;
}
Пример #12
0
/**
 * ot_util_ensure_directory_and_fsync:
 * @dir: Path to a directory
 * @cancellable: Cancellable
 * @error: Error
 *
 * Create @dir (and all intermediate parent directories), ensuring
 * that all entries are on disk.
 */
gboolean
ot_util_ensure_directory_and_fsync (GFile         *dir,
                                    GCancellable  *cancellable,
                                    GError       **error)
{
  gboolean ret = FALSE;
  int parentfd = -1;
  const char *basename = gs_file_get_basename_cached (dir);
  g_autoptr(GFile) parent = g_file_get_parent (dir);
  
 again:
  parentfd = open (gs_file_get_path_cached (parent),
                   O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC);
  if (parentfd == -1)
    {
      if (errno == ENOENT)
        {
          if (!ot_util_ensure_directory_and_fsync (parent, cancellable, error))
            goto out;
          goto again;
        }
      else
        {
          int errsv = errno;
          g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
                       "opendir: %s", g_strerror (errsv));
          goto out;
        }
    }
  
  if (mkdirat (parentfd, basename, 0777) == -1)
    {
      if (errno == EEXIST)
        {
          ;
        }
      else
        {
          int errsv = errno;
          g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
                       "mkdirat: %s", g_strerror (errsv));
          goto out;
        }
    }

  if (fsync (parentfd) == -1)
    {
      int errsv = errno;
      g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
                   "fsync: %s", g_strerror (errsv));
      goto out;
    }

  ret = TRUE;
 out:
  if (parentfd != -1)
    (void) close (parentfd);
  return ret;
}
Пример #13
0
/**
 * ostree_sysroot_get_deployment_origin_path:
 * @deployment_path: A deployment path
 *
 * Returns: (transfer full): Path to deployment origin file
 */
GFile *
ostree_sysroot_get_deployment_origin_path (GFile   *deployment_path)
{
  g_autoptr(GFile) deployment_parent = g_file_get_parent (deployment_path);
  return ot_gfile_resolve_path_printf (deployment_parent,
                                       "%s.origin",
                                       gs_file_get_path_cached (deployment_path));
}
gboolean
rpmostree_get_pkglist_for_root (GFile            *root,
                                HySack           *out_sack,
                                HyPackageList    *out_pkglist,
                                GCancellable     *cancellable,
                                GError          **error)
{
  gboolean ret = FALSE;
  int rc;
  _cleanup_hysack_ HySack sack = NULL;
  _cleanup_hyquery_ HyQuery query = NULL;
  _cleanup_hypackagelist_ HyPackageList pkglist = NULL;

#if BUILDOPT_HAWKEY_SACK_CREATE2
  sack = hy_sack_create (NULL, NULL,
                         gs_file_get_path_cached (root),
                         NULL,
                         HY_MAKE_CACHE_DIR);
#else
  sack = hy_sack_create (NULL, NULL,
                         gs_file_get_path_cached (root),
                         HY_MAKE_CACHE_DIR);
#endif
  if (sack == NULL)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Failed to create sack cache");
      goto out;
    }

  rc = hy_sack_load_system_repo (sack, NULL, 0);
  if (!hif_error_set_from_hawkey (rc, error))
    {
      g_prefix_error (error, "Failed to load system repo: ");
      goto out;
    }
  query = hy_query_create (sack);
  hy_query_filter (query, HY_PKG_REPONAME, HY_EQ, HY_SYSTEM_REPO_NAME);
  pkglist = hy_query_run (query);

  ret = TRUE;
  gs_transfer_out_value (out_sack, &sack);
  gs_transfer_out_value (out_pkglist, &pkglist);
 out:
  return ret;
}
Пример #15
0
/**
 * gs_file_rename:
 * @from: Current path
 * @to: New path
 * @cancellable: a #GCancellable
 * @error: a #GError
 *
 * This function wraps the raw Unix function rename().
 *
 * Returns: %TRUE on success, %FALSE on error
 */
gboolean
gs_file_rename (GFile          *from,
                GFile          *to,
                GCancellable   *cancellable,
                GError        **error)
{
    if (g_cancellable_set_error_if_cancelled (cancellable, error))
        return FALSE;

    if (rename (gs_file_get_path_cached (from),
                gs_file_get_path_cached (to)) < 0)
    {
        gs_set_prefix_error_from_errno (error, errno, "rename");
        return FALSE;
    }
    return TRUE;
}
Пример #16
0
gboolean
ostree_bootconfig_parser_parse (OstreeBootconfigParser  *self,
                                GFile           *path,
                                GCancellable    *cancellable,
                                GError         **error)
{
  return ostree_bootconfig_parser_parse_at (self, AT_FDCWD, gs_file_get_path_cached (path),
                                            cancellable, error);
}
static gboolean
copy_exports (GFile    *source,
              GFile    *destination,
              const char *source_prefix,
              const char *required_prefix,
              GCancellable  *cancellable,
              GError       **error)
{
  if (!gs_file_ensure_directory (destination, TRUE, cancellable, error))
    return FALSE;

  /* The fds are closed by this call */
  if (!export_dir (AT_FDCWD, gs_file_get_path_cached (source), source_prefix,
                   AT_FDCWD, gs_file_get_path_cached (destination),
                   required_prefix, cancellable, error))
    return FALSE;

  return TRUE;
}
Пример #18
0
/**
 * gs_file_set_all_xattrs:
 * @file: File descriptor
 * @xattrs: Extended attributes
 * @cancellable: Cancellable
 * @error: Error
 *
 * For each attribute in @xattrs, set its value on the file or
 * directory referred to by @file.  This function does not remove any
 * attributes not in @xattrs.
 */
gboolean
gs_file_set_all_xattrs (GFile         *file,
                        GVariant      *xattrs,
                        GCancellable  *cancellable,
                        GError       **error)
{
    return glnx_dfd_name_set_all_xattrs (AT_FDCWD,
                                         gs_file_get_path_cached (file),
                                         xattrs, cancellable, error);
}
Пример #19
0
static gboolean
ensure_sysroot_fd (OstreeSysroot          *self,
                   GError                **error)
{
  if (self->sysroot_fd == -1)
    {
      if (!glnx_opendirat (AT_FDCWD, gs_file_get_path_cached (self->path), TRUE,
                           &self->sysroot_fd, error))
        return FALSE;
    }
  return TRUE;
}
Пример #20
0
/**
 * gs_file_unlink:
 * @path: Path to file
 * @cancellable: a #GCancellable
 * @error: a #GError
 *
 * Like g_file_delete(), except this function does not follow Unix
 * symbolic links, and will delete a symbolic link even if it's
 * pointing to a nonexistent file.  In other words, this function
 * merely wraps the raw Unix function unlink().
 *
 * Returns: %TRUE on success, %FALSE on error
 */
gboolean
gs_file_unlink (GFile          *path,
                GCancellable   *cancellable,
                GError        **error)
{
    if (g_cancellable_set_error_if_cancelled (cancellable, error))
        return FALSE;

    if (unlink (gs_file_get_path_cached (path)) < 0)
    {
        gs_set_prefix_error_from_errno (error, errno, "unlink");
        return FALSE;
    }
    return TRUE;
}
Пример #21
0
static void
print_diff_item (char        prefix,
                 GFile      *base,
                 GFile      *file)
{
  if (g_file_is_native (file))
    {
      g_autofree char *relpath = g_file_get_relative_path (base, file);
      g_print ("%c    %s\n", prefix, relpath);
    }
  else
    {
      g_print ("%c    %s\n", prefix, gs_file_get_path_cached (file));
    }
}
Пример #22
0
/**
 * gs_file_open_dir_fd:
 * @path: Directory name
 * @out_fd: (out): File descriptor for directory
 * @cancellable: Cancellable
 * @error: Error
 *
 * On success, sets @out_fd to a file descriptor for the directory
 * that can be used with UNIX functions such as openat().
 */
gboolean
gs_file_open_dir_fd (GFile         *path,
                     int           *out_fd,
                     GCancellable  *cancellable,
                     GError       **error)
{
    /* Linux specific probably */
    *out_fd = open (gs_file_get_path_cached (path), O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC);
    if (*out_fd == -1)
    {
        gs_set_prefix_error_from_errno (error, errno, "open");
        return FALSE;
    }
    return TRUE;
}
Пример #23
0
/**
 * gs_file_ensure_directory_mode:
 * @dir: Path to create as directory
 * @mode: Create directory with these permissions
 * @cancellable: a #GCancellable
 * @error: a #GError
 *
 * Wraps UNIX mkdir() function with support for @cancellable, and
 * uses @error instead of errno.
 */
gboolean
gs_file_ensure_directory_mode (GFile         *dir,
                               guint          mode,
                               GCancellable  *cancellable,
                               GError       **error)
{
    if (g_cancellable_set_error_if_cancelled (cancellable, error))
        return FALSE;

    if (mkdir (gs_file_get_path_cached (dir), mode) == -1 && errno != EEXIST)
    {
        gs_set_prefix_error_from_errno (error, errno, "mkdir");
        return FALSE;
    }
    return TRUE;
}
Пример #24
0
/**
 * rpmostreed_sysroot_populate :
 *
 * loads internals and starts monitoring
 *
 * Returns: True on success
 */
gboolean
rpmostreed_sysroot_populate (RpmostreedSysroot *self,
			     GCancellable *cancellable,
                             GError **error)
{
  gboolean ret = FALSE;
  g_autoptr(GFile) sysroot_file = NULL;
  const char *sysroot_path;

  g_return_val_if_fail (self != NULL, FALSE);

  sysroot_path = rpmostree_sysroot_get_path (RPMOSTREE_SYSROOT (self));
  sysroot_file = g_file_new_for_path (sysroot_path);
  self->ot_sysroot = ostree_sysroot_new (sysroot_file);

  /* This creates and caches an OstreeRepo instance inside
   * OstreeSysroot to ensure subsequent ostree_sysroot_get_repo()
   * calls won't fail.
   */
  if (!ostree_sysroot_get_repo (self->ot_sysroot, &self->repo, cancellable, error))
    goto out;

  if (!sysroot_populate_deployments_unlocked (self, NULL, error))
    goto out;

  if (self->monitor == NULL)
    {
      const char *sysroot_path = gs_file_get_path_cached (ostree_sysroot_get_path (self->ot_sysroot));
      g_autofree char *sysroot_deploy_path = g_build_filename (sysroot_path, "ostree/deploy", NULL);
      g_autoptr(GFile) sysroot_deploy = g_file_new_for_path (sysroot_deploy_path);
      
      self->monitor = g_file_monitor (sysroot_deploy, 0, NULL, error);

      if (self->monitor == NULL)
        goto out;

      self->sig_changed = g_signal_connect (self->monitor,
                                            "changed",
                                            G_CALLBACK (on_deploy_changed),
                                            self);
    }

  ret = TRUE;
out:
  return ret;
}
Пример #25
0
/**
 * gs_file_ensure_directory:
 * @dir: Path to create as directory
 * @with_parents: Also create parent directories
 * @cancellable: a #GCancellable
 * @error: a #GError
 *
 * Like g_file_make_directory(), except does not throw an error if the
 * directory already exists.
 */
gboolean
gs_file_ensure_directory (GFile         *dir,
                          gboolean       with_parents,
                          GCancellable  *cancellable,
                          GError       **error)
{
    gboolean ret = FALSE;
    GError *temp_error = NULL;
    GFile *parent = NULL;

    if (!g_file_make_directory (dir, cancellable, &temp_error))
    {
        if (with_parents &&
                g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
        {
            parent = g_file_get_parent (dir);
            if (parent)
            {
                g_clear_error (&temp_error);

                if (!glnx_shutil_mkdir_p_at (AT_FDCWD,
                                             gs_file_get_path_cached (parent),
                                             0777,
                                             cancellable,
                                             error))
                    goto out;
            }
            if (!gs_file_ensure_directory (dir, FALSE, cancellable, error))
                goto out;
        }
        else if (!g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_EXISTS))
        {
            g_propagate_error (error, temp_error);
            goto out;
        }
        else
            g_clear_error (&temp_error);
    }

    ret = TRUE;
out:
    g_clear_object (&parent);
    return ret;
}
Пример #26
0
static gboolean
get_file_checksum (OstreeDiffFlags  flags,
                   GFile *f,
                   GFileInfo *f_info,
                   char  **out_checksum,
                   GCancellable *cancellable,
                   GError   **error)
{
  g_autofree char *ret_checksum = NULL;

  if (OSTREE_IS_REPO_FILE (f))
    {
      ret_checksum = g_strdup (ostree_repo_file_get_checksum ((OstreeRepoFile*)f));
    }
  else
    {
      g_autoptr(GVariant) xattrs = NULL;
      g_autoptr(GInputStream) in = NULL;

      if (!(flags & OSTREE_DIFF_FLAGS_IGNORE_XATTRS))
        {
          if (!glnx_dfd_name_get_all_xattrs (AT_FDCWD, gs_file_get_path_cached (f),
                                             &xattrs, cancellable, error))
            return FALSE;
        }

      if (g_file_info_get_file_type (f_info) == G_FILE_TYPE_REGULAR)
        {
          in = (GInputStream*)g_file_read (f, cancellable, error);
          if (!in)
            return FALSE;
        }

      g_autofree guchar *csum = NULL;
      if (!ostree_checksum_file_from_input (f_info, xattrs, in,
                                            OSTREE_OBJECT_TYPE_FILE,
                                            &csum, cancellable, error))
        return FALSE;
      ret_checksum = ostree_checksum_from_bytes (csum);
    }

  ot_transfer_out_value(out_checksum, &ret_checksum);
  return TRUE;
}
Пример #27
0
/* Given a directory @d, find the first child that is a directory,
 * returning it in @out_subdir.  If there are multiple directories,
 * return an error.
 */
static gboolean
find_ensure_one_subdirectory (GFile         *d,
                              GFile        **out_subdir,
                              GCancellable  *cancellable,
                              GError       **error)
{
    gboolean ret = FALSE;
    gs_unref_object GFileEnumerator *direnum = NULL;
    gs_unref_object GFile *ret_subdir = NULL;

    direnum = g_file_enumerate_children (d, "standard::name,standard::type", 0,
                                         cancellable, error);
    if (!direnum)
        goto out;

    while (TRUE)
    {
        GFileInfo *file_info;
        GFile *child;

        if (!gs_file_enumerator_iterate (direnum, &file_info, &child,
                                         cancellable, error))
            goto out;
        if (!file_info)
            break;

        if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
        {
            if (ret_subdir)
            {
                g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                             "Multiple subdirectories found in: %s", gs_file_get_path_cached (d));
                goto out;
            }
            ret_subdir = g_object_ref (child);
        }
    }

    ret = TRUE;
    gs_transfer_out_value (out_subdir, &ret_subdir);
out:
    return ret;
}
Пример #28
0
/**
 * gs_file_map_readonly:
 * @file: a #GFile
 * @cancellable:
 * @error:
 *
 * Return a #GBytes which references a readonly view of the contents of
 * @file.  This function uses #GMappedFile internally.
 *
 * Returns: (transfer full): a newly referenced #GBytes
 */
GBytes *
gs_file_map_readonly (GFile         *file,
                      GCancellable  *cancellable,
                      GError       **error)
{
    GMappedFile *mfile;
    GBytes *ret;

    if (g_cancellable_set_error_if_cancelled (cancellable, error))
        return NULL;

    mfile = g_mapped_file_new (gs_file_get_path_cached (file), FALSE, error);
    if (!mfile)
        return NULL;

    ret = g_mapped_file_get_bytes (mfile);
    g_mapped_file_unref (mfile);
    return ret;
}
Пример #29
0
static void
ostree_sysroot_set_property(GObject         *object,
                            guint            prop_id,
                            const GValue    *value,
                            GParamSpec      *pspec)
{
  OstreeSysroot *self = OSTREE_SYSROOT (object);

  switch (prop_id)
    {
    case PROP_PATH:
      /* Canonicalize */
      self->path = g_file_new_for_path (gs_file_get_path_cached (g_value_get_object (value)));
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}
Пример #30
0
/**
 * gs_file_sync_data:
 * @file: a #GFile
 * @cancellable:
 * @error:
 *
 * Wraps the UNIX fsync() function (or fdatasync(), if available), which
 * ensures that the data in @file is on non-volatile storage.
 */
gboolean
gs_file_sync_data (GFile          *file,
                   GCancellable   *cancellable,
                   GError        **error)
{
    gboolean ret = FALSE;
    int res;
    int fd = -1;

    if (!gs_file_openat_noatime (AT_FDCWD, gs_file_get_path_cached (file), &fd,
                                 cancellable, error))
        goto out;

    do
    {
#ifdef __linux
        res = fdatasync (fd);
#else
        res = fsync (fd);
#endif
    }
    while (G_UNLIKELY (res != 0 && errno == EINTR));
    if (res != 0)
    {
        gs_set_prefix_error_from_errno (error, errno, "fdatasync");
        goto out;
    }

    res = close_nointr (fd);
    if (res != 0)
    {
        gs_set_prefix_error_from_errno (error, errno, "close");
        goto out;
    }
    fd = -1;

    ret = TRUE;
out:
    if (fd != -1)
        close_nointr_noerror (fd);
    return ret;
}