core: Make checksum API also operate on directories
This commit is contained in:
parent
b8cef545d1
commit
7f64d5cec7
|
|
@ -41,6 +41,12 @@ ostree_validate_checksum_string (const char *sha256,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GVariant *
|
||||||
|
ostree_wrap_metadata_variant (OstreeSerializedVariantType type,
|
||||||
|
GVariant *metadata)
|
||||||
|
{
|
||||||
|
return g_variant_new ("(uv)", GUINT32_TO_BE ((guint32)type), metadata);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ostree_checksum_update_stat (GChecksum *checksum, guint32 uid, guint32 gid, guint32 mode)
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
static gboolean
|
||||||
ostree_checksum_file (GFile *f,
|
checksum_directory (GFile *f,
|
||||||
OstreeObjectType objtype,
|
GFileInfo *f_info,
|
||||||
GChecksum **out_checksum,
|
GChecksum **out_checksum,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error)
|
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;
|
const char *path = NULL;
|
||||||
GChecksum *content_sha256 = NULL;
|
GChecksum *content_sha256 = NULL;
|
||||||
GChecksum *content_and_meta_sha256 = NULL;
|
GChecksum *content_and_meta_sha256 = NULL;
|
||||||
ssize_t bytes_read;
|
ssize_t bytes_read;
|
||||||
GVariant *xattrs = NULL;
|
GVariant *xattrs = NULL;
|
||||||
char *basename = NULL;
|
char *basename = NULL;
|
||||||
gboolean ret = FALSE;
|
|
||||||
GFileInfo *file_info = NULL;
|
|
||||||
GInputStream *input = NULL;
|
GInputStream *input = NULL;
|
||||||
guint32 unix_mode;
|
guint32 unix_mode;
|
||||||
|
|
||||||
path = ot_gfile_get_path_cached (f);
|
path = ot_gfile_get_path_cached (f);
|
||||||
basename = g_path_get_basename (path);
|
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)
|
if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR)
|
||||||
{
|
{
|
||||||
input = (GInputStream*)g_file_read (f, cancellable, error);
|
input = (GInputStream*)g_file_read (f, cancellable, error);
|
||||||
|
|
@ -272,7 +304,6 @@ ostree_checksum_file (GFile *f,
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
out:
|
out:
|
||||||
g_clear_object (&input);
|
g_clear_object (&input);
|
||||||
g_clear_object (&file_info);
|
|
||||||
g_free (basename);
|
g_free (basename);
|
||||||
if (xattrs)
|
if (xattrs)
|
||||||
g_variant_unref (xattrs);
|
g_variant_unref (xattrs);
|
||||||
|
|
@ -281,39 +312,62 @@ ostree_checksum_file (GFile *f,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
gboolean
|
||||||
ostree_get_directory_metadata (GFile *dir,
|
ostree_get_directory_metadata (GFile *dir,
|
||||||
|
GFileInfo *dir_info,
|
||||||
GVariant **out_metadata,
|
GVariant **out_metadata,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
struct stat stbuf;
|
|
||||||
GVariant *xattrs = NULL;
|
GVariant *xattrs = NULL;
|
||||||
GVariant *ret_metadata = 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);
|
xattrs = ostree_get_xattrs_for_file (dir, error);
|
||||||
if (!xattrs)
|
if (!xattrs)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret_metadata = g_variant_new ("(uuuu@a(ayay))",
|
ret_metadata = g_variant_new ("(uuuu@a(ayay))",
|
||||||
OSTREE_DIR_META_VERSION,
|
OSTREE_DIR_META_VERSION,
|
||||||
GUINT32_TO_BE ((guint32)stbuf.st_uid),
|
GUINT32_TO_BE (g_file_info_get_attribute_uint32 (dir_info, "unix::uid")),
|
||||||
GUINT32_TO_BE ((guint32)stbuf.st_gid),
|
GUINT32_TO_BE (g_file_info_get_attribute_uint32 (dir_info, "unix::gid")),
|
||||||
GUINT32_TO_BE ((guint32)stbuf.st_mode),
|
GUINT32_TO_BE (g_file_info_get_attribute_uint32 (dir_info, "unix::mode")),
|
||||||
xattrs);
|
xattrs);
|
||||||
g_variant_ref_sink (ret_metadata);
|
g_variant_ref_sink (ret_metadata);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,9 @@ char *ostree_get_relative_object_path (const char *checksum,
|
||||||
GVariant *ostree_get_xattrs_for_file (GFile *f,
|
GVariant *ostree_get_xattrs_for_file (GFile *f,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
GVariant *ostree_wrap_metadata_variant (OstreeSerializedVariantType type,
|
||||||
|
GVariant *metadata);
|
||||||
|
|
||||||
gboolean ostree_set_xattrs (GFile *f, GVariant *xattrs,
|
gboolean ostree_set_xattrs (GFile *f, GVariant *xattrs,
|
||||||
GCancellable *cancellable, GError **error);
|
GCancellable *cancellable, GError **error);
|
||||||
|
|
||||||
|
|
@ -116,6 +119,7 @@ gboolean ostree_checksum_file (GFile *f,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
gboolean ostree_get_directory_metadata (GFile *dir,
|
gboolean ostree_get_directory_metadata (GFile *dir,
|
||||||
|
GFileInfo *dir_info,
|
||||||
GVariant **out_metadata,
|
GVariant **out_metadata,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
|
||||||
|
|
@ -557,13 +557,6 @@ ostree_repo_is_archive (OstreeRepo *self)
|
||||||
return priv->archive;
|
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
|
static gboolean
|
||||||
write_gvariant_to_tmp (OstreeRepo *self,
|
write_gvariant_to_tmp (OstreeRepo *self,
|
||||||
OstreeSerializedVariantType type,
|
OstreeSerializedVariantType type,
|
||||||
|
|
@ -582,7 +575,7 @@ write_gvariant_to_tmp (OstreeRepo *self,
|
||||||
GUnixOutputStream *stream = NULL;
|
GUnixOutputStream *stream = NULL;
|
||||||
GChecksum *checksum = 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);
|
tmp_name = g_build_filename (ot_gfile_get_path_cached (priv->tmp_dir), "variant-tmp-XXXXXX", NULL);
|
||||||
fd = g_mkstemp (tmp_name);
|
fd = g_mkstemp (tmp_name);
|
||||||
|
|
@ -709,10 +702,17 @@ import_directory_meta (OstreeRepo *self,
|
||||||
GChecksum *ret_checksum = NULL;
|
GChecksum *ret_checksum = NULL;
|
||||||
GVariant *dirmeta = NULL;
|
GVariant *dirmeta = NULL;
|
||||||
GFile *f = NULL;
|
GFile *f = NULL;
|
||||||
|
GFileInfo *f_info = NULL;
|
||||||
|
|
||||||
f = ot_util_new_file_for_path (path);
|
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;
|
goto out;
|
||||||
|
|
||||||
if (!import_gvariant_object (self, OSTREE_SERIALIZED_DIRMETA_VARIANT,
|
if (!import_gvariant_object (self, OSTREE_SERIALIZED_DIRMETA_VARIANT,
|
||||||
|
|
@ -726,6 +726,7 @@ import_directory_meta (OstreeRepo *self,
|
||||||
ret_checksum = NULL;
|
ret_checksum = NULL;
|
||||||
out:
|
out:
|
||||||
g_clear_object (&f);
|
g_clear_object (&f);
|
||||||
|
g_clear_object (&f_info);
|
||||||
if (ret_checksum)
|
if (ret_checksum)
|
||||||
g_checksum_free (ret_checksum);
|
g_checksum_free (ret_checksum);
|
||||||
if (dirmeta != NULL)
|
if (dirmeta != NULL)
|
||||||
|
|
@ -1884,8 +1885,6 @@ get_file_checksum (GFile *f,
|
||||||
{
|
{
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
GChecksum *tmp_checksum = NULL;
|
GChecksum *tmp_checksum = NULL;
|
||||||
GVariant *dirmeta = NULL;
|
|
||||||
GVariant *packed_dirmeta = NULL;
|
|
||||||
char *ret_checksum = NULL;
|
char *ret_checksum = NULL;
|
||||||
|
|
||||||
if (OSTREE_IS_REPO_FILE (f))
|
if (OSTREE_IS_REPO_FILE (f))
|
||||||
|
|
@ -1894,36 +1893,18 @@ get_file_checksum (GFile *f,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (g_file_info_get_file_type (f_info) == G_FILE_TYPE_DIRECTORY)
|
if (!ostree_checksum_file (f, OSTREE_OBJECT_TYPE_FILE,
|
||||||
{
|
&tmp_checksum, cancellable, error))
|
||||||
tmp_checksum = g_checksum_new (G_CHECKSUM_SHA256);
|
goto out;
|
||||||
if (!ostree_get_directory_metadata (f, &dirmeta, cancellable, error))
|
ret_checksum = g_strdup (g_checksum_get_string (tmp_checksum));
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
*out_checksum = ret_checksum;
|
*out_checksum = ret_checksum;
|
||||||
ret_checksum = NULL;
|
ret_checksum = NULL;
|
||||||
out:
|
out:
|
||||||
g_free (ret_checksum);
|
|
||||||
if (tmp_checksum)
|
if (tmp_checksum)
|
||||||
g_checksum_free (tmp_checksum);
|
g_checksum_free (tmp_checksum);
|
||||||
if (dirmeta)
|
|
||||||
g_variant_unref (dirmeta);
|
|
||||||
if (packed_dirmeta)
|
|
||||||
g_variant_unref (packed_dirmeta);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue