From 3ff4b1874c738746f6c4d81a46f4b8e4d63d0bca Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sun, 8 Sep 2013 19:31:44 -0400 Subject: [PATCH] core: Use openat() for reading bare file objects too ...unless we want xattrs, in which case we have to fallback to path lookup due to lack of llistxattrat(). This looks nicer in strace. --- src/libostree/ostree-repo-private.h | 4 -- src/libostree/ostree-repo.c | 105 ++++++++++++++++++++++------ 2 files changed, 84 insertions(+), 25 deletions(-) diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index f1ebced8..6df7d0ce 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -66,10 +66,6 @@ _ostree_repo_ensure_loose_objdir_at (int dfd, GCancellable *cancellable, GError **error); -GFile * -_ostree_repo_get_file_object_path (OstreeRepo *self, - const char *checksum); - gboolean _ostree_repo_find_object (OstreeRepo *self, OstreeObjectType objtype, diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index b43f3e05..5e1590bf 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -576,14 +576,6 @@ ostree_repo_get_parent (OstreeRepo *self) return self->parent_repo; } -GFile * -_ostree_repo_get_file_object_path (OstreeRepo *self, - const char *checksum) -{ - return _ostree_repo_get_object_path (self, checksum, OSTREE_OBJECT_TYPE_FILE); -} - - static gboolean append_object_dirs_from (OstreeRepo *self, GFile *dir, @@ -885,6 +877,76 @@ load_metadata_internal (OstreeRepo *self, return ret; } +static gboolean +query_info_for_bare_content_object (OstreeRepo *self, + const char *loose_path_buf, + GFileInfo **out_info, + GCancellable *cancellable, + GError **error) +{ + gboolean ret = FALSE; + struct stat stbuf; + int res; + gs_unref_object GFileInfo *ret_info = NULL; + + do + res = fstatat (self->objects_dir_fd, loose_path_buf, &stbuf, AT_SYMLINK_NOFOLLOW); + while (G_UNLIKELY (res == -1 && errno == EINTR)); + if (res == -1) + { + if (errno == ENOENT) + { + *out_info = NULL; + ret = TRUE; + goto out; + } + ot_util_set_error_from_errno (error, errno); + goto out; + } + + ret_info = g_file_info_new (); + + if (S_ISREG (stbuf.st_mode)) + { + g_file_info_set_file_type (ret_info, G_FILE_TYPE_REGULAR); + g_file_info_set_size (ret_info, stbuf.st_size); + } + else if (S_ISLNK (stbuf.st_mode)) + { + char targetbuf[PATH_MAX+1]; + ssize_t len; + + g_file_info_set_file_type (ret_info, G_FILE_TYPE_SYMBOLIC_LINK); + + do + len = readlinkat (self->objects_dir_fd, loose_path_buf, targetbuf, sizeof (targetbuf) - 1); + while (G_UNLIKELY (len == -1 && errno == EINTR)); + if (len == -1) + { + ot_util_set_error_from_errno (error, errno); + goto out; + } + targetbuf[len] = '\0'; + g_file_info_set_symlink_target (ret_info, targetbuf); + } + else + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Not a regular file or symlink: %s", loose_path_buf); + goto out; + } + + g_file_info_set_attribute_boolean (ret_info, "standard::is-symlink", S_ISLNK (stbuf.st_mode)); + g_file_info_set_attribute_uint32 (ret_info, "unix::uid", stbuf.st_uid); + g_file_info_set_attribute_uint32 (ret_info, "unix::gid", stbuf.st_gid); + g_file_info_set_attribute_uint32 (ret_info, "unix::mode", stbuf.st_mode); + + ret = TRUE; + gs_transfer_out_value (out_info, &ret_info); + out: + return ret; +} + /** * ostree_repo_load_file: * @self: Repo @@ -949,33 +1011,34 @@ ostree_repo_load_file (OstreeRepo *self, } else { - gs_unref_object GFile *loose_path = NULL; + char loose_path_buf[_OSTREE_LOOSE_PATH_MAX]; - loose_path = _ostree_repo_get_object_path (self, checksum, OSTREE_OBJECT_TYPE_FILE); + _ostree_loose_path (loose_path_buf, checksum, OSTREE_OBJECT_TYPE_FILE, self->mode); - if (!ot_gfile_query_info_allow_noent (loose_path, OSTREE_GIO_FAST_QUERYINFO, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - &ret_file_info, - cancellable, error)) + if (!query_info_for_bare_content_object (self, loose_path_buf, + &ret_file_info, + cancellable, error)) goto out; if (ret_file_info) { if (out_xattrs) { - if (!ostree_get_xattrs_for_file (loose_path, &ret_xattrs, + gs_unref_object GFile *full_path = + _ostree_repo_get_object_path (self, checksum, OSTREE_OBJECT_TYPE_FILE); + + if (!ostree_get_xattrs_for_file (full_path, &ret_xattrs, cancellable, error)) goto out; } if (out_input && g_file_info_get_file_type (ret_file_info) == G_FILE_TYPE_REGULAR) { - ret_input = (GInputStream*) gs_file_read_noatime (loose_path, cancellable, error); - if (!ret_input) - { - g_prefix_error (error, "Error opening loose file object %s: ", gs_file_get_path_cached (loose_path)); - goto out; - } + int fd = -1; + if (!gs_file_openat_noatime (self->objects_dir_fd, loose_path_buf, &fd, + cancellable, error)) + goto out; + ret_input = g_unix_input_stream_new (fd, TRUE); } found = TRUE;