From 91b6e5ded69ed03feb89ec7167007285dca9aa10 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Thu, 13 Apr 2023 17:22:37 -0400 Subject: lib/sysroot-cleanup: Convert bootdir listing to dfd-relative No functional change. --- src/libostree/ostree-sysroot-cleanup.c | 79 +++++++++++----------------------- 1 file changed, 25 insertions(+), 54 deletions(-) diff --git a/src/libostree/ostree-sysroot-cleanup.c b/src/libostree/ostree-sysroot-cleanup.c index 181dbd16..2b5c3e68 100644 --- a/src/libostree/ostree-sysroot-cleanup.c +++ b/src/libostree/ostree-sysroot-cleanup.c @@ -138,67 +138,40 @@ parse_bootdir_name (const char *name, static gboolean list_all_boot_directories (OstreeSysroot *self, - GPtrArray **out_bootdirs, + char ***out_bootdirs, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - g_autoptr(GFile) boot_ostree = NULL; - g_autoptr(GPtrArray) ret_bootdirs = NULL; - GError *temp_error = NULL; + g_autoptr(GPtrArray) ret_bootdirs = g_ptr_array_new_with_free_func (g_free); - boot_ostree = g_file_resolve_relative_path (self->path, "boot/ostree"); - - ret_bootdirs = g_ptr_array_new_with_free_func (g_object_unref); - - g_autoptr(GFileEnumerator) dir_enum = - g_file_enumerate_children (boot_ostree, 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; - } - } + gboolean exists = FALSE; + g_auto(GLnxDirFdIterator) dfd_iter = { 0, }; + if (self->boot_fd >= 0 && !ot_dfd_iter_init_allow_noent (self->boot_fd, "ostree", &dfd_iter, &exists, error)) + return FALSE; - while (TRUE) + while (exists) { - GFileInfo *file_info = NULL; - GFile *child = NULL; - const char *name; - - if (!g_file_enumerator_iterate (dir_enum, &file_info, &child, - NULL, error)) - goto out; - if (file_info == NULL) + struct dirent *dent; + if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, cancellable, error)) + return FALSE; + if (dent == NULL) break; - if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_DIRECTORY) + if (dent->d_type != DT_DIR) continue; /* Only look at directories ending in -CHECKSUM; nothing else * should be in here, but let's be conservative. */ - name = g_file_info_get_name (file_info); - if (!parse_bootdir_name (name, NULL, NULL)) + if (!parse_bootdir_name (dent->d_name, NULL, NULL)) continue; - g_ptr_array_add (ret_bootdirs, g_object_ref (child)); + g_ptr_array_add (ret_bootdirs, g_strdup (dent->d_name)); } - done: - ret = TRUE; - ot_transfer_out_value (out_bootdirs, &ret_bootdirs); - out: - return ret; + g_ptr_array_add (ret_bootdirs, NULL); + *out_bootdirs = (char**)g_ptr_array_free (g_steal_pointer (&ret_bootdirs), FALSE); + return TRUE; } /* A sysroot has at most one active "boot version" (pair of version,subversion) @@ -332,25 +305,23 @@ cleanup_old_deployments (OstreeSysroot *self, } /* Clean up boot directories */ - g_autoptr(GPtrArray) all_boot_dirs = NULL; - if (!list_all_boot_directories (self, &all_boot_dirs, - cancellable, error)) + g_auto(GStrv) all_boot_dirs = NULL; + if (!list_all_boot_directories (self, &all_boot_dirs, cancellable, error)) return FALSE; - for (guint i = 0; i < all_boot_dirs->len; i++) + for (char **it = all_boot_dirs; it && *it; it++) { - GFile *bootdir = all_boot_dirs->pdata[i]; - g_autofree char *osname = NULL; + char *bootdir = *it; g_autofree char *bootcsum = NULL; - if (!parse_bootdir_name (glnx_basename (gs_file_get_path_cached (bootdir)), - &osname, &bootcsum)) - g_assert_not_reached (); + if (!parse_bootdir_name (bootdir, NULL, &bootcsum)) + g_assert_not_reached (); /* checked in list_all_boot_directories() */ if (g_hash_table_lookup (active_boot_checksums, bootcsum)) continue; - if (!glnx_shutil_rm_rf_at (AT_FDCWD, gs_file_get_path_cached (bootdir), cancellable, error)) + g_autofree char *subpath = g_build_filename ("ostree", bootdir, NULL); + if (!glnx_shutil_rm_rf_at (self->boot_fd, subpath, cancellable, error)) return FALSE; } -- cgit v1.2.1 From 898b1fdc705cc7829a188a7f6351cbbf37fc237f Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Thu, 13 Apr 2023 17:22:38 -0400 Subject: lib/sysroot-cleanup: Make some static utility functions global Prep for future patch. --- src/libostree/ostree-sysroot-cleanup.c | 26 +++++++++++++------------- src/libostree/ostree-sysroot-private.h | 9 +++++++++ 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/libostree/ostree-sysroot-cleanup.c b/src/libostree/ostree-sysroot-cleanup.c index 2b5c3e68..619831d0 100644 --- a/src/libostree/ostree-sysroot-cleanup.c +++ b/src/libostree/ostree-sysroot-cleanup.c @@ -108,10 +108,10 @@ list_all_deployment_directories (OstreeSysroot *self, return TRUE; } -static gboolean -parse_bootdir_name (const char *name, - char **out_osname, - char **out_csum) +gboolean +_ostree_sysroot_parse_bootdir_name (const char *name, + char **out_osname, + char **out_csum) { const char *lastdash; @@ -136,11 +136,11 @@ parse_bootdir_name (const char *name, return TRUE; } -static gboolean -list_all_boot_directories (OstreeSysroot *self, - char ***out_bootdirs, - GCancellable *cancellable, - GError **error) +gboolean +_ostree_sysroot_list_all_boot_directories (OstreeSysroot *self, + char ***out_bootdirs, + GCancellable *cancellable, + GError **error) { g_autoptr(GPtrArray) ret_bootdirs = g_ptr_array_new_with_free_func (g_free); @@ -163,7 +163,7 @@ list_all_boot_directories (OstreeSysroot *self, /* Only look at directories ending in -CHECKSUM; nothing else * should be in here, but let's be conservative. */ - if (!parse_bootdir_name (dent->d_name, NULL, NULL)) + if (!_ostree_sysroot_parse_bootdir_name (dent->d_name, NULL, NULL)) continue; g_ptr_array_add (ret_bootdirs, g_strdup (dent->d_name)); @@ -306,7 +306,7 @@ cleanup_old_deployments (OstreeSysroot *self, /* Clean up boot directories */ g_auto(GStrv) all_boot_dirs = NULL; - if (!list_all_boot_directories (self, &all_boot_dirs, cancellable, error)) + if (!_ostree_sysroot_list_all_boot_directories (self, &all_boot_dirs, cancellable, error)) return FALSE; for (char **it = all_boot_dirs; it && *it; it++) @@ -314,8 +314,8 @@ cleanup_old_deployments (OstreeSysroot *self, char *bootdir = *it; g_autofree char *bootcsum = NULL; - if (!parse_bootdir_name (bootdir, NULL, &bootcsum)) - g_assert_not_reached (); /* checked in list_all_boot_directories() */ + if (!_ostree_sysroot_parse_bootdir_name (bootdir, NULL, &bootcsum)) + g_assert_not_reached (); /* checked in _ostree_sysroot_list_all_boot_directories() */ if (g_hash_table_lookup (active_boot_checksums, bootcsum)) continue; diff --git a/src/libostree/ostree-sysroot-private.h b/src/libostree/ostree-sysroot-private.h index a49a406c..dfa649cb 100644 --- a/src/libostree/ostree-sysroot-private.h +++ b/src/libostree/ostree-sysroot-private.h @@ -187,4 +187,13 @@ gboolean _ostree_sysroot_cleanup_internal (OstreeSysroot *sysroot, GCancellable *cancellable, GError **error); +gboolean _ostree_sysroot_parse_bootdir_name (const char *name, + char **out_osname, + char **out_csum); + +gboolean _ostree_sysroot_list_all_boot_directories (OstreeSysroot *self, + char ***out_bootdirs, + GCancellable *cancellable, + GError **error); + G_END_DECLS -- cgit v1.2.1 From 49eb8c04d547e9cc3cfcca4e0571deedd9f36040 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Thu, 13 Apr 2023 17:22:39 -0400 Subject: lib/sysroot-cleanup: Drop dead code We weren't actually using this `stbuf` anywhere. --- src/libostree/ostree-sysroot-cleanup.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/libostree/ostree-sysroot-cleanup.c b/src/libostree/ostree-sysroot-cleanup.c index 619831d0..d8347f45 100644 --- a/src/libostree/ostree-sysroot-cleanup.c +++ b/src/libostree/ostree-sysroot-cleanup.c @@ -257,13 +257,6 @@ cleanup_old_deployments (OstreeSysroot *self, GCancellable *cancellable, GError **error) { - /* Gather the device/inode of the rootfs, so we can double - * check we won't delete it. - */ - struct stat root_stbuf; - if (!glnx_fstatat (AT_FDCWD, "/", &root_stbuf, 0, error)) - return FALSE; - /* Load all active deployments referenced by bootloader configuration. */ g_autoptr(GHashTable) active_deployment_dirs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); -- cgit v1.2.1 From bf974e32fcd2b484ae440891a499a7d353489483 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Thu, 13 Apr 2023 17:22:40 -0400 Subject: lib/sysroot-cleanup: Factor out bootfs cleanup Crawling through the bootfs and the deployment dirs was already mostly separate. The only inefficiency here is that we now iterate over the array of active deployments twice when building the hash tables. No functional change otherwise. Prep for future patch. --- src/libostree/ostree-sysroot-cleanup.c | 43 +++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/src/libostree/ostree-sysroot-cleanup.c b/src/libostree/ostree-sysroot-cleanup.c index d8347f45..2fc2ffb4 100644 --- a/src/libostree/ostree-sysroot-cleanup.c +++ b/src/libostree/ostree-sysroot-cleanup.c @@ -260,23 +260,12 @@ cleanup_old_deployments (OstreeSysroot *self, /* Load all active deployments referenced by bootloader configuration. */ g_autoptr(GHashTable) active_deployment_dirs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - g_autoptr(GHashTable) active_boot_checksums = - g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - g_autoptr(GHashTable) active_overlay_initrds = - g_hash_table_new (g_str_hash, g_str_equal); /* borrows from deployment's bootconfig */ for (guint i = 0; i < self->deployments->len; i++) { OstreeDeployment *deployment = self->deployments->pdata[i]; char *deployment_path = ostree_sysroot_get_deployment_dirpath (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); - - OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (deployment); - char **initrds = ostree_bootconfig_parser_get_overlay_initrds (bootconfig); - for (char **it = initrds; it && *it; it++) - g_hash_table_add (active_overlay_initrds, (char*)glnx_basename (*it)); } /* Find all deployment directories, both active and inactive */ @@ -297,6 +286,35 @@ cleanup_old_deployments (OstreeSysroot *self, return FALSE; } + return TRUE; +} + +/* This function deletes any files in the bootfs unreferenced by the active + * bootloader configuration. + */ +static gboolean +cleanup_bootfs (OstreeSysroot *self, + GCancellable *cancellable, + GError **error) +{ + /* Load all active bootcsums and overlays referenced by bootloader configuration. */ + g_autoptr(GHashTable) active_boot_checksums = + g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + g_autoptr(GHashTable) active_overlay_initrds = + g_hash_table_new (g_str_hash, g_str_equal); /* borrows from deployment's bootconfig */ + for (guint i = 0; i < self->deployments->len; i++) + { + OstreeDeployment *deployment = self->deployments->pdata[i]; + char *bootcsum = g_strdup (ostree_deployment_get_bootcsum (deployment)); + /* Transfer ownership */ + g_hash_table_replace (active_boot_checksums, bootcsum, bootcsum); + + OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (deployment); + char **initrds = ostree_bootconfig_parser_get_overlay_initrds (bootconfig); + for (char **it = initrds; it && *it; it++) + g_hash_table_add (active_overlay_initrds, (char*)glnx_basename (*it)); + } + /* Clean up boot directories */ g_auto(GStrv) all_boot_dirs = NULL; if (!_ostree_sysroot_list_all_boot_directories (self, &all_boot_dirs, cancellable, error)) @@ -554,6 +572,9 @@ _ostree_sysroot_cleanup_internal (OstreeSysroot *self, if (!cleanup_old_deployments (self, cancellable, error)) return glnx_prefix_error (error, "Cleaning deployments"); + if (!cleanup_bootfs (self, cancellable, error)) + return glnx_prefix_error (error, "Cleaning bootfs"); + OstreeRepo *repo = ostree_sysroot_repo (self); if (!generate_deployment_refs (self, repo, self->bootversion, -- cgit v1.2.1 From a0681cd20190d96311738e50334426f218d96214 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Thu, 13 Apr 2023 17:22:41 -0400 Subject: lib/sysroot-cleanup: Make bootfs cleanup function global Prep for future patch. --- src/libostree/ostree-sysroot-cleanup.c | 10 +++++----- src/libostree/ostree-sysroot-private.h | 5 +++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/libostree/ostree-sysroot-cleanup.c b/src/libostree/ostree-sysroot-cleanup.c index 2fc2ffb4..533a4fdd 100644 --- a/src/libostree/ostree-sysroot-cleanup.c +++ b/src/libostree/ostree-sysroot-cleanup.c @@ -292,10 +292,10 @@ cleanup_old_deployments (OstreeSysroot *self, /* This function deletes any files in the bootfs unreferenced by the active * bootloader configuration. */ -static gboolean -cleanup_bootfs (OstreeSysroot *self, - GCancellable *cancellable, - GError **error) +gboolean +_ostree_sysroot_cleanup_bootfs (OstreeSysroot *self, + GCancellable *cancellable, + GError **error) { /* Load all active bootcsums and overlays referenced by bootloader configuration. */ g_autoptr(GHashTable) active_boot_checksums = @@ -572,7 +572,7 @@ _ostree_sysroot_cleanup_internal (OstreeSysroot *self, if (!cleanup_old_deployments (self, cancellable, error)) return glnx_prefix_error (error, "Cleaning deployments"); - if (!cleanup_bootfs (self, cancellable, error)) + if (!_ostree_sysroot_cleanup_bootfs (self, cancellable, error)) return glnx_prefix_error (error, "Cleaning bootfs"); OstreeRepo *repo = ostree_sysroot_repo (self); diff --git a/src/libostree/ostree-sysroot-private.h b/src/libostree/ostree-sysroot-private.h index dfa649cb..57ac6824 100644 --- a/src/libostree/ostree-sysroot-private.h +++ b/src/libostree/ostree-sysroot-private.h @@ -187,6 +187,11 @@ gboolean _ostree_sysroot_cleanup_internal (OstreeSysroot *sysroot, GCancellable *cancellable, GError **error); +gboolean +_ostree_sysroot_cleanup_bootfs (OstreeSysroot *self, + GCancellable *cancellable, + GError **error); + gboolean _ostree_sysroot_parse_bootdir_name (const char *name, char **out_osname, char **out_csum); -- cgit v1.2.1 From 462d413d2e8ef4e8196ac99c142dd165086f7b69 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Thu, 13 Apr 2023 17:22:42 -0400 Subject: libotutil: add utility functions for calculating directory size Prep for future patch. --- src/libotutil/ot-fs-utils.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/libotutil/ot-fs-utils.h | 7 +++++++ 2 files changed, 51 insertions(+) diff --git a/src/libotutil/ot-fs-utils.c b/src/libotutil/ot-fs-utils.c index 64ebc966..935b1bbc 100644 --- a/src/libotutil/ot-fs-utils.c +++ b/src/libotutil/ot-fs-utils.c @@ -245,3 +245,47 @@ ot_parse_file_by_line (const char *path, return TRUE; } + +/* Calculate the size of the files contained in a directory. Symlinks are not + * followed. */ +gboolean +ot_get_dir_size (int dfd, + const char *path, + guint64 *out_size, + GCancellable *cancellable, + GError **error) +{ + g_auto(GLnxDirFdIterator) dfd_iter = { 0, }; + if (!glnx_dirfd_iterator_init_at (dfd, path, FALSE, &dfd_iter, error)) + return FALSE; + + *out_size = 0; + while (TRUE) + { + 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_REG) + { + struct stat stbuf; + if (!glnx_fstatat (dfd_iter.fd, dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW, error)) + return FALSE; + + *out_size += stbuf.st_size; + } + else if (dent->d_type == DT_DIR) + { + guint64 subdir_size; + if (!ot_get_dir_size (dfd_iter.fd, dent->d_name, &subdir_size, cancellable, error)) + return FALSE; + + *out_size += subdir_size; + } + } + + return TRUE; +} diff --git a/src/libotutil/ot-fs-utils.h b/src/libotutil/ot-fs-utils.h index fad4c53d..f719381d 100644 --- a/src/libotutil/ot-fs-utils.h +++ b/src/libotutil/ot-fs-utils.h @@ -95,4 +95,11 @@ ot_parse_file_by_line (const char *path, GCancellable *cancellable, GError **error); +gboolean +ot_get_dir_size (int dfd, + const char *path, + guint64 *out_size, + GCancellable *cancellable, + GError **error); + G_END_DECLS -- cgit v1.2.1