diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c index aa03c3c0..8caff3f4 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); - } + 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 (fstatat (dir_fd, basename, &stbuf, AT_SYMLINK_NOFOLLOW) < 0) + if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR) { - ot_util_set_error_from_errno (error, errno); - goto out; - } - - if (S_ISREG(stbuf.st_mode)) - { - 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 ba5320ee..38d08ed6 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 59258338..60f38ba3 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 3cc72b9d..f9d748b6 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 1485acc2..0fd53f22 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"