static gboolean
relabel_recursively (OstreeSePolicy *sepolicy,
                     GFile          *dir,
                     GFileInfo      *dir_info,
                     GPtrArray      *path_parts,
                     GCancellable   *cancellable,
                     GError        **error)
{
  gboolean ret = FALSE;
  g_autoptr(GFileEnumerator) direnum = NULL;

  if (!relabel_one_path (sepolicy, dir, dir_info, path_parts,
                         cancellable, error))
    goto out;

  direnum = g_file_enumerate_children (dir, OSTREE_GIO_FAST_QUERYINFO,
                                       G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                       cancellable, error);
  if (!direnum)
    goto out;
  
  while (TRUE)
    {
      GFileInfo *file_info;
      GFile *child;
      GFileType ftype;

      if (!g_file_enumerator_iterate (direnum, &file_info, &child,
                                      cancellable, error))
        goto out;
      if (file_info == NULL)
        break;

      g_ptr_array_add (path_parts, (char*)g_file_info_get_name (file_info));

      ftype = g_file_info_get_file_type (file_info);
      if (ftype == G_FILE_TYPE_DIRECTORY)
        {
          if (!relabel_recursively (sepolicy, child, file_info, path_parts,
                                    cancellable, error))
            goto out;
        }
      else
        {
          if (!relabel_one_path (sepolicy, child, file_info, path_parts,
                                 cancellable, error))
            goto out;
        }

      g_ptr_array_remove_index (path_parts, path_parts->len - 1);
    }

  ret = TRUE;
 out:
  return ret;
}
static gboolean
visit_files_in_tree (GFile        *base,
                     VisitFileFunc visit_file,
                     gpointer      data)
{
  g_autoptr(GFileEnumerator) enumerator = NULL;
  GError **error = data;

  enumerator = g_file_enumerate_children (base,
                                          G_FILE_ATTRIBUTE_STANDARD_TYPE ","
                                          G_FILE_ATTRIBUTE_STANDARD_NAME,
                                          G_FILE_QUERY_INFO_NONE,
                                          NULL,
                                          NULL);
  if (!enumerator)
    return FALSE;

  do
    {
      GFileInfo *info;
      GFile *child;
      GFileType type;

      if (!g_file_enumerator_iterate (enumerator, &info, &child, NULL, error))
        return FALSE;

      if (!info)
        return TRUE;

      type = g_file_info_get_file_type (info);

      if (type == G_FILE_TYPE_REGULAR)
        {
          if (!visit_file (child, data))
            return FALSE;
        }
      else if (type == G_FILE_TYPE_DIRECTORY)
        {
          if (!visit_files_in_tree (child, visit_file, data))
            return FALSE;
        }
    }
  while (1);

  return TRUE;
}
Exemple #3
0
static gboolean
diff_add_dir_recurse (GFile          *d,
                      GPtrArray      *added,
                      GCancellable   *cancellable,
                      GError        **error)
{
  g_autoptr(GFileEnumerator) dir_enum =
    g_file_enumerate_children (d, OSTREE_GIO_FAST_QUERYINFO,
                               G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                               cancellable,
                               error);
  if (!dir_enum)
    return FALSE;

  while (TRUE)
    {
      GFileInfo *child_info;
      const char *name;

      if (!g_file_enumerator_iterate (dir_enum, &child_info, NULL,
                                      cancellable, error))
        return FALSE;
      if (child_info == NULL)
        break;

      name = g_file_info_get_name (child_info);

      g_autoptr(GFile) child = g_file_get_child (d, name);
      g_ptr_array_add (added, g_object_ref (child));

      if (g_file_info_get_file_type (child_info) == G_FILE_TYPE_DIRECTORY)
        {
          if (!diff_add_dir_recurse (child, added, cancellable, error))
            return FALSE;
        }
    }

  return TRUE;
}
/*
 * checkout_tree_at:
 * @self: Repo
 * @mode: Options controlling all files
 * @overwrite_mode: Whether or not to overwrite files
 * @destination_parent_fd: Place tree here
 * @destination_name: Use this name for tree
 * @source: Source tree
 * @source_info: Source info
 * @cancellable: Cancellable
 * @error: Error
 *
 * Like ostree_repo_checkout_tree(), but check out @source into the
 * relative @destination_name, located by @destination_parent_fd.
 */
static gboolean
checkout_tree_at (OstreeRepo                        *self,
                  OstreeRepoCheckoutOptions         *options,
                  int                                destination_parent_fd,
                  const char                        *destination_name,
                  OstreeRepoFile                    *source,
                  GFileInfo                         *source_info,
                  GCancellable                      *cancellable,
                  GError                           **error)
{
  gboolean ret = FALSE;
  gboolean did_exist = FALSE;
  glnx_fd_close int destination_dfd = -1;
  int res;
  g_autoptr(GVariant) xattrs = NULL;
  g_autoptr(GFileEnumerator) dir_enum = NULL;

  /* Create initially with mode 0700, then chown/chmod only when we're
   * done.  This avoids anyone else being able to operate on partially
   * constructed dirs.
   */
  do
    res = mkdirat (destination_parent_fd, destination_name, 0700);
  while (G_UNLIKELY (res == -1 && errno == EINTR));
  if (res == -1)
    {
      if (errno == EEXIST && options->overwrite_mode == OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES)
        did_exist = TRUE;
      else
        {
          glnx_set_error_from_errno (error);
          goto out;
        }
    }

  if (!glnx_opendirat (destination_parent_fd, destination_name, TRUE,
                       &destination_dfd, error))
    goto out;

  /* Set the xattrs now, so any derived labeling works */
  if (!did_exist && options->mode != OSTREE_REPO_CHECKOUT_MODE_USER)
    {
      if (!ostree_repo_file_get_xattrs (source, &xattrs, NULL, error))
        goto out;

      if (xattrs)
        {
          if (!glnx_fd_set_all_xattrs (destination_dfd, xattrs, cancellable, error))
            goto out;
        }
    }

  if (g_file_info_get_file_type (source_info) != G_FILE_TYPE_DIRECTORY)
    {
      ret = checkout_one_file_at (self, options,
                                  (GFile *) source,
                                  source_info,
                                  destination_dfd,
                                  g_file_info_get_name (source_info),
                                  cancellable, error);
      goto out;
    }
  dir_enum = g_file_enumerate_children ((GFile*)source,
                                        OSTREE_GIO_FAST_QUERYINFO, 
                                        G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                        cancellable, 
                                        error);
  if (!dir_enum)
    goto out;

  while (TRUE)
    {
      GFileInfo *file_info;
      GFile *src_child;
      const char *name;

      if (!g_file_enumerator_iterate (dir_enum, &file_info, &src_child,
                                      cancellable, error))
        goto out;
      if (file_info == NULL)
        break;

      name = g_file_info_get_name (file_info);

      if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
        {
          if (!checkout_tree_at (self, options,
                                 destination_dfd, name,
                                 (OstreeRepoFile*)src_child, file_info,
                                 cancellable, error))
            goto out;
        }
      else
        {
          if (!checkout_one_file_at (self, options,
                                     src_child, file_info,
                                     destination_dfd, name,
                                     cancellable, error))
            goto out;
        }
    }

  /* We do fchmod/fchown last so that no one else could access the
   * partially created directory and change content we're laying out.
   */
  if (!did_exist)
    {
      do
        res = fchmod (destination_dfd,
                      g_file_info_get_attribute_uint32 (source_info, "unix::mode"));
      while (G_UNLIKELY (res == -1 && errno == EINTR));
      if (G_UNLIKELY (res == -1))
        {
          glnx_set_error_from_errno (error);
          goto out;
        }
    }

  if (!did_exist && options->mode != OSTREE_REPO_CHECKOUT_MODE_USER)
    {
      do
        res = fchown (destination_dfd,
                      g_file_info_get_attribute_uint32 (source_info, "unix::uid"),
                      g_file_info_get_attribute_uint32 (source_info, "unix::gid"));
      while (G_UNLIKELY (res == -1 && errno == EINTR));
      if (G_UNLIKELY (res == -1))
        {
          glnx_set_error_from_errno (error);
          goto out;
        }
    }

  /* Set directory mtime to OSTREE_TIMESTAMP, so that it is constant for all checkouts.
   * Must be done after setting permissions and creating all children.
   */
  if (!did_exist)
    {
      const struct timespec times[2] = { { OSTREE_TIMESTAMP, UTIME_OMIT }, { OSTREE_TIMESTAMP, 0} };
      do
        res = futimens (destination_dfd, times);
      while (G_UNLIKELY (res == -1 && errno == EINTR));
      if (G_UNLIKELY (res == -1))
        {
          glnx_set_error_from_errno (error);
          goto out;
        }
    }

  if (fsync_is_enabled (self, options))
    {
      if (fsync (destination_dfd) == -1)
        {
          glnx_set_error_from_errno (error);
          goto out;
        }
    }

  ret = TRUE;
 out:
  return ret;
}
/**
 * ostree_repo_list_static_delta_names:
 * @self: Repo
 * @out_deltas: (out) (element-type utf8) (transfer container): String name of deltas (checksum-checksum.delta)
 * @cancellable: Cancellable
 * @error: Error
 *
 * This function synchronously enumerates all static deltas in the
 * repository, returning its result in @out_deltas.
 */
gboolean
ostree_repo_list_static_delta_names (OstreeRepo                  *self,
                                     GPtrArray                  **out_deltas,
                                     GCancellable                *cancellable,
                                     GError                     **error)
{
    gboolean ret = FALSE;
    g_autoptr(GPtrArray) ret_deltas = NULL;
    g_autoptr(GFileEnumerator) dir_enum = NULL;

    ret_deltas = g_ptr_array_new_with_free_func (g_free);

    if (g_file_query_exists (self->deltas_dir, NULL))
    {
        dir_enum = g_file_enumerate_children (self->deltas_dir, OSTREE_GIO_FAST_QUERYINFO,
                                              G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                              NULL, error);
        if (!dir_enum)
            goto out;

        while (TRUE)
        {
            g_autoptr(GFileEnumerator) dir_enum2 = NULL;
            GFileInfo *file_info;
            GFile *child;

            if (!g_file_enumerator_iterate (dir_enum, &file_info, &child,
                                            NULL, error))
                goto out;
            if (file_info == NULL)
                break;

            if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_DIRECTORY)
                continue;


            dir_enum2 = g_file_enumerate_children (child, OSTREE_GIO_FAST_QUERYINFO,
                                                   G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                                   NULL, error);
            if (!dir_enum2)
                goto out;

            while (TRUE)
            {
                GFileInfo *file_info2;
                GFile *child2;
                const char *name1;
                const char *name2;

                if (!g_file_enumerator_iterate (dir_enum2, &file_info2, &child2,
                                                NULL, error))
                    goto out;
                if (file_info2 == NULL)
                    break;

                if (g_file_info_get_file_type (file_info2) != G_FILE_TYPE_DIRECTORY)
                    continue;

                name1 = g_file_info_get_name (file_info);
                name2 = g_file_info_get_name (file_info2);

                {
                    g_autoptr(GFile) meta_path = g_file_get_child (child2, "superblock");

                    if (g_file_query_exists (meta_path, NULL))
                    {
                        g_autofree char *buf = g_strconcat (name1, name2, NULL);
                        GString *out = g_string_new ("");
                        char checksum[OSTREE_SHA256_STRING_LEN+1];
                        guchar csum[OSTREE_SHA256_DIGEST_LEN];
                        const char *dash = strchr (buf, '-');

                        ostree_checksum_b64_inplace_to_bytes (buf, csum);
                        ostree_checksum_inplace_from_bytes (csum, checksum);
                        g_string_append (out, checksum);
                        if (dash)
                        {
                            g_string_append_c (out, '-');
                            ostree_checksum_b64_inplace_to_bytes (dash+1, csum);
                            ostree_checksum_inplace_from_bytes (csum, checksum);
                            g_string_append (out, checksum);
                        }

                        g_ptr_array_add (ret_deltas, g_string_free (out, FALSE));
                    }
                }
            }
        }
    }

    ret = TRUE;
    if (out_deltas)
        *out_deltas = g_steal_pointer (&ret_deltas);
out:
    return ret;
}