Support for less/equal/greater version in requires/conflicts, etc
authorDan Winship <danw@gnome.org>
Mon Feb 04 14:25:45 2008 -0500 (2008-02-04)
changeset 109313b0a615c14
parent 108 340d92912f49
child 110 07a5bf8e7e6e
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
main.c
razor.c
razor.h
rpm.c
test-driver.c
yum.c
     1.1 --- a/import.c	Mon Feb 04 10:46:29 2008 -0500
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,379 +0,0 @@
     1.4 -#define _GNU_SOURCE
     1.5 -
     1.6 -#include <string.h>
     1.7 -#include <stdio.h>
     1.8 -#include <sys/stat.h>
     1.9 -#include <sys/mman.h>
    1.10 -#include <unistd.h>
    1.11 -#include <fcntl.h>
    1.12 -#include <errno.h>
    1.13 -
    1.14 -#include <expat.h>
    1.15 -#include <zlib.h>
    1.16 -#include <rpm/rpmlib.h>
    1.17 -#include <rpm/rpmdb.h>
    1.18 -#include "razor.h"
    1.19 -
    1.20 -/* Import a yum filelist as a razor package set. */
    1.21 -
    1.22 -enum {
    1.23 -	YUM_STATE_BEGIN,
    1.24 -	YUM_STATE_PACKAGE_NAME,
    1.25 -	YUM_STATE_CHECKSUM,
    1.26 -	YUM_STATE_REQUIRES,
    1.27 -	YUM_STATE_PROVIDES,
    1.28 -	YUM_STATE_OBSOLETES,
    1.29 -	YUM_STATE_CONFLICTS,
    1.30 -	YUM_STATE_FILE
    1.31 -};
    1.32 -
    1.33 -struct yum_context {
    1.34 -	XML_Parser primary_parser;
    1.35 -	XML_Parser filelists_parser;
    1.36 -	XML_Parser current_parser;
    1.37 -
    1.38 -	struct razor_importer *importer;
    1.39 -	struct import_property_context *current_property_context;
    1.40 -	char name[256], buffer[512], *p;
    1.41 -	char pkgid[128];
    1.42 -	int state;
    1.43 -};
    1.44 -
    1.45 -static void
    1.46 -yum_primary_start_element(void *data, const char *name, const char **atts)
    1.47 -{
    1.48 -	struct yum_context *ctx = data;
    1.49 -	const char *n, *version, *release;
    1.50 -	char buffer[128];
    1.51 -	int i;
    1.52 -
    1.53 -	if (strcmp(name, "name") == 0) {
    1.54 -		ctx->state = YUM_STATE_PACKAGE_NAME;
    1.55 -		ctx->p = ctx->name;
    1.56 -	} else if (strcmp(name, "version") == 0) {
    1.57 -		version = NULL;
    1.58 -		release = NULL;
    1.59 -		for (i = 0; atts[i]; i += 2) {
    1.60 -			if (strcmp(atts[i], "ver") == 0)
    1.61 -				version = atts[i + 1];
    1.62 -			else if (strcmp(atts[i], "rel") == 0)
    1.63 -				release = atts[i + 1];
    1.64 -		}
    1.65 -		if (version == NULL || release == NULL) {
    1.66 -			fprintf(stderr, "invalid version tag, "
    1.67 -				"missing version or  release attribute\n");
    1.68 -			return;
    1.69 -		}
    1.70 -
    1.71 -		snprintf(buffer, sizeof buffer, "%s-%s", version, release);
    1.72 -		razor_importer_begin_package(ctx->importer, ctx->name, buffer);
    1.73 -	} else if (strcmp(name, "checksum") == 0) {
    1.74 -		ctx->p = ctx->pkgid;
    1.75 -		ctx->state = YUM_STATE_CHECKSUM;
    1.76 -	} else if (strcmp(name, "rpm:requires") == 0) {
    1.77 -		ctx->state = YUM_STATE_REQUIRES;
    1.78 -	} else if (strcmp(name, "rpm:provides") == 0) {
    1.79 -		ctx->state = YUM_STATE_PROVIDES;
    1.80 -	} else if (strcmp(name, "rpm:obsoletes") == 0) {
    1.81 -		ctx->state = YUM_STATE_OBSOLETES;
    1.82 -	} else if (strcmp(name, "rpm:conflicts") == 0) {
    1.83 -		ctx->state = YUM_STATE_CONFLICTS;
    1.84 -	} else if (strcmp(name, "rpm:entry") == 0 &&
    1.85 -		   ctx->state != YUM_STATE_BEGIN) {
    1.86 -		n = NULL;
    1.87 -		version = NULL;
    1.88 -		release = NULL;
    1.89 -		for (i = 0; atts[i]; i += 2) {
    1.90 -			if (strcmp(atts[i], "name") == 0)
    1.91 -				n = atts[i + 1];
    1.92 -			else if (strcmp(atts[i], "ver") == 0)
    1.93 -				version = atts[i + 1];
    1.94 -			else if (strcmp(atts[i], "rel") == 0)
    1.95 -				release = atts[i + 1];
    1.96 -		}
    1.97 -
    1.98 -		if (n == NULL) {
    1.99 -			fprintf(stderr, "invalid rpm:entry, "
   1.100 -				"missing name or version attributes\n");
   1.101 -			return;
   1.102 -		}
   1.103 -
   1.104 -		if (version && release)
   1.105 -			snprintf(buffer, sizeof buffer,
   1.106 -				 "%s-%s", version, release);
   1.107 -		else if (version)
   1.108 -			strcpy(buffer, version);
   1.109 -		else
   1.110 -			buffer[0] = '\0';
   1.111 -			
   1.112 -		switch (ctx->state) {
   1.113 -		case YUM_STATE_REQUIRES:
   1.114 -			razor_importer_add_property(ctx->importer, n, buffer,
   1.115 -						    RAZOR_PROPERTY_REQUIRES);
   1.116 -			break;
   1.117 -		case YUM_STATE_PROVIDES:
   1.118 -			razor_importer_add_property(ctx->importer, n, buffer,
   1.119 -						    RAZOR_PROPERTY_PROVIDES);
   1.120 -			break;
   1.121 -		case YUM_STATE_OBSOLETES:
   1.122 -			razor_importer_add_property(ctx->importer, n, buffer,
   1.123 -						    RAZOR_PROPERTY_OBSOLETES);
   1.124 -			break;
   1.125 -		case YUM_STATE_CONFLICTS:
   1.126 -			razor_importer_add_property(ctx->importer, n, buffer,
   1.127 -						    RAZOR_PROPERTY_CONFLICTS);
   1.128 -			break;
   1.129 -		}
   1.130 -	}
   1.131 -}
   1.132 -
   1.133 -static void
   1.134 -yum_primary_end_element (void *data, const char *name)
   1.135 -{
   1.136 -	struct yum_context *ctx = data;
   1.137 -
   1.138 -	switch (ctx->state) {
   1.139 -	case YUM_STATE_PACKAGE_NAME:
   1.140 -	case YUM_STATE_CHECKSUM:
   1.141 -	case YUM_STATE_FILE:
   1.142 -		ctx->state = YUM_STATE_BEGIN;
   1.143 -		break;
   1.144 -	}
   1.145 -
   1.146 -	if (strcmp(name, "package") == 0) {
   1.147 -		XML_StopParser(ctx->current_parser, XML_TRUE);
   1.148 -		ctx->current_parser = ctx->filelists_parser;
   1.149 -	}
   1.150 -}
   1.151 -
   1.152 -static void
   1.153 -yum_character_data (void *data, const XML_Char *s, int len)
   1.154 -{
   1.155 -	struct yum_context *ctx = data;
   1.156 -
   1.157 -	switch (ctx->state) {
   1.158 -	case YUM_STATE_PACKAGE_NAME:
   1.159 -	case YUM_STATE_CHECKSUM:
   1.160 -	case YUM_STATE_FILE:
   1.161 -		memcpy(ctx->p, s, len);
   1.162 -		ctx->p += len;
   1.163 -		*ctx->p = '\0';
   1.164 -		break;
   1.165 -	}
   1.166 -}
   1.167 -
   1.168 -static void
   1.169 -yum_filelists_start_element(void *data, const char *name, const char **atts)
   1.170 -{
   1.171 -	struct yum_context *ctx = data;
   1.172 -	const char *pkg, *pkgid;
   1.173 -	int i;
   1.174 -
   1.175 -	if (strcmp(name, "package") == 0) {
   1.176 -		pkg = NULL;
   1.177 -		pkgid = NULL;
   1.178 -		for (i = 0; atts[i]; i += 2) {
   1.179 -			if (strcmp(atts[i], "name") == 0)
   1.180 -				pkg = atts[i + 1];
   1.181 -			else if (strcmp(atts[i], "pkgid") == 0)
   1.182 -				pkgid = atts[i + 1];
   1.183 -		}
   1.184 -		if (strcmp(pkgid, ctx->pkgid) != 0)
   1.185 -			fprintf(stderr, "primary.xml and filelists.xml "
   1.186 -				"mismatch for %s: %s vs %s",
   1.187 -				pkg, pkgid, ctx->pkgid);
   1.188 -	} else if (strcmp(name, "file") == 0) {
   1.189 -		ctx->state = YUM_STATE_FILE;
   1.190 -		ctx->p = ctx->buffer;
   1.191 -	}
   1.192 -}
   1.193 -
   1.194 -
   1.195 -static void
   1.196 -yum_filelists_end_element (void *data, const char *name)
   1.197 -{
   1.198 -	struct yum_context *ctx = data;
   1.199 -
   1.200 -	ctx->state = YUM_STATE_BEGIN;
   1.201 -	if (strcmp(name, "package") == 0) {
   1.202 -		XML_StopParser(ctx->current_parser, XML_TRUE);
   1.203 -		ctx->current_parser = ctx->primary_parser;
   1.204 -		razor_importer_finish_package(ctx->importer);
   1.205 -	} else if (strcmp(name, "file") == 0)
   1.206 -		razor_importer_add_file(ctx->importer, ctx->buffer);
   1.207 -
   1.208 -}
   1.209 -
   1.210 -#define XML_BUFFER_SIZE 4096
   1.211 -
   1.212 -struct razor_set *
   1.213 -razor_set_create_from_yum(void)
   1.214 -{
   1.215 -	struct yum_context ctx;
   1.216 -	void *buf;
   1.217 -	int len, ret;
   1.218 -	gzFile primary, filelists;
   1.219 -	XML_ParsingStatus status;
   1.220 -
   1.221 -	ctx.importer = razor_importer_new();	
   1.222 -	ctx.state = YUM_STATE_BEGIN;
   1.223 -
   1.224 -	ctx.primary_parser = XML_ParserCreate(NULL);
   1.225 -	XML_SetUserData(ctx.primary_parser, &ctx);
   1.226 -	XML_SetElementHandler(ctx.primary_parser,
   1.227 -			      yum_primary_start_element,
   1.228 -			      yum_primary_end_element);
   1.229 -	XML_SetCharacterDataHandler(ctx.primary_parser,
   1.230 -				    yum_character_data);
   1.231 -
   1.232 -	ctx.filelists_parser = XML_ParserCreate(NULL);
   1.233 -	XML_SetUserData(ctx.filelists_parser, &ctx);
   1.234 -	XML_SetElementHandler(ctx.filelists_parser,
   1.235 -			      yum_filelists_start_element,
   1.236 -			      yum_filelists_end_element);
   1.237 -	XML_SetCharacterDataHandler(ctx.filelists_parser,
   1.238 -				    yum_character_data);
   1.239 -
   1.240 -	primary = gzopen("primary.xml.gz", "rb");
   1.241 -	if (primary == NULL)
   1.242 -		return NULL;
   1.243 -	filelists = gzopen("filelists.xml.gz", "rb");
   1.244 -	if (filelists == NULL)
   1.245 -		return NULL;
   1.246 -
   1.247 -	ctx.current_parser = ctx.primary_parser;
   1.248 -
   1.249 -	do {
   1.250 -		XML_GetParsingStatus(ctx.current_parser, &status);
   1.251 -		switch (status.parsing) {
   1.252 -		case XML_SUSPENDED:
   1.253 -			ret = XML_ResumeParser(ctx.current_parser);
   1.254 -			break;
   1.255 -		case XML_PARSING:
   1.256 -		case XML_INITIALIZED:
   1.257 -			buf = XML_GetBuffer(ctx.current_parser,
   1.258 -					    XML_BUFFER_SIZE);
   1.259 -			if (ctx.current_parser == ctx.primary_parser)
   1.260 -				len = gzread(primary, buf, XML_BUFFER_SIZE);
   1.261 -			else
   1.262 -				len = gzread(filelists, buf, XML_BUFFER_SIZE);
   1.263 -			if (len < 0) {
   1.264 -				fprintf(stderr,
   1.265 -					"couldn't read input: %s\n",
   1.266 -					strerror(errno));
   1.267 -				return NULL;
   1.268 -			}
   1.269 -
   1.270 -			XML_ParseBuffer(ctx.current_parser, len, len == 0);
   1.271 -			break;
   1.272 -		case XML_FINISHED:
   1.273 -			break;
   1.274 -		}
   1.275 -	} while (status.parsing != XML_FINISHED);
   1.276 -
   1.277 -
   1.278 -	XML_ParserFree(ctx.primary_parser);
   1.279 -	XML_ParserFree(ctx.filelists_parser);
   1.280 -
   1.281 -	gzclose(primary);
   1.282 -	gzclose(filelists);
   1.283 -
   1.284 -	return razor_importer_finish(ctx.importer);
   1.285 -}
   1.286 -
   1.287 -union rpm_entry {
   1.288 -	void *p;
   1.289 -	char *string;
   1.290 -	char **list;
   1.291 -	unsigned int *flags;
   1.292 -};
   1.293 -
   1.294 -static void
   1.295 -add_properties(struct razor_importer *importer,
   1.296 -	       enum razor_property_type property_type,
   1.297 -	       Header h, int_32 name_tag, int_32 version_tag, int_32 flags_tag)
   1.298 -{
   1.299 -	union rpm_entry names, versions, flags;
   1.300 -	int_32 i, type, count;
   1.301 -
   1.302 -	headerGetEntry(h, name_tag, &type, &names.p, &count);
   1.303 -	headerGetEntry(h, version_tag, &type, &versions.p, &count);
   1.304 -	headerGetEntry(h, flags_tag, &type, &flags.p, &count);
   1.305 -
   1.306 -	for (i = 0; i < count; i++)
   1.307 -		razor_importer_add_property(importer,
   1.308 -					    names.list[i],
   1.309 -					    versions.list[i],
   1.310 -					    property_type);
   1.311 -}
   1.312 -
   1.313 -struct razor_set *
   1.314 -razor_set_create_from_rpmdb(void)
   1.315 -{
   1.316 -	struct razor_importer *importer;
   1.317 -	rpmdbMatchIterator iter;
   1.318 -	Header h;
   1.319 -	int_32 type, count, i;
   1.320 -	union rpm_entry name, version, release;
   1.321 -	union rpm_entry basenames, dirnames, dirindexes;
   1.322 -	char filename[PATH_MAX];
   1.323 -	rpmdb db;
   1.324 -
   1.325 -	rpmReadConfigFiles(NULL, NULL);
   1.326 -
   1.327 -	if (rpmdbOpen("", &db, O_RDONLY, 0644) != 0) {
   1.328 -		fprintf(stderr, "cannot open rpm database\n");
   1.329 -		exit(1);
   1.330 -	}
   1.331 -
   1.332 -	importer = razor_importer_new();
   1.333 -
   1.334 -	iter = rpmdbInitIterator(db, 0, NULL, 0);
   1.335 -	while (h = rpmdbNextIterator(iter), h != NULL) {
   1.336 -		headerGetEntry(h, RPMTAG_NAME, &type, &name.p, &count);
   1.337 -		headerGetEntry(h, RPMTAG_VERSION, &type, &version.p, &count);
   1.338 -		headerGetEntry(h, RPMTAG_RELEASE, &type, &release.p, &count);
   1.339 -		snprintf(filename, sizeof filename, "%s-%s",
   1.340 -			 version.string, release.string);
   1.341 -		razor_importer_begin_package(importer, name.string, filename);
   1.342 -
   1.343 -		add_properties(importer, RAZOR_PROPERTY_REQUIRES, h,
   1.344 -			       RPMTAG_REQUIRENAME,
   1.345 -			       RPMTAG_REQUIREVERSION,
   1.346 -			       RPMTAG_REQUIREFLAGS);
   1.347 -
   1.348 -		add_properties(importer, RAZOR_PROPERTY_PROVIDES, h,
   1.349 -			       RPMTAG_PROVIDENAME,
   1.350 -			       RPMTAG_PROVIDEVERSION,
   1.351 -			       RPMTAG_PROVIDEFLAGS);
   1.352 -
   1.353 -		add_properties(importer, RAZOR_PROPERTY_OBSOLETES, h,
   1.354 -			       RPMTAG_OBSOLETENAME,
   1.355 -			       RPMTAG_OBSOLETEVERSION,
   1.356 -			       RPMTAG_OBSOLETEFLAGS);
   1.357 -
   1.358 -		add_properties(importer, RAZOR_PROPERTY_CONFLICTS, h,
   1.359 -			       RPMTAG_CONFLICTNAME,
   1.360 -			       RPMTAG_CONFLICTVERSION,
   1.361 -			       RPMTAG_CONFLICTFLAGS);
   1.362 -
   1.363 -		headerGetEntry(h, RPMTAG_BASENAMES, &type,
   1.364 -			       &basenames.p, &count);
   1.365 -		headerGetEntry(h, RPMTAG_DIRNAMES, &type,
   1.366 -			       &dirnames.p, &count);
   1.367 -		headerGetEntry(h, RPMTAG_DIRINDEXES, &type,
   1.368 -			       &dirindexes.p, &count);
   1.369 -		for (i = 0; i < count; i++) {
   1.370 -			snprintf(filename, sizeof filename, "%s%s",
   1.371 -				 dirnames.list[dirindexes.flags[i]],
   1.372 -				 basenames.list[i]);
   1.373 -			razor_importer_add_file(importer, filename);
   1.374 -		}
   1.375 -
   1.376 -		razor_importer_finish_package(importer);
   1.377 -	}
   1.378 -
   1.379 -	rpmdbClose(db);
   1.380 -
   1.381 -	return razor_importer_finish(importer);
   1.382 -}
     2.1 --- a/main.c	Mon Feb 04 10:46:29 2008 -0500
     2.2 +++ b/main.c	Mon Feb 04 14:25:45 2008 -0500
     2.3 @@ -14,6 +14,10 @@
     2.4  static const char *rawhide_repo_filename = "rawhide.repo";
     2.5  static const char *updated_repo_filename = "system-updated.repo";
     2.6  
     2.7 +static const char *relations[] = {
     2.8 +	"<", "<=", "=", ">=", ">"
     2.9 +};
    2.10 +
    2.11  static int
    2.12  command_list(int argc, const char *argv[])
    2.13  {
    2.14 @@ -46,6 +50,7 @@
    2.15  	struct razor_property_iterator *pi;
    2.16  	const char *name, *version;
    2.17  	enum razor_property_type type;
    2.18 +	enum razor_version_relation relation;
    2.19  
    2.20  	set = razor_set_open(repo_filename);
    2.21  	if (package_name)
    2.22 @@ -55,13 +60,15 @@
    2.23  
    2.24  	pi = razor_property_iterator_create(set, package);
    2.25  	while (razor_property_iterator_next(pi, &property,
    2.26 -					    &name, &version, &type)) {
    2.27 +					    &name, &relation, &version,
    2.28 +					    &type)) {
    2.29  		if (type != required_type)
    2.30  			continue;
    2.31  		if (version[0] == '\0')
    2.32  			printf("%s\n", name);
    2.33  		else
    2.34 -			printf("%s-%s\n", name, version);
    2.35 +			printf("%s %s %s\n", name, relations[relation],
    2.36 +			       version);
    2.37  	}
    2.38  	razor_property_iterator_destroy(pi);
    2.39  
    2.40 @@ -168,6 +175,7 @@
    2.41  	struct razor_property_iterator *pi;
    2.42  	const char *name, *version;
    2.43  	enum razor_property_type type;
    2.44 +	enum razor_version_relation relation;
    2.45  
    2.46  	if (ref_name == NULL)
    2.47  		return 0;
    2.48 @@ -178,10 +186,12 @@
    2.49  
    2.50  	pi = razor_property_iterator_create(set, NULL);
    2.51  	while (razor_property_iterator_next(pi, &property,
    2.52 -					    &name, &version, &type)) {
    2.53 +					    &name, &relation, &version,
    2.54 +					    &type)) {
    2.55  		if (strcmp(ref_name, name) != 0)
    2.56  			continue;
    2.57 -		if (ref_version && strcmp(ref_version, version) != 0)
    2.58 +		if (ref_version && relation == RAZOR_VERSION_EQUAL &&
    2.59 +		    strcmp(ref_version, version) != 0)
    2.60  			continue;
    2.61  		if (ref_type != type)
    2.62  			continue;
     3.1 --- a/razor.c	Mon Feb 04 10:46:29 2008 -0500
     3.2 +++ b/razor.c	Mon Feb 04 14:25:45 2008 -0500
     3.3 @@ -58,6 +58,7 @@
     3.4  
     3.5  struct razor_property {
     3.6  	uint32_t name;
     3.7 +	uint32_t relation;
     3.8  	uint32_t version;
     3.9  	uint32_t packages;
    3.10  };
    3.11 @@ -440,7 +441,9 @@
    3.12  
    3.13  void
    3.14  razor_importer_add_property(struct razor_importer *importer,
    3.15 -			    const char *name, const char *version,
    3.16 +			    const char *name,
    3.17 +			    enum razor_version_relation relation,
    3.18 +			    const char *version,
    3.19  			    enum razor_property_type type)
    3.20  {
    3.21  	struct razor_property *p;
    3.22 @@ -448,6 +451,7 @@
    3.23  
    3.24  	p = array_add(&importer->set->properties, sizeof *p);
    3.25  	p->name = hashtable_tokenize(&importer->table, name) | (type << 30);
    3.26 +	p->relation = relation;
    3.27  	p->version = hashtable_tokenize(&importer->table, version);
    3.28  	p->packages = importer->package -
    3.29  		(struct razor_package *) importer->set->packages.data;
    3.30 @@ -642,10 +646,13 @@
    3.31  	struct razor_set *set = data;
    3.32  	char *pool = set->string_pool.data;
    3.33  
    3.34 -	if (prop1->name == prop2->name)
    3.35 -		return versioncmp(&pool[prop1->version],
    3.36 -				  &pool[prop2->version]);
    3.37 -	else if ((prop1->name & RAZOR_ENTRY_MASK) == (prop2->name & RAZOR_ENTRY_MASK))
    3.38 +	if (prop1->name == prop2->name) {
    3.39 +		if (prop1->relation == prop2->relation)
    3.40 +			return versioncmp(&pool[prop1->version],
    3.41 +					  &pool[prop2->version]);
    3.42 +		else
    3.43 +			return prop1->relation - prop2->relation;
    3.44 +	} else if ((prop1->name & RAZOR_ENTRY_MASK) == (prop2->name & RAZOR_ENTRY_MASK))
    3.45  		return (prop1->name >> 30) - (prop2->name >> 30);
    3.46  	else
    3.47  		return strcmp(&pool[prop1->name & RAZOR_ENTRY_MASK],
    3.48 @@ -671,9 +678,11 @@
    3.49  	rmap = malloc(count * sizeof *map);
    3.50  	pkgs = zalloc(count * sizeof *pkgs);
    3.51  	for (rp = set->properties.data, up = rp, i = 0; rp < rp_end; rp++, i++) {
    3.52 -		if (rp->name != up->name || rp->version != up->version) {
    3.53 +		if (rp->name != up->name || rp->relation != up->relation ||
    3.54 +		    rp->version != up->version) {
    3.55  			up++;
    3.56  			up->name = rp->name;
    3.57 +			up->relation = rp->relation;
    3.58  			up->version = rp->version;
    3.59  		}
    3.60  
    3.61 @@ -1061,7 +1070,9 @@
    3.62  int
    3.63  razor_property_iterator_next(struct razor_property_iterator *pi,
    3.64  			     struct razor_property **property,
    3.65 -			     const char **name, const char **version,
    3.66 +			     const char **name,
    3.67 +			     enum razor_version_relation *relation,
    3.68 +			     const char **version,
    3.69  			     enum razor_property_type *type)
    3.70  {
    3.71  	char *pool;
    3.72 @@ -1082,6 +1093,7 @@
    3.73  		pool = pi->set->string_pool.data;
    3.74  		*property = p;
    3.75  		*name = &pool[p->name & RAZOR_ENTRY_MASK];
    3.76 +		*relation = p->relation;
    3.77  		*version = &pool[p->version];
    3.78  		*type = p->name >> 30;
    3.79  	} else {
    3.80 @@ -1443,12 +1455,14 @@
    3.81  
    3.82  static uint32_t
    3.83  add_property(struct razor_merger *merger,
    3.84 -	     const char *name, const char *version, int type)
    3.85 +	     const char *name, enum razor_version_relation relation,
    3.86 +	     const char *version, int type)
    3.87  {
    3.88  	struct razor_property *p;
    3.89  
    3.90  	p = array_add(&merger->set->properties, sizeof *p);
    3.91  	p->name = hashtable_tokenize(&merger->table, name) | (type << 30);
    3.92 +	p->relation = relation;
    3.93  	p->version = hashtable_tokenize(&merger->table, version);
    3.94  
    3.95  	return p - (struct razor_property *) merger->set->properties.data;
    3.96 @@ -1494,21 +1508,26 @@
    3.97  		else
    3.98  			cmp = 1;
    3.99  		if (cmp == 0)
   3.100 +			cmp = p1->relation - p2->relation;
   3.101 +		if (cmp == 0)
   3.102  			cmp = versioncmp(&pool1[p1->version],
   3.103  					 &pool2[p2->version]);
   3.104  		if (cmp < 0) {
   3.105  			map1[i++] = add_property(merger,
   3.106  						 &pool1[p1->name & RAZOR_ENTRY_MASK],
   3.107 +						 p1->relation,
   3.108  						 &pool1[p1->version],
   3.109  						 (p1->name >> 30));
   3.110  		} else if (cmp > 0) {
   3.111  			map2[j++] = add_property(merger,
   3.112  						 &pool2[p2->name & RAZOR_ENTRY_MASK],
   3.113 +						 p2->relation,
   3.114  						 &pool2[p2->version],
   3.115  						 (p2->name >> 30));
   3.116  		} else  {
   3.117  			map1[i++] = map2[j++] = add_property(merger,
   3.118  							     &pool1[p1->name & RAZOR_ENTRY_MASK],
   3.119 +							     p1->relation,
   3.120  							     &pool1[p1->version],
   3.121  							     (p1->name >> 30));
   3.122  		}
     4.1 --- a/razor.h	Mon Feb 04 10:46:29 2008 -0500
     4.2 +++ b/razor.h	Mon Feb 04 14:25:45 2008 -0500
     4.3 @@ -14,6 +14,14 @@
     4.4  	RAZOR_PROPERTY_OBSOLETES
     4.5  };
     4.6  
     4.7 +enum razor_version_relation {
     4.8 +	RAZOR_VERSION_LESS,
     4.9 +	RAZOR_VERSION_LESS_OR_EQUAL,
    4.10 +	RAZOR_VERSION_EQUAL,
    4.11 +	RAZOR_VERSION_GREATER_OR_EQUAL,
    4.12 +	RAZOR_VERSION_GREATER
    4.13 +};
    4.14 +
    4.15  struct razor_set *razor_set_create(void);
    4.16  struct razor_set *razor_set_open(const char *filename);
    4.17  void razor_set_destroy(struct razor_set *set);
    4.18 @@ -43,7 +51,9 @@
    4.19  			       struct razor_package *package);
    4.20  int razor_property_iterator_next(struct razor_property_iterator *pi,
    4.21  				 struct razor_property **property,
    4.22 -				 const char **name, const char **version,
    4.23 +				 const char **name,
    4.24 +				 enum razor_version_relation *relation,
    4.25 +				 const char **version,
    4.26  				 enum razor_property_type *type);
    4.27  void
    4.28  razor_property_iterator_destroy(struct razor_property_iterator *pi);
    4.29 @@ -76,7 +86,9 @@
    4.30  void razor_importer_begin_package(struct razor_importer *importer,
    4.31  				const char *name, const char *version);
    4.32  void razor_importer_add_property(struct razor_importer *importer,
    4.33 -				 const char *name, const char *version,
    4.34 +				 const char *name,
    4.35 +				 enum razor_version_relation relation,
    4.36 +				 const char *version,
    4.37  				 enum razor_property_type type);
    4.38  void razor_importer_add_file(struct razor_importer *importer,
    4.39  			     const char *name);
     5.1 --- a/rpm.c	Mon Feb 04 10:46:29 2008 -0500
     5.2 +++ b/rpm.c	Mon Feb 04 14:25:45 2008 -0500
     5.3 @@ -9,6 +9,7 @@
     5.4  #include <unistd.h>
     5.5  #include <arpa/inet.h>
     5.6  #include <rpm/rpmlib.h>
     5.7 +#include <rpm/rpmdb.h>
     5.8  #include <zlib.h>
     5.9  
    5.10  #include "razor.h"
    5.11 @@ -73,22 +74,47 @@
    5.12  	return NULL;
    5.13  }
    5.14  
    5.15 +static enum razor_version_relation
    5.16 +rpm_to_razor_flags (uint_32 flags)
    5.17 +{
    5.18 +	switch (flags & (RPMSENSE_LESS | RPMSENSE_EQUAL | RPMSENSE_GREATER)) {
    5.19 +	case RPMSENSE_LESS:
    5.20 +		return RAZOR_VERSION_LESS;
    5.21 +	case RPMSENSE_LESS|RPMSENSE_EQUAL:
    5.22 +		return RAZOR_VERSION_LESS_OR_EQUAL;
    5.23 +	case RPMSENSE_EQUAL:
    5.24 +		return RAZOR_VERSION_EQUAL;
    5.25 +	case RPMSENSE_GREATER|RPMSENSE_EQUAL:
    5.26 +		return RAZOR_VERSION_GREATER_OR_EQUAL;
    5.27 +	case RPMSENSE_GREATER:
    5.28 +		return RAZOR_VERSION_GREATER;
    5.29 +	}
    5.30 +
    5.31 +	/* FIXME? */
    5.32 +	return RAZOR_VERSION_EQUAL;
    5.33 +}
    5.34 +
    5.35  static void
    5.36  import_properties(struct razor_importer *importer, unsigned long type,
    5.37  		  struct razor_rpm *rpm,
    5.38  		  int name_tag, int version_tag, int flags_tag)
    5.39  {
    5.40  	const char *name, *version;
    5.41 +	uint_32 flags;
    5.42  	unsigned int i, count;
    5.43  
    5.44  	name = razor_rpm_get_indirect(rpm, name_tag, &count);
    5.45  	if (name == NULL)
    5.46  		return;
    5.47  
    5.48 +	flags = *(uint_32 *)razor_rpm_get_indirect(rpm, flags_tag, &count);
    5.49 +
    5.50  	/* FIXME: Concat version and release. */
    5.51  	version = razor_rpm_get_indirect(rpm, version_tag, &count);
    5.52  	for (i = 0; i < count; i++) {
    5.53 -		razor_importer_add_property(importer, name, version, type);
    5.54 +		razor_importer_add_property(importer, name,
    5.55 +					    rpm_to_razor_flags (flags),
    5.56 +					    version, type);
    5.57  		name += strlen(name) + 1;
    5.58  		version += strlen(version) + 1;
    5.59  	}
    5.60 @@ -534,3 +560,101 @@
    5.61  
    5.62  	return 0;
    5.63  }
    5.64 +
    5.65 +union rpm_entry {
    5.66 +	void *p;
    5.67 +	char *string;
    5.68 +	char **list;
    5.69 +	uint_32 *flags;
    5.70 +};
    5.71 +
    5.72 +static void
    5.73 +add_properties(struct razor_importer *importer,
    5.74 +	       enum razor_property_type property_type,
    5.75 +	       Header h, int_32 name_tag, int_32 version_tag, int_32 flags_tag)
    5.76 +{
    5.77 +	union rpm_entry names, versions, flags;
    5.78 +	int_32 i, type, count;
    5.79 +
    5.80 +	headerGetEntry(h, name_tag, &type, &names.p, &count);
    5.81 +	headerGetEntry(h, version_tag, &type, &versions.p, &count);
    5.82 +	headerGetEntry(h, flags_tag, &type, &flags.p, &count);
    5.83 +
    5.84 +	for (i = 0; i < count; i++)
    5.85 +		razor_importer_add_property(importer,
    5.86 +					    names.list[i],
    5.87 +					    rpm_to_razor_flags (flags.flags[i]),
    5.88 +					    versions.list[i],
    5.89 +					    property_type);
    5.90 +}
    5.91 +
    5.92 +struct razor_set *
    5.93 +razor_set_create_from_rpmdb(void)
    5.94 +{
    5.95 +	struct razor_importer *importer;
    5.96 +	rpmdbMatchIterator iter;
    5.97 +	Header h;
    5.98 +	int_32 type, count, i;
    5.99 +	union rpm_entry name, version, release;
   5.100 +	union rpm_entry basenames, dirnames, dirindexes;
   5.101 +	char filename[PATH_MAX];
   5.102 +	rpmdb db;
   5.103 +
   5.104 +	rpmReadConfigFiles(NULL, NULL);
   5.105 +
   5.106 +	if (rpmdbOpen("", &db, O_RDONLY, 0644) != 0) {
   5.107 +		fprintf(stderr, "cannot open rpm database\n");
   5.108 +		exit(1);
   5.109 +	}
   5.110 +
   5.111 +	importer = razor_importer_new();
   5.112 +
   5.113 +	iter = rpmdbInitIterator(db, 0, NULL, 0);
   5.114 +	while (h = rpmdbNextIterator(iter), h != NULL) {
   5.115 +		headerGetEntry(h, RPMTAG_NAME, &type, &name.p, &count);
   5.116 +		headerGetEntry(h, RPMTAG_VERSION, &type, &version.p, &count);
   5.117 +		headerGetEntry(h, RPMTAG_RELEASE, &type, &release.p, &count);
   5.118 +		snprintf(filename, sizeof filename, "%s-%s",
   5.119 +			 version.string, release.string);
   5.120 +		razor_importer_begin_package(importer, name.string, filename);
   5.121 +
   5.122 +		add_properties(importer, RAZOR_PROPERTY_REQUIRES, h,
   5.123 +			       RPMTAG_REQUIRENAME,
   5.124 +			       RPMTAG_REQUIREVERSION,
   5.125 +			       RPMTAG_REQUIREFLAGS);
   5.126 +
   5.127 +		add_properties(importer, RAZOR_PROPERTY_PROVIDES, h,
   5.128 +			       RPMTAG_PROVIDENAME,
   5.129 +			       RPMTAG_PROVIDEVERSION,
   5.130 +			       RPMTAG_PROVIDEFLAGS);
   5.131 +
   5.132 +		add_properties(importer, RAZOR_PROPERTY_OBSOLETES, h,
   5.133 +			       RPMTAG_OBSOLETENAME,
   5.134 +			       RPMTAG_OBSOLETEVERSION,
   5.135 +			       RPMTAG_OBSOLETEFLAGS);
   5.136 +
   5.137 +		add_properties(importer, RAZOR_PROPERTY_CONFLICTS, h,
   5.138 +			       RPMTAG_CONFLICTNAME,
   5.139 +			       RPMTAG_CONFLICTVERSION,
   5.140 +			       RPMTAG_CONFLICTFLAGS);
   5.141 +
   5.142 +		headerGetEntry(h, RPMTAG_BASENAMES, &type,
   5.143 +			       &basenames.p, &count);
   5.144 +		headerGetEntry(h, RPMTAG_DIRNAMES, &type,
   5.145 +			       &dirnames.p, &count);
   5.146 +		headerGetEntry(h, RPMTAG_DIRINDEXES, &type,
   5.147 +			       &dirindexes.p, &count);
   5.148 +		for (i = 0; i < count; i++) {
   5.149 +			snprintf(filename, sizeof filename, "%s%s",
   5.150 +				 dirnames.list[dirindexes.flags[i]],
   5.151 +				 basenames.list[i]);
   5.152 +			razor_importer_add_file(importer, filename);
   5.153 +		}
   5.154 +
   5.155 +		razor_importer_finish_package(importer);
   5.156 +	}
   5.157 +
   5.158 +	rpmdbClose(db);
   5.159 +
   5.160 +	return razor_importer_finish(importer);
   5.161 +}
     6.1 --- a/test-driver.c	Mon Feb 04 10:46:29 2008 -0500
     6.2 +++ b/test-driver.c	Mon Feb 04 14:25:45 2008 -0500
     6.3 @@ -95,7 +95,8 @@
     6.4  		exit(-1);
     6.5  	}
     6.6  	
     6.7 -	razor_importer_add_property(ctx->importer, name, version, type);
     6.8 +	razor_importer_add_property(ctx->importer, name,
     6.9 +				    RAZOR_VERSION_EQUAL, version, type);
    6.10  }
    6.11  
    6.12  static void
    6.13 @@ -190,6 +191,7 @@
    6.14  	struct razor_property *property;
    6.15  	const char *name, *version;
    6.16  	enum razor_property_type type;
    6.17 +	enum razor_version_relation relation;
    6.18  
    6.19  	if (ctx->package_iterator != NULL) {
    6.20  		if (razor_package_iterator_next(ctx->package_iterator,
    6.21 @@ -206,7 +208,8 @@
    6.22  	if (ctx->property_iterator != NULL) {
    6.23  		if (razor_property_iterator_next(ctx->property_iterator,
    6.24  						 &property,
    6.25 -						 &name, &version, &type)) {
    6.26 +						 &name, &relation, &version,
    6.27 +						 &type)) {
    6.28  			fprintf(stderr, "too few properties in set\n");
    6.29  			exit(-1);
    6.30  		}
    6.31 @@ -251,6 +254,7 @@
    6.32  	struct razor_property *property;
    6.33  	const char *name, *version, *ref_name, *ref_version;
    6.34  	enum razor_property_type type;
    6.35 +	enum razor_version_relation relation;
    6.36  	int same_version;
    6.37  
    6.38  	if (ctx->property_iterator == NULL) {
    6.39 @@ -262,7 +266,7 @@
    6.40  
    6.41  	get_atts(atts, "name", &ref_name, "eq", &ref_version, NULL);
    6.42  	if (!razor_property_iterator_next(ctx->property_iterator, &property,
    6.43 -					  &name, &version, &type)) {
    6.44 +					  &name, &relation, &version, &type)) {
    6.45  		fprintf(stderr, "too many properties in set\n");
    6.46  		exit(-1);
    6.47  	}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/yum.c	Mon Feb 04 14:25:45 2008 -0500
     7.3 @@ -0,0 +1,312 @@
     7.4 +#define _GNU_SOURCE
     7.5 +
     7.6 +#include <string.h>
     7.7 +#include <stdio.h>
     7.8 +#include <sys/stat.h>
     7.9 +#include <sys/mman.h>
    7.10 +#include <unistd.h>
    7.11 +#include <fcntl.h>
    7.12 +#include <errno.h>
    7.13 +
    7.14 +#include <expat.h>
    7.15 +#include <zlib.h>
    7.16 +#include "razor.h"
    7.17 +
    7.18 +/* Import a yum filelist as a razor package set. */
    7.19 +
    7.20 +enum {
    7.21 +	YUM_STATE_BEGIN,
    7.22 +	YUM_STATE_PACKAGE_NAME,
    7.23 +	YUM_STATE_CHECKSUM,
    7.24 +	YUM_STATE_REQUIRES,
    7.25 +	YUM_STATE_PROVIDES,
    7.26 +	YUM_STATE_OBSOLETES,
    7.27 +	YUM_STATE_CONFLICTS,
    7.28 +	YUM_STATE_FILE
    7.29 +};
    7.30 +
    7.31 +struct yum_context {
    7.32 +	XML_Parser primary_parser;
    7.33 +	XML_Parser filelists_parser;
    7.34 +	XML_Parser current_parser;
    7.35 +
    7.36 +	struct razor_importer *importer;
    7.37 +	struct import_property_context *current_property_context;
    7.38 +	char name[256], buffer[512], *p;
    7.39 +	char pkgid[128];
    7.40 +	int state;
    7.41 +};
    7.42 +
    7.43 +static enum razor_version_relation
    7.44 +yum_to_razor_flags (const char *flags)
    7.45 +{
    7.46 +	/* FIXME? */
    7.47 +	if (!flags)
    7.48 +		return RAZOR_VERSION_EQUAL;
    7.49 +
    7.50 +	if (flags[0] == 'L') {
    7.51 +		if (flags[1] == 'T')
    7.52 +			return RAZOR_VERSION_LESS;
    7.53 +		else
    7.54 +			return RAZOR_VERSION_LESS_OR_EQUAL;
    7.55 +	} else if (flags[0] == 'G') {
    7.56 +		if (flags[1] == 'T')
    7.57 +			return RAZOR_VERSION_GREATER;
    7.58 +		else
    7.59 +			return RAZOR_VERSION_GREATER_OR_EQUAL;
    7.60 +	} else
    7.61 +		return RAZOR_VERSION_EQUAL;
    7.62 +}
    7.63 +
    7.64 +static void
    7.65 +yum_primary_start_element(void *data, const char *name, const char **atts)
    7.66 +{
    7.67 +	struct yum_context *ctx = data;
    7.68 +	const char *n, *version, *release, *flags;
    7.69 +	char buffer[128];
    7.70 +	int i;
    7.71 +
    7.72 +	if (strcmp(name, "name") == 0) {
    7.73 +		ctx->state = YUM_STATE_PACKAGE_NAME;
    7.74 +		ctx->p = ctx->name;
    7.75 +	} else if (strcmp(name, "version") == 0) {
    7.76 +		version = NULL;
    7.77 +		release = NULL;
    7.78 +		for (i = 0; atts[i]; i += 2) {
    7.79 +			if (strcmp(atts[i], "ver") == 0)
    7.80 +				version = atts[i + 1];
    7.81 +			else if (strcmp(atts[i], "rel") == 0)
    7.82 +				release = atts[i + 1];
    7.83 +		}
    7.84 +		if (version == NULL || release == NULL) {
    7.85 +			fprintf(stderr, "invalid version tag, "
    7.86 +				"missing version or  release attribute\n");
    7.87 +			return;
    7.88 +		}
    7.89 +
    7.90 +		snprintf(buffer, sizeof buffer, "%s-%s", version, release);
    7.91 +		razor_importer_begin_package(ctx->importer, ctx->name, buffer);
    7.92 +	} else if (strcmp(name, "checksum") == 0) {
    7.93 +		ctx->p = ctx->pkgid;
    7.94 +		ctx->state = YUM_STATE_CHECKSUM;
    7.95 +	} else if (strcmp(name, "rpm:requires") == 0) {
    7.96 +		ctx->state = YUM_STATE_REQUIRES;
    7.97 +	} else if (strcmp(name, "rpm:provides") == 0) {
    7.98 +		ctx->state = YUM_STATE_PROVIDES;
    7.99 +	} else if (strcmp(name, "rpm:obsoletes") == 0) {
   7.100 +		ctx->state = YUM_STATE_OBSOLETES;
   7.101 +	} else if (strcmp(name, "rpm:conflicts") == 0) {
   7.102 +		ctx->state = YUM_STATE_CONFLICTS;
   7.103 +	} else if (strcmp(name, "rpm:entry") == 0 &&
   7.104 +		   ctx->state != YUM_STATE_BEGIN) {
   7.105 +		n = NULL;
   7.106 +		version = NULL;
   7.107 +		release = NULL;
   7.108 +		flags = NULL;
   7.109 +		for (i = 0; atts[i]; i += 2) {
   7.110 +			if (strcmp(atts[i], "name") == 0)
   7.111 +				n = atts[i + 1];
   7.112 +			else if (strcmp(atts[i], "ver") == 0)
   7.113 +				version = atts[i + 1];
   7.114 +			else if (strcmp(atts[i], "rel") == 0)
   7.115 +				release = atts[i + 1];
   7.116 +			else if (strcmp(atts[i], "flags") == 0)
   7.117 +				flags = atts[i + 1];
   7.118 +		}
   7.119 +
   7.120 +		if (n == NULL) {
   7.121 +			fprintf(stderr, "invalid rpm:entry, "
   7.122 +				"missing name or version attributes\n");
   7.123 +			return;
   7.124 +		}
   7.125 +
   7.126 +		if (version && release)
   7.127 +			snprintf(buffer, sizeof buffer,
   7.128 +				 "%s-%s", version, release);
   7.129 +		else if (version)
   7.130 +			strcpy(buffer, version);
   7.131 +		else
   7.132 +			buffer[0] = '\0';
   7.133 +			
   7.134 +		switch (ctx->state) {
   7.135 +		case YUM_STATE_REQUIRES:
   7.136 +			razor_importer_add_property(ctx->importer, n,
   7.137 +						    yum_to_razor_flags (flags),
   7.138 +						    buffer,
   7.139 +						    RAZOR_PROPERTY_REQUIRES);
   7.140 +			break;
   7.141 +		case YUM_STATE_PROVIDES:
   7.142 +			razor_importer_add_property(ctx->importer, n,
   7.143 +						    yum_to_razor_flags (flags),
   7.144 +						    buffer,
   7.145 +						    RAZOR_PROPERTY_PROVIDES);
   7.146 +			break;
   7.147 +		case YUM_STATE_OBSOLETES:
   7.148 +			razor_importer_add_property(ctx->importer, n,
   7.149 +						    yum_to_razor_flags (flags),
   7.150 +						    buffer,
   7.151 +						    RAZOR_PROPERTY_OBSOLETES);
   7.152 +			break;
   7.153 +		case YUM_STATE_CONFLICTS:
   7.154 +			razor_importer_add_property(ctx->importer, n,
   7.155 +						    yum_to_razor_flags (flags),
   7.156 +						    buffer,
   7.157 +						    RAZOR_PROPERTY_CONFLICTS);
   7.158 +			break;
   7.159 +		}
   7.160 +	}
   7.161 +}
   7.162 +
   7.163 +static void
   7.164 +yum_primary_end_element (void *data, const char *name)
   7.165 +{
   7.166 +	struct yum_context *ctx = data;
   7.167 +
   7.168 +	switch (ctx->state) {
   7.169 +	case YUM_STATE_PACKAGE_NAME:
   7.170 +	case YUM_STATE_CHECKSUM:
   7.171 +	case YUM_STATE_FILE:
   7.172 +		ctx->state = YUM_STATE_BEGIN;
   7.173 +		break;
   7.174 +	}
   7.175 +
   7.176 +	if (strcmp(name, "package") == 0) {
   7.177 +		XML_StopParser(ctx->current_parser, XML_TRUE);
   7.178 +		ctx->current_parser = ctx->filelists_parser;
   7.179 +	}
   7.180 +}
   7.181 +
   7.182 +static void
   7.183 +yum_character_data (void *data, const XML_Char *s, int len)
   7.184 +{
   7.185 +	struct yum_context *ctx = data;
   7.186 +
   7.187 +	switch (ctx->state) {
   7.188 +	case YUM_STATE_PACKAGE_NAME:
   7.189 +	case YUM_STATE_CHECKSUM:
   7.190 +	case YUM_STATE_FILE:
   7.191 +		memcpy(ctx->p, s, len);
   7.192 +		ctx->p += len;
   7.193 +		*ctx->p = '\0';
   7.194 +		break;
   7.195 +	}
   7.196 +}
   7.197 +
   7.198 +static void
   7.199 +yum_filelists_start_element(void *data, const char *name, const char **atts)
   7.200 +{
   7.201 +	struct yum_context *ctx = data;
   7.202 +	const char *pkg, *pkgid;
   7.203 +	int i;
   7.204 +
   7.205 +	if (strcmp(name, "package") == 0) {
   7.206 +		pkg = NULL;
   7.207 +		pkgid = NULL;
   7.208 +		for (i = 0; atts[i]; i += 2) {
   7.209 +			if (strcmp(atts[i], "name") == 0)
   7.210 +				pkg = atts[i + 1];
   7.211 +			else if (strcmp(atts[i], "pkgid") == 0)
   7.212 +				pkgid = atts[i + 1];
   7.213 +		}
   7.214 +		if (strcmp(pkgid, ctx->pkgid) != 0)
   7.215 +			fprintf(stderr, "primary.xml and filelists.xml "
   7.216 +				"mismatch for %s: %s vs %s",
   7.217 +				pkg, pkgid, ctx->pkgid);
   7.218 +	} else if (strcmp(name, "file") == 0) {
   7.219 +		ctx->state = YUM_STATE_FILE;
   7.220 +		ctx->p = ctx->buffer;
   7.221 +	}
   7.222 +}
   7.223 +
   7.224 +
   7.225 +static void
   7.226 +yum_filelists_end_element (void *data, const char *name)
   7.227 +{
   7.228 +	struct yum_context *ctx = data;
   7.229 +
   7.230 +	ctx->state = YUM_STATE_BEGIN;
   7.231 +	if (strcmp(name, "package") == 0) {
   7.232 +		XML_StopParser(ctx->current_parser, XML_TRUE);
   7.233 +		ctx->current_parser = ctx->primary_parser;
   7.234 +		razor_importer_finish_package(ctx->importer);
   7.235 +	} else if (strcmp(name, "file") == 0)
   7.236 +		razor_importer_add_file(ctx->importer, ctx->buffer);
   7.237 +
   7.238 +}
   7.239 +
   7.240 +#define XML_BUFFER_SIZE 4096
   7.241 +
   7.242 +struct razor_set *
   7.243 +razor_set_create_from_yum(void)
   7.244 +{
   7.245 +	struct yum_context ctx;
   7.246 +	void *buf;
   7.247 +	int len, ret;
   7.248 +	gzFile primary, filelists;
   7.249 +	XML_ParsingStatus status;
   7.250 +
   7.251 +	ctx.importer = razor_importer_new();	
   7.252 +	ctx.state = YUM_STATE_BEGIN;
   7.253 +
   7.254 +	ctx.primary_parser = XML_ParserCreate(NULL);
   7.255 +	XML_SetUserData(ctx.primary_parser, &ctx);
   7.256 +	XML_SetElementHandler(ctx.primary_parser,
   7.257 +			      yum_primary_start_element,
   7.258 +			      yum_primary_end_element);
   7.259 +	XML_SetCharacterDataHandler(ctx.primary_parser,
   7.260 +				    yum_character_data);
   7.261 +
   7.262 +	ctx.filelists_parser = XML_ParserCreate(NULL);
   7.263 +	XML_SetUserData(ctx.filelists_parser, &ctx);
   7.264 +	XML_SetElementHandler(ctx.filelists_parser,
   7.265 +			      yum_filelists_start_element,
   7.266 +			      yum_filelists_end_element);
   7.267 +	XML_SetCharacterDataHandler(ctx.filelists_parser,
   7.268 +				    yum_character_data);
   7.269 +
   7.270 +	primary = gzopen("primary.xml.gz", "rb");
   7.271 +	if (primary == NULL)
   7.272 +		return NULL;
   7.273 +	filelists = gzopen("filelists.xml.gz", "rb");
   7.274 +	if (filelists == NULL)
   7.275 +		return NULL;
   7.276 +
   7.277 +	ctx.current_parser = ctx.primary_parser;
   7.278 +
   7.279 +	do {
   7.280 +		XML_GetParsingStatus(ctx.current_parser, &status);
   7.281 +		switch (status.parsing) {
   7.282 +		case XML_SUSPENDED:
   7.283 +			ret = XML_ResumeParser(ctx.current_parser);
   7.284 +			break;
   7.285 +		case XML_PARSING:
   7.286 +		case XML_INITIALIZED:
   7.287 +			buf = XML_GetBuffer(ctx.current_parser,
   7.288 +					    XML_BUFFER_SIZE);
   7.289 +			if (ctx.current_parser == ctx.primary_parser)
   7.290 +				len = gzread(primary, buf, XML_BUFFER_SIZE);
   7.291 +			else
   7.292 +				len = gzread(filelists, buf, XML_BUFFER_SIZE);
   7.293 +			if (len < 0) {
   7.294 +				fprintf(stderr,
   7.295 +					"couldn't read input: %s\n",
   7.296 +					strerror(errno));
   7.297 +				return NULL;
   7.298 +			}
   7.299 +
   7.300 +			XML_ParseBuffer(ctx.current_parser, len, len == 0);
   7.301 +			break;
   7.302 +		case XML_FINISHED:
   7.303 +			break;
   7.304 +		}
   7.305 +	} while (status.parsing != XML_FINISHED);
   7.306 +
   7.307 +
   7.308 +	XML_ParserFree(ctx.primary_parser);
   7.309 +	XML_ParserFree(ctx.filelists_parser);
   7.310 +
   7.311 +	gzclose(primary);
   7.312 +	gzclose(filelists);
   7.313 +
   7.314 +	return razor_importer_finish(ctx.importer);
   7.315 +}