gboolean ostree_create_temp_regular_file (GFile *dir, const char *prefix, const char *suffix, GFile **out_file, GOutputStream **out_stream, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; ot_lobj GFile *ret_file = NULL; ot_lobj GOutputStream *ret_stream = NULL; if (!ostree_create_temp_file_from_input (dir, prefix, suffix, NULL, NULL, NULL, &ret_file, cancellable, error)) goto out; ret_stream = (GOutputStream*)g_file_append_to (ret_file, 0, cancellable, error); if (ret_stream == NULL) goto out; ret = TRUE; ot_transfer_out_value(out_file, &ret_file); ot_transfer_out_value(out_stream, &ret_stream); out: return ret; }
/* Used by the remote builtins which are special in taking --sysroot or --repo */ gboolean ostree_parse_sysroot_or_repo_option (GOptionContext *context, const char *sysroot_path, const char *repo_path, OstreeSysroot **out_sysroot, OstreeRepo **out_repo, GCancellable *cancellable, GError **error) { g_autoptr(OstreeSysroot) sysroot = NULL; g_autoptr(OstreeRepo) repo = NULL; if (sysroot_path) { g_autoptr(GFile) sysroot_file = g_file_new_for_path (sysroot_path); sysroot = ostree_sysroot_new (sysroot_file); if (!ostree_sysroot_load (sysroot, cancellable, error)) return FALSE; if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error)) return FALSE; } else { repo = parse_repo_option (context, repo_path, FALSE, cancellable, error); if (!repo) return FALSE; } ot_transfer_out_value (out_sysroot, &sysroot); ot_transfer_out_value (out_repo, &repo); return TRUE; }
gboolean ostree_zlib_file_header_parse (GVariant *metadata, GFileInfo **out_file_info, GVariant **out_xattrs, GError **error) { gboolean ret = FALSE; guint64 size; guint32 uid, gid, mode, rdev; const char *symlink_target; ot_lobj GFileInfo *ret_file_info = NULL; ot_lvariant GVariant *ret_xattrs = NULL; g_variant_get (metadata, "(tuuuu&s@a(ayay))", &size, &uid, &gid, &mode, &rdev, &symlink_target, &ret_xattrs); size = GUINT64_FROM_BE (size); uid = GUINT32_FROM_BE (uid); gid = GUINT32_FROM_BE (gid); mode = GUINT32_FROM_BE (mode); rdev = GUINT32_FROM_BE (rdev); ret_file_info = g_file_info_new (); g_file_info_set_size (ret_file_info, size); g_file_info_set_attribute_uint32 (ret_file_info, "standard::type", ot_gfile_type_for_mode (mode)); g_file_info_set_attribute_boolean (ret_file_info, "standard::is-symlink", S_ISLNK (mode)); g_file_info_set_attribute_uint32 (ret_file_info, "unix::uid", uid); g_file_info_set_attribute_uint32 (ret_file_info, "unix::gid", gid); g_file_info_set_attribute_uint32 (ret_file_info, "unix::mode", mode); if (S_ISREG (mode)) { ; } else if (S_ISLNK (mode)) { g_file_info_set_attribute_byte_string (ret_file_info, "standard::symlink-target", symlink_target); } else if (S_ISCHR (mode) || S_ISBLK (mode)) { g_file_info_set_attribute_uint32 (ret_file_info, "unix::rdev", rdev); } else if (S_ISFIFO (mode)) { ; } else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Corrupted archive file; invalid mode %u", mode); goto out; } ret = TRUE; ot_transfer_out_value(out_file_info, &ret_file_info); ot_transfer_out_value(out_xattrs, &ret_xattrs); out: return ret; }
gboolean ot_gfile_load_contents_utf8 (GFile *file, char **out_contents, char **out_etag, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; gsize len; ot_lfree char *ret_contents = NULL; ot_lfree char *ret_etag = NULL; if (!g_file_load_contents (file, cancellable, &ret_contents, &len, &ret_etag, error)) goto out; if (!g_utf8_validate (ret_contents, len, NULL)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Invalid UTF-8"); goto out; } ret = TRUE; ot_transfer_out_value (out_contents, &ret_contents); ot_transfer_out_value (out_etag, &ret_etag); out: return ret; }
gboolean ot_gfile_load_contents_utf8_allow_noent (GFile *path, char **out_contents, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; GError *temp_error = NULL; g_autofree char *ret_contents = NULL; ret_contents = gs_file_load_contents_utf8 (path, cancellable, &temp_error); if (!ret_contents) { if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) { g_clear_error (&temp_error); } else { g_propagate_error (error, temp_error); goto out; } } ret = TRUE; ot_transfer_out_value (out_contents, &ret_contents); out: return ret; }
gboolean ot_gfile_query_symlink_target_allow_noent (GFile *path, GFile **out_target, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; g_autoptr(GFileInfo) file_info = NULL; g_autoptr(GFile) ret_target = NULL; if (!ot_gfile_query_info_allow_noent (path, OSTREE_GIO_FAST_QUERYINFO, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, &file_info, cancellable, error)) goto out; if (file_info != NULL) { if (!ot_gfile_get_symlink_target_from_info (path, file_info, &ret_target, cancellable, error)) goto out; } ret = TRUE; ot_transfer_out_value (out_target, &ret_target); out: return ret; }
gboolean ot_gfile_query_info_allow_noent (GFile *path, const char *queryopts, GFileQueryInfoFlags flags, GFileInfo **out_info, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; g_autoptr(GFileInfo) ret_file_info = NULL; GError *temp_error = NULL; ret_file_info = g_file_query_info (path, queryopts, flags, cancellable, &temp_error); if (!ret_file_info) { if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) { g_clear_error (&temp_error); } else { g_propagate_error (error, temp_error); goto out; } } ret = TRUE; ot_transfer_out_value (out_info, &ret_file_info); out: return ret; }
static gboolean diff_files (OstreeDiffFlags flags, GFile *a, GFileInfo *a_info, GFile *b, GFileInfo *b_info, OstreeDiffItem **out_item, GCancellable *cancellable, GError **error) { g_autofree char *checksum_a = NULL; g_autofree char *checksum_b = NULL; if (!get_file_checksum (flags, a, a_info, &checksum_a, cancellable, error)) return FALSE; if (!get_file_checksum (flags, b, b_info, &checksum_b, cancellable, error)) return FALSE; g_autoptr(OstreeDiffItem) ret_item = NULL; if (strcmp (checksum_a, checksum_b) != 0) { ret_item = diff_item_new (a, a_info, b, b_info, checksum_a, checksum_b); } ot_transfer_out_value(out_item, &ret_item); return TRUE; }
static gboolean parse_file_or_commit (OstreeRepo *repo, const char *arg, GFile **out_file, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; g_autoptr(GFile) ret_file = NULL; if (g_str_has_prefix (arg, "/") || g_str_has_prefix (arg, "./") ) { ret_file = g_file_new_for_path (arg); } else { if (!ostree_repo_read_commit (repo, arg, &ret_file, NULL, cancellable, error)) goto out; } ret = TRUE; ot_transfer_out_value (out_file, &ret_file); out: return ret; }
static gboolean resolve_refspec_fallback (OstreeRepo *self, const char *remote, const char *ref, gboolean allow_noent, char **out_rev, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; g_autofree char *ret_rev = NULL; if (self->parent_repo) { if (!resolve_refspec (self->parent_repo, remote, ref, allow_noent, &ret_rev, error)) goto out; } else if (!allow_noent) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "Refspec '%s%s%s' not found", remote ? remote : "", remote ? ":" : "", ref); goto out; } ret = TRUE; ot_transfer_out_value (out_rev, &ret_rev); out: return ret; }
gboolean ot_keyfile_get_value_with_default_group_optional (GKeyFile *keyfile, const char *section, const char *value, const char *default_value, char **out_value, GError **error) { gboolean ret = FALSE; GError *local_error = NULL; g_autofree char *ret_value = NULL; g_return_val_if_fail (keyfile != NULL, ret); g_return_val_if_fail (section != NULL, ret); g_return_val_if_fail (value != NULL, ret); if (!ot_keyfile_get_value_with_default (keyfile, section, value, default_value, &ret_value, &local_error)) { if (g_error_matches (local_error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) { g_clear_error (&local_error); ret_value = g_strdup (default_value); } else { g_propagate_error (error, local_error); goto out; } } ret = TRUE; ot_transfer_out_value(out_value, &ret_value); out: return ret; }
static gboolean load_remote_repo_config (OtPullData *pull_data, GKeyFile **out_keyfile, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; gs_free char *contents = NULL; GKeyFile *ret_keyfile = NULL; SoupURI *target_uri = NULL; target_uri = suburi_new (pull_data->base_uri, "config", NULL); if (!fetch_uri_contents_utf8_sync (pull_data, target_uri, &contents, cancellable, error)) goto out; ret_keyfile = g_key_file_new (); if (!g_key_file_load_from_data (ret_keyfile, contents, strlen (contents), 0, error)) goto out; ret = TRUE; ot_transfer_out_value (out_keyfile, &ret_keyfile); out: g_clear_pointer (&ret_keyfile, (GDestroyNotify) g_key_file_unref); g_clear_pointer (&target_uri, (GDestroyNotify) soup_uri_free); return ret; }
/** * Read all input from @src, allocating a new #GVariant from it into * output variable @out_variant. @src will be closed as a result. * * Note the returned @out_variant is not floating. */ gboolean ot_util_variant_from_stream (GInputStream *src, const GVariantType *type, gboolean trusted, GVariant **out_variant, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; gs_unref_object GMemoryOutputStream *data_stream = NULL; gs_unref_variant GVariant *ret_variant = NULL; data_stream = (GMemoryOutputStream*)g_memory_output_stream_new (NULL, 0, g_realloc, g_free); if (g_output_stream_splice ((GOutputStream*)data_stream, src, G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, cancellable, error) < 0) goto out; ret_variant = g_variant_new_from_data (type, g_memory_output_stream_get_data (data_stream), g_memory_output_stream_get_data_size (data_stream), trusted, (GDestroyNotify) g_object_unref, data_stream); data_stream = NULL; /* Transfer ownership */ g_variant_ref_sink (ret_variant); ret = TRUE; ot_transfer_out_value (out_variant, &ret_variant); out: return ret; }
gboolean ot_gfile_get_symlink_target_from_info (GFile *path, GFileInfo *file_info, GFile **out_target, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; const char *target; g_autoptr(GFile) path_parent = NULL; g_autoptr(GFile) ret_target = NULL; if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_SYMBOLIC_LINK) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Not a symbolic link"); goto out; } path_parent = g_file_get_parent (path); target = g_file_info_get_symlink_target (file_info); g_assert (target); ret_target = g_file_resolve_relative_path (path_parent, target); ret = TRUE; out: ot_transfer_out_value (out_target, &ret_target); return ret; }
/** * ot_util_variant_map: * @src: a #GFile * @type: Use this for variant * @trusted: See documentation of g_variant_new_from_data() * @out_variant: (out): Return location for new variant * @error: * * Memory-map @src, and store a new #GVariant referring to this memory * in @out_variant. Note the returned @out_variant is not floating. */ gboolean ot_util_variant_map (GFile *src, const GVariantType *type, gboolean trusted, GVariant **out_variant, GError **error) { gboolean ret = FALSE; gs_unref_variant GVariant *ret_variant = NULL; GMappedFile *mfile = NULL; mfile = gs_file_map_noatime (src, NULL, error); if (!mfile) goto out; ret_variant = g_variant_new_from_data (type, g_mapped_file_get_contents (mfile), g_mapped_file_get_length (mfile), trusted, (GDestroyNotify) g_mapped_file_unref, mfile); mfile = NULL; g_variant_ref_sink (ret_variant); ret = TRUE; ot_transfer_out_value(out_variant, &ret_variant); out: if (mfile) g_mapped_file_unref (mfile); return ret; }
static gboolean fetch_ref_contents (OtPullData *pull_data, const char *ref, char **out_contents, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; gs_free char *ret_contents = NULL; SoupURI *target_uri = NULL; target_uri = suburi_new (pull_data->base_uri, "refs", "heads", ref, NULL); if (!fetch_uri_contents_utf8_sync (pull_data, target_uri, &ret_contents, cancellable, error)) goto out; g_strchomp (ret_contents); if (!ostree_validate_checksum_string (ret_contents, error)) goto out; ret = TRUE; ot_transfer_out_value (out_contents, &ret_contents); out: if (target_uri) soup_uri_free (target_uri); return ret; }
static gboolean parse_rev_file (OstreeRepo *self, GFile *f, char **sha256, GError **error) { gboolean ret = FALSE; GError *temp_error = NULL; gs_free char *rev = NULL; if ((rev = gs_file_load_contents_utf8 (f, NULL, &temp_error)) == NULL) goto out; if (rev == NULL) { if (g_error_matches (temp_error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) { g_clear_error (&temp_error); } else { g_propagate_error (error, temp_error); goto out; } } else { g_strchomp (rev); } if (g_str_has_prefix (rev, "ref: ")) { gs_unref_object GFile *ref = NULL; char *ref_sha256; gboolean subret; ref = g_file_resolve_relative_path (self->local_heads_dir, rev + 5); subret = parse_rev_file (self, ref, &ref_sha256, error); if (!subret) { g_free (ref_sha256); goto out; } g_free (rev); rev = ref_sha256; } else { if (!ostree_validate_checksum_string (rev, error)) goto out; } ot_transfer_out_value(sha256, &rev); ret = TRUE; out: return ret; }
static gboolean list_all_deployment_directories (OstreeSysroot *self, GPtrArray **out_deployments, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; gs_unref_object GFileEnumerator *dir_enum = NULL; gs_unref_object GFile *deploydir = NULL; gs_unref_ptrarray GPtrArray *ret_deployments = NULL; GError *temp_error = NULL; deploydir = g_file_resolve_relative_path (self->path, "ostree/deploy"); ret_deployments = g_ptr_array_new_with_free_func (g_object_unref); dir_enum = g_file_enumerate_children (deploydir, OSTREE_GIO_FAST_QUERYINFO, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, cancellable, &temp_error); if (!dir_enum) { if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) { g_clear_error (&temp_error); goto done; } else { g_propagate_error (error, temp_error); goto out; } } while (TRUE) { GFileInfo *file_info = NULL; GFile *child = NULL; if (!gs_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; if (!_ostree_sysroot_list_deployment_dirs_for_os (child, ret_deployments, cancellable, error)) goto out; } done: ret = TRUE; ot_transfer_out_value (out_deployments, &ret_deployments); out: return ret; }
gboolean ostree_content_file_parse (gboolean compressed, GFile *content_path, gboolean trusted, GInputStream **out_input, GFileInfo **out_file_info, GVariant **out_xattrs, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; guint64 length; struct stat stbuf; ot_lobj GInputStream *file_input = NULL; ot_lobj GInputStream *ret_input = NULL; ot_lobj GFileInfo *content_file_info = NULL; ot_lobj GFileInfo *ret_file_info = NULL; ot_lvariant GVariant *ret_xattrs = NULL; file_input = (GInputStream*)gs_file_read_noatime (content_path, cancellable, error); if (!file_input) goto out; if (fstat (g_file_descriptor_based_get_fd ((GFileDescriptorBased*)file_input), &stbuf) < 0) { ot_util_set_error_from_errno (error, errno); goto out; } length = stbuf.st_size; if (!ostree_content_stream_parse (compressed, file_input, length, trusted, out_input ? &ret_input : NULL, &ret_file_info, &ret_xattrs, cancellable, error)) goto out; ret = TRUE; ot_transfer_out_value (out_input, &ret_input); ot_transfer_out_value (out_file_info, &ret_file_info); ot_transfer_out_value (out_xattrs, &ret_xattrs); out: return ret; }
gboolean ostree_get_xattrs_for_file (GFile *f, GVariant **out_xattrs, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; const char *path; ssize_t bytes_read; ot_lvariant GVariant *ret_xattrs = NULL; ot_lfree char *xattr_names = NULL; ot_lfree char *xattr_names_canonical = NULL; GVariantBuilder builder; gboolean builder_initialized = FALSE; path = ot_gfile_get_path_cached (f); g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ayay)")); builder_initialized = TRUE; bytes_read = llistxattr (path, NULL, 0); if (bytes_read < 0) { if (errno != ENOTSUP) { ot_util_set_error_from_errno (error, errno); goto out; } } else if (bytes_read > 0) { xattr_names = g_malloc (bytes_read); if (llistxattr (path, xattr_names, bytes_read) < 0) { ot_util_set_error_from_errno (error, errno); goto out; } xattr_names_canonical = canonicalize_xattrs (xattr_names, bytes_read); if (!read_xattr_name_array (path, xattr_names_canonical, bytes_read, &builder, error)) goto out; } ret_xattrs = g_variant_builder_end (&builder); g_variant_ref_sink (ret_xattrs); ret = TRUE; ot_transfer_out_value (out_xattrs, &ret_xattrs); out: if (!builder_initialized) g_variant_builder_clear (&builder); return ret; }
static gboolean fetch_uri_contents_utf8_sync (OtPullData *pull_data, SoupURI *uri, char **out_contents, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; const guint8 nulchar = 0; gs_free char *ret_contents = NULL; gs_unref_object GMemoryOutputStream *buf = NULL; OstreeFetchUriSyncData fetch_data = { 0, }; if (g_cancellable_set_error_if_cancelled (cancellable, error)) return FALSE; fetch_data.pull_data = pull_data; pull_data->fetching_sync_uri = uri; ostree_fetcher_stream_uri_async (pull_data->fetcher, uri, cancellable, fetch_uri_sync_on_complete, &fetch_data); run_mainloop_monitor_fetcher (pull_data); if (!fetch_data.result_stream) goto out; buf = (GMemoryOutputStream*)g_memory_output_stream_new (NULL, 0, g_realloc, g_free); if (g_output_stream_splice ((GOutputStream*)buf, fetch_data.result_stream, G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE, cancellable, error) < 0) goto out; /* Add trailing NUL */ if (!g_output_stream_write ((GOutputStream*)buf, &nulchar, 1, cancellable, error)) goto out; if (!g_output_stream_close ((GOutputStream*)buf, cancellable, error)) goto out; ret_contents = g_memory_output_stream_steal_data (buf); if (!g_utf8_validate (ret_contents, -1, NULL)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Invalid UTF-8"); goto out; } ret = TRUE; ot_transfer_out_value (out_contents, &ret_contents); out: g_clear_object (&(fetch_data.result_stream)); return ret; }
static gboolean parse_ref_summary (const char *contents, GHashTable **out_refs, GError **error) { gboolean ret = FALSE; gs_unref_hashtable GHashTable *ret_refs = NULL; char **lines = NULL; char **iter = NULL; char *ref = NULL; char *sha256 = NULL; ret_refs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); lines = g_strsplit_set (contents, "\n", -1); for (iter = lines; *iter; iter++) { const char *line = *iter; const char *spc; if (!*line) continue; spc = strchr (line, ' '); if (!spc) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Invalid ref summary file; missing ' ' in line"); goto out; } g_free (ref); ref = g_strdup (spc + 1); if (!ostree_validate_rev (ref, error)) goto out; g_free (sha256); sha256 = g_strndup (line, spc - line); if (!ostree_validate_checksum_string (sha256, error)) goto out; g_hash_table_replace (ret_refs, ref, sha256); /* Transfer ownership */ ref = NULL; sha256 = NULL; } ret = TRUE; ot_transfer_out_value (out_refs, &ret_refs); out: g_strfreev (lines); return ret; }
gboolean ostree_checksum_file_from_input (GFileInfo *file_info, GVariant *xattrs, GInputStream *in, OstreeObjectType objtype, guchar **out_csum, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; ot_lfree guchar *ret_csum = NULL; GChecksum *checksum = NULL; checksum = g_checksum_new (G_CHECKSUM_SHA256); if (OSTREE_OBJECT_TYPE_IS_META (objtype)) { if (!ot_gio_splice_update_checksum (NULL, in, checksum, cancellable, error)) goto out; } else if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY) { ot_lvariant GVariant *dirmeta = ostree_create_directory_metadata (file_info, xattrs); g_checksum_update (checksum, g_variant_get_data (dirmeta), g_variant_get_size (dirmeta)); } else { ot_lvariant GVariant *file_header = NULL; file_header = ostree_file_header_new (file_info, xattrs); if (!ostree_write_file_header_update_checksum (NULL, file_header, checksum, cancellable, error)) goto out; if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR) { if (!ot_gio_splice_update_checksum (NULL, in, checksum, cancellable, error)) goto out; } } ret_csum = ot_csum_from_gchecksum (checksum); ret = TRUE; ot_transfer_out_value (out_csum, &ret_csum); out: g_clear_pointer (&checksum, (GDestroyNotify)g_checksum_free); return ret; }
static gboolean parse_statoverride_file (GHashTable **out_mode_add, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; gsize len; char **iter = NULL; /* nofree */ g_autoptr(GHashTable) ret_hash = NULL; g_autoptr(GFile) path = NULL; g_autofree char *contents = NULL; char **lines = NULL; path = g_file_new_for_path (opt_statoverride_file); if (!g_file_load_contents (path, cancellable, &contents, &len, NULL, error)) goto out; ret_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); lines = g_strsplit (contents, "\n", -1); for (iter = lines; iter && *iter; iter++) { const char *line = *iter; if (*line == '+') { const char *spc; guint mode_add; spc = strchr (line + 1, ' '); if (!spc) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Malformed statoverride file"); goto out; } mode_add = (guint32)(gint32)g_ascii_strtod (line + 1, NULL); g_hash_table_insert (ret_hash, g_strdup (spc + 1), GUINT_TO_POINTER((gint32)mode_add)); } } ret = TRUE; ot_transfer_out_value (out_mode_add, &ret_hash); out: g_strfreev (lines); return ret; }
/** * ostree_repo_resolve_partial_checksum: * @self: Repo * @refspec: A refspec * @full_checksum (out) (transfer full): A full checksum corresponding to the truncated ref given * @error: Error * * Look up the existing refspec checksums. If the given ref is a unique truncated beginning * of a valid checksum it will return that checksum in the parameter @full_checksum */ static gboolean ostree_repo_resolve_partial_checksum (OstreeRepo *self, const char *refspec, char **full_checksum, GError **error) { static const char hexchars[] = "0123456789abcdef"; g_autofree char *ret_rev = NULL; g_return_val_if_fail (error == NULL || *error == NULL, FALSE); /* If the input is longer than OSTREE_SHA256_STRING_LEN chars or contains non-hex chars, don't bother looking for it as an object */ const gsize off = strspn (refspec, hexchars); if (off > OSTREE_SHA256_STRING_LEN || refspec[off] != '\0') return TRUE; /* this looks through all objects and adds them to the ref_list if: a) they are a commit object AND b) the obj checksum starts with the partual checksum defined by "refspec" */ g_autoptr(GHashTable) ref_list = NULL; if (!ostree_repo_list_commit_objects_starting_with (self, refspec, &ref_list, NULL, error)) return FALSE; guint length = g_hash_table_size (ref_list); GHashTableIter hashiter; gpointer key, value; GVariant *first_commit = NULL; g_hash_table_iter_init (&hashiter, ref_list); if (g_hash_table_iter_next (&hashiter, &key, &value)) first_commit = (GVariant*) key; OstreeObjectType objtype; const char *checksum = NULL; if (first_commit) ostree_object_name_deserialize (first_commit, &checksum, &objtype); /* length more than one - multiple commits match partial refspec: is not unique */ if (length > 1) return glnx_throw (error, "Refspec %s not unique", refspec); /* length is 1 - a single matching commit gives us our revision */ else if (length == 1) ret_rev = g_strdup (checksum); /* Note: if length is 0, then code will return TRUE because there is no error, but it will return full_checksum = NULL to signal to continue parsing */ ot_transfer_out_value (full_checksum, &ret_rev); return TRUE; }
gboolean ostree_raw_file_to_content_stream (GInputStream *input, GFileInfo *file_info, GVariant *xattrs, GInputStream **out_input, guint64 *out_length, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; gpointer header_data; gsize header_size; ot_lobj GInputStream *ret_input = NULL; ot_lvariant GVariant *file_header = NULL; ot_lptrarray GPtrArray *streams = NULL; ot_lobj GOutputStream *header_out_stream = NULL; ot_lobj GInputStream *header_in_stream = NULL; file_header = ostree_file_header_new (file_info, xattrs); header_out_stream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free); if (!ostree_write_variant_with_size (header_out_stream, file_header, 0, NULL, NULL, cancellable, error)) goto out; if (!g_output_stream_close (header_out_stream, cancellable, error)) goto out; header_size = g_memory_output_stream_get_data_size ((GMemoryOutputStream*) header_out_stream); header_data = g_memory_output_stream_steal_data ((GMemoryOutputStream*) header_out_stream); header_in_stream = g_memory_input_stream_new_from_data (header_data, header_size, g_free); streams = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref); g_ptr_array_add (streams, g_object_ref (header_in_stream)); if (input) g_ptr_array_add (streams, g_object_ref (input)); ret_input = (GInputStream*)ostree_chain_input_stream_new (streams); ret = TRUE; ot_transfer_out_value (out_input, &ret_input); if (out_length) *out_length = header_size + g_file_info_get_size (file_info); out: return ret; }
gboolean ostree_checksum_file (GFile *f, OstreeObjectType objtype, guchar **out_csum, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; ot_lobj GFileInfo *file_info = NULL; ot_lobj GInputStream *in = NULL; ot_lvariant GVariant *xattrs = NULL; ot_lfree guchar *ret_csum = NULL; if (g_cancellable_set_error_if_cancelled (cancellable, error)) return FALSE; file_info = g_file_query_info (f, OSTREE_GIO_FAST_QUERYINFO, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, cancellable, error); if (!file_info) goto out; if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR) { in = (GInputStream*)g_file_read (f, cancellable, error); if (!in) goto out; } if (objtype == OSTREE_OBJECT_TYPE_FILE) { if (!ostree_get_xattrs_for_file (f, &xattrs, cancellable, error)) goto out; } if (!ostree_checksum_file_from_input (file_info, xattrs, in, objtype, &ret_csum, cancellable, error)) goto out; ret = TRUE; ot_transfer_out_value(out_csum, &ret_csum); out: return ret; }
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; }
static gboolean find_ref_in_remotes (OstreeRepo *self, const char *rev, GFile **out_file, GError **error) { gboolean ret = FALSE; g_autoptr(GFileEnumerator) dir_enum = NULL; g_autoptr(GFile) ret_file = NULL; dir_enum = g_file_enumerate_children (self->remote_heads_dir, OSTREE_GIO_FAST_QUERYINFO, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, error); if (!dir_enum) goto out; while (TRUE) { GFileInfo *file_info; GFile *child; if (!gs_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; g_clear_object (&ret_file); ret_file = g_file_resolve_relative_path (child, rev); if (!g_file_query_exists (ret_file, NULL)) g_clear_object (&ret_file); else break; } ret = TRUE; ot_transfer_out_value (out_file, &ret_file); out: return ret; }
static gboolean get_kernel_path_from_release (const char *release, GFile **out_path, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; ot_lfree char *name = NULL; ot_lobj GFile *possible_path = NULL; /* TODO - replace this with grubby code */ name = g_strconcat ("vmlinuz-", release, NULL); possible_path = ot_gfile_from_build_path ("/boot", name, NULL); if (!g_file_query_exists (possible_path, cancellable)) g_clear_object (&possible_path); ret = TRUE; ot_transfer_out_value (out_path, &possible_path); /* out: */ return ret; }