summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Walters <walters@verbum.org>2014-07-31 18:50:19 -0400
committerColin Walters <walters@verbum.org>2014-08-04 16:14:35 -0400
commit53b7bc3b469c783b0db899b3797672e377b8d9e6 (patch)
tree48ed5ed3ae86f4bfd56cba992a6c814e66e4b247
parent9bd229dff58ddb96f08e9307a1a668efc3548db5 (diff)
downloadostree-53b7bc3b469c783b0db899b3797672e377b8d9e6.tar.gz
WIP: metalink code
-rw-r--r--Makefile-libostree.am2
-rw-r--r--src/libostree/ostree-metalink.c314
-rw-r--r--src/libostree/ostree-metalink.h62
-rw-r--r--src/libostree/ostree-repo-pull.c28
4 files changed, 398 insertions, 8 deletions
diff --git a/Makefile-libostree.am b/Makefile-libostree.am
index 1b756001..e7b141ae 100644
--- a/Makefile-libostree.am
+++ b/Makefile-libostree.am
@@ -112,6 +112,8 @@ if USE_LIBSOUP
libostree_1_la_SOURCES += \
src/libostree/ostree-fetcher.h \
src/libostree/ostree-fetcher.c \
+ src/libostree/ostree-metalink.h \
+ src/libostree/ostree-metalink.c \
src/libostree/ostree-repo-pull.c \
$(NULL)
libostree_1_la_CFLAGS += $(OT_INTERNAL_SOUP_CFLAGS)
diff --git a/src/libostree/ostree-metalink.c b/src/libostree/ostree-metalink.c
new file mode 100644
index 00000000..f217461e
--- /dev/null
+++ b/src/libostree/ostree-metalink.c
@@ -0,0 +1,314 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2014 Colin Walters <walters@verbum.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "ostree-metalink.h"
+
+#include "otutil.h"
+#include "libgsystem.h"
+
+typedef enum {
+ OSTREE_METALINK_STATE_INITIAL,
+ OSTREE_METALINK_STATE_METALINK,
+ OSTREE_METALINK_STATE_FILES,
+ OSTREE_METALINK_STATE_FILE,
+ OSTREE_METALINK_STATE_SIZE,
+ OSTREE_METALINK_STATE_VERIFICATION,
+ OSTREE_METALINK_STATE_HASH,
+ OSTREE_METALINK_STATE_RESOURCES,
+ OSTREE_METALINK_STATE_URL,
+
+ OSTREE_METALINK_STATE_PASSTHROUGH, /* Ignoring unknown elements */
+ OSTREE_METALINK_STATE_ERROR
+} OstreeMetalinkState;
+
+struct OstreeMetalink
+{
+ GObject parent_instance;
+
+ OstreeMetalink *fetcher;
+
+ guint passthrough_depth;
+ OstreeMetalinkState passthrough_previous;
+
+ char *file_name;
+ guint64 size;
+ guint verification_known :1;
+ GChecksumType verification_type;
+ char *verification_value;
+
+ GPtrArray *urls;
+
+ OstreeMetalinkState state;
+};
+
+G_DEFINE_TYPE (OstreeMetalink, _ostree_metalink, G_TYPE_OBJECT)
+
+static void
+state_transition (OstreeMetalink *self,
+ OstreeMetalinkState new_state)
+{
+ g_assert (self->state != new_state);
+ self->state = new_state;
+}
+
+static void
+unknown_element (OstreeMetalink *self,
+ const char *element_name,
+ GError **error)
+{
+ state_transition (self, OSTREE_METALINK_STATE_PASSTHROUGH);
+ g_assert (self->passthrough_depth == 0);
+}
+
+static void
+metalink_parser_start (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ gpointer user_data,
+ GError **error)
+{
+ OstreeMetalink *self = user_data;
+
+ switch (self->state)
+ {
+ case OSTREE_METALINK_STATE_INITIAL:
+ if (strcmp (element_name, "metalink") == 0)
+ state_transition (self, OSTREE_METALINK_STATE_METALINK);
+ else
+ unknown_element (self, element_name, error);
+ break;
+ case OSTREE_METALINK_STATE_METALINK:
+ if (strcmp (element_name, "files") == 0)
+ state_transition (self, OSTREE_METALINK_STATE_FILES);
+ else
+ unknown_element (self, element_name, error);
+ break;
+ case OSTREE_METALINK_STATE_FILES:
+ if (strcmp (element_name, "file") == 0)
+ {
+ const char *file_name;
+
+ state_transition (self, OSTREE_METALINK_STATE_FILE);
+
+ g_clear_pointer (&self->file_name, g_free);
+ if (!g_markup_collect_attributes (element_name,
+ attribute_names,
+ attribute_values,
+ error,
+ G_MARKUP_COLLECT_STRING,
+ "name",
+ &file_name,
+ G_MARKUP_COLLECT_INVALID))
+ goto out;
+
+ self->file_name = g_strdup (file_name);
+ }
+ else
+ unknown_element (self, element_name, error);
+ break;
+ case OSTREE_METALINK_STATE_FILE:
+ if (strcmp (element_name, "size") == 0)
+ state_transition (self, OSTREE_METALINK_STATE_SIZE);
+ else if (strcmp (element_name, "verification") == 0)
+ state_transition (self, OSTREE_METALINK_STATE_VERIFICATION);
+ else if (strcmp (element_name, "resources") == 0)
+ state_transition (self, OSTREE_METALINK_STATE_RESOURCES);
+ else
+ unknown_element (self, element_name, error);
+ break;
+ case OSTREE_METALINK_STATE_SIZE:
+ unknown_element (self, element_name, error);
+ break;
+ case OSTREE_METALINK_STATE_VERIFICATION:
+ if (strcmp (element_name, "hash") == 0)
+ {
+ gs_free char *verification_type_str = NULL;
+
+ state_transition (self, OSTREE_METALINK_STATE_HASH);
+ if (!g_markup_collect_attributes (element_name,
+ attribute_names,
+ attribute_values,
+ error,
+ G_MARKUP_COLLECT_STRING,
+ "name",
+ &verification_type_str,
+ G_MARKUP_COLLECT_INVALID))
+ goto out;
+
+ /* Only accept sha256/sha512 */
+ self->verification_known = TRUE;
+ if (strcmp (verification_type_str, "sha256") == 0)
+ self->verification_type = G_CHECKSUM_SHA256;
+ else if (strcmp (verification_type_str, "sha512") == 0)
+ self->verification_type = G_CHECKSUM_SHA512;
+ else
+ self->verification_known = FALSE;
+ }
+ else
+ unknown_element (self, element_name, error);
+ break;
+ case OSTREE_METALINK_STATE_HASH:
+ unknown_element (self, element_name, error);
+ break;
+ case OSTREE_METALINK_STATE_RESOURCES:
+ if (strcmp (element_name, "url") == 0)
+ {
+ const char *protocol;
+
+ if (!g_markup_collect_attributes (element_name,
+ attribute_names,
+ attribute_values,
+ error,
+ G_MARKUP_COLLECT_STRING,
+ "protocol",
+ &protocol,
+ G_MARKUP_COLLECT_INVALID))
+ goto out;
+
+ /* Ignore non-HTTP resources */
+ if (!(strcmp (protocol, "http") == 0 || strcmp (protocol, "https") == 0))
+ state_transition (self, OSTREE_METALINK_STATE_PASSTHROUGH);
+ else
+ state_transition (self, OSTREE_METALINK_STATE_URL);
+ }
+ else
+ unknown_element (self, element_name, error);
+ break;
+ case OSTREE_METALINK_STATE_URL:
+ unknown_element (self, element_name, error);
+ break;
+ case OSTREE_METALINK_STATE_PASSTHROUGH:
+ self->passthrough_depth++;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ out:
+ return;
+}
+
+static void
+metalink_parser_end (GMarkupParseContext *context,
+ const gchar *element_name,
+ gpointer user_data,
+ GError **error)
+{
+ OstreeMetalink *self = user_data;
+}
+
+static void
+metalink_parser_text (GMarkupParseContext *context,
+ const gchar *text,
+ gsize text_len,
+ gpointer user_data,
+ GError **error)
+{
+ OstreeMetalink *self = user_data;
+
+ switch (self->state)
+ {
+ case OSTREE_METALINK_STATE_INITIAL:
+ break;
+ case OSTREE_METALINK_STATE_METALINK:
+ break;
+ case OSTREE_METALINK_STATE_FILES:
+ break;
+ case OSTREE_METALINK_STATE_FILE:
+ break;
+ case OSTREE_METALINK_STATE_SIZE:
+ {
+ gs_free char *duped = g_strndup (text, text_len);
+ self->size = g_ascii_strtoull (duped, NULL, 10);
+ }
+ break;
+ case OSTREE_METALINK_STATE_VERIFICATION:
+ break;
+ case OSTREE_METALINK_STATE_HASH:
+ {
+ g_clear_pointer (&self->verification_value, g_free);
+ self->verification_value = g_strndup (text, text_len);
+ }
+ break;
+ case OSTREE_METALINK_STATE_RESOURCES:
+ break;
+ case OSTREE_METALINK_STATE_URL:
+ break;
+ case OSTREE_METALINK_STATE_PASSTHROUGH:
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ out:
+ return;
+}
+
+static void
+_ostree_metalink_finalize (GObject *object)
+{
+ OstreeMetalink *self;
+
+ self = OSTREE_METALINK (object);
+
+ G_OBJECT_CLASS (_ostree_metalink_parent_class)->finalize (object);
+}
+
+static void
+_ostree_metalink_class_init (OstreeMetalinkClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = _ostree_metalink_finalize;
+}
+
+static void
+_ostree_metalink_init (OstreeMetalink *self)
+{
+ self->urls = g_ptr_array_new_with_free_func (g_free);
+}
+
+OstreeMetalink *
+_ostree_metalink_new (OstreeFetcher *fetcher,
+ const char *requested_file,
+ guint64 max_size,
+ SoupURI *uri)
+{
+ OstreeMetalink *self = (OstreeMetalink*)g_object_new (OSTREE_TYPE_METALINK, NULL);
+
+ return self;
+}
+
+void
+_ostree_metalink_request_async (OstreeMetalink *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+}
+
+GFile *
+_ostree_metalink_request_finish (OstreeMetalink *self,
+ GAsyncResult *result,
+ GError **error)
+{
+}
diff --git a/src/libostree/ostree-metalink.h b/src/libostree/ostree-metalink.h
new file mode 100644
index 00000000..bb81292c
--- /dev/null
+++ b/src/libostree/ostree-metalink.h
@@ -0,0 +1,62 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2014 Colin Walters <walters@verbum.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#pragma once
+
+#ifndef __GI_SCANNER__
+
+#include "ostree-fetcher.h"
+
+G_BEGIN_DECLS
+
+#define OSTREE_TYPE_METALINK (_ostree_metalink_get_type ())
+#define OSTREE_METALINK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), OSTREE_TYPE_METALINK, OstreeMetalink))
+#define OSTREE_METALINK_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), OSTREE_TYPE_METALINK, OstreeMetalinkClass))
+#define OSTREE_IS_METALINK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), OSTREE_TYPE_METALINK))
+#define OSTREE_IS_METALINK_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), OSTREE_TYPE_METALINK))
+#define OSTREE_METALINK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), OSTREE_TYPE_METALINK, OstreeMetalinkClass))
+
+typedef struct OstreeMetalinkClass OstreeMetalinkClass;
+typedef struct OstreeMetalink OstreeMetalink;
+
+struct OstreeMetalinkClass
+{
+ GObjectClass parent_class;
+};
+
+GType _ostree_metalink_get_type (void) G_GNUC_CONST;
+
+OstreeMetalink *_ostree_metalink_new (OstreeFetcher *fetcher,
+ const char *requested_file,
+ guint64 max_size,
+ SoupURI *uri);
+
+void _ostree_metalink_request_async (OstreeMetalink *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GFile *_ostree_metalink_request_finish (OstreeMetalink *self,
+ GAsyncResult *result,
+ GError **error);
+
+G_END_DECLS
+
+#endif
diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c
index 2cdc6c15..9be8f324 100644
--- a/src/libostree/ostree-repo-pull.c
+++ b/src/libostree/ostree-repo-pull.c
@@ -1030,6 +1030,7 @@ ostree_repo_pull (OstreeRepo *self,
gs_free char *remote_key = NULL;
gs_free char *path = NULL;
gs_free char *baseurl = NULL;
+ gs_free char *metalink_url = NULL;
gs_unref_hashtable GHashTable *requested_refs_to_fetch = NULL;
gs_unref_hashtable GHashTable *commits_to_fetch = NULL;
gs_free char *remote_mode_str = NULL;
@@ -1070,11 +1071,29 @@ ostree_repo_pull (OstreeRepo *self,
remote_key);
goto out;
}
- if (!repo_get_string_key_inherit (self, remote_key, "url", &baseurl, error))
+
+ if (!ot_keyfile_get_value_with_default (self, remote_key, "metalink", &metalink_url, error))
goto out;
+ if (!metalink_url)
+ {
+ if (!repo_get_string_key_inherit (self, remote_key, "url", &baseurl, error))
+ goto out;
+ }
+ else
+ {
+ FIXME - need to retrieve the metalink value, extract checksum for ref from it
+ }
+
pull_data->base_uri = soup_uri_new (baseurl);
+ if (!pull_data->base_uri)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Failed to parse url '%s'", baseurl);
+ goto out;
+ }
+
#ifdef HAVE_GPGME
if (!ot_keyfile_get_boolean_with_default (config, remote_key, "gpg-verify",
TRUE, &pull_data->gpg_verify, error))
@@ -1148,13 +1167,6 @@ ostree_repo_pull (OstreeRepo *self,
}
}
- if (!pull_data->base_uri)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Failed to parse url '%s'", baseurl);
- goto out;
- }
-
if (!load_remote_repo_config (pull_data, &remote_config, cancellable, error))
goto out;