[ostree] core: Use openat() for reading bare file objects too



commit 3ff4b1874c738746f6c4d81a46f4b8e4d63d0bca
Author: Colin Walters <walters verbum org>
Date:   Sun Sep 8 19:31:44 2013 -0400

    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 f1ebced..6df7d0c 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 b43f3e0..5e1590b 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;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]