[ostree] core: Make checksum API also operate on directories



commit 7f64d5cec745fdbc25c4151ef92032cee1587fa4
Author: Colin Walters <walters verbum org>
Date:   Fri Nov 18 06:34:54 2011 -0500

    core: Make checksum API also operate on directories

 src/libostree/ostree-core.c |  118 +++++++++++++++++++++++++++++++------------
 src/libostree/ostree-core.h |    4 ++
 src/libostree/ostree-repo.c |   47 +++++------------
 3 files changed, 104 insertions(+), 65 deletions(-)
---
diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c
index 8caff3f..7e47046 100644
--- a/src/libostree/ostree-core.c
+++ b/src/libostree/ostree-core.c
@@ -41,6 +41,12 @@ ostree_validate_checksum_string (const char *sha256,
   return TRUE;
 }
 
+GVariant *
+ostree_wrap_metadata_variant (OstreeSerializedVariantType type,
+                              GVariant *metadata)
+{
+  return g_variant_new ("(uv)", GUINT32_TO_BE ((guint32)type), metadata);
+}
 
 void
 ostree_checksum_update_stat (GChecksum *checksum, guint32 uid, guint32 gid, guint32 mode)
@@ -174,33 +180,59 @@ ostree_get_xattrs_for_file (GFile      *f,
   return ret;
 }
 
-gboolean
-ostree_checksum_file (GFile            *f,
-                      OstreeObjectType objtype,
-                      GChecksum       **out_checksum,
-                      GCancellable     *cancellable,
-                      GError          **error)
+static gboolean
+checksum_directory (GFile          *f,
+                    GFileInfo      *f_info,
+                    GChecksum     **out_checksum,
+                    GCancellable   *cancellable,
+                    GError        **error)
+{
+  gboolean ret = FALSE;
+  GVariant *dirmeta = NULL;
+  GVariant *packed = NULL;
+  GChecksum *ret_checksum = NULL;
+
+  if (!ostree_get_directory_metadata (f, f_info, &dirmeta, cancellable, error))
+    goto out;
+  packed = ostree_wrap_metadata_variant (OSTREE_SERIALIZED_DIRMETA_VARIANT, dirmeta);
+  ret_checksum = g_checksum_new (G_CHECKSUM_SHA256);
+  g_checksum_update (ret_checksum, g_variant_get_data (packed),
+                     g_variant_get_size (packed));
+
+  ret = TRUE;
+  *out_checksum = ret_checksum;
+  ret_checksum = NULL;
+ out:
+  if (ret_checksum)
+    g_checksum_free (ret_checksum);
+  if (dirmeta)
+    g_variant_unref (dirmeta);
+  if (packed)
+    g_variant_unref (packed);
+  return ret;
+}
+
+static gboolean
+checksum_nondirectory (GFile            *f,
+                       GFileInfo        *file_info,
+                       OstreeObjectType objtype,
+                       GChecksum       **out_checksum,
+                       GCancellable     *cancellable,
+                       GError          **error)
 {
+  gboolean ret = FALSE;
   const char *path = NULL;
   GChecksum *content_sha256 = NULL;
   GChecksum *content_and_meta_sha256 = NULL;
   ssize_t bytes_read;
   GVariant *xattrs = NULL;
   char *basename = NULL;
-  gboolean ret = FALSE;
-  GFileInfo *file_info = NULL;
   GInputStream *input = NULL;
   guint32 unix_mode;
 
   path = ot_gfile_get_path_cached (f);
   basename = g_path_get_basename (path);
 
-  file_info = g_file_query_info (f, OSTREE_GIO_FAST_QUERYINFO,
-                                 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
-                                 cancellable, error);
-  if (!file_info)
-    goto out;
-
   if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR)
     {
       input = (GInputStream*)g_file_read (f, cancellable, error);
@@ -272,7 +304,6 @@ ostree_checksum_file (GFile            *f,
   ret = TRUE;
  out:
   g_clear_object (&input);
-  g_clear_object (&file_info);
   g_free (basename);
   if (xattrs)
     g_variant_unref (xattrs);
@@ -282,38 +313,61 @@ ostree_checksum_file (GFile            *f,
 }
 
 gboolean
+ostree_checksum_file (GFile            *f,
+                      OstreeObjectType objtype,
+                      GChecksum       **out_checksum,
+                      GCancellable     *cancellable,
+                      GError          **error)
+{
+  gboolean ret = FALSE;
+  GFileInfo *file_info = NULL;
+  GChecksum *ret_checksum = NULL;
+
+  file_info = g_file_query_info (f, OSTREE_GIO_FAST_QUERYINFO,
+                                 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+                                 cancellable, error);
+  if (!file_info)
+    goto out;
+
+  if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
+    {
+      if (!checksum_directory (f, file_info, &ret_checksum, cancellable, error))
+        goto out;
+    }
+  else
+    {
+      if (!checksum_nondirectory (f, file_info, objtype, &ret_checksum, cancellable, error))
+        goto out;
+    }
+
+  ret = TRUE;
+  *out_checksum = ret_checksum;
+  ret_checksum = NULL;
+ out:
+  g_clear_object (&file_info);
+  return ret;
+}
+
+gboolean
 ostree_get_directory_metadata (GFile        *dir,
+                               GFileInfo    *dir_info,
                                GVariant    **out_metadata,
                                GCancellable *cancellable,
                                GError      **error)
 {
   gboolean ret = FALSE;
-  struct stat stbuf;
   GVariant *xattrs = NULL;
   GVariant *ret_metadata = NULL;
 
-  if (lstat (ot_gfile_get_path_cached (dir), &stbuf) < 0)
-    {
-      ot_util_set_error_from_errno (error, errno);
-      goto out;
-    }
-  
-  if (!S_ISDIR(stbuf.st_mode))
-    {
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                   "Not a directory: '%s'", ot_gfile_get_path_cached (dir));
-      goto out;
-    }
-
   xattrs = ostree_get_xattrs_for_file (dir, error);
   if (!xattrs)
     goto out;
 
   ret_metadata = g_variant_new ("(uuuu a(ayay))",
                                 OSTREE_DIR_META_VERSION,
-                                GUINT32_TO_BE ((guint32)stbuf.st_uid),
-                                GUINT32_TO_BE ((guint32)stbuf.st_gid),
-                                GUINT32_TO_BE ((guint32)stbuf.st_mode),
+                                GUINT32_TO_BE (g_file_info_get_attribute_uint32 (dir_info, "unix::uid")),
+                                GUINT32_TO_BE (g_file_info_get_attribute_uint32 (dir_info, "unix::gid")),
+                                GUINT32_TO_BE (g_file_info_get_attribute_uint32 (dir_info, "unix::mode")),
                                 xattrs);
   g_variant_ref_sink (ret_metadata);
 
diff --git a/src/libostree/ostree-core.h b/src/libostree/ostree-core.h
index 38d08ed..3e779e5 100644
--- a/src/libostree/ostree-core.h
+++ b/src/libostree/ostree-core.h
@@ -101,6 +101,9 @@ char *ostree_get_relative_object_path (const char *checksum,
 GVariant *ostree_get_xattrs_for_file (GFile       *f,
                                       GError     **error);
 
+GVariant *ostree_wrap_metadata_variant (OstreeSerializedVariantType type,
+                                        GVariant *metadata);
+
 gboolean ostree_set_xattrs (GFile *f, GVariant *xattrs,
                             GCancellable *cancellable, GError **error);
 
@@ -116,6 +119,7 @@ gboolean ostree_checksum_file (GFile             *f,
                                GError           **error);
 
 gboolean ostree_get_directory_metadata (GFile *dir,
+                                        GFileInfo *dir_info,
                                         GVariant  **out_metadata,
                                         GCancellable *cancellable,
                                         GError **error);
diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c
index 60f38ba..2b28fdc 100644
--- a/src/libostree/ostree-repo.c
+++ b/src/libostree/ostree-repo.c
@@ -557,13 +557,6 @@ ostree_repo_is_archive (OstreeRepo  *self)
   return priv->archive;
 }
 
-static GVariant *
-pack_metadata_variant (OstreeSerializedVariantType type,
-                       GVariant                   *variant)
-{
-  return g_variant_new ("(uv)", GUINT32_TO_BE ((guint32)type), variant);
-}
-
 static gboolean
 write_gvariant_to_tmp (OstreeRepo  *self,
                        OstreeSerializedVariantType type,
@@ -582,7 +575,7 @@ write_gvariant_to_tmp (OstreeRepo  *self,
   GUnixOutputStream *stream = NULL;
   GChecksum *checksum = NULL;
 
-  serialized = pack_metadata_variant (type, variant);
+  serialized = ostree_wrap_metadata_variant (type, variant);
 
   tmp_name = g_build_filename (ot_gfile_get_path_cached (priv->tmp_dir), "variant-tmp-XXXXXX", NULL);
   fd = g_mkstemp (tmp_name);
@@ -709,10 +702,17 @@ import_directory_meta (OstreeRepo  *self,
   GChecksum *ret_checksum = NULL;
   GVariant *dirmeta = NULL;
   GFile *f = NULL;
+  GFileInfo *f_info = NULL;
 
   f = ot_util_new_file_for_path (path);
 
-  if (!ostree_get_directory_metadata (f, &dirmeta, NULL, error))
+  f_info = g_file_query_info (f, OSTREE_GIO_FAST_QUERYINFO,
+                              G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+                              NULL, error);
+  if (!f_info)
+    goto out;
+
+  if (!ostree_get_directory_metadata (f, f_info, &dirmeta, NULL, error))
     goto out;
   
   if (!import_gvariant_object (self, OSTREE_SERIALIZED_DIRMETA_VARIANT, 
@@ -726,6 +726,7 @@ import_directory_meta (OstreeRepo  *self,
   ret_checksum = NULL;
  out:
   g_clear_object (&f);
+  g_clear_object (&f_info);
   if (ret_checksum)
     g_checksum_free (ret_checksum);
   if (dirmeta != NULL)
@@ -1884,8 +1885,6 @@ get_file_checksum (GFile  *f,
 {
   gboolean ret = FALSE;
   GChecksum *tmp_checksum = NULL;
-  GVariant *dirmeta = NULL;
-  GVariant *packed_dirmeta = NULL;
   char *ret_checksum = NULL;
 
   if (OSTREE_IS_REPO_FILE (f))
@@ -1894,36 +1893,18 @@ get_file_checksum (GFile  *f,
     }
   else
     {
-      if (g_file_info_get_file_type (f_info) == G_FILE_TYPE_DIRECTORY)
-        {
-          tmp_checksum = g_checksum_new (G_CHECKSUM_SHA256);
-          if (!ostree_get_directory_metadata (f, &dirmeta, cancellable, error))
-            goto out;
-          packed_dirmeta = pack_metadata_variant (OSTREE_SERIALIZED_DIRMETA_VARIANT, dirmeta);
-          g_checksum_update (tmp_checksum, g_variant_get_data (packed_dirmeta),
-                             g_variant_get_size (packed_dirmeta));
-          ret_checksum = g_strdup (g_checksum_get_string (tmp_checksum));
-        }
-      else
-        {
-          if (!ostree_checksum_file (f, OSTREE_OBJECT_TYPE_FILE,
-                                     &tmp_checksum, cancellable, error))
-            goto out;
-          ret_checksum = g_strdup (g_checksum_get_string (tmp_checksum));
-        }
+      if (!ostree_checksum_file (f, OSTREE_OBJECT_TYPE_FILE,
+                                 &tmp_checksum, cancellable, error))
+        goto out;
+      ret_checksum = g_strdup (g_checksum_get_string (tmp_checksum));
     }
 
   ret = TRUE;
   *out_checksum = ret_checksum;
   ret_checksum = NULL;
  out:
-  g_free (ret_checksum);
   if (tmp_checksum)
     g_checksum_free (tmp_checksum);
-  if (dirmeta)
-    g_variant_unref (dirmeta);
-  if (packed_dirmeta)
-    g_variant_unref (packed_dirmeta);
   return ret;
 }
 



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