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; }
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; }