diff --git a/src/libostree/ostree-sysroot-cleanup.c b/src/libostree/ostree-sysroot-cleanup.c index 825d6c4d..30f1936d 100644 --- a/src/libostree/ostree-sysroot-cleanup.c +++ b/src/libostree/ostree-sysroot-cleanup.c @@ -292,26 +292,26 @@ cleanup_old_deployments (OstreeSysroot *self, GError **error) { gboolean ret = FALSE; - guint32 root_device; - guint64 root_inode; + struct stat root_stbuf; 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; + if (stat ("/", &root_stbuf) != 0) + { + glnx_set_error_from_errno (error); + goto out; + } - active_deployment_dirs = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL); + active_deployment_dirs = g_hash_table_new_full (g_str_hash, (GEqualFunc)g_str_equal, g_free, 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 *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); @@ -325,29 +325,38 @@ cleanup_old_deployments (OstreeSysroot *self, 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); + g_autofree char *deployment_path = ostree_sysroot_get_deployment_dirpath (self, deployment); + g_autofree char *origin_relpath = ostree_deployment_get_origin_relpath (deployment); + if (!g_hash_table_lookup (active_deployment_dirs, deployment_path)) { - guint32 device; - guint64 inode; + struct stat stbuf; + glnx_fd_close int deployment_fd = -1; - if (!_ostree_sysroot_get_devino (deployment_path, &device, &inode, - cancellable, error)) + if (!glnx_opendirat (self->sysroot_fd, deployment_path, TRUE, + &deployment_fd, error)) goto out; + if (fstat (deployment_fd, &stbuf) != 0) + { + glnx_set_error_from_errno (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) + if (stbuf.st_dev == root_stbuf.st_dev && + stbuf.st_ino == root_stbuf.st_ino) continue; - if (!_ostree_linuxfs_alter_immutable_flag (deployment_path, FALSE, - cancellable, error)) + if (!_ostree_linuxfs_fd_alter_immutable_flag (deployment_fd, FALSE, + cancellable, error)) goto out; - if (!gs_shutil_rm_rf (deployment_path, cancellable, error)) + + if (!glnx_shutil_rm_rf_at (self->sysroot_fd, deployment_path, cancellable, error)) goto out; - if (!gs_shutil_rm_rf (origin_path, cancellable, error)) + if (!glnx_shutil_rm_rf_at (self->sysroot_fd, origin_relpath, cancellable, error)) goto out; } } diff --git a/src/libostree/ostree-sysroot-private.h b/src/libostree/ostree-sysroot-private.h index e7dcef20..03224dec 100644 --- a/src/libostree/ostree-sysroot-private.h +++ b/src/libostree/ostree-sysroot-private.h @@ -68,12 +68,12 @@ _ostree_sysroot_list_deployment_dirs_for_os (GFile *osdir, GCancellable *cancellable, GError **error); -gboolean -_ostree_sysroot_get_devino (GFile *path, - guint32 *out_device, - guint64 *out_inode, - GCancellable *cancellable, - GError **error); +char * +_ostree_sysroot_get_origin_relpath (GFile *path, + guint32 *out_device, + guint64 *out_inode, + GCancellable *cancellable, + GError **error); char *_ostree_sysroot_join_lines (GPtrArray *lines); diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index baa84887..2afc59c3 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -191,28 +191,6 @@ ensure_sysroot_fd (OstreeSysroot *self, return TRUE; } -gboolean -_ostree_sysroot_get_devino (GFile *path, - guint32 *out_device, - guint64 *out_inode, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - gs_unref_object GFileInfo *finfo = g_file_query_info (path, "unix::device,unix::inode", - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - cancellable, error); - - if (!finfo) - goto out; - - ret = TRUE; - *out_device = g_file_info_get_attribute_uint32 (finfo, "unix::device"); - *out_inode = g_file_info_get_attribute_uint64 (finfo, "unix::inode"); - out: - return ret; -} - /** * ostree_sysroot_ensure_initialized: * @self: Sysroot @@ -1009,21 +987,32 @@ find_booted_deployment (OstreeSysroot *self, GError **error) { gboolean ret = FALSE; - gs_unref_object GFile *active_root = g_file_new_for_path ("/"); + struct stat root_stbuf; + struct stat self_stbuf; gs_unref_object OstreeDeployment *ret_deployment = NULL; - if (g_file_equal (active_root, self->path)) + if (stat ("/", &root_stbuf) != 0) + { + glnx_set_error_from_errno (error); + goto out; + } + + if (!ensure_sysroot_fd (self, error)) + goto out; + + if (fstat (self->sysroot_fd, &self_stbuf) != 0) + { + glnx_set_error_from_errno (error); + goto out; + } + + if (root_stbuf.st_dev == self_stbuf.st_dev && + root_stbuf.st_ino == self_stbuf.st_ino) { guint i; const char *bootlink_arg; __attribute__((cleanup(_ostree_kernel_args_cleanup))) OstreeKernelArgs *kernel_args = NULL; - guint32 root_device; - guint64 root_inode; - if (!_ostree_sysroot_get_devino (active_root, &root_device, &root_inode, - cancellable, error)) - goto out; - if (!parse_kernel_commandline (&kernel_args, cancellable, error)) goto out; @@ -1033,20 +1022,23 @@ find_booted_deployment (OstreeSysroot *self, for (i = 0; i < deployments->len; i++) { OstreeDeployment *deployment = deployments->pdata[i]; - gs_unref_object GFile *deployment_path = ostree_sysroot_get_deployment_directory (self, deployment); - guint32 device; - guint64 inode; + g_autofree char *deployment_path = ostree_sysroot_get_deployment_dirpath (self, deployment); + struct stat stbuf; - if (!_ostree_sysroot_get_devino (deployment_path, &device, &inode, - cancellable, error)) - goto out; + if (fstatat (self->sysroot_fd, deployment_path, &stbuf, 0) != 0) + { + glnx_set_error_from_errno (error); + goto out; + } - if (device == root_device && inode == root_inode) + if (stbuf.st_dev == root_stbuf.st_dev && + stbuf.st_ino == root_stbuf.st_ino) { ret_deployment = g_object_ref (deployment); break; } } + if (ret_deployment == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,