rhughes@241: /* rhughes@241: * Copyright (C) 2008 Kristian Høgsberg rhughes@241: * Copyright (C) 2008 Red Hat, Inc rhughes@241: * rhughes@241: * This program is free software; you can redistribute it and/or modify rhughes@241: * it under the terms of the GNU General Public License as published by rhughes@241: * the Free Software Foundation; either version 2 of the License, or rhughes@241: * (at your option) any later version. rhughes@241: * rhughes@241: * This program is distributed in the hope that it will be useful, rhughes@241: * but WITHOUT ANY WARRANTY; without even the implied warranty of rhughes@241: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the rhughes@241: * GNU General Public License for more details. rhughes@241: * rhughes@241: * You should have received a copy of the GNU General Public License along rhughes@241: * with this program; if not, write to the Free Software Foundation, Inc., rhughes@241: * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. rhughes@241: */ rhughes@241: rhughes@241: #define _GNU_SOURCE rhughes@241: rhughes@241: #include rhughes@241: #include krh@247: #include rhughes@241: #include rhughes@241: #include rhughes@241: #include rhughes@241: #include rhughes@241: rhughes@241: #include rhughes@241: #include rhughes@241: #include "razor.h" rhughes@241: rhughes@241: /* Import a yum filelist as a razor package set. */ rhughes@241: rhughes@241: enum { rhughes@241: YUM_STATE_BEGIN, rhughes@241: YUM_STATE_PACKAGE_NAME, rhughes@241: YUM_STATE_PACKAGE_ARCH, jbowes@258: YUM_STATE_SUMMARY, jbowes@258: YUM_STATE_DESCRIPTION, jbowes@258: YUM_STATE_URL, jbowes@258: YUM_STATE_LICENSE, rhughes@241: YUM_STATE_CHECKSUM, rhughes@241: YUM_STATE_REQUIRES, rhughes@241: YUM_STATE_PROVIDES, rhughes@241: YUM_STATE_OBSOLETES, rhughes@241: YUM_STATE_CONFLICTS, rhughes@241: YUM_STATE_FILE rhughes@241: }; rhughes@241: rhughes@241: struct yum_context { rhughes@241: XML_Parser primary_parser; rhughes@241: XML_Parser filelists_parser; rhughes@241: XML_Parser current_parser; rhughes@241: rhughes@241: struct razor_importer *importer; rhughes@241: struct import_property_context *current_property_context; jbowes@258: char name[256], arch[64], summary[512], description[4096]; jbowes@258: char url[256], license[64], buffer[512], *p; rhughes@241: char pkgid[128]; krh@247: uint32_t property_type; rhughes@241: int state; jbowes@263: jbowes@263: int total, current; rhughes@241: }; rhughes@241: krh@247: static uint32_t krh@247: yum_to_razor_relation (const char *flags) rhughes@241: { rhughes@241: if (flags[0] == 'L') { rhughes@241: if (flags[1] == 'T') krh@247: return RAZOR_PROPERTY_LESS; rhughes@241: else krh@247: return RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL; rhughes@241: } else if (flags[0] == 'G') { rhughes@241: if (flags[1] == 'T') krh@247: return RAZOR_PROPERTY_GREATER; rhughes@241: else krh@247: return RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL; rhughes@241: } else krh@247: return RAZOR_PROPERTY_EQUAL; rhughes@241: } rhughes@241: rhughes@241: static void rhughes@241: yum_primary_start_element(void *data, const char *name, const char **atts) rhughes@241: { rhughes@241: struct yum_context *ctx = data; krh@247: const char *n, *epoch, *version, *release; rhughes@241: char buffer[128]; krh@247: uint32_t pre, relation, flags; rhughes@241: int i; rhughes@241: jbowes@263: if (strcmp(name, "metadata") == 0) { jbowes@263: for (i = 0; atts[i]; i += 2) { jbowes@263: if (strcmp(atts[i], "packages") == 0) jbowes@263: ctx->total = atoi(atts[i + 1]); jbowes@263: } jbowes@263: } else if (strcmp(name, "name") == 0) { rhughes@241: ctx->state = YUM_STATE_PACKAGE_NAME; rhughes@241: ctx->p = ctx->name; rhughes@241: } else if (strcmp(name, "arch") == 0) { rhughes@241: ctx->state = YUM_STATE_PACKAGE_ARCH; rhughes@241: ctx->p = ctx->arch; rhughes@241: } else if (strcmp(name, "version") == 0) { rhughes@241: epoch = NULL; rhughes@241: version = NULL; rhughes@241: release = NULL; rhughes@241: for (i = 0; atts[i]; i += 2) { rhughes@241: if (strcmp(atts[i], "epoch") == 0) rhughes@241: epoch = atts[i + 1]; rhughes@241: else if (strcmp(atts[i], "ver") == 0) rhughes@241: version = atts[i + 1]; rhughes@241: else if (strcmp(atts[i], "rel") == 0) rhughes@241: release = atts[i + 1]; rhughes@241: } rhughes@241: if (version == NULL || release == NULL) { rhughes@241: fprintf(stderr, "invalid version tag, " rhughes@241: "missing version or release attribute\n"); rhughes@241: return; rhughes@241: } rhughes@241: rhughes@241: razor_build_evr(buffer, sizeof buffer, epoch, version, release); rhughes@241: razor_importer_begin_package(ctx->importer, rhughes@241: ctx->name, buffer, ctx->arch); jbowes@258: } else if (strcmp(name, "summary") == 0) { jbowes@258: ctx->p = ctx->summary; jbowes@258: ctx->state = YUM_STATE_SUMMARY; jbowes@258: } else if (strcmp(name, "description") == 0) { jbowes@258: ctx->p = ctx->description; jbowes@258: ctx->state = YUM_STATE_DESCRIPTION; jbowes@258: } else if (strcmp(name, "url") == 0) { jbowes@258: ctx->p = ctx->url; jbowes@258: ctx->state = YUM_STATE_URL; rhughes@241: } else if (strcmp(name, "checksum") == 0) { rhughes@241: ctx->p = ctx->pkgid; rhughes@241: ctx->state = YUM_STATE_CHECKSUM; jbowes@258: } else if (strcmp(name, "rpm:license") == 0) { jbowes@258: ctx->p = ctx->license; jbowes@258: ctx->state = YUM_STATE_LICENSE; rhughes@241: } else if (strcmp(name, "rpm:requires") == 0) { rhughes@241: ctx->state = YUM_STATE_REQUIRES; krh@247: ctx->property_type = RAZOR_PROPERTY_REQUIRES; rhughes@241: } else if (strcmp(name, "rpm:provides") == 0) { rhughes@241: ctx->state = YUM_STATE_PROVIDES; krh@247: ctx->property_type = RAZOR_PROPERTY_PROVIDES; rhughes@241: } else if (strcmp(name, "rpm:obsoletes") == 0) { rhughes@241: ctx->state = YUM_STATE_OBSOLETES; krh@247: ctx->property_type = RAZOR_PROPERTY_OBSOLETES; rhughes@241: } else if (strcmp(name, "rpm:conflicts") == 0) { rhughes@241: ctx->state = YUM_STATE_CONFLICTS; krh@247: ctx->property_type = RAZOR_PROPERTY_CONFLICTS; rhughes@241: } else if (strcmp(name, "rpm:entry") == 0 && rhughes@241: ctx->state != YUM_STATE_BEGIN) { rhughes@241: n = NULL; rhughes@241: epoch = NULL; rhughes@241: version = NULL; rhughes@241: release = NULL; krh@247: relation = RAZOR_PROPERTY_EQUAL; krh@247: pre = 0; rhughes@241: for (i = 0; atts[i]; i += 2) { rhughes@241: if (strcmp(atts[i], "name") == 0) rhughes@241: n = atts[i + 1]; rhughes@241: else if (strcmp(atts[i], "epoch") == 0) rhughes@241: epoch = atts[i + 1]; rhughes@241: else if (strcmp(atts[i], "ver") == 0) rhughes@241: version = atts[i + 1]; rhughes@241: else if (strcmp(atts[i], "rel") == 0) rhughes@241: release = atts[i + 1]; rhughes@241: else if (strcmp(atts[i], "flags") == 0) krh@247: relation = yum_to_razor_relation(atts[i + 1]); krh@247: else if (strcmp(atts[i], "pre") == 0) ali@418: pre = RAZOR_PROPERTY_PRE; rhughes@241: } rhughes@241: rhughes@241: if (n == NULL) { rhughes@241: fprintf(stderr, "invalid rpm:entry, " rhughes@241: "missing name or version attributes\n"); rhughes@241: return; rhughes@241: } rhughes@241: rhughes@241: razor_build_evr(buffer, sizeof buffer, epoch, version, release); krh@247: flags = ctx->property_type | relation | pre; krh@247: razor_importer_add_property(ctx->importer, n, flags, buffer); rhughes@241: } rhughes@241: } rhughes@241: rhughes@241: static void rhughes@241: yum_primary_end_element (void *data, const char *name) rhughes@241: { rhughes@241: struct yum_context *ctx = data; rhughes@241: rhughes@241: switch (ctx->state) { rhughes@241: case YUM_STATE_PACKAGE_NAME: rhughes@241: case YUM_STATE_PACKAGE_ARCH: jbowes@258: case YUM_STATE_SUMMARY: jbowes@258: case YUM_STATE_DESCRIPTION: jbowes@258: case YUM_STATE_URL: jbowes@258: case YUM_STATE_LICENSE: rhughes@241: case YUM_STATE_CHECKSUM: rhughes@241: case YUM_STATE_FILE: rhughes@241: ctx->state = YUM_STATE_BEGIN; rhughes@241: break; rhughes@241: } rhughes@241: rhughes@241: if (strcmp(name, "package") == 0) { jbowes@258: razor_importer_add_details(ctx->importer, ctx->summary, jbowes@258: ctx->description, ctx->url, jbowes@258: ctx->license); jbowes@258: rhughes@241: XML_StopParser(ctx->current_parser, XML_TRUE); rhughes@241: ctx->current_parser = ctx->filelists_parser; jbowes@263: jbowes@263: printf("\rimporting %d/%d", ++ctx->current, ctx->total); jbowes@263: fflush(stdout); rhughes@241: } rhughes@241: } rhughes@241: rhughes@241: static void rhughes@241: yum_character_data (void *data, const XML_Char *s, int len) rhughes@241: { rhughes@241: struct yum_context *ctx = data; rhughes@241: rhughes@241: switch (ctx->state) { rhughes@241: case YUM_STATE_PACKAGE_NAME: rhughes@241: case YUM_STATE_PACKAGE_ARCH: jbowes@258: case YUM_STATE_SUMMARY: jbowes@258: case YUM_STATE_DESCRIPTION: jbowes@258: case YUM_STATE_URL: jbowes@258: case YUM_STATE_LICENSE: rhughes@241: case YUM_STATE_CHECKSUM: rhughes@241: case YUM_STATE_FILE: rhughes@241: memcpy(ctx->p, s, len); rhughes@241: ctx->p += len; rhughes@241: *ctx->p = '\0'; rhughes@241: break; rhughes@241: } rhughes@241: } rhughes@241: rhughes@241: static void rhughes@241: yum_filelists_start_element(void *data, const char *name, const char **atts) rhughes@241: { rhughes@241: struct yum_context *ctx = data; rhughes@241: const char *pkg, *pkgid; rhughes@241: int i; rhughes@241: rhughes@241: if (strcmp(name, "package") == 0) { rhughes@241: pkg = NULL; rhughes@241: pkgid = NULL; rhughes@241: for (i = 0; atts[i]; i += 2) { rhughes@241: if (strcmp(atts[i], "name") == 0) rhughes@241: pkg = atts[i + 1]; rhughes@241: else if (strcmp(atts[i], "pkgid") == 0) rhughes@241: pkgid = atts[i + 1]; rhughes@241: } rhughes@241: if (strcmp(pkgid, ctx->pkgid) != 0) rhughes@241: fprintf(stderr, "primary.xml and filelists.xml " rhughes@241: "mismatch for %s: %s vs %s", rhughes@241: pkg, pkgid, ctx->pkgid); rhughes@241: } else if (strcmp(name, "file") == 0) { rhughes@241: ctx->state = YUM_STATE_FILE; rhughes@241: ctx->p = ctx->buffer; rhughes@241: } rhughes@241: } rhughes@241: rhughes@241: rhughes@241: static void rhughes@241: yum_filelists_end_element (void *data, const char *name) rhughes@241: { rhughes@241: struct yum_context *ctx = data; rhughes@241: rhughes@241: ctx->state = YUM_STATE_BEGIN; rhughes@241: if (strcmp(name, "package") == 0) { rhughes@241: XML_StopParser(ctx->current_parser, XML_TRUE); rhughes@241: ctx->current_parser = ctx->primary_parser; rhughes@241: razor_importer_finish_package(ctx->importer); rhughes@241: } else if (strcmp(name, "file") == 0) rhughes@241: razor_importer_add_file(ctx->importer, ctx->buffer); rhughes@241: rhughes@241: } rhughes@241: rhughes@241: #define XML_BUFFER_SIZE 4096 rhughes@241: rhughes@241: struct razor_set * rhughes@241: razor_set_create_from_yum(void) rhughes@241: { ali@394: struct yum_context ctx={0}; rhughes@241: void *buf; rhughes@241: int len, ret; rhughes@241: gzFile primary, filelists; rhughes@241: XML_ParsingStatus status; rhughes@241: krh@249: ctx.importer = razor_importer_create(); rhughes@241: ctx.state = YUM_STATE_BEGIN; rhughes@241: rhughes@241: ctx.primary_parser = XML_ParserCreate(NULL); rhughes@241: XML_SetUserData(ctx.primary_parser, &ctx); rhughes@241: XML_SetElementHandler(ctx.primary_parser, rhughes@241: yum_primary_start_element, rhughes@241: yum_primary_end_element); rhughes@241: XML_SetCharacterDataHandler(ctx.primary_parser, rhughes@241: yum_character_data); rhughes@241: rhughes@241: ctx.filelists_parser = XML_ParserCreate(NULL); rhughes@241: XML_SetUserData(ctx.filelists_parser, &ctx); rhughes@241: XML_SetElementHandler(ctx.filelists_parser, rhughes@241: yum_filelists_start_element, rhughes@241: yum_filelists_end_element); rhughes@241: XML_SetCharacterDataHandler(ctx.filelists_parser, rhughes@241: yum_character_data); rhughes@241: rhughes@241: primary = gzopen("primary.xml.gz", "rb"); rhughes@241: if (primary == NULL) rhughes@241: return NULL; rhughes@241: filelists = gzopen("filelists.xml.gz", "rb"); rhughes@241: if (filelists == NULL) rhughes@241: return NULL; rhughes@241: rhughes@241: ctx.current_parser = ctx.primary_parser; rhughes@241: jbowes@263: ctx.current = 0; jbowes@263: rhughes@241: do { rhughes@241: XML_GetParsingStatus(ctx.current_parser, &status); rhughes@241: switch (status.parsing) { rhughes@241: case XML_SUSPENDED: rhughes@241: ret = XML_ResumeParser(ctx.current_parser); rhughes@241: break; rhughes@241: case XML_PARSING: rhughes@241: case XML_INITIALIZED: rhughes@241: buf = XML_GetBuffer(ctx.current_parser, rhughes@241: XML_BUFFER_SIZE); rhughes@241: if (ctx.current_parser == ctx.primary_parser) rhughes@241: len = gzread(primary, buf, XML_BUFFER_SIZE); rhughes@241: else rhughes@241: len = gzread(filelists, buf, XML_BUFFER_SIZE); rhughes@241: if (len < 0) { rhughes@241: fprintf(stderr, rhughes@241: "couldn't read input: %s\n", rhughes@241: strerror(errno)); rhughes@241: return NULL; rhughes@241: } rhughes@241: rhughes@241: XML_ParseBuffer(ctx.current_parser, len, len == 0); rhughes@241: break; rhughes@241: case XML_FINISHED: rhughes@241: break; rhughes@241: } rhughes@241: } while (status.parsing != XML_FINISHED); rhughes@241: rhughes@241: rhughes@241: XML_ParserFree(ctx.primary_parser); rhughes@241: XML_ParserFree(ctx.filelists_parser); rhughes@241: rhughes@241: gzclose(primary); rhughes@241: gzclose(filelists); rhughes@241: jbowes@263: printf ("\nsaving\n"); rhughes@241: return razor_importer_finish(ctx.importer); rhughes@241: }