diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index a90cdc84..ce2c62b3 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -34,20 +34,16 @@ static gboolean commit_loose_object_trusted (OstreeRepo *self, - const char *checksum, - OstreeObjectType objtype, + const char *loose_path, const char *tempfile_name, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; char loose_prefix[3]; - char loose_objpath[_OSTREE_LOOSE_PATH_MAX]; - _ostree_loose_path (loose_objpath, checksum, objtype, self->mode); - - loose_prefix[0] = loose_objpath[0]; - loose_prefix[1] = loose_objpath[1]; + loose_prefix[0] = loose_path[0]; + loose_prefix[1] = loose_path[1]; loose_prefix[2] = '\0'; if (G_UNLIKELY (mkdirat (self->objects_dir_fd, loose_prefix, 0777) == -1)) { @@ -60,7 +56,7 @@ commit_loose_object_trusted (OstreeRepo *self, } if (G_UNLIKELY (renameat (self->tmp_dir_fd, tempfile_name, - self->objects_dir_fd, loose_objpath) < 0)) + self->objects_dir_fd, loose_path) == -1)) { if (errno != EEXIST) { @@ -155,6 +151,7 @@ write_object (OstreeRepo *self, GChecksum *checksum = NULL; gboolean temp_file_is_regular; gboolean is_symlink = FALSE; + char loose_objpath[_OSTREE_LOOSE_PATH_MAX]; g_return_val_if_fail (self->in_transaction, FALSE); @@ -165,9 +162,15 @@ write_object (OstreeRepo *self, if (expected_checksum) { - if (!_ostree_repo_find_object (self, objtype, expected_checksum, &stored_path, - cancellable, error)) + if (!_ostree_repo_has_loose_object (self, expected_checksum, objtype, + &have_obj, loose_objpath, + cancellable, error)) goto out; + if (have_obj) + { + ret = TRUE; + goto out; + } } repo_mode = ostree_repo_get_mode (self); @@ -290,8 +293,9 @@ write_object (OstreeRepo *self, } } - if (!ostree_repo_has_object (self, objtype, actual_checksum, &have_obj, - cancellable, error)) + if (!_ostree_repo_has_loose_object (self, actual_checksum, objtype, + &have_obj, loose_objpath, + cancellable, error)) goto out; do_commit = !have_obj; @@ -358,7 +362,7 @@ write_object (OstreeRepo *self, (void) close (fd); } } - if (!commit_loose_object_trusted (self, actual_checksum, objtype, temp_filename, + if (!commit_loose_object_trusted (self, loose_objpath, temp_filename, cancellable, error)) goto out; g_clear_pointer (&temp_filename, g_free); diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index de65df67..0060ca48 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -76,6 +76,15 @@ _ostree_repo_find_object (OstreeRepo *self, GCancellable *cancellable, GError **error); +gboolean +_ostree_repo_has_loose_object (OstreeRepo *self, + const char *checksum, + OstreeObjectType objtype, + gboolean *out_is_stored, + char *loose_path_buf, + GCancellable *cancellable, + GError **error); + gboolean _ostree_repo_get_loose_object_dirs (OstreeRepo *self, GPtrArray **out_object_dirs, diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 7db46979..db3869e6 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -989,6 +989,43 @@ ostree_repo_load_object_stream (OstreeRepo *self, return ret; } +/* + * _ostree_repo_has_loose_object: + * @loose_path_buf: Buffer of size _OSTREE_LOOSE_PATH_MAX + * + * Locate object in repository; if it exists, @out_is_stored will be + * set to TRUE. @loose_path_buf is always set to the loose path. + */ +gboolean +_ostree_repo_has_loose_object (OstreeRepo *self, + const char *checksum, + OstreeObjectType objtype, + gboolean *out_is_stored, + char *loose_path_buf, + GCancellable *cancellable, + GError **error) +{ + gboolean ret = FALSE; + struct stat stbuf; + int res; + + _ostree_loose_path (loose_path_buf, checksum, objtype, self->mode); + + do + res = fstatat (self->objects_dir_fd, loose_path_buf, &stbuf, AT_SYMLINK_NOFOLLOW); + while (G_UNLIKELY (res == -1 && errno == EINTR)); + if (res == -1 && errno != ENOENT) + { + ot_util_set_error_from_errno (error, errno); + goto out; + } + + ret = TRUE; + *out_is_stored = (res != -1); + out: + return ret; +} + gboolean _ostree_repo_find_object (OstreeRepo *self, OstreeObjectType objtype, @@ -998,25 +1035,18 @@ _ostree_repo_find_object (OstreeRepo *self, GError **error) { gboolean ret = FALSE; - struct stat stbuf; - gs_unref_object GFile *object_path = NULL; - gs_unref_object GFile *ret_stored_path = NULL; + gboolean has_object; + char loose_path[_OSTREE_LOOSE_PATH_MAX]; - object_path = _ostree_repo_get_object_path (self, checksum, objtype); - - if (lstat (gs_file_get_path_cached (object_path), &stbuf) == 0) - { - ret_stored_path = object_path; - object_path = NULL; /* Transfer ownership */ - } - else if (errno != ENOENT) - { - ot_util_set_error_from_errno (error, errno); - goto out; - } + if (!_ostree_repo_has_loose_object (self, checksum, objtype, &has_object, loose_path, + cancellable, error)) + goto out; ret = TRUE; - ot_transfer_out_value (out_stored_path, &ret_stored_path); + if (has_object) + *out_stored_path = g_file_resolve_relative_path (self->objects_dir, loose_path); + else + *out_stored_path = NULL; out: return ret; }