/** * 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; }
/** * 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; }
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 (!gs_file_enumerator_iterate (direnum, &file_info, &child, cancellable, error)) goto out; if (file_info == NULL) break; g_ptr_array_add (path_parts, (char*)gs_file_get_basename_cached (child)); 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 move_to_dir (GFile *src, GFile *dest_dir, GCancellable *cancellable, GError **error) { gs_unref_object GFile *dest = g_file_get_child (dest_dir, gs_file_get_basename_cached (src)); return gs_file_rename (src, dest, cancellable, error); }
/** * ot_gfile_atomic_symlink_swap: * @path: Replace the contents of this symbolic link * @target: New symbolic link target * @cancellable: * @error * * Create a new temporary symbolic link, then use the Unix rename() * function to atomically replace @path with the new symbolic link. * Do not use this function inside directories such as /tmp as it uses * a predicatable file name. */ gboolean ot_gfile_atomic_symlink_swap (GFile *path, const char *target, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; g_autoptr(GFile) parent = g_file_get_parent (path); g_autofree char *tmpname = g_strconcat (gs_file_get_basename_cached (path), ".tmp", NULL); g_autoptr(GFile) tmppath = g_file_get_child (parent, tmpname); int parent_dfd = -1; if (!ot_gfile_ensure_unlinked (tmppath, cancellable, error)) goto out; if (!g_file_make_symbolic_link (tmppath, target, cancellable, error)) goto out; if (!gs_file_open_dir_fd (parent, &parent_dfd, cancellable, error)) goto out; /* Ensure the link has hit disk */ if (fsync (parent_dfd) != 0) { gs_set_error_from_errno (error, errno); goto out; } if (!gs_file_rename (tmppath, path, cancellable, error)) goto out; /* And sync again for good measure */ if (fsync (parent_dfd) != 0) { gs_set_error_from_errno (error, errno); goto out; } ret = TRUE; out: if (parent_dfd != -1) (void) close (parent_dfd); return ret; }
static gboolean do_kernel_prep (GFile *yumroot, JsonObject *treefile, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; gs_unref_object GFile *bootdir = g_file_get_child (yumroot, "boot"); gs_unref_object GFile *kernel_path = NULL; gs_unref_object GFile *initramfs_path = NULL; const char *boot_checksum_str = NULL; GChecksum *boot_checksum = NULL; g_autofree char *kver = NULL; if (!find_kernel_and_initramfs_in_bootdir (bootdir, &kernel_path, &initramfs_path, cancellable, error)) goto out; if (kernel_path == NULL) { gs_unref_object GFile *mod_dir = g_file_resolve_relative_path (yumroot, "usr/lib/modules"); gs_unref_object GFile *modversion_dir = NULL; if (!find_ensure_one_subdirectory (mod_dir, &modversion_dir, cancellable, error)) goto out; if (modversion_dir) { kver = g_file_get_basename (modversion_dir); if (!find_kernel_and_initramfs_in_bootdir (modversion_dir, &kernel_path, &initramfs_path, cancellable, error)) goto out; } } if (kernel_path == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Unable to find kernel (vmlinuz) in /boot or /usr/lib/modules"); goto out; } if (initramfs_path) { g_print ("Removing RPM-generated '%s'\n", gs_file_get_path_cached (initramfs_path)); if (!gs_shutil_rm_rf (initramfs_path, cancellable, error)) goto out; } if (!kver) { const char *kname = gs_file_get_basename_cached (kernel_path); const char *kver_p; kver_p = strchr (kname, '-'); g_assert (kver_p); kver = g_strdup (kver_p + 1); } /* OSTree needs to own this */ { gs_unref_object GFile *loaderdir = g_file_get_child (bootdir, "loader"); if (!gs_shutil_rm_rf (loaderdir, cancellable, error)) goto out; } { char *child_argv[] = { "depmod", (char*)kver, NULL }; if (!run_sync_in_root (yumroot, "depmod", child_argv, error)) goto out; } /* Ensure the /etc/machine-id file is present and empty. Apparently systemd doesn't work when the file is missing (as of systemd-219-9.fc22) but it is correctly populated if the file is there. */ g_print ("Creating empty machine-id\n"); { const char *hardcoded_machine_id = ""; gs_unref_object GFile *machineid_path = g_file_resolve_relative_path (yumroot, "etc/machine-id"); if (!g_file_replace_contents (machineid_path, hardcoded_machine_id, strlen (hardcoded_machine_id), NULL, FALSE, 0, NULL, cancellable, error)) goto out; } { gboolean reproducible; gs_unref_ptrarray GPtrArray *dracut_argv = g_ptr_array_new (); if (!dracut_supports_reproducible (yumroot, &reproducible, cancellable, error)) goto out; g_ptr_array_add (dracut_argv, "dracut"); g_ptr_array_add (dracut_argv, "-v"); if (reproducible) { g_ptr_array_add (dracut_argv, "--reproducible"); g_ptr_array_add (dracut_argv, "--gzip"); } g_ptr_array_add (dracut_argv, "--tmpdir=/tmp"); g_ptr_array_add (dracut_argv, "-f"); g_ptr_array_add (dracut_argv, "/var/tmp/initramfs.img"); g_ptr_array_add (dracut_argv, (char*)kver); if (json_object_has_member (treefile, "initramfs-args")) { guint i, len; JsonArray *initramfs_args; initramfs_args = json_object_get_array_member (treefile, "initramfs-args"); len = json_array_get_length (initramfs_args); for (i = 0; i < len; i++) { const char *arg = _rpmostree_jsonutil_array_require_string_element (initramfs_args, i, error); if (!arg) goto out; g_ptr_array_add (dracut_argv, (char*)arg); } } g_ptr_array_add (dracut_argv, NULL); if (!run_sync_in_root (yumroot, "dracut", (char**)dracut_argv->pdata, error)) goto out; } initramfs_path = g_file_resolve_relative_path (yumroot, "var/tmp/initramfs.img"); if (!g_file_query_exists (initramfs_path, NULL)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Dracut failed to generate '%s'", gs_file_get_path_cached (initramfs_path)); goto out; } { gs_free char *initramfs_name = g_strconcat ("initramfs-", kver, ".img", NULL); gs_unref_object GFile *initramfs_dest = g_file_get_child (bootdir, initramfs_name); if (!gs_file_rename (initramfs_path, initramfs_dest, cancellable, error)) goto out; /* Transfer ownership */ g_object_unref (initramfs_path); initramfs_path = initramfs_dest; initramfs_dest = NULL; } boot_checksum = g_checksum_new (G_CHECKSUM_SHA256); if (!_rpmostree_util_update_checksum_from_file (boot_checksum, kernel_path, cancellable, error)) goto out; if (!_rpmostree_util_update_checksum_from_file (boot_checksum, initramfs_path, cancellable, error)) goto out; boot_checksum_str = g_checksum_get_string (boot_checksum); { gs_free char *new_kernel_name = g_strconcat (gs_file_get_basename_cached (kernel_path), "-", boot_checksum_str, NULL); gs_unref_object GFile *new_kernel_path = g_file_get_child (bootdir, new_kernel_name); gs_free char *new_initramfs_name = g_strconcat (gs_file_get_basename_cached (initramfs_path), "-", boot_checksum_str, NULL); gs_unref_object GFile *new_initramfs_path = g_file_get_child (bootdir, new_initramfs_name); if (!gs_file_rename (kernel_path, new_kernel_path, cancellable, error)) goto out; if (!gs_file_rename (initramfs_path, new_initramfs_path, cancellable, error)) goto out; } ret = TRUE; out: if (boot_checksum) g_checksum_free (boot_checksum); return ret; }
gboolean rpmostree_treefile_postprocessing (GFile *yumroot, GFile *context_directory, GBytes *serialized_treefile, JsonObject *treefile, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; guint i, len; JsonArray *units = NULL; JsonArray *remove = NULL; const char *default_target = NULL; const char *postprocess_script = NULL; if (json_object_has_member (treefile, "units")) units = json_object_get_array_member (treefile, "units"); if (units) len = json_array_get_length (units); else len = 0; { gs_unref_object GFile *multiuser_wants_dir = g_file_resolve_relative_path (yumroot, "etc/systemd/system/multi-user.target.wants"); if (!gs_file_ensure_directory (multiuser_wants_dir, TRUE, cancellable, error)) goto out; for (i = 0; i < len; i++) { const char *unitname = _rpmostree_jsonutil_array_require_string_element (units, i, error); gs_unref_object GFile *unit_link_target = NULL; gs_free char *symlink_target = NULL; if (!unitname) goto out; symlink_target = g_strconcat ("/usr/lib/systemd/system/", unitname, NULL); unit_link_target = g_file_get_child (multiuser_wants_dir, unitname); if (g_file_query_file_type (unit_link_target, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL) == G_FILE_TYPE_SYMBOLIC_LINK) continue; g_print ("Adding %s to multi-user.target.wants\n", unitname); if (!g_file_make_symbolic_link (unit_link_target, symlink_target, cancellable, error)) goto out; } } { gs_unref_object GFile *target_treefile_dir_path = g_file_resolve_relative_path (yumroot, "usr/share/rpm-ostree"); gs_unref_object GFile *target_treefile_path = g_file_get_child (target_treefile_dir_path, "treefile.json"); const guint8 *buf; gsize len; if (!gs_file_ensure_directory (target_treefile_dir_path, TRUE, cancellable, error)) goto out; g_print ("Writing '%s'\n", gs_file_get_path_cached (target_treefile_path)); buf = g_bytes_get_data (serialized_treefile, &len); if (!g_file_replace_contents (target_treefile_path, (char*)buf, len, NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, cancellable, error)) goto out; } if (!_rpmostree_jsonutil_object_get_optional_string_member (treefile, "default_target", &default_target, error)) goto out; if (default_target != NULL) { gs_unref_object GFile *default_target_path = g_file_resolve_relative_path (yumroot, "etc/systemd/system/default.target"); gs_free char *dest_default_target_path = g_strconcat ("/usr/lib/systemd/system/", default_target, NULL); (void) gs_file_unlink (default_target_path, NULL, NULL); if (!g_file_make_symbolic_link (default_target_path, dest_default_target_path, cancellable, error)) goto out; } if (json_object_has_member (treefile, "remove-files")) { remove = json_object_get_array_member (treefile, "remove-files"); len = json_array_get_length (remove); } else len = 0; for (i = 0; i < len; i++) { const char *val = _rpmostree_jsonutil_array_require_string_element (remove, i, error); gs_unref_object GFile *child = NULL; if (!val) return FALSE; if (g_path_is_absolute (val)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "'remove' elements must be relative"); goto out; } child = g_file_resolve_relative_path (yumroot, val); if (g_file_query_exists (child, NULL)) { g_print ("Removing '%s'\n", val); if (!gs_shutil_rm_rf (child, cancellable, error)) goto out; } else { g_printerr ("warning: Targeted path for remove-files does not exist: %s\n", gs_file_get_path_cached (child)); } } if (json_object_has_member (treefile, "remove-from-packages")) { g_autoptr(RpmOstreeRefSack) refsack = NULL; _cleanup_hypackagelist_ HyPackageList pkglist = NULL; guint i; remove = json_object_get_array_member (treefile, "remove-from-packages"); len = json_array_get_length (remove); if (!rpmostree_get_pkglist_for_root (AT_FDCWD, gs_file_get_path_cached (yumroot), &refsack, &pkglist, cancellable, error)) { g_prefix_error (error, "Reading package set: "); goto out; } for (i = 0; i < len; i++) { JsonArray *elt = json_array_get_array_element (remove, i); if (!handle_remove_files_from_package (yumroot, refsack, elt, cancellable, error)) goto out; } } if (!_rpmostree_jsonutil_object_get_optional_string_member (treefile, "postprocess-script", &postprocess_script, error)) goto out; if (postprocess_script) { const char *yumroot_path = gs_file_get_path_cached (yumroot); gs_unref_object GFile *src = g_file_resolve_relative_path (context_directory, postprocess_script); const char *bn = gs_file_get_basename_cached (src); gs_free char *binpath = g_strconcat ("/usr/bin/rpmostree-postprocess-", bn, NULL); gs_free char *destpath = g_strconcat (yumroot_path, binpath, NULL); gs_unref_object GFile *dest = g_file_new_for_path (destpath); /* Clone all the things */ if (!g_file_copy (src, dest, 0, cancellable, NULL, NULL, error)) { g_prefix_error (error, "Copying postprocess-script '%s' into target: ", bn); goto out; } g_print ("Executing postprocessing script '%s'\n", bn); { char *child_argv[] = { binpath, NULL }; if (!run_sync_in_root (yumroot, binpath, child_argv, error)) { g_prefix_error (error, "While executing postprocessing script '%s': ", bn); goto out; } } g_print ("Finished postprocessing script '%s'\n", bn); } ret = TRUE; out: return ret; }
static gboolean cleanup_old_deployments (OstreeSysroot *self, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; guint32 root_device; guint64 root_inode; guint i; gs_unref_object GFile *active_root = g_file_new_for_path ("/"); gs_unref_hashtable GHashTable *active_deployment_dirs = NULL; gs_unref_hashtable GHashTable *active_boot_checksums = NULL; gs_unref_ptrarray GPtrArray *all_deployment_dirs = NULL; gs_unref_ptrarray GPtrArray *all_boot_dirs = NULL; if (!_ostree_sysroot_get_devino (active_root, &root_device, &root_inode, cancellable, error)) goto out; active_deployment_dirs = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL); active_boot_checksums = g_hash_table_new_full (g_str_hash, (GEqualFunc)g_str_equal, g_free, NULL); for (i = 0; i < self->deployments->len; i++) { OstreeDeployment *deployment = self->deployments->pdata[i]; GFile *deployment_path = ostree_sysroot_get_deployment_directory (self, deployment); char *bootcsum = g_strdup (ostree_deployment_get_bootcsum (deployment)); /* Transfer ownership */ g_hash_table_replace (active_deployment_dirs, deployment_path, deployment_path); g_hash_table_replace (active_boot_checksums, bootcsum, bootcsum); } if (!list_all_deployment_directories (self, &all_deployment_dirs, cancellable, error)) goto out; for (i = 0; i < all_deployment_dirs->len; i++) { OstreeDeployment *deployment = all_deployment_dirs->pdata[i]; gs_unref_object GFile *deployment_path = ostree_sysroot_get_deployment_directory (self, deployment); gs_unref_object GFile *origin_path = ostree_sysroot_get_deployment_origin_path (deployment_path); if (!g_hash_table_lookup (active_deployment_dirs, deployment_path)) { guint32 device; guint64 inode; if (!_ostree_sysroot_get_devino (deployment_path, &device, &inode, cancellable, error)) goto out; /* This shouldn't happen, because higher levels should * disallow having the booted deployment not in the active * deployment list, but let's be extra safe. */ if (device == root_device && inode == root_inode) continue; if (!gs_shutil_rm_rf (deployment_path, cancellable, error)) goto out; if (!gs_shutil_rm_rf (origin_path, cancellable, error)) goto out; } } if (!list_all_boot_directories (self, &all_boot_dirs, cancellable, error)) goto out; for (i = 0; i < all_boot_dirs->len; i++) { GFile *bootdir = all_boot_dirs->pdata[i]; gs_free char *osname = NULL; gs_free char *bootcsum = NULL; if (!parse_bootdir_name (gs_file_get_basename_cached (bootdir), &osname, &bootcsum)) g_assert_not_reached (); if (g_hash_table_lookup (active_boot_checksums, bootcsum)) continue; if (!gs_shutil_rm_rf (bootdir, cancellable, error)) goto out; } ret = TRUE; out: return ret; }
gboolean _ostree_sysroot_list_deployment_dirs_for_os (GFile *osdir, GPtrArray *inout_deployments, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; const char *osname = gs_file_get_basename_cached (osdir); gs_unref_object GFileEnumerator *dir_enum = NULL; gs_unref_object GFile *osdeploy_dir = NULL; GError *temp_error = NULL; osdeploy_dir = g_file_get_child (osdir, "deploy"); dir_enum = g_file_enumerate_children (osdeploy_dir, OSTREE_GIO_FAST_QUERYINFO, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &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) { const char *name; GFileInfo *file_info = NULL; GFile *child = NULL; gs_unref_object OstreeDeployment *deployment = NULL; gs_free char *csum = NULL; gint deployserial; if (!gs_file_enumerator_iterate (dir_enum, &file_info, &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) continue; if (!_ostree_sysroot_parse_deploy_path_name (name, &csum, &deployserial, error)) goto out; deployment = ostree_deployment_new (-1, osname, csum, deployserial, NULL, -1); g_ptr_array_add (inout_deployments, g_object_ref (deployment)); } done: ret = TRUE; out: return ret; }
static gboolean do_kernel_prep (GFile *yumroot, JsonObject *treefile, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; gs_unref_object GFile *bootdir = g_file_get_child (yumroot, "boot"); gs_unref_object GFile *kernel_path = NULL; gs_unref_object GFile *initramfs_path = NULL; const char *boot_checksum_str = NULL; GChecksum *boot_checksum = NULL; const char *kname; const char *kver; if (!find_kernel_and_initramfs_in_bootdir (bootdir, &kernel_path, &initramfs_path, cancellable, error)) goto out; if (initramfs_path) { g_print ("Removing RPM-generated '%s'\n", gs_file_get_path_cached (initramfs_path)); if (!gs_shutil_rm_rf (initramfs_path, cancellable, error)) goto out; } kname = gs_file_get_basename_cached (kernel_path); kver = strchr (kname, '-'); g_assert (kver); kver += 1; /* OSTree needs to own this */ { gs_unref_object GFile *loaderdir = g_file_get_child (bootdir, "loader"); if (!gs_shutil_rm_rf (loaderdir, cancellable, error)) goto out; } { char *child_argv[] = { "depmod", (char*)kver, NULL }; if (!run_sync_in_root (yumroot, "/usr/sbin/depmod", child_argv, error)) goto out; } /* Copy of code from gnome-continuous; yes, we hardcode the machine id for now, because distributing pre-generated initramfs images with dracut/systemd at the moment effectively requires this. http://lists.freedesktop.org/archives/systemd-devel/2013-July/011770.html */ g_print ("Hardcoding machine-id\n"); { const char *hardcoded_machine_id = "45bb3b96146aa94f299b9eb43646eb35\n"; gs_unref_object GFile *machineid_path = g_file_resolve_relative_path (yumroot, "etc/machine-id"); if (!g_file_replace_contents (machineid_path, hardcoded_machine_id, strlen (hardcoded_machine_id), NULL, FALSE, 0, NULL, cancellable, error)) goto out; } { gs_unref_ptrarray GPtrArray *dracut_argv = g_ptr_array_new (); g_ptr_array_add (dracut_argv, "dracut"); g_ptr_array_add (dracut_argv, "-v"); g_ptr_array_add (dracut_argv, "--tmpdir=/tmp"); g_ptr_array_add (dracut_argv, "-f"); g_ptr_array_add (dracut_argv, "/var/tmp/initramfs.img"); g_ptr_array_add (dracut_argv, (char*)kver); if (json_object_has_member (treefile, "initramfs-args")) { guint i, len; JsonArray *initramfs_args; initramfs_args = json_object_get_array_member (treefile, "initramfs-args"); len = json_array_get_length (initramfs_args); for (i = 0; i < len; i++) { const char *arg = _rpmostree_jsonutil_array_require_string_element (initramfs_args, i, error); if (!arg) goto out; g_ptr_array_add (dracut_argv, (char*)arg); } } g_ptr_array_add (dracut_argv, NULL); if (!run_sync_in_root (yumroot, "/usr/sbin/dracut", (char**)dracut_argv->pdata, error)) goto out; } initramfs_path = g_file_resolve_relative_path (yumroot, "var/tmp/initramfs.img"); if (!g_file_query_exists (initramfs_path, NULL)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Dracut failed to generate '%s'", gs_file_get_path_cached (initramfs_path)); goto out; } { gs_free char *initramfs_name = g_strconcat ("initramfs-", kver, ".img", NULL); gs_unref_object GFile *initramfs_dest = g_file_get_child (bootdir, initramfs_name); if (!gs_file_rename (initramfs_path, initramfs_dest, cancellable, error)) goto out; /* Transfer ownership */ g_object_unref (initramfs_path); initramfs_path = initramfs_dest; initramfs_dest = NULL; } boot_checksum = g_checksum_new (G_CHECKSUM_SHA256); if (!_rpmostree_util_update_checksum_from_file (boot_checksum, kernel_path, cancellable, error)) goto out; if (!_rpmostree_util_update_checksum_from_file (boot_checksum, initramfs_path, cancellable, error)) goto out; boot_checksum_str = g_checksum_get_string (boot_checksum); { gs_free char *new_kernel_name = g_strconcat (gs_file_get_basename_cached (kernel_path), "-", boot_checksum_str, NULL); gs_unref_object GFile *new_kernel_path = g_file_get_child (bootdir, new_kernel_name); gs_free char *new_initramfs_name = g_strconcat (gs_file_get_basename_cached (initramfs_path), "-", boot_checksum_str, NULL); gs_unref_object GFile *new_initramfs_path = g_file_get_child (bootdir, new_initramfs_name); if (!gs_file_rename (kernel_path, new_kernel_path, cancellable, error)) goto out; if (!gs_file_rename (initramfs_path, new_initramfs_path, cancellable, error)) goto out; } ret = TRUE; out: if (boot_checksum) g_checksum_free (boot_checksum); return ret; }
/** * ostree_repo_list_static_delta_names: * @self: Repo * @out_deltas: (out) (element-type utf8): 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; gs_unref_ptrarray GPtrArray *ret_deltas = NULL; gs_unref_object 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) { gs_unref_object GFileEnumerator *dir_enum2 = NULL; 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; 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 (!gs_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 = gs_file_get_basename_cached (child); name2 = gs_file_get_basename_cached (child2); { gs_unref_object GFile *meta_path = g_file_get_child (child2, "superblock"); if (g_file_query_exists (meta_path, NULL)) { gs_free char *buf = g_strconcat (name1, name2, NULL); GString *out = g_string_new (""); char checksum[65]; guchar csum[32]; 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; gs_transfer_out_value (out_deltas, &ret_deltas); out: return ret; }