diff --git a/libglnx b/libglnx index c1ae7ce1..162d1f6b 160000 --- a/libglnx +++ b/libglnx @@ -1 +1 @@ -Subproject commit c1ae7ce1bf9c9175b26d1d933757503a0cc368e3 +Subproject commit 162d1f6b58c9b501f47080e99aa1fd36864a89f9 diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 4cab2f46..3aa72700 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -842,65 +842,58 @@ devino_equal (gconstpointer a, } static gboolean -scan_loose_devino (OstreeRepo *self, - GHashTable *devino_cache, - GCancellable *cancellable, - GError **error) +scan_one_loose_devino (OstreeRepo *self, + int object_dir_fd, + GHashTable *devino_cache, + GCancellable *cancellable, + GError **error) { gboolean ret = FALSE; - guint i; - OstreeRepoMode repo_mode; - gs_unref_ptrarray GPtrArray *object_dirs = NULL; + int res; + g_auto(GLnxDirFdIterator) dfd_iter = { 0, }; - if (self->parent_repo) - { - if (!scan_loose_devino (self->parent_repo, devino_cache, cancellable, error)) - goto out; - } - - repo_mode = ostree_repo_get_mode (self); - - if (!_ostree_repo_get_loose_object_dirs (self, &object_dirs, cancellable, error)) + if (!glnx_dirfd_iterator_init_at (object_dir_fd, ".", FALSE, + &dfd_iter, error)) goto out; - - for (i = 0; i < object_dirs->len; i++) + + while (TRUE) { - GFile *objdir = object_dirs->pdata[i]; - gs_unref_object GFileEnumerator *enumerator = NULL; - gs_unref_object GFileInfo *file_info = NULL; - const char *dirname; + struct dirent *dent; + g_auto(GLnxDirFdIterator) child_dfd_iter = { 0, }; - enumerator = g_file_enumerate_children (objdir, OSTREE_GIO_FAST_QUERYINFO, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - cancellable, - error); - if (!enumerator) + if (!glnx_dirfd_iterator_next_dent (&dfd_iter, &dent, cancellable, error)) goto out; + + if (dent == NULL) + break; - dirname = gs_file_get_basename_cached (objdir); + /* All object directories only have two character entries */ + if (strlen (dent->d_name) != 2) + continue; + + if (!glnx_dirfd_iterator_init_at (dfd_iter.fd, dent->d_name, FALSE, + &child_dfd_iter, error)) + goto out; while (TRUE) { - const char *name; - const char *dot; - guint32 type; + struct stat stbuf; OstreeDevIno *key; + struct dirent *child_dent; + const char *dot; GString *checksum; gboolean skip; + const char *name; - if (!gs_file_enumerator_iterate (enumerator, &file_info, NULL, - NULL, error)) + if (!glnx_dirfd_iterator_next_dent (&child_dfd_iter, &child_dent, cancellable, error)) goto out; - if (file_info == NULL) + + if (child_dent == NULL) break; - name = g_file_info_get_attribute_byte_string (file_info, "standard::name"); - type = g_file_info_get_attribute_uint32 (file_info, "standard::type"); + name = child_dent->d_name; - if (type == G_FILE_TYPE_DIRECTORY) - continue; - - switch (repo_mode) + switch (self->mode) { case OSTREE_REPO_MODE_ARCHIVE_Z2: case OSTREE_REPO_MODE_BARE: @@ -915,17 +908,27 @@ scan_loose_devino (OstreeRepo *self, dot = strrchr (name, '.'); g_assert (dot); - + + /* Skip anything that doesn't look like a 64 character checksum */ if ((dot - name) != 62) continue; - checksum = g_string_new (dirname); + do + res = fstatat (child_dfd_iter.fd, child_dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW); + while (G_UNLIKELY (res == -1 && errno == EINTR)); + if (res == -1) + { + glnx_set_error_from_errno (error); + goto out; + } + + checksum = g_string_new (dent->d_name); g_string_append_len (checksum, name, 62); - + key = g_new (OstreeDevIno, 1); - key->dev = g_file_info_get_attribute_uint32 (file_info, "unix::device"); - key->ino = g_file_info_get_attribute_uint64 (file_info, "unix::inode"); - + key->dev = stbuf.st_dev; + key->ino = stbuf.st_ino; + g_hash_table_replace (devino_cache, key, g_string_free (checksum, FALSE)); } } @@ -935,6 +938,36 @@ scan_loose_devino (OstreeRepo *self, return ret; } +static gboolean +scan_loose_devino (OstreeRepo *self, + GHashTable *devino_cache, + GCancellable *cancellable, + GError **error) +{ + gboolean ret = FALSE; + + if (self->parent_repo) + { + if (!scan_loose_devino (self->parent_repo, devino_cache, cancellable, error)) + goto out; + } + + if (self->mode == OSTREE_REPO_MODE_ARCHIVE_Z2) + { + if (!scan_one_loose_devino (self, self->uncompressed_objects_dir_fd, devino_cache, + cancellable, error)) + goto out; + } + + if (!scan_one_loose_devino (self, self->objects_dir_fd, + devino_cache, cancellable, error)) + goto out; + + ret = TRUE; + out: + return ret; +} + static const char * devino_cache_lookup (OstreeRepo *self, guint32 device, @@ -1096,6 +1129,7 @@ rename_pending_loose_objects (OstreeRepo *self, if (!S_ISDIR (stbuf.st_mode)) continue; + /* All object directories only have two character entries */ if (strlen (dent->d_name) != 2) continue; diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index a96d9d64..3bb4576b 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -112,12 +112,6 @@ _ostree_repo_has_loose_object (OstreeRepo *self, GCancellable *cancellable, GError **error); -gboolean -_ostree_repo_get_loose_object_dirs (OstreeRepo *self, - GPtrArray **out_object_dirs, - GCancellable *cancellable, - GError **error); - gboolean _ostree_repo_write_directory_meta (OstreeRepo *self, GFileInfo *file_info, diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index d8e5ab7c..57028250 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -1511,89 +1511,6 @@ ostree_repo_get_parent (OstreeRepo *self) return self->parent_repo; } -static gboolean -append_object_dirs_from (OstreeRepo *self, - GFile *dir, - GPtrArray *object_dirs, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - GError *temp_error = NULL; - gs_unref_object GFileEnumerator *enumerator = NULL; - - enumerator = g_file_enumerate_children (dir, OSTREE_GIO_FAST_QUERYINFO, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - cancellable, - &temp_error); - if (!enumerator) - { - if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) - { - g_clear_error (&temp_error); - ret = TRUE; - } - else - g_propagate_error (error, temp_error); - - goto out; - } - - while (TRUE) - { - GFileInfo *file_info; - const char *name; - guint32 type; - - if (!gs_file_enumerator_iterate (enumerator, &file_info, NULL, - NULL, error)) - goto out; - if (file_info == NULL) - break; - - name = g_file_info_get_attribute_byte_string (file_info, "standard::name"); - type = g_file_info_get_attribute_uint32 (file_info, "standard::type"); - - if (strlen (name) == 2 && type == G_FILE_TYPE_DIRECTORY) - { - GFile *objdir = g_file_get_child (g_file_enumerator_get_container (enumerator), name); - g_ptr_array_add (object_dirs, objdir); /* transfer ownership */ - } - } - - ret = TRUE; - out: - return ret; -} - -gboolean -_ostree_repo_get_loose_object_dirs (OstreeRepo *self, - GPtrArray **out_object_dirs, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - gs_unref_ptrarray GPtrArray *ret_object_dirs = NULL; - - ret_object_dirs = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref); - - if (ostree_repo_get_mode (self) == OSTREE_REPO_MODE_ARCHIVE_Z2) - { - if (!append_object_dirs_from (self, self->uncompressed_objects_dir, ret_object_dirs, - cancellable, error)) - goto out; - } - - if (!append_object_dirs_from (self, self->objects_dir, ret_object_dirs, - cancellable, error)) - goto out; - - ret = TRUE; - ot_transfer_out_value (out_object_dirs, &ret_object_dirs); - out: - return ret; -} - static gboolean list_loose_objects_at (OstreeRepo *self, GHashTable *inout_objects,