From 61950692c304ad53cab3f1c7d71806fbc153a63d Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 4 Feb 2008 14:25:45 -0500 Subject: [PATCH] Support for less/equal/greater version in requires/conflicts, etc Add less/equal/greater information to razor_property, and update importers and other code. Move the rpm importer from import.c to rpm.c to avoid code duplication, and then rename import.c to yum.c since that's all that's left. --- import.c | 379 --------------------------------------------------------- main.c | 18 ++- razor.c | 35 ++++-- razor.h | 16 ++- rpm.c | 126 +++++++++++++++++++- test-driver.c | 10 +- yum.c | 312 +++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 499 insertions(+), 397 deletions(-) delete mode 100644 import.c create mode 100644 yum.c diff --git a/import.c b/import.c deleted file mode 100644 index 68e0a73..0000000 --- a/import.c +++ /dev/null @@ -1,379 +0,0 @@ -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include "razor.h" - -/* Import a yum filelist as a razor package set. */ - -enum { - YUM_STATE_BEGIN, - YUM_STATE_PACKAGE_NAME, - 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], buffer[512], *p; - char pkgid[128]; - int state; -}; - -static void -yum_primary_start_element(void *data, const char *name, const char **atts) -{ - struct yum_context *ctx = data; - const char *n, *version, *release; - char buffer[128]; - int i; - - if (strcmp(name, "name") == 0) { - ctx->state = YUM_STATE_PACKAGE_NAME; - ctx->p = ctx->name; - } else if (strcmp(name, "version") == 0) { - version = NULL; - release = NULL; - for (i = 0; atts[i]; i += 2) { - 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; - } - - snprintf(buffer, sizeof buffer, "%s-%s", version, release); - razor_importer_begin_package(ctx->importer, ctx->name, buffer); - } 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; - version = NULL; - release = NULL; - for (i = 0; atts[i]; i += 2) { - if (strcmp(atts[i], "name") == 0) - n = 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 (n == NULL) { - fprintf(stderr, "invalid rpm:entry, " - "missing name or version attributes\n"); - return; - } - - if (version && release) - snprintf(buffer, sizeof buffer, - "%s-%s", version, release); - else if (version) - strcpy(buffer, version); - else - buffer[0] = '\0'; - - switch (ctx->state) { - case YUM_STATE_REQUIRES: - razor_importer_add_property(ctx->importer, n, buffer, - RAZOR_PROPERTY_REQUIRES); - break; - case YUM_STATE_PROVIDES: - razor_importer_add_property(ctx->importer, n, buffer, - RAZOR_PROPERTY_PROVIDES); - break; - case YUM_STATE_OBSOLETES: - razor_importer_add_property(ctx->importer, n, buffer, - RAZOR_PROPERTY_OBSOLETES); - break; - case YUM_STATE_CONFLICTS: - razor_importer_add_property(ctx->importer, n, 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_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_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); -} - -union rpm_entry { - void *p; - char *string; - char **list; - unsigned int *flags; -}; - -static void -add_properties(struct razor_importer *importer, - enum razor_property_type property_type, - Header h, int_32 name_tag, int_32 version_tag, int_32 flags_tag) -{ - union rpm_entry names, versions, flags; - int_32 i, type, count; - - headerGetEntry(h, name_tag, &type, &names.p, &count); - headerGetEntry(h, version_tag, &type, &versions.p, &count); - headerGetEntry(h, flags_tag, &type, &flags.p, &count); - - for (i = 0; i < count; i++) - razor_importer_add_property(importer, - names.list[i], - versions.list[i], - property_type); -} - -struct razor_set * -razor_set_create_from_rpmdb(void) -{ - struct razor_importer *importer; - rpmdbMatchIterator iter; - Header h; - int_32 type, count, i; - union rpm_entry name, version, release; - union rpm_entry basenames, dirnames, dirindexes; - char filename[PATH_MAX]; - rpmdb db; - - rpmReadConfigFiles(NULL, NULL); - - if (rpmdbOpen("", &db, O_RDONLY, 0644) != 0) { - fprintf(stderr, "cannot open rpm database\n"); - exit(1); - } - - importer = razor_importer_new(); - - iter = rpmdbInitIterator(db, 0, NULL, 0); - while (h = rpmdbNextIterator(iter), h != NULL) { - headerGetEntry(h, RPMTAG_NAME, &type, &name.p, &count); - headerGetEntry(h, RPMTAG_VERSION, &type, &version.p, &count); - headerGetEntry(h, RPMTAG_RELEASE, &type, &release.p, &count); - snprintf(filename, sizeof filename, "%s-%s", - version.string, release.string); - razor_importer_begin_package(importer, name.string, filename); - - add_properties(importer, RAZOR_PROPERTY_REQUIRES, h, - RPMTAG_REQUIRENAME, - RPMTAG_REQUIREVERSION, - RPMTAG_REQUIREFLAGS); - - add_properties(importer, RAZOR_PROPERTY_PROVIDES, h, - RPMTAG_PROVIDENAME, - RPMTAG_PROVIDEVERSION, - RPMTAG_PROVIDEFLAGS); - - add_properties(importer, RAZOR_PROPERTY_OBSOLETES, h, - RPMTAG_OBSOLETENAME, - RPMTAG_OBSOLETEVERSION, - RPMTAG_OBSOLETEFLAGS); - - add_properties(importer, RAZOR_PROPERTY_CONFLICTS, h, - RPMTAG_CONFLICTNAME, - RPMTAG_CONFLICTVERSION, - RPMTAG_CONFLICTFLAGS); - - headerGetEntry(h, RPMTAG_BASENAMES, &type, - &basenames.p, &count); - headerGetEntry(h, RPMTAG_DIRNAMES, &type, - &dirnames.p, &count); - headerGetEntry(h, RPMTAG_DIRINDEXES, &type, - &dirindexes.p, &count); - for (i = 0; i < count; i++) { - snprintf(filename, sizeof filename, "%s%s", - dirnames.list[dirindexes.flags[i]], - basenames.list[i]); - razor_importer_add_file(importer, filename); - } - - razor_importer_finish_package(importer); - } - - rpmdbClose(db); - - return razor_importer_finish(importer); -} diff --git a/main.c b/main.c index 9e6e5f1..b52fbcb 100644 --- a/main.c +++ b/main.c @@ -14,6 +14,10 @@ static const char *repo_filename = "system.repo"; static const char *rawhide_repo_filename = "rawhide.repo"; static const char *updated_repo_filename = "system-updated.repo"; +static const char *relations[] = { + "<", "<=", "=", ">=", ">" +}; + static int command_list(int argc, const char *argv[]) { @@ -46,6 +50,7 @@ list_properties(const char *package_name, struct razor_property_iterator *pi; const char *name, *version; enum razor_property_type type; + enum razor_version_relation relation; set = razor_set_open(repo_filename); if (package_name) @@ -55,13 +60,15 @@ list_properties(const char *package_name, pi = razor_property_iterator_create(set, package); while (razor_property_iterator_next(pi, &property, - &name, &version, &type)) { + &name, &relation, &version, + &type)) { if (type != required_type) continue; if (version[0] == '\0') printf("%s\n", name); else - printf("%s-%s\n", name, version); + printf("%s %s %s\n", name, relations[relation], + version); } razor_property_iterator_destroy(pi); @@ -168,6 +175,7 @@ list_property_packages(const char *ref_name, struct razor_property_iterator *pi; const char *name, *version; enum razor_property_type type; + enum razor_version_relation relation; if (ref_name == NULL) return 0; @@ -178,10 +186,12 @@ list_property_packages(const char *ref_name, pi = razor_property_iterator_create(set, NULL); while (razor_property_iterator_next(pi, &property, - &name, &version, &type)) { + &name, &relation, &version, + &type)) { if (strcmp(ref_name, name) != 0) continue; - if (ref_version && strcmp(ref_version, version) != 0) + if (ref_version && relation == RAZOR_VERSION_EQUAL && + strcmp(ref_version, version) != 0) continue; if (ref_type != type) continue; diff --git a/razor.c b/razor.c index 8ff6e92..759819e 100644 --- a/razor.c +++ b/razor.c @@ -58,6 +58,7 @@ struct razor_package { struct razor_property { uint32_t name; + uint32_t relation; uint32_t version; uint32_t packages; }; @@ -440,7 +441,9 @@ razor_importer_finish_package(struct razor_importer *importer) void razor_importer_add_property(struct razor_importer *importer, - const char *name, const char *version, + const char *name, + enum razor_version_relation relation, + const char *version, enum razor_property_type type) { struct razor_property *p; @@ -448,6 +451,7 @@ razor_importer_add_property(struct razor_importer *importer, p = array_add(&importer->set->properties, sizeof *p); p->name = hashtable_tokenize(&importer->table, name) | (type << 30); + p->relation = relation; p->version = hashtable_tokenize(&importer->table, version); p->packages = importer->package - (struct razor_package *) importer->set->packages.data; @@ -642,10 +646,13 @@ compare_properties(const void *p1, const void *p2, void *data) struct razor_set *set = data; char *pool = set->string_pool.data; - if (prop1->name == prop2->name) - return versioncmp(&pool[prop1->version], - &pool[prop2->version]); - else if ((prop1->name & RAZOR_ENTRY_MASK) == (prop2->name & RAZOR_ENTRY_MASK)) + if (prop1->name == prop2->name) { + if (prop1->relation == prop2->relation) + return versioncmp(&pool[prop1->version], + &pool[prop2->version]); + else + return prop1->relation - prop2->relation; + } else if ((prop1->name & RAZOR_ENTRY_MASK) == (prop2->name & RAZOR_ENTRY_MASK)) return (prop1->name >> 30) - (prop2->name >> 30); else return strcmp(&pool[prop1->name & RAZOR_ENTRY_MASK], @@ -671,9 +678,11 @@ uniqueify_properties(struct razor_set *set) rmap = malloc(count * sizeof *map); pkgs = zalloc(count * sizeof *pkgs); for (rp = set->properties.data, up = rp, i = 0; rp < rp_end; rp++, i++) { - if (rp->name != up->name || rp->version != up->version) { + if (rp->name != up->name || rp->relation != up->relation || + rp->version != up->version) { up++; up->name = rp->name; + up->relation = rp->relation; up->version = rp->version; } @@ -1061,7 +1070,9 @@ razor_property_iterator_create(struct razor_set *set, int razor_property_iterator_next(struct razor_property_iterator *pi, struct razor_property **property, - const char **name, const char **version, + const char **name, + enum razor_version_relation *relation, + const char **version, enum razor_property_type *type) { char *pool; @@ -1082,6 +1093,7 @@ razor_property_iterator_next(struct razor_property_iterator *pi, pool = pi->set->string_pool.data; *property = p; *name = &pool[p->name & RAZOR_ENTRY_MASK]; + *relation = p->relation; *version = &pool[p->version]; *type = p->name >> 30; } else { @@ -1443,12 +1455,14 @@ merge_packages(struct razor_merger *merger, struct array *packages) static uint32_t add_property(struct razor_merger *merger, - const char *name, const char *version, int type) + const char *name, enum razor_version_relation relation, + const char *version, int type) { struct razor_property *p; p = array_add(&merger->set->properties, sizeof *p); p->name = hashtable_tokenize(&merger->table, name) | (type << 30); + p->relation = relation; p->version = hashtable_tokenize(&merger->table, version); return p - (struct razor_property *) merger->set->properties.data; @@ -1494,21 +1508,26 @@ merge_properties(struct razor_merger *merger) else cmp = 1; if (cmp == 0) + cmp = p1->relation - p2->relation; + if (cmp == 0) cmp = versioncmp(&pool1[p1->version], &pool2[p2->version]); if (cmp < 0) { map1[i++] = add_property(merger, &pool1[p1->name & RAZOR_ENTRY_MASK], + p1->relation, &pool1[p1->version], (p1->name >> 30)); } else if (cmp > 0) { map2[j++] = add_property(merger, &pool2[p2->name & RAZOR_ENTRY_MASK], + p2->relation, &pool2[p2->version], (p2->name >> 30)); } else { map1[i++] = map2[j++] = add_property(merger, &pool1[p1->name & RAZOR_ENTRY_MASK], + p1->relation, &pool1[p1->version], (p1->name >> 30)); } diff --git a/razor.h b/razor.h index edd9351..6ecd950 100644 --- a/razor.h +++ b/razor.h @@ -14,6 +14,14 @@ enum razor_property_type { RAZOR_PROPERTY_OBSOLETES }; +enum razor_version_relation { + RAZOR_VERSION_LESS, + RAZOR_VERSION_LESS_OR_EQUAL, + RAZOR_VERSION_EQUAL, + RAZOR_VERSION_GREATER_OR_EQUAL, + RAZOR_VERSION_GREATER +}; + struct razor_set *razor_set_create(void); struct razor_set *razor_set_open(const char *filename); void razor_set_destroy(struct razor_set *set); @@ -43,7 +51,9 @@ razor_property_iterator_create(struct razor_set *set, struct razor_package *package); int razor_property_iterator_next(struct razor_property_iterator *pi, struct razor_property **property, - const char **name, const char **version, + const char **name, + enum razor_version_relation *relation, + const char **version, enum razor_property_type *type); void razor_property_iterator_destroy(struct razor_property_iterator *pi); @@ -76,7 +86,9 @@ void razor_importer_destroy(struct razor_importer *importer); void razor_importer_begin_package(struct razor_importer *importer, const char *name, const char *version); void razor_importer_add_property(struct razor_importer *importer, - const char *name, const char *version, + const char *name, + enum razor_version_relation relation, + const char *version, enum razor_property_type type); void razor_importer_add_file(struct razor_importer *importer, const char *name); diff --git a/rpm.c b/rpm.c index 3b3a01b..5091afc 100644 --- a/rpm.c +++ b/rpm.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "razor.h" @@ -73,22 +74,47 @@ razor_rpm_get_indirect(struct razor_rpm *rpm, return NULL; } +static enum razor_version_relation +rpm_to_razor_flags (uint_32 flags) +{ + switch (flags & (RPMSENSE_LESS | RPMSENSE_EQUAL | RPMSENSE_GREATER)) { + case RPMSENSE_LESS: + return RAZOR_VERSION_LESS; + case RPMSENSE_LESS|RPMSENSE_EQUAL: + return RAZOR_VERSION_LESS_OR_EQUAL; + case RPMSENSE_EQUAL: + return RAZOR_VERSION_EQUAL; + case RPMSENSE_GREATER|RPMSENSE_EQUAL: + return RAZOR_VERSION_GREATER_OR_EQUAL; + case RPMSENSE_GREATER: + return RAZOR_VERSION_GREATER; + } + + /* FIXME? */ + return RAZOR_VERSION_EQUAL; +} + static void import_properties(struct razor_importer *importer, unsigned long type, struct razor_rpm *rpm, int name_tag, int version_tag, int flags_tag) { const char *name, *version; + uint_32 flags; unsigned int i, count; name = razor_rpm_get_indirect(rpm, name_tag, &count); if (name == NULL) return; + flags = *(uint_32 *)razor_rpm_get_indirect(rpm, flags_tag, &count); + /* FIXME: Concat version and release. */ version = razor_rpm_get_indirect(rpm, version_tag, &count); for (i = 0; i < count; i++) { - razor_importer_add_property(importer, name, version, type); + razor_importer_add_property(importer, name, + rpm_to_razor_flags (flags), + version, type); name += strlen(name) + 1; version += strlen(version) + 1; } @@ -534,3 +560,101 @@ razor_importer_add_rpm(struct razor_importer *importer, struct razor_rpm *rpm) return 0; } + +union rpm_entry { + void *p; + char *string; + char **list; + uint_32 *flags; +}; + +static void +add_properties(struct razor_importer *importer, + enum razor_property_type property_type, + Header h, int_32 name_tag, int_32 version_tag, int_32 flags_tag) +{ + union rpm_entry names, versions, flags; + int_32 i, type, count; + + headerGetEntry(h, name_tag, &type, &names.p, &count); + headerGetEntry(h, version_tag, &type, &versions.p, &count); + headerGetEntry(h, flags_tag, &type, &flags.p, &count); + + for (i = 0; i < count; i++) + razor_importer_add_property(importer, + names.list[i], + rpm_to_razor_flags (flags.flags[i]), + versions.list[i], + property_type); +} + +struct razor_set * +razor_set_create_from_rpmdb(void) +{ + struct razor_importer *importer; + rpmdbMatchIterator iter; + Header h; + int_32 type, count, i; + union rpm_entry name, version, release; + union rpm_entry basenames, dirnames, dirindexes; + char filename[PATH_MAX]; + rpmdb db; + + rpmReadConfigFiles(NULL, NULL); + + if (rpmdbOpen("", &db, O_RDONLY, 0644) != 0) { + fprintf(stderr, "cannot open rpm database\n"); + exit(1); + } + + importer = razor_importer_new(); + + iter = rpmdbInitIterator(db, 0, NULL, 0); + while (h = rpmdbNextIterator(iter), h != NULL) { + headerGetEntry(h, RPMTAG_NAME, &type, &name.p, &count); + headerGetEntry(h, RPMTAG_VERSION, &type, &version.p, &count); + headerGetEntry(h, RPMTAG_RELEASE, &type, &release.p, &count); + snprintf(filename, sizeof filename, "%s-%s", + version.string, release.string); + razor_importer_begin_package(importer, name.string, filename); + + add_properties(importer, RAZOR_PROPERTY_REQUIRES, h, + RPMTAG_REQUIRENAME, + RPMTAG_REQUIREVERSION, + RPMTAG_REQUIREFLAGS); + + add_properties(importer, RAZOR_PROPERTY_PROVIDES, h, + RPMTAG_PROVIDENAME, + RPMTAG_PROVIDEVERSION, + RPMTAG_PROVIDEFLAGS); + + add_properties(importer, RAZOR_PROPERTY_OBSOLETES, h, + RPMTAG_OBSOLETENAME, + RPMTAG_OBSOLETEVERSION, + RPMTAG_OBSOLETEFLAGS); + + add_properties(importer, RAZOR_PROPERTY_CONFLICTS, h, + RPMTAG_CONFLICTNAME, + RPMTAG_CONFLICTVERSION, + RPMTAG_CONFLICTFLAGS); + + headerGetEntry(h, RPMTAG_BASENAMES, &type, + &basenames.p, &count); + headerGetEntry(h, RPMTAG_DIRNAMES, &type, + &dirnames.p, &count); + headerGetEntry(h, RPMTAG_DIRINDEXES, &type, + &dirindexes.p, &count); + for (i = 0; i < count; i++) { + snprintf(filename, sizeof filename, "%s%s", + dirnames.list[dirindexes.flags[i]], + basenames.list[i]); + razor_importer_add_file(importer, filename); + } + + razor_importer_finish_package(importer); + } + + rpmdbClose(db); + + return razor_importer_finish(importer); +} diff --git a/test-driver.c b/test-driver.c index 6eb40f5..5fbdc40 100644 --- a/test-driver.c +++ b/test-driver.c @@ -95,7 +95,8 @@ parse_property(struct test_context *ctx, const char **atts, exit(-1); } - razor_importer_add_property(ctx->importer, name, version, type); + razor_importer_add_property(ctx->importer, name, + RAZOR_VERSION_EQUAL, version, type); } static void @@ -190,6 +191,7 @@ verify_end(struct test_context *ctx) struct razor_property *property; const char *name, *version; enum razor_property_type type; + enum razor_version_relation relation; if (ctx->package_iterator != NULL) { if (razor_package_iterator_next(ctx->package_iterator, @@ -206,7 +208,8 @@ verify_end(struct test_context *ctx) if (ctx->property_iterator != NULL) { if (razor_property_iterator_next(ctx->property_iterator, &property, - &name, &version, &type)) { + &name, &relation, &version, + &type)) { fprintf(stderr, "too few properties in set\n"); exit(-1); } @@ -251,6 +254,7 @@ verify_property(struct test_context *ctx, struct razor_property *property; const char *name, *version, *ref_name, *ref_version; enum razor_property_type type; + enum razor_version_relation relation; int same_version; if (ctx->property_iterator == NULL) { @@ -262,7 +266,7 @@ verify_property(struct test_context *ctx, get_atts(atts, "name", &ref_name, "eq", &ref_version, NULL); if (!razor_property_iterator_next(ctx->property_iterator, &property, - &name, &version, &type)) { + &name, &relation, &version, &type)) { fprintf(stderr, "too many properties in set\n"); exit(-1); } diff --git a/yum.c b/yum.c new file mode 100644 index 0000000..8937077 --- /dev/null +++ b/yum.c @@ -0,0 +1,312 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "razor.h" + +/* Import a yum filelist as a razor package set. */ + +enum { + YUM_STATE_BEGIN, + YUM_STATE_PACKAGE_NAME, + 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], 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, *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, "version") == 0) { + version = NULL; + release = NULL; + for (i = 0; atts[i]; i += 2) { + 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; + } + + snprintf(buffer, sizeof buffer, "%s-%s", version, release); + razor_importer_begin_package(ctx->importer, ctx->name, buffer); + } 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; + 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], "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; + } + + if (version && release) + snprintf(buffer, sizeof buffer, + "%s-%s", version, release); + else if (version) + strcpy(buffer, version); + else + buffer[0] = '\0'; + + 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_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_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); +} -- 1.7.1