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.
This commit is contained in:
Colin Walters 2013-09-08 19:31:44 -04:00
parent a071a3ec3a
commit 3ff4b1874c
2 changed files with 84 additions and 25 deletions

View File

@ -66,10 +66,6 @@ _ostree_repo_ensure_loose_objdir_at (int dfd,
GCancellable *cancellable, GCancellable *cancellable,
GError **error); GError **error);
GFile *
_ostree_repo_get_file_object_path (OstreeRepo *self,
const char *checksum);
gboolean gboolean
_ostree_repo_find_object (OstreeRepo *self, _ostree_repo_find_object (OstreeRepo *self,
OstreeObjectType objtype, OstreeObjectType objtype,

View File

@ -576,14 +576,6 @@ ostree_repo_get_parent (OstreeRepo *self)
return self->parent_repo; 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 static gboolean
append_object_dirs_from (OstreeRepo *self, append_object_dirs_from (OstreeRepo *self,
GFile *dir, GFile *dir,
@ -885,6 +877,76 @@ load_metadata_internal (OstreeRepo *self,
return ret; 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: * ostree_repo_load_file:
* @self: Repo * @self: Repo
@ -949,33 +1011,34 @@ ostree_repo_load_file (OstreeRepo *self,
} }
else 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, if (!query_info_for_bare_content_object (self, loose_path_buf,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, &ret_file_info,
&ret_file_info, cancellable, error))
cancellable, error))
goto out; goto out;
if (ret_file_info) if (ret_file_info)
{ {
if (out_xattrs) 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)) cancellable, error))
goto out; goto out;
} }
if (out_input && g_file_info_get_file_type (ret_file_info) == G_FILE_TYPE_REGULAR) 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); int fd = -1;
if (!ret_input) if (!gs_file_openat_noatime (self->objects_dir_fd, loose_path_buf, &fd,
{ cancellable, error))
g_prefix_error (error, "Error opening loose file object %s: ", gs_file_get_path_cached (loose_path)); goto out;
goto out; ret_input = g_unix_input_stream_new (fd, TRUE);
}
} }
found = TRUE; found = TRUE;