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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
@ -281,39 +312,62 @@ ostree_checksum_file (GFile *f,
|
|||
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
|
||||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue