mirror of
https://github.com/ostreedev/ostree.git
synced 2024-12-25 01:34:34 +03:00
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.
This commit is contained in:
parent
2c2b9c0e00
commit
b8cef545d1
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user