[ostree/wip/objtype] more WIP
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ostree/wip/objtype] more WIP
- Date: Thu, 15 Dec 2011 04:39:08 +0000 (UTC)
commit 5a96d4e10f87831bf786947781f785f7371f5b07
Author: Colin Walters <walters verbum org>
Date: Wed Dec 14 23:38:30 2011 -0500
more WIP
src/libostree/ostree-core.c | 143 +++++++++++++------------
src/libostree/ostree-core.h | 16 ++--
src/libostree/ostree-repo-file.c | 4 +-
src/libostree/ostree-repo.c | 200 +++++++++++++++++++++++------------
src/ostree/ostree-pull.c | 6 +
src/ostree/ot-builtin-fsck.c | 43 ++++----
src/ostree/ot-builtin-local-clone.c | 16 +++-
7 files changed, 256 insertions(+), 172 deletions(-)
---
diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c
index 4b38c4e..e7c45fc 100644
--- a/src/libostree/ostree-core.c
+++ b/src/libostree/ostree-core.c
@@ -245,13 +245,16 @@ ostree_checksum_file_from_input (GFileInfo *file_info,
goto out;
}
- ostree_checksum_update_stat (ret_checksum,
- 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"));
- /* FIXME - ensure empty xattrs are the same as NULL xattrs */
- if (xattrs)
- g_checksum_update (ret_checksum, (guint8*)g_variant_get_data (xattrs), g_variant_get_size (xattrs));
+ if (objtype != OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT)
+ {
+ ostree_checksum_update_stat (ret_checksum,
+ 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"));
+ /* FIXME - ensure empty xattrs are the same as NULL xattrs */
+ if (xattrs)
+ g_checksum_update (ret_checksum, (guint8*)g_variant_get_data (xattrs), g_variant_get_size (xattrs));
+ }
ret = TRUE;
ot_transfer_out_value (out_checksum, &ret_checksum);
@@ -291,7 +294,7 @@ ostree_checksum_file (GFile *f,
goto out;
}
- if (!OSTREE_OBJECT_TYPE_IS_META(objtype))
+ if (objtype == OSTREE_OBJECT_TYPE_RAW_FILE)
{
xattrs = ostree_get_xattrs_for_file (f, error);
if (!xattrs)
@@ -454,7 +457,7 @@ ostree_parse_metadata_file (GFile *file,
GVariant *container = NULL;
guint32 actual_type;
- if (!ot_util_variant_map (file, G_VARIANT_TYPE (OSTREE_SERIALIZED_VARIANT_FORMAT),
+ if (!ot_util_variant_map (file, OSTREE_SERIALIZED_VARIANT_FORMAT,
&container, error))
goto out;
@@ -486,12 +489,53 @@ ostree_parse_metadata_file (GFile *file,
return ret;
}
+const char *
+ostree_object_type_to_string (OstreeObjectType objtype)
+{
+ switch (objtype)
+ {
+ case OSTREE_OBJECT_TYPE_RAW_FILE:
+ return "file";
+ case OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT:
+ return "archive-content";
+ case OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META:
+ return "archive-meta";
+ case OSTREE_OBJECT_TYPE_DIR_TREE:
+ return "dirtree";
+ case OSTREE_OBJECT_TYPE_DIR_META:
+ return "dirmeta";
+ case OSTREE_OBJECT_TYPE_COMMIT:
+ return "commit";
+ default:
+ g_assert_not_reached ();
+ return NULL;
+ }
+}
+
+OstreeObjectType
+ostree_object_type_from_string (const char *str)
+{
+ if (!strcmp (str, "file"))
+ return OSTREE_OBJECT_TYPE_RAW_FILE;
+ else if (!strcmp (str, "archive-content"))
+ return OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT;
+ else if (!strcmp (str, "archive-meta"))
+ return OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META;
+ else if (!strcmp (str, "dirtree"))
+ return OSTREE_OBJECT_TYPE_DIR_TREE;
+ else if (!strcmp (str, "dirmeta"))
+ return OSTREE_OBJECT_TYPE_DIR_META;
+ else if (!strcmp (str, "commit"))
+ return OSTREE_OBJECT_TYPE_COMMIT;
+ g_assert_not_reached ();
+ return 0;
+}
+
char *
ostree_get_relative_object_path (const char *checksum,
OstreeObjectType type)
{
GString *path;
- const char *type_string;
g_assert (strlen (checksum) == 64);
@@ -500,37 +544,15 @@ ostree_get_relative_object_path (const char *checksum,
g_string_append_len (path, checksum, 2);
g_string_append_c (path, '/');
g_string_append (path, checksum + 2);
- switch (type)
- {
- case OSTREE_OBJECT_TYPE_RAW_FILE:
- type_string = ".file";
- break;
- case OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT:
- type_string = ".archive-content";
- break;
- case OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META:
- type_string = ".archive-meta";
- break;
- case OSTREE_OBJECT_TYPE_DIR_TREE:
- type_string = ".dirtree";
- break;
- case OSTREE_OBJECT_TYPE_DIR_META:
- type_string = ".dirmeta";
- break;
- case OSTREE_OBJECT_TYPE_COMMIT:
- type_string = ".commit";
- break;
- default:
- g_assert_not_reached ();
- }
- g_string_append (path, type_string);
+ g_string_append_c (path, '.');
+ g_string_append (path, ostree_object_type_to_string (type));
+
return g_string_free (path, FALSE);
}
GVariant *
ostree_create_archive_file_metadata (GFileInfo *finfo,
- GVariant *xattrs,
- const char *content_checksum)
+ GVariant *xattrs)
{
guint32 uid, gid, mode, rdev;
GVariantBuilder pack_builder;
@@ -543,8 +565,6 @@ ostree_create_archive_file_metadata (GFileInfo *finfo,
g_variant_builder_init (&pack_builder, OSTREE_ARCHIVED_FILE_VARIANT_FORMAT);
g_variant_builder_add (&pack_builder, "u", GUINT32_TO_BE (0)); /* Version */
- /* If you later add actual metadata here, don't forget to byteswap it to Big Endian if necessary */
- g_variant_builder_add (&pack_builder, "@a{sv}", g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0));
g_variant_builder_add (&pack_builder, "u", GUINT32_TO_BE (uid));
g_variant_builder_add (&pack_builder, "u", GUINT32_TO_BE (gid));
g_variant_builder_add (&pack_builder, "u", GUINT32_TO_BE (mode));
@@ -556,8 +576,6 @@ ostree_create_archive_file_metadata (GFileInfo *finfo,
g_variant_builder_add (&pack_builder, "@a(ayay)", xattrs ? xattrs : g_variant_new_array (G_VARIANT_TYPE ("(ayay)"), NULL, 0));
- g_variant_builder_add (&pack_builder, "s", content_checksum);
-
ret = g_variant_builder_end (&pack_builder);
g_variant_ref_sink (ret);
@@ -568,20 +586,17 @@ gboolean
ostree_parse_archived_file_meta (GVariant *metadata,
GFileInfo **out_file_info,
GVariant **out_xattrs,
- char **out_content_checksum,
GError **error)
{
gboolean ret = FALSE;
GFileInfo *ret_file_info = NULL;
- GVariant *metametadata = NULL;
GVariant *ret_xattrs = NULL;
guint32 version, uid, gid, mode, rdev;
const char *symlink_target;
- char *ret_content_checksum;
- g_variant_get (metadata, "(u a{sv}uuuu&s a(ayay)s)",
- &version, &metametadata, &uid, &gid, &mode, &rdev,
- &symlink_target, &ret_xattrs, &ret_content_checksum);
+ g_variant_get (metadata, "(uuuuu&s a(ayay))",
+ &version, &uid, &gid, &mode, &rdev,
+ &symlink_target, &ret_xattrs);
version = GUINT32_FROM_BE (version);
if (version != 0)
@@ -596,12 +611,6 @@ ostree_parse_archived_file_meta (GVariant *metadata,
mode = GUINT32_FROM_BE (mode);
rdev = GUINT32_FROM_BE (rdev);
- if (!ostree_validate_checksum_string (ret_content_checksum, error))
- {
- g_prefix_error (error, "While parsing archived file metadata: ");
- goto out;
- }
-
ret_file_info = g_file_info_new ();
g_file_info_set_attribute_uint32 (ret_file_info, "standard::type", ot_gfile_type_for_mode (mode));
g_file_info_set_attribute_boolean (ret_file_info, "standard::is-symlink", S_ISLNK (mode));
@@ -635,12 +644,9 @@ ostree_parse_archived_file_meta (GVariant *metadata,
ret = TRUE;
ot_transfer_out_value(out_file_info, &ret_file_info);
ot_transfer_out_value(out_xattrs, &ret_xattrs);
- ot_transfer_out_value(out_content_checksum, &ret_content_checksum);
out:
g_clear_object (&ret_file_info);
ot_clear_gvariant (&ret_xattrs);
- ot_clear_gvariant (&metametadata);
- g_free (ret_content_checksum);
return ret;
}
@@ -659,7 +665,11 @@ ostree_create_file_from_input (GFile *dest_file,
GFileOutputStream *out = NULL;
guint32 uid, gid, mode;
GChecksum *ret_checksum = NULL;
- gboolean is_meta = OSTREE_OBJECT_TYPE_IS_META (objtype);
+ gboolean is_meta;
+ gboolean is_archived_content;
+
+ is_meta = OSTREE_OBJECT_TYPE_IS_META (objtype);
+ is_archived_content = objtype == OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT;
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return FALSE;
@@ -670,14 +680,13 @@ ostree_create_file_from_input (GFile *dest_file,
}
else
{
- mode = S_IFREG | 0666;
+ mode = S_IFREG | 0664;
}
dest_path = ot_gfile_get_path_cached (dest_file);
if (S_ISDIR (mode))
{
- if (mkdir (ot_gfile_get_path_cached (dest_file),
- g_file_info_get_attribute_uint32 (finfo, "unix::mode")) < 0)
+ if (mkdir (ot_gfile_get_path_cached (dest_file), mode) < 0)
{
ot_util_set_error_from_errno (error, errno);
goto out;
@@ -748,7 +757,7 @@ ostree_create_file_from_input (GFile *dest_file,
goto out;
}
- if (finfo != NULL)
+ if (finfo != NULL && !is_meta && !is_archived_content)
{
uid = g_file_info_get_attribute_uint32 (finfo, "unix::uid");
gid = g_file_info_get_attribute_uint32 (finfo, "unix::gid");
@@ -759,11 +768,6 @@ ostree_create_file_from_input (GFile *dest_file,
goto out;
}
}
- else
- {
- uid = geteuid ();
- gid = getegid ();
- }
if (!S_ISLNK (mode))
{
@@ -781,9 +785,14 @@ ostree_create_file_from_input (GFile *dest_file,
goto out;
}
- if (ret_checksum && !is_meta)
+ if (ret_checksum && !is_meta && !is_archived_content)
{
- ostree_checksum_update_stat (ret_checksum, uid, gid, mode);
+ g_assert (finfo != NULL);
+
+ ostree_checksum_update_stat (ret_checksum,
+ g_file_info_get_attribute_uint32 (finfo, "unix::uid"),
+ g_file_info_get_attribute_uint32 (finfo, "unix::gid"),
+ mode);
if (xattrs)
g_checksum_update (ret_checksum, (guint8*)g_variant_get_data (xattrs), g_variant_get_size (xattrs));
}
diff --git a/src/libostree/ostree-core.h b/src/libostree/ostree-core.h
index 08100e0..e18ba91 100644
--- a/src/libostree/ostree-core.h
+++ b/src/libostree/ostree-core.h
@@ -43,7 +43,7 @@ typedef enum {
#define OSTREE_OBJECT_TYPE_IS_META(t) (t >= 3 && t <= 6)
#define OSTREE_OBJECT_TYPE_LAST OSTREE_OBJECT_TYPE_COMMIT
-#define OSTREE_SERIALIZED_VARIANT_FORMAT "(uv)"
+#define OSTREE_SERIALIZED_VARIANT_FORMAT G_VARIANT_TYPE("(uv)")
/*
* xattr objects:
@@ -87,25 +87,25 @@ typedef enum {
#define OSTREE_COMMIT_GVARIANT_FORMAT "(ua{sv}ssstss)"
/* Archive file objects:
- *
- * metadata variant:
* u - Version
- * a(sv) - metadata (yes I put metadata in your metadata)
* u - uid
* u - gid
* u - mode
* u - rdev
* s - symlink target
* a(ayay) - xattrs
- * s - content checksum
*/
-#define OSTREE_ARCHIVED_FILE_VARIANT_FORMAT G_VARIANT_TYPE ("(ua{sv}uuuusa(ayay)s)")
+#define OSTREE_ARCHIVED_FILE_VARIANT_FORMAT G_VARIANT_TYPE ("(uuuuusa(ayay))")
gboolean ostree_validate_checksum_string (const char *sha256,
GError **error);
void ostree_checksum_update_stat (GChecksum *checksum, guint32 uid, guint32 gid, guint32 mode);
+const char * ostree_object_type_to_string (OstreeObjectType objtype);
+
+OstreeObjectType ostree_object_type_from_string (const char *str);
+
char *ostree_get_relative_object_path (const char *checksum,
OstreeObjectType type);
@@ -181,13 +181,11 @@ gboolean ostree_create_temp_regular_file (GFile *dir,
GError **error);
GVariant *ostree_create_archive_file_metadata (GFileInfo *file_info,
- GVariant *xattrs,
- const char *content_checksum);
+ GVariant *xattrs);
gboolean ostree_parse_archived_file_meta (GVariant *data,
GFileInfo **out_file_info,
GVariant **out_xattrs,
- char **out_content_checksum,
GError **error);
diff --git a/src/libostree/ostree-repo-file.c b/src/libostree/ostree-repo-file.c
index d8e3b8f..81222d8 100644
--- a/src/libostree/ostree-repo-file.c
+++ b/src/libostree/ostree-repo-file.c
@@ -323,7 +323,7 @@ _ostree_repo_file_get_xattrs (OstreeRepoFile *self,
&metadata, error))
goto out;
- if (!ostree_parse_archived_file_meta (metadata, NULL, &ret_xattrs, NULL, error))
+ if (!ostree_parse_archived_file_meta (metadata, NULL, &ret_xattrs, error))
goto out;
}
else
@@ -1041,7 +1041,7 @@ _ostree_repo_file_tree_query_child (OstreeRepoFile *self,
if (!ostree_parse_metadata_file (local_child, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META,
&archive_metadata, error))
goto out;
- if (!ostree_parse_archived_file_meta (archive_metadata, &ret_info, NULL, NULL, error))
+ if (!ostree_parse_archived_file_meta (archive_metadata, &ret_info, NULL, error))
goto out;
}
else
diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c
index 4be3a35..0722b11 100644
--- a/src/libostree/ostree-repo.c
+++ b/src/libostree/ostree-repo.c
@@ -37,8 +37,6 @@
#include "ostree-libarchive-input-stream.h"
#endif
-#define PENDING_TRANSACTION_OBJECT_GVARIANT_FORMAT (G_VARIANT_TYPE("(us)"))
-
enum {
PROP_0,
@@ -185,7 +183,7 @@ ostree_repo_init (OstreeRepo *self)
priv->pending_transaction_tmpfiles = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free,
- (GDestroyNotify)g_variant_unref);
+ g_free);
}
OstreeRepo*
@@ -670,6 +668,13 @@ ostree_repo_get_file_object_path (OstreeRepo *self,
return ostree_repo_get_object_path (self, checksum, get_objtype_for_repo_file (self));
}
+static char *
+create_checksum_and_objtype (const char *checksum,
+ OstreeObjectType objtype)
+{
+ return g_strconcat (checksum, ".", ostree_object_type_to_string (objtype), NULL);
+}
+
gboolean
ostree_repo_has_object (OstreeRepo *self,
OstreeObjectType objtype,
@@ -680,9 +685,12 @@ ostree_repo_has_object (OstreeRepo *self,
{
gboolean ret = FALSE;
OstreeRepoPrivate *priv = GET_PRIVATE (self);
+ char *tmp_key = NULL;
GFile *object_path = NULL;
- if (g_hash_table_lookup (priv->pending_transaction_tmpfiles, checksum))
+ tmp_key = create_checksum_and_objtype (checksum, objtype);
+
+ if (g_hash_table_lookup (priv->pending_transaction_tmpfiles, tmp_key))
{
*out_have_object = TRUE;
}
@@ -695,6 +703,7 @@ ostree_repo_has_object (OstreeRepo *self,
ret = TRUE;
/* out: */
+ g_free (tmp_key);
g_clear_object (&object_path);
return ret;
}
@@ -745,30 +754,44 @@ impl_stage_archive_file_object_from_raw (OstreeRepo *self,
if (!ostree_create_temp_file_from_input (priv->tmp_dir,
"archive-tmp-", NULL,
temp_info, NULL, input,
- OSTREE_OBJECT_TYPE_RAW_FILE,
+ OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT,
&temp_file,
- &content_checksum,
+ &ret_checksum,
cancellable, error))
goto out;
-
- archive_metadata = ostree_create_archive_file_metadata (file_info, xattrs,
- g_checksum_get_string (content_checksum));
-
+
+ ostree_checksum_update_stat (ret_checksum,
+ 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"));
+ /* FIXME - ensure empty xattrs are the same as NULL xattrs */
+ if (xattrs)
+ g_checksum_update (ret_checksum, (guint8*)g_variant_get_data (xattrs), g_variant_get_size (xattrs));
+
+ if (expected_checksum && strcmp (g_checksum_get_string (ret_checksum), expected_checksum) != 0)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Corrupted object %s (actual checksum is %s)",
+ expected_checksum, g_checksum_get_string (ret_checksum));
+ goto out;
+ }
+
g_hash_table_insert (priv->pending_transaction_tmpfiles,
- g_strdup (g_checksum_get_string (content_checksum)),
- g_variant_new ("(us)", OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT,
- ot_gfile_get_basename_cached (temp_file)));
+ create_checksum_and_objtype (g_checksum_get_string (ret_checksum), OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT),
+ g_strdup (ot_gfile_get_basename_cached (temp_file)));
+
+ archive_metadata = ostree_create_archive_file_metadata (file_info, xattrs);
serialized = ostree_wrap_metadata_variant (OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META, archive_metadata);
mem = g_memory_input_stream_new_from_data (g_variant_get_data (serialized),
g_variant_get_size (serialized),
NULL);
-
+
if (!stage_object (self, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META,
NULL, NULL, mem,
- expected_checksum, out_checksum ? &ret_checksum : NULL, cancellable, error))
+ g_checksum_get_string (ret_checksum), NULL, cancellable, error))
goto out;
-
+
ret = TRUE;
ot_transfer_out_value (out_checksum, &ret_checksum);
out:
@@ -795,73 +818,95 @@ impl_stage_raw_file_object_from_archive (OstreeRepo *self,
gboolean ret = FALSE;
OstreeRepoPrivate *priv = GET_PRIVATE (self);
GFile *temp_file = NULL;
- GChecksum *ret_checksum = NULL;
GVariant *archive_metadata = NULL;
GMemoryOutputStream *tmp_archive_meta = NULL;
GFileInfo *archived_info = NULL;
GVariant *archived_xattrs = NULL;
- char *archived_content_checksum = NULL;
- GVariant *archived_content = NULL; /* const */
- guint32 pending_objtype;
+ char *archived_content_key = NULL;
const char *archived_content_path;
GFile *archived_content_file = NULL;
GInputStream *archived_content_input = NULL;
+ GVariant *variant = NULL;
+ guint32 archive_meta_objtype;
+
+ if (!expected_checksum)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ "Can't stage untrusted archive in bare repository");
+ goto out;
+ }
+ g_assert (out_checksum == NULL);
tmp_archive_meta = (GMemoryOutputStream*)g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
- if (!g_output_stream_splice ((GOutputStream*)tmp_archive_meta, input, 0, cancellable, error))
+ if (!g_output_stream_splice ((GOutputStream*)tmp_archive_meta, input, G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, cancellable, error))
goto out;
- archive_metadata = g_variant_new_from_data (OSTREE_ARCHIVED_FILE_VARIANT_FORMAT,
- g_memory_output_stream_get_data (tmp_archive_meta),
- g_memory_output_stream_get_size (tmp_archive_meta),
- FALSE, NULL, NULL);
+ variant = g_variant_new_from_data (OSTREE_SERIALIZED_VARIANT_FORMAT,
+ g_memory_output_stream_get_data (tmp_archive_meta),
+ g_memory_output_stream_get_data_size (tmp_archive_meta),
+ FALSE, (GDestroyNotify)g_object_unref, g_object_ref (tmp_archive_meta));
+ g_clear_object (&tmp_archive_meta);
+
+ g_variant_get (variant, "(uv)", &archive_meta_objtype, &archive_metadata);
+ ot_util_variant_take_ref (archive_metadata);
+ archive_meta_objtype = GUINT32_FROM_BE (archive_meta_objtype);
+ if (archive_meta_objtype != OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Archived file has invalid object type '%d'",
+ archive_meta_objtype);
+ goto out;
+ }
if (!ostree_parse_archived_file_meta (archive_metadata, &archived_info,
- &archived_xattrs, &archived_content_checksum, error))
+ &archived_xattrs, error))
goto out;
+
+ archived_content_key = create_checksum_and_objtype (expected_checksum, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT);
- archived_content = g_hash_table_lookup (priv->pending_transaction_tmpfiles, archived_content_checksum);
- if (archived_content == NULL)
+ archived_content_path = g_hash_table_lookup (priv->pending_transaction_tmpfiles, archived_content_key);
+ if (archived_content_path == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Archived file references uncommitted content '%s'",
- archived_content_checksum);
+ "Archived file references unstaged content '%s'",
+ expected_checksum);
goto out;
}
- g_variant_get (archived_content, "(u&s)", &pending_objtype, &archived_content_path);
- g_assert (pending_objtype == OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT);
-
archived_content_file = g_file_get_child (priv->tmp_dir, archived_content_path);
- archived_content_input = (GInputStream*)g_file_read (archived_content_file, cancellable, error);
- if (!archived_content_input)
- goto out;
+ if (g_file_info_get_file_type (archived_info) == G_FILE_TYPE_REGULAR)
+ {
+ archived_content_input = (GInputStream*)g_file_read (archived_content_file, cancellable, error);
+ if (!archived_content_input)
+ goto out;
+ }
if (!ostree_create_temp_file_from_input (priv->tmp_dir,
"store-tmp-", NULL,
archived_info, archived_xattrs,
archived_content_input,
OSTREE_OBJECT_TYPE_RAW_FILE,
- &temp_file, &ret_checksum,
+ &temp_file, NULL,
cancellable, error))
goto out;
g_hash_table_insert (priv->pending_transaction_tmpfiles,
- g_strdup (g_checksum_get_string (ret_checksum)),
- g_variant_new ("(us)", OSTREE_OBJECT_TYPE_RAW_FILE,
- ot_gfile_get_basename_cached (temp_file)));
+ create_checksum_and_objtype (expected_checksum, OSTREE_OBJECT_TYPE_RAW_FILE),
+ g_strdup (ot_gfile_get_basename_cached (temp_file)));
+ g_hash_table_remove (priv->pending_transaction_tmpfiles, archived_content_key);
ret = TRUE;
out:
g_clear_object (&temp_file);
g_clear_object (&tmp_archive_meta);
+ ot_clear_gvariant (&variant);
ot_clear_gvariant (&archive_metadata);
g_clear_object (&archived_info);
ot_clear_gvariant (&archived_xattrs);
g_clear_object (&archived_content_input);
g_clear_object (&archived_content_file);
- g_free (archived_content_checksum);
+ g_free (archived_content_key);
return ret;
}
@@ -883,6 +928,8 @@ stage_object (OstreeRepo *self,
GFile *temp_file = NULL;
gboolean already_exists;
const char *actual_checksum;
+
+ g_return_val_if_fail (priv->in_transaction, FALSE);
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return FALSE;
@@ -897,6 +944,18 @@ stage_object (OstreeRepo *self,
else
already_exists = FALSE;
+ if (objtype == OSTREE_OBJECT_TYPE_RAW_FILE || objtype == OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT)
+ {
+ g_assert (file_info != NULL);
+ if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR)
+ g_assert (input != NULL);
+ }
+ else if (OSTREE_OBJECT_TYPE_IS_META (objtype))
+ {
+ g_assert (xattrs == NULL);
+ g_assert (input != NULL);
+ }
+
if (!already_exists)
{
if (objtype == OSTREE_OBJECT_TYPE_RAW_FILE && priv->mode == OSTREE_REPO_MODE_ARCHIVE)
@@ -917,17 +976,14 @@ stage_object (OstreeRepo *self,
}
else
{
- if (objtype == OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT && priv->mode == OSTREE_REPO_MODE_ARCHIVE)
+ if (priv->mode == OSTREE_REPO_MODE_ARCHIVE
+ && expected_checksum == NULL
+ && (objtype == OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META
+ || objtype == OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT))
{
- temp_info = dup_file_info_owned_by_me (file_info);
- if (!ostree_create_temp_file_from_input (priv->tmp_dir,
- "store-tmp-", NULL,
- temp_info, NULL, input,
- objtype,
- &temp_file,
- out_checksum ? &ret_checksum : NULL,
- cancellable, error))
- goto out;
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ "Importing untrusted archive files into an archive repo is not supported");
+ goto out;
}
else
{
@@ -956,8 +1012,8 @@ stage_object (OstreeRepo *self,
}
g_hash_table_insert (priv->pending_transaction_tmpfiles,
- g_strdup (actual_checksum),
- g_variant_new ("(us)", objtype, ot_gfile_get_basename_cached (temp_file)));
+ create_checksum_and_objtype (actual_checksum, objtype),
+ g_strdup (ot_gfile_get_basename_cached (temp_file)));
g_clear_object (&temp_file);
}
}
@@ -1034,6 +1090,7 @@ ostree_repo_commit_transaction (OstreeRepo *self,
GFile *f = NULL;
GHashTableIter iter;
gpointer key, value;
+ char *checksum = NULL;
g_return_val_if_fail (priv->in_transaction == TRUE, FALSE);
@@ -1042,12 +1099,17 @@ ostree_repo_commit_transaction (OstreeRepo *self,
g_hash_table_iter_init (&iter, priv->pending_transaction_tmpfiles);
while (g_hash_table_iter_next (&iter, &key, &value))
{
- const char *checksum = key;
- GVariant *data = value;
- guint32 objtype;
- const char *filename;
+ const char *checksum_and_type = key;
+ const char *filename = value;
+ const char *type_str;
+ OstreeObjectType objtype;
- g_variant_get (data, "(u&s)", &objtype, &filename);
+ type_str = strrchr (checksum_and_type, '.');
+ g_assert (type_str);
+ g_free (checksum);
+ checksum = g_strndup (checksum_and_type, type_str - checksum_and_type);
+
+ objtype = ostree_object_type_from_string (type_str + 1);
g_clear_object (&f);
f = g_file_get_child (priv->tmp_dir, filename);
@@ -1058,6 +1120,7 @@ ostree_repo_commit_transaction (OstreeRepo *self,
ret = TRUE;
out:
+ g_free (checksum);
g_hash_table_remove_all (priv->pending_transaction_tmpfiles);
g_clear_object (&f);
return ret;
@@ -2084,9 +2147,9 @@ iter_object_dir (OstreeRepo *self,
if (g_str_has_suffix (name, ".file"))
objtype = OSTREE_OBJECT_TYPE_RAW_FILE;
else if (g_str_has_suffix (name, ".archive-meta"))
- objtype = OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT;
- else if (g_str_has_suffix (name, ".archive-content"))
objtype = OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META;
+ else if (g_str_has_suffix (name, ".archive-content"))
+ objtype = OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT;
else if (g_str_has_suffix (name, ".dirtree"))
objtype = OSTREE_OBJECT_TYPE_DIR_TREE;
else if (g_str_has_suffix (name, ".dirmeta"))
@@ -2238,7 +2301,6 @@ checkout_tree (OstreeRepo *self,
GError *temp_error = NULL;
GVariant *archive_metadata = NULL;
GFileInfo *file_info = NULL;
- char *archive_content_checksum = NULL;
GVariant *xattrs = NULL;
GFileEnumerator *dir_enum = NULL;
GFile *src_child = NULL;
@@ -2295,19 +2357,20 @@ checkout_tree (OstreeRepo *self,
if (!ostree_parse_metadata_file (object_path, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META, &archive_metadata, error))
goto out;
- g_free (archive_content_checksum);
- archive_content_checksum = NULL;
ot_clear_gvariant (&xattrs);
- if (!ostree_parse_archived_file_meta (archive_metadata, NULL, &xattrs, &archive_content_checksum, error))
+ if (!ostree_parse_archived_file_meta (archive_metadata, NULL, &xattrs, error))
goto out;
g_clear_object (&content_object_path);
- content_object_path = ostree_repo_get_object_path (self, archive_content_checksum, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT);
+ content_object_path = ostree_repo_get_object_path (self, checksum, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT);
g_clear_object (&content_input);
- content_input = (GInputStream*)g_file_read (content_object_path, cancellable, error);
- if (!content_input)
- goto out;
+ if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR)
+ {
+ content_input = (GInputStream*)g_file_read (content_object_path, cancellable, error);
+ if (!content_input)
+ goto out;
+ }
if (!checkout_file_from_input (dest_path, mode, file_info, xattrs,
content_input, cancellable, error))
@@ -2342,7 +2405,6 @@ checkout_tree (OstreeRepo *self,
g_clear_object (&content_object_path);
g_clear_object (&content_input);
g_clear_object (&dest_path);
- g_free (archive_content_checksum);
g_free (dest_path);
return ret;
}
diff --git a/src/ostree/ostree-pull.c b/src/ostree/ostree-pull.c
index 38f76d8..0f377e0 100644
--- a/src/ostree/ostree-pull.c
+++ b/src/ostree/ostree-pull.c
@@ -373,9 +373,15 @@ ostree_builtin_pull (int argc, char **argv, const char *repo_path, GError **erro
{
if (!ostree_validate_checksum_string (rev, error))
goto out;
+
+ if (!ostree_repo_prepare_transaction (repo, NULL, error))
+ goto out;
if (!store_commit_recurse (repo, soup, base_uri, rev, error))
goto out;
+
+ if (!ostree_repo_commit_transaction (repo, NULL, error))
+ goto out;
if (!ostree_repo_write_ref (repo, remote, branch, rev, error))
goto out;
diff --git a/src/ostree/ot-builtin-fsck.c b/src/ostree/ot-builtin-fsck.c
index 0043ff5..1fec01d 100644
--- a/src/ostree/ot-builtin-fsck.c
+++ b/src/ostree/ot-builtin-fsck.c
@@ -42,16 +42,15 @@ typedef struct {
static gboolean
checksum_archived_file (OtFsckData *data,
+ const char *exp_checksum,
GFile *file,
GChecksum **out_checksum,
GError **error)
{
gboolean ret = FALSE;
GChecksum *ret_checksum = NULL;
- GInputStream *in = NULL;
GVariant *archive_metadata = NULL;
GVariant *xattrs = NULL;
- char *content_checksum = NULL;
GFile *content_path = NULL;
GInputStream *content_input = NULL;
GFileInfo *file_info = NULL;
@@ -62,23 +61,27 @@ checksum_archived_file (OtFsckData *data,
if (!ostree_parse_metadata_file (file, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META, &archive_metadata, error))
goto out;
- if (!ostree_parse_archived_file_meta (archive_metadata, &file_info, &xattrs, &content_checksum, error))
+ if (!ostree_parse_archived_file_meta (archive_metadata, &file_info, &xattrs, error))
goto out;
- content_path = ostree_repo_get_object_path (data->repo, content_checksum, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT);
- content_input = (GInputStream*)g_file_read (content_path, NULL, error);
- if (!content_input)
- goto out;
+ content_path = ostree_repo_get_object_path (data->repo, exp_checksum, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT);
+
+ if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR)
+ {
+ content_input = (GInputStream*)g_file_read (content_path, NULL, error);
+ if (!content_input)
+ goto out;
+ }
ret_checksum = g_checksum_new (G_CHECKSUM_SHA256);
mode = g_file_info_get_attribute_uint32 (file_info, "unix::mode");
if (S_ISREG (mode))
{
- g_assert (in != NULL);
+ g_assert (content_input != NULL);
do
{
- if (!g_input_stream_read_all (in, buf, sizeof(buf), &bytes_read, NULL, error))
+ if (!g_input_stream_read_all (content_input, buf, sizeof(buf), &bytes_read, NULL, error))
goto out;
g_checksum_update (ret_checksum, (guint8*)buf, bytes_read);
}
@@ -110,11 +113,9 @@ checksum_archived_file (OtFsckData *data,
ot_transfer_out_value (out_checksum, &ret_checksum);
out:
ot_clear_checksum (&ret_checksum);
- g_clear_object (&in);
g_clear_object (&file_info);
ot_clear_gvariant (&xattrs);
ot_clear_gvariant (&archive_metadata);
- g_free (content_checksum);
g_clear_object (&content_path);
g_clear_object (&content_input);
return ret;
@@ -129,40 +130,38 @@ object_iter_callback (OstreeRepo *repo,
gpointer user_data)
{
OtFsckData *data = user_data;
- const char *path = NULL;
GChecksum *real_checksum = NULL;
GError *error = NULL;
- path = ot_gfile_get_path_cached (objf);
-
/* nlinks = g_file_info_get_attribute_uint32 (file_info, "unix::nlink");
if (nlinks < 2 && !quiet)
g_printerr ("note: floating object: %s\n", path); */
- if (ostree_repo_get_mode (repo) == OSTREE_REPO_MODE_ARCHIVE
- && !OSTREE_OBJECT_TYPE_IS_META (objtype))
+ if (objtype == OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META)
{
- if (!g_str_has_suffix (path, ".archive"))
+ if (!g_str_has_suffix (ot_gfile_get_path_cached (objf), ".archive-meta"))
{
g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Invalid archive filename '%s'",
- path);
+ ot_gfile_get_path_cached (objf));
goto out;
}
- if (!checksum_archived_file (data, objf, &real_checksum, &error))
+ if (!checksum_archived_file (data, exp_checksum, objf, &real_checksum, &error))
goto out;
}
+ else if (objtype == OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT)
+ ; /* Handled above */
else
{
if (!ostree_checksum_file (objf, objtype, &real_checksum, NULL, &error))
goto out;
}
- if (strcmp (exp_checksum, g_checksum_get_string (real_checksum)) != 0)
+ if (real_checksum && strcmp (exp_checksum, g_checksum_get_string (real_checksum)) != 0)
{
data->had_error = TRUE;
- g_printerr ("ERROR: corrupted object '%s' expected checksum: %s\n",
- exp_checksum, g_checksum_get_string (real_checksum));
+ g_printerr ("ERROR: corrupted object '%s'; actual checksum: %s\n",
+ ot_gfile_get_path_cached (objf), g_checksum_get_string (real_checksum));
}
data->n_objects++;
diff --git a/src/ostree/ot-builtin-local-clone.c b/src/ostree/ot-builtin-local-clone.c
index b730acf..c50f764 100644
--- a/src/ostree/ot-builtin-local-clone.c
+++ b/src/ostree/ot-builtin-local-clone.c
@@ -25,7 +25,8 @@
#include "ot-builtins.h"
#include "ostree.h"
-#include <glib/gi18n.h>
+#include <unistd.h>
+#include <stdlib.h>
static GOptionEntry options[] = {
{ NULL }
@@ -101,8 +102,10 @@ object_iter_callback (OstreeRepo *repo,
if (objtype == OSTREE_OBJECT_TYPE_RAW_FILE)
xattrs = ostree_get_xattrs_for_file (objfile, &error);
- if (objtype == OSTREE_OBJECT_TYPE_RAW_FILE
- || objtype == OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT)
+ if (((objtype == OSTREE_OBJECT_TYPE_RAW_FILE
+ || objtype == OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT)
+ && g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR)
+ || OSTREE_OBJECT_TYPE_IS_META (objtype))
{
input = (GInputStream*)g_file_read (objfile, NULL, &error);
if (!input)
@@ -121,6 +124,7 @@ object_iter_callback (OstreeRepo *repo,
{
g_printerr ("%s\n", error->message);
g_clear_error (&error);
+ exit (1);
}
}
@@ -182,8 +186,14 @@ ostree_builtin_local_clone (int argc, char **argv, const char *repo_path, GError
data.uids_differ = g_file_info_get_attribute_uint32 (src_info, "unix::uid") != g_file_info_get_attribute_uint32 (dest_info, "unix::uid");
+ if (!ostree_repo_prepare_transaction (data.dest_repo, NULL, error))
+ goto out;
+
if (!ostree_repo_iter_objects (data.src_repo, object_iter_callback, &data, error))
goto out;
+
+ if (!ostree_repo_commit_transaction (data.dest_repo, NULL, error))
+ goto out;
src_dir = g_file_resolve_relative_path (src_repo_dir, "refs/heads");
dest_dir = g_file_resolve_relative_path (dest_repo_dir, "refs/heads");
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]