[ostree] core: CHANGE CHECKSUM ALGORITHM, port checksum API to GFile



commit b8cef545d18738deaf4ba5e394c648fbbeb5cbef
Author: Colin Walters <walters verbum org>
Date:   Thu Nov 17 19:32:01 2011 -0500

    core: CHANGE CHECKSUM ALGORITHM, port checksum API to GFile
    
    This commit originally was to port ostree_stat_and_checksum_file() to
    GFile*, but I noticed that the checksum code was reading data in host
    endianness.  Fix that while we're here.
    
    This invalidates all existing repositories.

 src/libostree/ostree-core.c  |  112 ++++++++++++++++--------------------------
 src/libostree/ostree-core.h  |   14 +++---
 src/libostree/ostree-repo.c  |   13 +++--
 src/ostree/ot-builtin-fsck.c |    7 ++-
 tests/t0000-basic.sh         |    4 +-
 5 files changed, 64 insertions(+), 86 deletions(-)
---
diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c
index aa03c3c..8caff3f 100644
--- a/src/libostree/ostree-core.c
+++ b/src/libostree/ostree-core.c
@@ -45,7 +45,10 @@ ostree_validate_checksum_string (const char *sha256,
 void
 ostree_checksum_update_stat (GChecksum *checksum, guint32 uid, guint32 gid, guint32 mode)
 {
-  guint32 perms = (mode & ~S_IFMT);
+  guint32 perms;
+  perms = GUINT32_TO_BE (mode & ~S_IFMT);
+  uid = GUINT32_TO_BE (uid);
+  gid = GUINT32_TO_BE (gid);
   g_checksum_update (checksum, (guint8*) &uid, 4);
   g_checksum_update (checksum, (guint8*) &gid, 4);
   g_checksum_update (checksum, (guint8*) &perms, 4);
@@ -172,57 +175,37 @@ ostree_get_xattrs_for_file (GFile      *f,
 }
 
 gboolean
-ostree_stat_and_checksum_file (int dir_fd, const char *path,
-                               OstreeObjectType objtype,
-                               GChecksum **out_checksum,
-                               struct stat *out_stbuf,
-                               GError **error)
+ostree_checksum_file (GFile            *f,
+                      OstreeObjectType objtype,
+                      GChecksum       **out_checksum,
+                      GCancellable     *cancellable,
+                      GError          **error)
 {
-  GFile *f = NULL;
+  const char *path = NULL;
   GChecksum *content_sha256 = NULL;
   GChecksum *content_and_meta_sha256 = NULL;
-  char *stat_string = NULL;
   ssize_t bytes_read;
   GVariant *xattrs = NULL;
-  int fd = -1;
-  DIR *temp_dir = NULL;
   char *basename = NULL;
   gboolean ret = FALSE;
-  char *symlink_target = NULL;
-  char *device_id = NULL;
-  struct stat stbuf;
-
-  f = ot_util_new_file_for_path (path);
+  GFileInfo *file_info = NULL;
+  GInputStream *input = NULL;
+  guint32 unix_mode;
 
+  path = ot_gfile_get_path_cached (f);
   basename = g_path_get_basename (path);
 
-  if (dir_fd == -1)
-    {
-      char *dirname = g_path_get_dirname (path);
-      temp_dir = opendir (dirname);
-      if (temp_dir == NULL)
-        {
-          ot_util_set_error_from_errno (error, errno);
-          g_free (dirname);
-        }
-      g_free (dirname);
-      dir_fd = dirfd (temp_dir);
-    }
-
-  if (fstatat (dir_fd, basename, &stbuf, AT_SYMLINK_NOFOLLOW) < 0)
-    {
-      ot_util_set_error_from_errno (error, errno);
-      goto out;
-    }
+  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 (S_ISREG(stbuf.st_mode))
+  if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR)
     {
-      fd = ot_util_open_file_read_at (dir_fd, basename, error);
-      if (fd < 0)
-        {
-          ot_util_set_error_from_errno (error, errno);
-          goto out;
-        }
+      input = (GInputStream*)g_file_read (f, cancellable, error);
+      if (!input)
+        goto out;
     }
 
   if (objtype == OSTREE_OBJECT_TYPE_FILE)
@@ -233,40 +216,35 @@ ostree_stat_and_checksum_file (int dir_fd, const char *path,
     }
 
   content_sha256 = g_checksum_new (G_CHECKSUM_SHA256);
+
+  unix_mode = g_file_info_get_attribute_uint32 (file_info, "unix::mode");
  
-  if (S_ISREG(stbuf.st_mode))
+  if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR)
     {
       guint8 buf[8192];
 
-      while ((bytes_read = read (fd, buf, sizeof (buf))) > 0)
+      while ((bytes_read = g_input_stream_read (input, buf, sizeof (buf), cancellable, error)) > 0)
         g_checksum_update (content_sha256, buf, bytes_read);
       if (bytes_read < 0)
-        {
-          ot_util_set_error_from_errno (error, errno);
-          goto out;
-        }
+        goto out;
     }
-  else if (S_ISLNK(stbuf.st_mode))
+  else if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_SYMBOLIC_LINK)
     {
-      symlink_target = g_malloc (PATH_MAX);
+      const char *symlink_target = g_file_info_get_symlink_target (file_info);
 
       g_assert (objtype == OSTREE_OBJECT_TYPE_FILE);
+      g_assert (symlink_target != NULL);
       
-      bytes_read = readlinkat (dir_fd, basename, symlink_target, PATH_MAX);
-      if (bytes_read < 0)
-        {
-          ot_util_set_error_from_errno (error, errno);
-          goto out;
-        }
-      g_checksum_update (content_sha256, (guint8*)symlink_target, bytes_read);
+      g_checksum_update (content_sha256, (guint8*)symlink_target, strlen (symlink_target));
     }
-  else if (S_ISCHR(stbuf.st_mode) || S_ISBLK(stbuf.st_mode))
+  else if (S_ISCHR(unix_mode) || S_ISBLK(unix_mode))
     {
+      guint32 rdev = g_file_info_get_attribute_uint32 (file_info, "unix::rdev");
       g_assert (objtype == OSTREE_OBJECT_TYPE_FILE);
-      device_id = g_strdup_printf ("%u", (guint)stbuf.st_rdev);
-      g_checksum_update (content_sha256, (guint8*)device_id, strlen (device_id));
+      rdev = GUINT32_TO_BE (rdev);
+      g_checksum_update (content_sha256, (guint8*)&rdev, 4);
     }
-  else if (S_ISFIFO(stbuf.st_mode))
+  else if (S_ISFIFO(unix_mode))
     {
       g_assert (objtype == OSTREE_OBJECT_TYPE_FILE);
     }
@@ -283,23 +261,19 @@ ostree_stat_and_checksum_file (int dir_fd, const char *path,
 
   if (objtype == OSTREE_OBJECT_TYPE_FILE)
     {
-      ostree_checksum_update_stat (content_and_meta_sha256, stbuf.st_uid,
-                                   stbuf.st_gid, stbuf.st_mode);
+      ostree_checksum_update_stat (content_and_meta_sha256,
+                                   g_file_info_get_attribute_uint32 (file_info, "unix::uid"),
+                                   g_file_info_get_attribute_uint32 (file_info, "unix::gid"),
+                                   g_file_info_get_attribute_uint32 (file_info, "unix::mode"));
       g_checksum_update (content_and_meta_sha256, (guint8*)g_variant_get_data (xattrs), g_variant_get_size (xattrs));
     }
 
-  *out_stbuf = stbuf;
   *out_checksum = content_and_meta_sha256;
   ret = TRUE;
  out:
-  g_clear_object (&f);
-  if (fd >= 0)
-    close (fd);
-  if (temp_dir != NULL)
-    closedir (temp_dir);
-  g_free (symlink_target);
+  g_clear_object (&input);
+  g_clear_object (&file_info);
   g_free (basename);
-  g_free (stat_string);
   if (xattrs)
     g_variant_unref (xattrs);
   if (content_sha256)
diff --git a/src/libostree/ostree-core.h b/src/libostree/ostree-core.h
index ba5320e..38d08ed 100644
--- a/src/libostree/ostree-core.h
+++ b/src/libostree/ostree-core.h
@@ -92,6 +92,8 @@ typedef enum {
 gboolean ostree_validate_checksum_string (const char *sha256,
                                           GError    **error);
 
+void ostree_checksum_update_stat (GChecksum *checksum, guint32 uid, guint32 gid, guint32 mode);
+
 char *ostree_get_relative_object_path (const char *checksum,
                                        OstreeObjectType type,
                                        gboolean         archive);
@@ -107,11 +109,11 @@ gboolean ostree_parse_metadata_file (GFile                       *file,
                                      GVariant                   **out_variant,
                                      GError                     **error);
 
-gboolean ostree_stat_and_checksum_file (int dirfd, const char *path,
-                                        OstreeObjectType type,
-                                        GChecksum **out_checksum,
-                                        struct stat *out_stbuf,
-                                        GError **error);
+gboolean ostree_checksum_file (GFile             *f,
+                               OstreeObjectType   type,
+                               GChecksum        **out_checksum,
+                               GCancellable      *cancellable,
+                               GError           **error);
 
 gboolean ostree_get_directory_metadata (GFile *dir,
                                         GVariant  **out_metadata,
@@ -154,7 +156,5 @@ gboolean ostree_unpack_object (const char   *path,
                                GChecksum   **out_checksum,
                                GError      **error);
 
-void ostree_checksum_update_stat (GChecksum *checksum, guint32 uid, guint32 gid, guint32 mode);
-
 
 #endif /* _OSTREE_REPO */
diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c
index 5925833..60f38ba 100644
--- a/src/libostree/ostree-repo.c
+++ b/src/libostree/ostree-repo.c
@@ -1211,13 +1211,15 @@ add_one_file_to_tree_and_import (OstreeRepo   *self,
 {
   gboolean ret = FALSE;
   GChecksum *checksum = NULL;
-  struct stat stbuf;
   gboolean did_exist;
+  GFile *f = NULL;
   
   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
   g_assert (tree != NULL);
 
-  if (!ostree_stat_and_checksum_file (-1, abspath, OSTREE_OBJECT_TYPE_FILE, &checksum, &stbuf, error))
+  f = ot_util_new_file_for_path (abspath);
+
+  if (!ostree_checksum_file (f, OSTREE_OBJECT_TYPE_FILE, &checksum, NULL, error))
     goto out;
 
   if (!ostree_repo_store_object_trusted (self, abspath, g_checksum_get_string (checksum),
@@ -1229,6 +1231,7 @@ add_one_file_to_tree_and_import (OstreeRepo   *self,
 
   ret = TRUE;
  out:
+  g_clear_object (&f);
   if (checksum)
     g_checksum_free (checksum);
   return ret;
@@ -1884,7 +1887,6 @@ get_file_checksum (GFile  *f,
   GVariant *dirmeta = NULL;
   GVariant *packed_dirmeta = NULL;
   char *ret_checksum = NULL;
-  struct stat stbuf;
 
   if (OSTREE_IS_REPO_FILE (f))
     {
@@ -1904,9 +1906,8 @@ get_file_checksum (GFile  *f,
         }
       else
         {
-          if (!ostree_stat_and_checksum_file (-1, ot_gfile_get_path_cached (f),
-                                              OSTREE_OBJECT_TYPE_FILE,
-                                              &tmp_checksum, &stbuf, error))
+          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));
         }
diff --git a/src/ostree/ot-builtin-fsck.c b/src/ostree/ot-builtin-fsck.c
index 3cc72b9..f9d748b 100644
--- a/src/ostree/ot-builtin-fsck.c
+++ b/src/ostree/ot-builtin-fsck.c
@@ -121,7 +121,6 @@ object_iter_callback (OstreeRepo  *repo,
                       gpointer       user_data)
 {
   OtFsckData *data = user_data;
-  struct stat stbuf;
   GChecksum *checksum = NULL;
   GError *error = NULL;
   char *dirname = NULL;
@@ -131,6 +130,9 @@ object_iter_callback (OstreeRepo  *repo,
   gboolean packed = FALSE;
   OstreeObjectType objtype;
   char *dot;
+  GFile *f = NULL;
+
+  f = ot_util_new_file_for_path (path);
 
   /* nlinks = g_file_info_get_attribute_uint32 (file_info, "unix::nlink");
      if (nlinks < 2 && !quiet)
@@ -155,7 +157,7 @@ object_iter_callback (OstreeRepo  *repo,
     }
   else
     {
-      if (!ostree_stat_and_checksum_file (-1, path, objtype, &checksum, &stbuf, &error))
+      if (!ostree_checksum_file (f, objtype, &checksum, NULL, &error))
         goto out;
     }
 
@@ -178,6 +180,7 @@ object_iter_callback (OstreeRepo  *repo,
   data->n_objects++;
 
  out:
+  g_clear_object (&f);
   if (checksum != NULL)
     g_checksum_free (checksum);
   g_free (dirname);
diff --git a/tests/t0000-basic.sh b/tests/t0000-basic.sh
index 1485acc..0fd53f2 100755
--- a/tests/t0000-basic.sh
+++ b/tests/t0000-basic.sh
@@ -26,8 +26,8 @@ echo "1..15"
 setup_test_repository "regular"
 echo "ok setup"
 
-assert_file_has_content ${test_tmpdir}/repo/objects/f2/c7a70e5e252c1cb7a018d98f34cbf01d553185e9adc775e10213f4187fa91a.file moo
-assert_streq "$(readlink ${test_tmpdir}/repo/objects/cf/443bea5eb400bc25b376c07925cc06cd05235d5fb38f20cd5f7ca53b7b3b10.file)" nonexistent
+assert_file_has_content ${test_tmpdir}/repo/objects/3a/9b4a6fb6885c2548e35c9382b316ad073ef7c1872a97cc9661e6403777cbaf.file moo
+assert_streq "$(readlink ${test_tmpdir}/repo/objects/d4/69b152ab4c8ddcfdfd5b15510560bcb76ae4ffea6eace4074435e5a5d05622.file)" nonexistent
 
 echo "ok check"
 



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