/** * glnx_dirfd_iterator_init_at: * @dfd: File descriptor, may be AT_FDCWD or -1 * @path: Path, may be relative to @df * @follow: If %TRUE and the last component of @path is a symlink, follow it * @out_dfd_iter: (out caller-allocates): A directory iterator, will be initialized * @error: Error * * Initialize @out_dfd_iter from @dfd and @path. */ gboolean glnx_dirfd_iterator_init_at (int dfd, const char *path, gboolean follow, GLnxDirFdIterator *out_dfd_iter, GError **error) { gboolean ret = FALSE; glnx_fd_close int fd = -1; if (!glnx_opendirat (dfd, path, follow, &fd, error)) goto out; if (!glnx_dirfd_iterator_init_take_fd (fd, out_dfd_iter, error)) goto out; fd = -1; /* Transfer ownership */ 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) { g_autoptr(GPtrArray) ret_deltas = NULL; glnx_fd_close int dfd = -1; ret_deltas = g_ptr_array_new_with_free_func (g_free); dfd = glnx_opendirat_with_errno (self->repo_dir_fd, "deltas", TRUE); if (dfd < 0) { if (errno != ENOENT) { glnx_set_error_from_errno (error); return FALSE; } } else { g_auto(GLnxDirFdIterator) dfd_iter = { 0, }; if (!glnx_dirfd_iterator_init_take_fd (dfd, &dfd_iter, error)) return FALSE; dfd = -1; while (TRUE) { g_auto(GLnxDirFdIterator) sub_dfd_iter = { 0, }; struct dirent *dent; if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, cancellable, error)) return FALSE; if (dent == NULL) break; if (dent->d_type != DT_DIR) continue; if (!glnx_dirfd_iterator_init_at (dfd_iter.fd, dent->d_name, FALSE, &sub_dfd_iter, error)) return FALSE; while (TRUE) { struct dirent *sub_dent; const char *name1; const char *name2; g_autofree char *superblock_subpath = NULL; struct stat stbuf; if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&sub_dfd_iter, &sub_dent, cancellable, error)) return FALSE; if (sub_dent == NULL) break; if (dent->d_type != DT_DIR) continue; name1 = dent->d_name; name2 = sub_dent->d_name; superblock_subpath = g_strconcat (name2, "/superblock", NULL); if (fstatat (sub_dfd_iter.fd, superblock_subpath, &stbuf, 0) < 0) { if (errno != ENOENT) { glnx_set_error_from_errno (error); return FALSE; } } else { 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)); } } } } if (out_deltas) *out_deltas = g_steal_pointer (&ret_deltas); return TRUE; }
gboolean _ostree_sysroot_read_boot_loader_configs (OstreeSysroot *self, int bootversion, GPtrArray **out_loader_configs, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; int fd; /* Temporary owned by iterator */ g_autofree char *entries_path = g_strdup_printf ("boot/loader.%d/entries", bootversion); g_autoptr(GPtrArray) ret_loader_configs = NULL; g_auto(GLnxDirFdIterator) dfd_iter = { 0, }; if (!ensure_sysroot_fd (self, error)) goto out; ret_loader_configs = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref); fd = glnx_opendirat_with_errno (self->sysroot_fd, entries_path, TRUE); if (fd == -1) { if (errno == ENOENT) goto done; else { glnx_set_error_from_errno (error); goto out; } } if (!glnx_dirfd_iterator_init_take_fd (fd, &dfd_iter, error)) goto out; while (TRUE) { struct dirent *dent; struct stat stbuf; if (!glnx_dirfd_iterator_next_dent (&dfd_iter, &dent, cancellable, error)) goto out; if (dent == NULL) break; if (fstatat (dfd_iter.fd, dent->d_name, &stbuf, 0) != 0) { glnx_set_error_from_errno (error); goto out; } if (g_str_has_prefix (dent->d_name, "ostree-") && g_str_has_suffix (dent->d_name, ".conf") && S_ISREG (stbuf.st_mode)) { glnx_unref_object OstreeBootconfigParser *config = ostree_bootconfig_parser_new (); if (!ostree_bootconfig_parser_parse_at (config, dfd_iter.fd, dent->d_name, cancellable, error)) { g_prefix_error (error, "Parsing %s: ", dent->d_name); goto out; } g_ptr_array_add (ret_loader_configs, g_object_ref (config)); } } done: gs_transfer_out_value (out_loader_configs, &ret_loader_configs); ret = TRUE; out: return ret; }