summaryrefslogtreecommitdiff
path: root/src/import-yum.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/import-yum.c')
-rw-r--r--src/import-yum.c337
1 files changed, 337 insertions, 0 deletions
diff --git a/src/import-yum.c b/src/import-yum.c
new file mode 100644
index 0000000..c461a15
--- /dev/null
+++ b/src/import-yum.c
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
+ * Copyright (C) 2008 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define _GNU_SOURCE
+
+#include <string.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <expat.h>
+#include <zlib.h>
+#include "razor.h"
+
+/* Import a yum filelist as a razor package set. */
+
+enum {
+ YUM_STATE_BEGIN,
+ YUM_STATE_PACKAGE_NAME,
+ YUM_STATE_PACKAGE_ARCH,
+ YUM_STATE_CHECKSUM,
+ YUM_STATE_REQUIRES,
+ YUM_STATE_PROVIDES,
+ YUM_STATE_OBSOLETES,
+ YUM_STATE_CONFLICTS,
+ YUM_STATE_FILE
+};
+
+struct yum_context {
+ XML_Parser primary_parser;
+ XML_Parser filelists_parser;
+ XML_Parser current_parser;
+
+ struct razor_importer *importer;
+ struct import_property_context *current_property_context;
+ char name[256], arch[64], buffer[512], *p;
+ char pkgid[128];
+ int state;
+};
+
+static enum razor_version_relation
+yum_to_razor_flags (const char *flags)
+{
+ /* FIXME? */
+ if (!flags)
+ return RAZOR_VERSION_EQUAL;
+
+ if (flags[0] == 'L') {
+ if (flags[1] == 'T')
+ return RAZOR_VERSION_LESS;
+ else
+ return RAZOR_VERSION_LESS_OR_EQUAL;
+ } else if (flags[0] == 'G') {
+ if (flags[1] == 'T')
+ return RAZOR_VERSION_GREATER;
+ else
+ return RAZOR_VERSION_GREATER_OR_EQUAL;
+ } else
+ return RAZOR_VERSION_EQUAL;
+}
+
+static void
+yum_primary_start_element(void *data, const char *name, const char **atts)
+{
+ struct yum_context *ctx = data;
+ const char *n, *epoch, *version, *release, *flags;
+ char buffer[128];
+ int i;
+
+ if (strcmp(name, "name") == 0) {
+ ctx->state = YUM_STATE_PACKAGE_NAME;
+ ctx->p = ctx->name;
+ } else if (strcmp(name, "arch") == 0) {
+ ctx->state = YUM_STATE_PACKAGE_ARCH;
+ ctx->p = ctx->arch;
+ } else if (strcmp(name, "version") == 0) {
+ epoch = NULL;
+ version = NULL;
+ release = NULL;
+ for (i = 0; atts[i]; i += 2) {
+ if (strcmp(atts[i], "epoch") == 0)
+ epoch = atts[i + 1];
+ else if (strcmp(atts[i], "ver") == 0)
+ version = atts[i + 1];
+ else if (strcmp(atts[i], "rel") == 0)
+ release = atts[i + 1];
+ }
+ if (version == NULL || release == NULL) {
+ fprintf(stderr, "invalid version tag, "
+ "missing version or release attribute\n");
+ return;
+ }
+
+ razor_build_evr(buffer, sizeof buffer, epoch, version, release);
+ razor_importer_begin_package(ctx->importer,
+ ctx->name, buffer, ctx->arch);
+ } else if (strcmp(name, "checksum") == 0) {
+ ctx->p = ctx->pkgid;
+ ctx->state = YUM_STATE_CHECKSUM;
+ } else if (strcmp(name, "rpm:requires") == 0) {
+ ctx->state = YUM_STATE_REQUIRES;
+ } else if (strcmp(name, "rpm:provides") == 0) {
+ ctx->state = YUM_STATE_PROVIDES;
+ } else if (strcmp(name, "rpm:obsoletes") == 0) {
+ ctx->state = YUM_STATE_OBSOLETES;
+ } else if (strcmp(name, "rpm:conflicts") == 0) {
+ ctx->state = YUM_STATE_CONFLICTS;
+ } else if (strcmp(name, "rpm:entry") == 0 &&
+ ctx->state != YUM_STATE_BEGIN) {
+ n = NULL;
+ epoch = NULL;
+ version = NULL;
+ release = NULL;
+ flags = NULL;
+ for (i = 0; atts[i]; i += 2) {
+ if (strcmp(atts[i], "name") == 0)
+ n = atts[i + 1];
+ else if (strcmp(atts[i], "epoch") == 0)
+ epoch = atts[i + 1];
+ else if (strcmp(atts[i], "ver") == 0)
+ version = atts[i + 1];
+ else if (strcmp(atts[i], "rel") == 0)
+ release = atts[i + 1];
+ else if (strcmp(atts[i], "flags") == 0)
+ flags = atts[i + 1];
+ }
+
+ if (n == NULL) {
+ fprintf(stderr, "invalid rpm:entry, "
+ "missing name or version attributes\n");
+ return;
+ }
+
+ razor_build_evr(buffer, sizeof buffer, epoch, version, release);
+ switch (ctx->state) {
+ case YUM_STATE_REQUIRES:
+ razor_importer_add_property(ctx->importer, n,
+ yum_to_razor_flags (flags),
+ buffer,
+ RAZOR_PROPERTY_REQUIRES);
+ break;
+ case YUM_STATE_PROVIDES:
+ razor_importer_add_property(ctx->importer, n,
+ yum_to_razor_flags (flags),
+ buffer,
+ RAZOR_PROPERTY_PROVIDES);
+ break;
+ case YUM_STATE_OBSOLETES:
+ razor_importer_add_property(ctx->importer, n,
+ yum_to_razor_flags (flags),
+ buffer,
+ RAZOR_PROPERTY_OBSOLETES);
+ break;
+ case YUM_STATE_CONFLICTS:
+ razor_importer_add_property(ctx->importer, n,
+ yum_to_razor_flags (flags),
+ buffer,
+ RAZOR_PROPERTY_CONFLICTS);
+ break;
+ }
+ }
+}
+
+static void
+yum_primary_end_element (void *data, const char *name)
+{
+ struct yum_context *ctx = data;
+
+ switch (ctx->state) {
+ case YUM_STATE_PACKAGE_NAME:
+ case YUM_STATE_PACKAGE_ARCH:
+ case YUM_STATE_CHECKSUM:
+ case YUM_STATE_FILE:
+ ctx->state = YUM_STATE_BEGIN;
+ break;
+ }
+
+ if (strcmp(name, "package") == 0) {
+ XML_StopParser(ctx->current_parser, XML_TRUE);
+ ctx->current_parser = ctx->filelists_parser;
+ }
+}
+
+static void
+yum_character_data (void *data, const XML_Char *s, int len)
+{
+ struct yum_context *ctx = data;
+
+ switch (ctx->state) {
+ case YUM_STATE_PACKAGE_NAME:
+ case YUM_STATE_PACKAGE_ARCH:
+ case YUM_STATE_CHECKSUM:
+ case YUM_STATE_FILE:
+ memcpy(ctx->p, s, len);
+ ctx->p += len;
+ *ctx->p = '\0';
+ break;
+ }
+}
+
+static void
+yum_filelists_start_element(void *data, const char *name, const char **atts)
+{
+ struct yum_context *ctx = data;
+ const char *pkg, *pkgid;
+ int i;
+
+ if (strcmp(name, "package") == 0) {
+ pkg = NULL;
+ pkgid = NULL;
+ for (i = 0; atts[i]; i += 2) {
+ if (strcmp(atts[i], "name") == 0)
+ pkg = atts[i + 1];
+ else if (strcmp(atts[i], "pkgid") == 0)
+ pkgid = atts[i + 1];
+ }
+ if (strcmp(pkgid, ctx->pkgid) != 0)
+ fprintf(stderr, "primary.xml and filelists.xml "
+ "mismatch for %s: %s vs %s",
+ pkg, pkgid, ctx->pkgid);
+ } else if (strcmp(name, "file") == 0) {
+ ctx->state = YUM_STATE_FILE;
+ ctx->p = ctx->buffer;
+ }
+}
+
+
+static void
+yum_filelists_end_element (void *data, const char *name)
+{
+ struct yum_context *ctx = data;
+
+ ctx->state = YUM_STATE_BEGIN;
+ if (strcmp(name, "package") == 0) {
+ XML_StopParser(ctx->current_parser, XML_TRUE);
+ ctx->current_parser = ctx->primary_parser;
+ razor_importer_finish_package(ctx->importer);
+ } else if (strcmp(name, "file") == 0)
+ razor_importer_add_file(ctx->importer, ctx->buffer);
+
+}
+
+#define XML_BUFFER_SIZE 4096
+
+struct razor_set *
+razor_set_create_from_yum(void)
+{
+ struct yum_context ctx;
+ void *buf;
+ int len, ret;
+ gzFile primary, filelists;
+ XML_ParsingStatus status;
+
+ ctx.importer = razor_importer_new();
+ ctx.state = YUM_STATE_BEGIN;
+
+ ctx.primary_parser = XML_ParserCreate(NULL);
+ XML_SetUserData(ctx.primary_parser, &ctx);
+ XML_SetElementHandler(ctx.primary_parser,
+ yum_primary_start_element,
+ yum_primary_end_element);
+ XML_SetCharacterDataHandler(ctx.primary_parser,
+ yum_character_data);
+
+ ctx.filelists_parser = XML_ParserCreate(NULL);
+ XML_SetUserData(ctx.filelists_parser, &ctx);
+ XML_SetElementHandler(ctx.filelists_parser,
+ yum_filelists_start_element,
+ yum_filelists_end_element);
+ XML_SetCharacterDataHandler(ctx.filelists_parser,
+ yum_character_data);
+
+ primary = gzopen("primary.xml.gz", "rb");
+ if (primary == NULL)
+ return NULL;
+ filelists = gzopen("filelists.xml.gz", "rb");
+ if (filelists == NULL)
+ return NULL;
+
+ ctx.current_parser = ctx.primary_parser;
+
+ do {
+ XML_GetParsingStatus(ctx.current_parser, &status);
+ switch (status.parsing) {
+ case XML_SUSPENDED:
+ ret = XML_ResumeParser(ctx.current_parser);
+ break;
+ case XML_PARSING:
+ case XML_INITIALIZED:
+ buf = XML_GetBuffer(ctx.current_parser,
+ XML_BUFFER_SIZE);
+ if (ctx.current_parser == ctx.primary_parser)
+ len = gzread(primary, buf, XML_BUFFER_SIZE);
+ else
+ len = gzread(filelists, buf, XML_BUFFER_SIZE);
+ if (len < 0) {
+ fprintf(stderr,
+ "couldn't read input: %s\n",
+ strerror(errno));
+ return NULL;
+ }
+
+ XML_ParseBuffer(ctx.current_parser, len, len == 0);
+ break;
+ case XML_FINISHED:
+ break;
+ }
+ } while (status.parsing != XML_FINISHED);
+
+
+ XML_ParserFree(ctx.primary_parser);
+ XML_ParserFree(ctx.filelists_parser);
+
+ gzclose(primary);
+ gzclose(filelists);
+
+ return razor_importer_finish(ctx.importer);
+}