librazor/razor.c
author Kristian H?gsberg <krh@redhat.com>
Thu Jun 19 15:09:48 2008 -0400 (2008-06-19)
changeset 246 f92d8239324e
parent 241 c3eb520e2219
child 247 63444a10fb8e
permissions -rw-r--r--
Handle NULL dirnames when importing rpms into a set.
     1 /*
     2  * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
     3  * Copyright (C) 2008  Red Hat, Inc
     4  *
     5  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation; either version 2 of the License, or
     8  * (at your option) any later version.
     9  *
    10  * This program is distributed in the hope that it will be useful,
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  * GNU General Public License for more details.
    14  *
    15  * You should have received a copy of the GNU General Public License along
    16  * with this program; if not, write to the Free Software Foundation, Inc.,
    17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    18  */
    19 
    20 #define _GNU_SOURCE
    21 
    22 #include <stdlib.h>
    23 #include <stddef.h>
    24 #include <stdint.h>
    25 #include <stdio.h>
    26 #include <string.h>
    27 #include <sys/types.h>
    28 #include <sys/stat.h>
    29 #include <sys/mman.h>
    30 #include <unistd.h>
    31 #include <fcntl.h>
    32 #include <errno.h>
    33 #include <ctype.h>
    34 #include <fnmatch.h>
    35 
    36 #include "razor.h"
    37 #include "razor-internal.h"
    38 #include "types.h"
    39 
    40 struct razor_set_section {
    41 	uint32_t type;
    42 	uint32_t offset;
    43 	uint32_t size;
    44 };
    45 
    46 struct razor_set_header {
    47 	uint32_t magic;
    48 	uint32_t version;
    49 	struct razor_set_section sections[0];
    50 };
    51 
    52 #define RAZOR_MAGIC 0x7a7a7a7a
    53 #define RAZOR_VERSION 1
    54 
    55 #define RAZOR_STRING_POOL	0
    56 #define RAZOR_PACKAGES		1
    57 #define RAZOR_PROPERTIES	2
    58 #define RAZOR_FILES		3
    59 #define RAZOR_PACKAGE_POOL	4
    60 #define RAZOR_PROPERTY_POOL	5
    61 #define RAZOR_FILE_POOL		6
    62 
    63 struct razor_package {
    64 	uint name  : 24;
    65 	uint flags : 8;
    66 	uint32_t version;
    67 	uint32_t arch;
    68 	struct list_head properties;
    69 	struct list_head files;
    70 };
    71 
    72 struct razor_property {
    73 	uint name  : 24;
    74 	uint flags : 6;
    75 	enum razor_property_type type : 2;
    76 	enum razor_version_relation relation : 32;
    77 	uint32_t version;
    78 	struct list_head packages;
    79 };
    80 
    81 struct razor_entry {
    82 	uint name  : 24;
    83 	uint flags : 8;
    84 	uint32_t start;
    85 	struct list_head packages;
    86 };
    87 
    88 #define RAZOR_ENTRY_LAST	0x80
    89 
    90 struct razor_set {
    91 	struct array string_pool;
    92  	struct array packages;
    93  	struct array properties;
    94  	struct array files;
    95 	struct array package_pool;
    96  	struct array property_pool;
    97  	struct array file_pool;
    98 	struct razor_set_header *header;
    99 };
   100 
   101 struct import_entry {
   102 	uint32_t package;
   103 	char *name;
   104 };
   105 
   106 struct import_directory {
   107 	uint32_t name, count;
   108 	struct array files;
   109 	struct array packages;
   110 	struct import_directory *last;
   111 };
   112 
   113 struct razor_importer {
   114 	struct razor_set *set;
   115 	struct hashtable table;
   116 	struct razor_package *package;
   117 	struct array properties;
   118 	struct array files;
   119 	struct array file_requires;
   120 };
   121 
   122 static void *
   123 zalloc(size_t size)
   124 {
   125 	void *p;
   126 
   127 	p = malloc(size);
   128 	memset(p, 0, size);
   129 
   130 	return p;
   131 }
   132 
   133 struct razor_set_section razor_sections[] = {
   134 	{ RAZOR_STRING_POOL,	offsetof(struct razor_set, string_pool) },
   135 	{ RAZOR_PACKAGES,	offsetof(struct razor_set, packages) },
   136 	{ RAZOR_PROPERTIES,	offsetof(struct razor_set, properties) },
   137 	{ RAZOR_FILES,		offsetof(struct razor_set, files) },
   138 	{ RAZOR_PACKAGE_POOL,	offsetof(struct razor_set, package_pool) },
   139 	{ RAZOR_PROPERTY_POOL,	offsetof(struct razor_set, property_pool) },
   140 	{ RAZOR_FILE_POOL,	offsetof(struct razor_set, file_pool) },
   141 };
   142 
   143 struct razor_set *
   144 razor_set_create(void)
   145 {
   146 	struct razor_set *set;
   147 	struct razor_entry *e;
   148 	char *empty;
   149 
   150 	set = zalloc(sizeof *set);
   151 
   152 	e = array_add(&set->files, sizeof *e);
   153 	empty = array_add(&set->string_pool, 1);
   154 	*empty = '\0';
   155 	e->name = 0;
   156 	e->flags = RAZOR_ENTRY_LAST;
   157 	e->start = 0;
   158 	list_set_empty(&e->packages);
   159 
   160 	return set;
   161 }
   162 
   163 struct razor_set *
   164 razor_set_open(const char *filename)
   165 {
   166 	struct razor_set *set;
   167 	struct razor_set_section *s;
   168 	struct stat stat;
   169 	struct array *array;
   170 	int fd;
   171 
   172 	set = zalloc(sizeof *set);
   173 	fd = open(filename, O_RDONLY);
   174 	if (fstat(fd, &stat) < 0)
   175 		return NULL;
   176 	set->header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
   177 	if (set->header == MAP_FAILED) {
   178 		free(set);
   179 		return NULL;
   180 	}
   181 
   182 	for (s = set->header->sections; ~s->type; s++) {
   183 		if (s->type >= ARRAY_SIZE(razor_sections))
   184 			continue;
   185 		if (s->type != razor_sections[s->type].type)
   186 			continue;
   187 		array = (void *) set + razor_sections[s->type].offset;
   188 		array->data = (void *) set->header + s->offset;
   189 		array->size = s->size;
   190 		array->alloc = s->size;
   191 	}
   192 	close(fd);
   193 
   194 	return set;
   195 }
   196 
   197 void
   198 razor_set_destroy(struct razor_set *set)
   199 {
   200 	unsigned int size;
   201 	struct array *a;
   202 	int i;
   203 
   204 	if (set->header) {
   205 		for (i = 0; set->header->sections[i].type; i++)
   206 			;
   207 		size = set->header->sections[i].type;
   208 		munmap(set->header, size);
   209 	} else {
   210 		for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
   211 			a = (void *) set + razor_sections[i].offset;
   212 			free(a->data);
   213 		}
   214 	}
   215 
   216 	free(set);
   217 }
   218 
   219 int
   220 razor_set_write_to_fd(struct razor_set *set, int fd)
   221 {
   222 	char data[4096];
   223 	struct razor_set_header *header = (struct razor_set_header *) data;
   224 	struct array *a;
   225 	uint32_t offset;
   226 	int i;
   227 
   228 	memset(data, 0, sizeof data);
   229 	header->magic = RAZOR_MAGIC;
   230 	header->version = RAZOR_VERSION;
   231 	offset = sizeof data;
   232 
   233 	for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
   234 		if (razor_sections[i].type != i)
   235 			continue;
   236 		a = (void *) set + razor_sections[i].offset;
   237 		header->sections[i].type = i;
   238 		header->sections[i].offset = offset;
   239 		header->sections[i].size = a->size;
   240 		offset += ALIGN(a->size, 4096);
   241 	}
   242 
   243 	header->sections[i].type = ~0;
   244 	header->sections[i].offset = 0;
   245 	header->sections[i].size = 0;
   246 
   247 	razor_write(fd, data, sizeof data);
   248 	memset(data, 0, sizeof data);
   249 	for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
   250 		if (razor_sections[i].type != i)
   251 			continue;
   252 		a = (void *) set + razor_sections[i].offset;
   253 		razor_write(fd, a->data, a->size);
   254 		razor_write(fd, data, ALIGN(a->size, 4096) - a->size);
   255 	}
   256 
   257 	return 0;
   258 }
   259 
   260 int
   261 razor_set_write(struct razor_set *set, const char *filename)
   262 {
   263 	int fd, status;
   264 
   265 	fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
   266 	if (fd < 0)
   267 		return -1;
   268 
   269 	status = razor_set_write_to_fd(set, fd);
   270 	if (status) {
   271 	    close(fd);
   272 	    return status;
   273 	}
   274 
   275 	return close(fd);
   276 }
   277 
   278 void
   279 razor_build_evr(char *evr_buf, int size, const char *epoch,
   280 		const char *version, const char *release)
   281 {
   282 	int len;
   283 
   284 	if (!version || !*version) {
   285 		*evr_buf = '\0';
   286 		return;
   287 	}
   288 
   289 	if (epoch && *epoch && strcmp(epoch, "0") != 0) {
   290 		len = snprintf(evr_buf, size, "%s:", epoch);
   291 		evr_buf += len;
   292 		size -= len;
   293 	}
   294 	len = snprintf(evr_buf, size, "%s", version);
   295 	evr_buf += len;
   296 	size -= len;
   297 	if (release && *release)
   298 		snprintf(evr_buf, size, "-%s", release);
   299 }
   300 
   301 void
   302 razor_importer_begin_package(struct razor_importer *importer,
   303 			     const char *name,
   304 			     const char *version,
   305 			     const char *arch)
   306 {
   307 	struct razor_package *p;
   308 
   309 	p = array_add(&importer->set->packages, sizeof *p);
   310 	p->name = hashtable_tokenize(&importer->table, name);
   311 	p->flags = 0;
   312 	p->version = hashtable_tokenize(&importer->table, version);
   313 	p->arch = hashtable_tokenize(&importer->table, arch);
   314 
   315 	importer->package = p;
   316 	array_init(&importer->properties);
   317 }
   318 
   319 void
   320 razor_importer_finish_package(struct razor_importer *importer)
   321 {
   322 	list_set_array(&importer->package->properties,
   323 		       &importer->set->property_pool,
   324 		       &importer->properties,
   325 		       1);
   326 
   327 	array_release(&importer->properties);
   328 }
   329 
   330 void
   331 razor_importer_add_property(struct razor_importer *importer,
   332 			    const char *name,
   333 			    enum razor_version_relation relation,
   334 			    const char *version,
   335 			    enum razor_property_type type)
   336 {
   337 	struct razor_property *p;
   338 	uint32_t *r;
   339 
   340 	p = array_add(&importer->set->properties, sizeof *p);
   341 	p->name = hashtable_tokenize(&importer->table, name);
   342 	p->flags = 0;
   343 	p->type = type;
   344 	p->relation = relation;
   345 	p->version = hashtable_tokenize(&importer->table, version);
   346 	list_set_ptr(&p->packages, importer->package -
   347 		     (struct razor_package *) importer->set->packages.data);
   348 
   349 	r = array_add(&importer->properties, sizeof *r);
   350 	*r = p - (struct razor_property *) importer->set->properties.data;
   351 
   352 	if (type == RAZOR_PROPERTY_REQUIRES && *name == '/') {
   353 		r = array_add(&importer->file_requires, sizeof *r);
   354 		*r = p->name;
   355 	}
   356 }
   357 
   358 void
   359 razor_importer_add_file(struct razor_importer *importer, const char *name)
   360 {
   361 	struct import_entry *e;
   362 
   363 	e = array_add(&importer->files, sizeof *e);
   364 
   365 	e->package = importer->package -
   366 		(struct razor_package *) importer->set->packages.data;
   367 	e->name = strdup(name);
   368 }
   369 
   370 struct razor_importer *
   371 razor_importer_new(void)
   372 {
   373 	struct razor_importer *importer;
   374 
   375 	importer = zalloc(sizeof *importer);
   376 	importer->set = razor_set_create();
   377 	hashtable_init(&importer->table, &importer->set->string_pool);
   378 
   379 	return importer;
   380 }
   381 
   382 /* Destroy an importer without creating the set. */
   383 void
   384 razor_importer_destroy(struct razor_importer *importer)
   385 {
   386 	/* FIXME: write this */
   387 }
   388 
   389 static int
   390 versioncmp(const char *s1, const char *s2)
   391 {
   392 	const char *p1, *p2;
   393 	long n1, n2;
   394 	int res;
   395 
   396 	n1 = strtol(s1, (char **) &p1, 10);
   397 	n2 = strtol(s2, (char **) &p2, 10);
   398 
   399 	/* Epoch; if one but not the other has an epoch set, default
   400 	 * the epoch-less version to 0. */
   401 	res = (*p1 == ':') - (*p2 == ':');
   402 	if (res < 0) {
   403 		n1 = 0;
   404 		p1 = s1;
   405 		p2++;
   406 	} else if (res > 0) {
   407 		p1++;
   408 		n2 = 0;
   409 		p2 = s2;
   410 	}
   411 
   412 	if (n1 != n2)
   413 		return n1 - n2;
   414 	while (*p1 && *p2) {
   415 		if (*p1 != *p2)
   416 			return *p1 - *p2;
   417 		p1++;
   418 		p2++;
   419 		if (isdigit(*p1) && isdigit(*p2))
   420 			return versioncmp(p1, p2);
   421 	}
   422 
   423 	return *p1 - *p2;
   424 }
   425 
   426 static int
   427 compare_packages(const void *p1, const void *p2, void *data)
   428 {
   429 	const struct razor_package *pkg1 = p1, *pkg2 = p2;
   430 	struct razor_set *set = data;
   431 	char *pool = set->string_pool.data;
   432 
   433 	/* FIXME: what if the flags are different? */
   434 	if (pkg1->name == pkg2->name)
   435 		return versioncmp(&pool[pkg1->version], &pool[pkg2->version]);
   436 	else
   437 		return strcmp(&pool[pkg1->name], &pool[pkg2->name]);
   438 }
   439 
   440 static int
   441 compare_properties(const void *p1, const void *p2, void *data)
   442 {
   443 	const struct razor_property *prop1 = p1, *prop2 = p2;
   444 	struct razor_set *set = data;
   445 	char *pool = set->string_pool.data;
   446 
   447 	if (prop1->name != prop2->name)
   448 		return strcmp(&pool[prop1->name], &pool[prop2->name]);
   449 	else if (prop1->type != prop2->type)
   450 		return prop1->type - prop2->type;
   451 	else if (prop1->relation != prop2->relation)
   452 		return prop1->relation - prop2->relation;
   453 	else
   454 		return versioncmp(&pool[prop1->version], &pool[prop2->version]);
   455 }
   456 
   457 static uint32_t *
   458 uniqueify_properties(struct razor_set *set)
   459 {
   460 	struct razor_property *rp, *up, *rp_end;
   461 	struct array *pkgs, *p;
   462 	struct list_head *r;
   463 	uint32_t *map, *rmap;
   464 	int i, count, unique;
   465 
   466 	count = set->properties.size / sizeof(struct razor_property);
   467 	map = razor_qsort_with_data(set->properties.data,
   468 				    count,
   469 				    sizeof(struct razor_property),
   470 				    compare_properties,
   471 				    set);
   472 
   473 	rp_end = set->properties.data + set->properties.size;
   474 	rmap = malloc(count * sizeof *map);
   475 	pkgs = zalloc(count * sizeof *pkgs);
   476 	for (rp = set->properties.data, up = rp, i = 0; rp < rp_end; rp++, i++) {
   477 		if (rp->name != up->name || rp->type != up->type ||
   478 		    rp->relation != up->relation || rp->version != up->version) {
   479 			up++;
   480 			up->name = rp->name;
   481 			up->flags = 0;
   482 			up->type = rp->type;
   483 			up->relation = rp->relation;
   484 			up->version = rp->version;
   485 		}
   486 
   487 		unique = up - (struct razor_property *) set->properties.data;
   488 		rmap[map[i]] = unique;
   489 		r = array_add(&pkgs[unique], sizeof *r);
   490 		*r = rp->packages;
   491 	}
   492 	free(map);
   493 
   494 	if (up != rp)
   495 		up++;
   496 	set->properties.size = (void *) up - set->properties.data;
   497 	rp_end = up;
   498 	for (rp = set->properties.data, p = pkgs; rp < rp_end; rp++, p++) {
   499 		list_set_array(&rp->packages, &set->package_pool, p, 0);
   500 		array_release(p);
   501 	}
   502 
   503 	free(pkgs);
   504 
   505 	return rmap;
   506 }
   507 
   508 static int
   509 compare_filenames(const void *p1, const void *p2, void *data)
   510 {
   511 	const struct import_entry *e1 = p1;
   512 	const struct import_entry *e2 = p2;
   513 	const char *n1 = e1->name;
   514 	const char *n2 = e2->name;
   515 
   516 	/* Need to make sure that the contents of a directory
   517 	 * are sorted immediately after it. So "foo/bar" has to
   518 	 * sort before "foo.conf"
   519 	 *
   520 	 * FIXME: this is about 60% slower than strcmp
   521 	 */
   522 	while (*n1 && *n2) {
   523 		if (*n1 < *n2)
   524 			return *n2 == '/' ? 1 : -1;
   525 		else if (*n1 > *n2)
   526 			return *n1 == '/' ? -1 : 1;
   527 		n1++;
   528 		n2++;
   529 	}
   530 	if (*n1)
   531 		return 1;
   532 	else if (*n2)
   533 		return -1;
   534 	else
   535 		return 0;
   536 }
   537 
   538 static void
   539 count_entries(struct import_directory *d)
   540 {
   541 	struct import_directory *p, *end;
   542 
   543 	p = d->files.data;
   544 	end = d->files.data + d->files.size;
   545 	d->count = 0;
   546 	while (p < end) {
   547 		count_entries(p);
   548 		d->count += p->count + 1;
   549 		p++;
   550 	}
   551 }
   552 
   553 static void
   554 serialize_files(struct razor_set *set,
   555 		struct import_directory *d, struct array *array)
   556 {
   557 	struct import_directory *p, *end;
   558 	struct razor_entry *e = NULL;
   559 	uint32_t s;
   560 
   561 	p = d->files.data;
   562 	end = d->files.data + d->files.size;
   563 	s = array->size / sizeof *e + d->files.size / sizeof *p;
   564 	while (p < end) {
   565 		e = array_add(array, sizeof *e);
   566 		e->name = p->name;
   567 		e->flags = 0;
   568 		e->start = p->count > 0 ? s : 0;
   569 		s += p->count;
   570 
   571 		list_set_array(&e->packages, &set->package_pool, &p->packages, 0);
   572 		array_release(&p->packages);
   573 		p++;
   574 	}
   575 	if (e != NULL)
   576 		e->flags |= RAZOR_ENTRY_LAST;
   577 
   578 	p = d->files.data;
   579 	end = d->files.data + d->files.size;
   580 	while (p < end) {
   581 		serialize_files(set, p, array);
   582 		p++;
   583 	}
   584 }
   585 
   586 static void
   587 remap_property_package_links(struct array *properties, uint32_t *rmap)
   588 {
   589 	struct razor_property *p, *end;
   590 
   591 	end = properties->data + properties->size;
   592 	for (p = properties->data; p < end; p++)
   593 		list_remap_head(&p->packages, rmap);
   594 }
   595 
   596 static void
   597 build_file_tree(struct razor_importer *importer)
   598 {
   599 	int count, i, length;
   600 	struct import_entry *filenames;
   601 	char *f, *end;
   602 	uint32_t name, *r;
   603 	char dirname[256];
   604 	struct import_directory *d, root;
   605 	struct razor_entry *e;
   606 
   607 	count = importer->files.size / sizeof (struct import_entry);
   608 	razor_qsort_with_data(importer->files.data,
   609 			      count,
   610 			      sizeof (struct import_entry),
   611 			      compare_filenames,
   612 			      NULL);
   613 
   614 	root.name = hashtable_tokenize(&importer->table, "");
   615 	array_init(&root.files);
   616 	array_init(&root.packages);
   617 	root.last = NULL;
   618 
   619 	filenames = importer->files.data;
   620 	for (i = 0; i < count; i++) {
   621 		f = filenames[i].name;
   622 		if (*f != '/')
   623 			continue;
   624 		f++;
   625 
   626 		d = &root;
   627 		while (*f) {
   628 			end = strchr(f, '/');
   629 			if (end == NULL)
   630 				end = f + strlen(f);
   631 			length = end - f;
   632 			memcpy(dirname, f, length);
   633 			dirname[length] ='\0';
   634 			name = hashtable_tokenize(&importer->table, dirname);
   635 			if (d->last == NULL || d->last->name != name) {
   636 				d->last = array_add(&d->files, sizeof *d);
   637 				d->last->name = name;
   638 				d->last->last = NULL;
   639 				array_init(&d->last->files);
   640 				array_init(&d->last->packages);
   641 			}
   642 			d = d->last;
   643 			f = end + 1;
   644 			if (*end == '\0')
   645 				break;
   646 		}
   647 
   648 		r = array_add(&d->packages, sizeof *r);
   649 		*r = filenames[i].package;
   650 		free(filenames[i].name);
   651 	}
   652 
   653 	count_entries(&root);
   654 	e = importer->set->files.data;
   655 	e->name = root.name;
   656 	e->flags = RAZOR_ENTRY_LAST;
   657 	e->start = importer->files.size ? 1 : 0;
   658 	list_set_empty(&e->packages);
   659 
   660 	serialize_files(importer->set, &root, &importer->set->files);
   661 
   662 	array_release(&importer->files);
   663 }
   664 
   665 static struct razor_entry *
   666 find_entry(struct razor_set *set, struct razor_entry *dir, const char *pattern);
   667 
   668 static void
   669 list_to_array(struct list *list, struct array *array)
   670 {
   671 	uint32_t *item;
   672 
   673 	while (list) {
   674 		 item = array_add(array, sizeof *item);
   675 		 *item = list->data;
   676 		 list = list_next(list);
   677 	}
   678 }
   679 
   680 static int
   681 compare_file_requires(const void *p1, const void *p2, void *data)
   682 {
   683 	uint32_t *f1 = (void *)p1, *f2 = (void *)p2;
   684 	const char *pool = data;
   685 
   686 	return strcmp(&pool[*f1], &pool[*f2]);
   687 }
   688 
   689 static void
   690 find_file_provides(struct razor_importer *importer)
   691 {
   692 	struct razor_property *prop;
   693 	struct razor_entry *top, *entry;
   694 	struct razor_package *packages;
   695 	struct array pkgprops;
   696 	struct list *pkg;
   697 	uint32_t *req, *req_start, *req_end;
   698 	uint32_t *map, *newprop;
   699 	char *pool;
   700 
   701 	pool = importer->set->string_pool.data;
   702 	packages = importer->set->packages.data;
   703 	top = importer->set->files.data;
   704 
   705 	req = req_start = importer->file_requires.data;
   706 	req_end = importer->file_requires.data + importer->file_requires.size;
   707 	map = razor_qsort_with_data(req, req_end - req, sizeof *req,
   708 				    compare_file_requires, pool);
   709 	free(map);
   710 
   711 	for (req = req_start; req < req_end; req++) {
   712 		if (req > req_start && req[0] == req[-1])
   713 			continue;
   714 		entry = find_entry(importer->set, top, &pool[*req]);
   715 		if (!entry)
   716 			continue;
   717 
   718 		for (pkg = list_first(&entry->packages, &importer->set->package_pool); pkg; pkg = list_next(pkg)) {
   719 			prop = array_add(&importer->set->properties, sizeof *prop);
   720 			prop->name = *req;
   721 			prop->type = RAZOR_PROPERTY_PROVIDES;
   722 			prop->relation = RAZOR_VERSION_EQUAL;
   723 			prop->version = hashtable_tokenize(&importer->table, "");
   724 			list_set_ptr(&prop->packages, pkg->data);
   725 
   726 			/* Update property list of pkg */
   727 			array_init(&pkgprops);
   728 			list_to_array(list_first(&packages[pkg->data].properties, &importer->set->property_pool), &pkgprops);
   729 			newprop = array_add(&pkgprops, sizeof *newprop);
   730 			*newprop = prop - (struct razor_property *)importer->set->properties.data;
   731 			list_set_array(&packages[pkg->data].properties, &importer->set->property_pool, &pkgprops, 1);
   732 			array_release(&pkgprops);
   733 		}
   734 	}
   735 
   736 	array_release(&importer->file_requires);
   737 }
   738 
   739 static void
   740 build_package_file_lists(struct razor_set *set, uint32_t *rmap)
   741 {
   742 	struct razor_package *p, *packages;
   743 	struct array *pkgs;
   744 	struct razor_entry *e, *end;
   745 	struct list *r;
   746 	uint32_t *q;
   747 	int i, count;
   748 
   749 	count = set->packages.size / sizeof *p;
   750 	pkgs = zalloc(count * sizeof *pkgs);
   751 
   752 	end = set->files.data + set->files.size;
   753 	for (e = set->files.data; e < end; e++) {
   754 		list_remap_head(&e->packages, rmap);
   755 		r = list_first(&e->packages, &set->package_pool);
   756 		while (r) {
   757 			q = array_add(&pkgs[r->data], sizeof *q);
   758 			*q = e - (struct razor_entry *) set->files.data;
   759 			r = list_next(r);
   760 		}
   761 	}
   762 
   763 	packages = set->packages.data;
   764 	for (i = 0; i < count; i++) {
   765 		list_set_array(&packages[i].files, &set->file_pool, &pkgs[i], 0);
   766 		array_release(&pkgs[i]);
   767 	}
   768 	free(pkgs);
   769 }
   770 
   771 struct razor_set *
   772 razor_importer_finish(struct razor_importer *importer)
   773 {
   774 	struct razor_set *set;
   775 	uint32_t *map, *rmap;
   776 	int i, count;
   777 
   778 	build_file_tree(importer);
   779 	find_file_provides(importer);
   780 
   781 	map = uniqueify_properties(importer->set);
   782 	list_remap_pool(&importer->set->property_pool, map);
   783 	free(map);
   784 
   785 	count = importer->set->packages.size / sizeof(struct razor_package);
   786 	map = razor_qsort_with_data(importer->set->packages.data,
   787 				    count,
   788 				    sizeof(struct razor_package),
   789 				    compare_packages,
   790 				    importer->set);
   791 
   792 	rmap = malloc(count * sizeof *rmap);
   793 	for (i = 0; i < count; i++)
   794 		rmap[map[i]] = i;
   795 	free(map);
   796 
   797 	list_remap_pool(&importer->set->package_pool, rmap);
   798 	build_package_file_lists(importer->set, rmap);
   799 	remap_property_package_links(&importer->set->properties, rmap);
   800 	free(rmap);
   801 
   802 	set = importer->set;
   803 	hashtable_release(&importer->table);
   804 	free(importer);
   805 
   806 	return set;
   807 }
   808 
   809 struct razor_package_iterator {
   810 	struct razor_set *set;
   811 	struct razor_package *package, *end;
   812 	struct list *index;
   813 	int free_index;
   814 };
   815 
   816 static struct razor_package_iterator *
   817 razor_package_iterator_create_with_index(struct razor_set *set,
   818 					 struct list *index)
   819 {
   820 	struct razor_package_iterator *pi;
   821 
   822 	pi = zalloc(sizeof *pi);
   823 	pi->set = set;
   824 	pi->index = index;
   825 
   826 	return pi;
   827 }
   828 
   829 struct razor_package_iterator *
   830 razor_package_iterator_create(struct razor_set *set)
   831 {
   832 	struct razor_package_iterator *pi;
   833 
   834 	pi = zalloc(sizeof *pi);
   835 	pi->set = set;
   836 	pi->end = set->packages.data + set->packages.size;
   837 	pi->package = set->packages.data;
   838 
   839 	return pi;
   840 }
   841 
   842 static void
   843 razor_package_iterator_init_for_property(struct razor_package_iterator *pi,
   844 					 struct razor_set *set,
   845 					 struct razor_property *property)
   846 {
   847 	memset(pi, 0, sizeof *pi);
   848 	pi->set = set;
   849 	pi->index = list_first(&property->packages, &set->package_pool);
   850 }
   851 
   852 struct razor_package_iterator *
   853 razor_package_iterator_create_for_property(struct razor_set *set,
   854 					   struct razor_property *property)
   855 {
   856 	struct list *index;
   857 
   858 	index = list_first(&property->packages, &set->package_pool);
   859 	return razor_package_iterator_create_with_index(set, index);
   860 }
   861 
   862 int
   863 razor_package_iterator_next(struct razor_package_iterator *pi,
   864 			    struct razor_package **package,
   865 			    const char **name,
   866 			    const char **version,
   867 			    const char **arch)
   868 {
   869 	char *pool;
   870 	int valid;
   871 	struct razor_package *p, *packages;
   872 
   873 	if (pi->package) {
   874 		p = pi->package++;
   875 		valid = p < pi->end;
   876 	} else if (pi->index) {
   877 		packages = pi->set->packages.data;
   878 		p = &packages[pi->index->data];
   879 		pi->index = list_next(pi->index);
   880 		valid = 1;
   881 	} else
   882 		valid = 0;
   883 
   884 	if (valid) {
   885 		pool = pi->set->string_pool.data;
   886 		*package = p;
   887 		*name = &pool[p->name];
   888 		*version = &pool[p->version];
   889 		*arch = &pool[p->arch];
   890 	} else {
   891 		*package = NULL;
   892 	}
   893 
   894 	return valid;
   895 }
   896 
   897 void
   898 razor_package_iterator_destroy(struct razor_package_iterator *pi)
   899 {
   900 	if (pi->free_index)
   901 		free(pi->index);
   902 
   903 	free(pi);
   904 }
   905 
   906 struct razor_package *
   907 razor_set_get_package(struct razor_set *set, const char *package)
   908 {
   909 	struct razor_package_iterator *pi;
   910 	struct razor_package *p;
   911 	const char *name, *version, *arch;
   912 
   913 	pi = razor_package_iterator_create(set);
   914 	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
   915 		if (strcmp(package, name) == 0)
   916 			break;
   917 	}
   918 	razor_package_iterator_destroy(pi);
   919 
   920 	return p;
   921 }
   922 
   923 struct razor_property_iterator {
   924 	struct razor_set *set;
   925 	struct razor_property *property, *end;
   926 	struct list *index;
   927 };
   928 
   929 struct razor_property_iterator *
   930 razor_property_iterator_create(struct razor_set *set,
   931 			       struct razor_package *package)
   932 {
   933 	struct razor_property_iterator *pi;
   934 
   935 	pi = zalloc(sizeof *pi);
   936 	pi->set = set;
   937 
   938 	if (package) {
   939 		pi->index = list_first(&package->properties,
   940 				       &set->property_pool);
   941 	} else {
   942 		pi->property = set->properties.data;
   943 		pi->end = set->properties.data + set->properties.size;
   944 	}
   945 
   946 	return pi;
   947 }
   948 
   949 int
   950 razor_property_iterator_next(struct razor_property_iterator *pi,
   951 			     struct razor_property **property,
   952 			     const char **name,
   953 			     enum razor_version_relation *relation,
   954 			     const char **version,
   955 			     enum razor_property_type *type)
   956 {
   957 	char *pool;
   958 	int valid;
   959 	struct razor_property *p, *properties;
   960 
   961 	if (pi->property) {
   962 		p = pi->property++;
   963 		valid = p < pi->end;
   964 	} else if (pi->index) {
   965 		properties = pi->set->properties.data;
   966 		p = &properties[pi->index->data];
   967 		pi->index = list_next(pi->index);
   968 		valid = 1;
   969 	} else
   970 		valid = 0;
   971 
   972 	if (valid) {
   973 		pool = pi->set->string_pool.data;
   974 		*property = p;
   975 		*name = &pool[p->name];
   976 		*relation = p->relation;
   977 		*version = &pool[p->version];
   978 		*type = p->type;
   979 	} else {
   980 		*property = NULL;
   981 	}
   982 
   983 	return valid;
   984 }
   985 
   986 void
   987 razor_property_iterator_destroy(struct razor_property_iterator *pi)
   988 {
   989 	free(pi);
   990 }
   991 
   992 static struct razor_entry *
   993 find_entry(struct razor_set *set, struct razor_entry *dir, const char *pattern)
   994 {
   995 	struct razor_entry *e;
   996 	const char *n, *pool = set->string_pool.data;
   997 	int len;
   998 
   999 	e = (struct razor_entry *) set->files.data + dir->start;
  1000 	do {
  1001 		n = pool + e->name;
  1002 		if (strcmp(pattern + 1, n) == 0)
  1003 			return e;
  1004 		len = strlen(n);
  1005 		if (e->start != 0 && strncmp(pattern + 1, n, len) == 0 &&
  1006 		    pattern[len + 1] == '/') {
  1007 			return find_entry(set, e, pattern + len + 1);
  1008 		}
  1009 	} while (!((e++)->flags & RAZOR_ENTRY_LAST));
  1010 
  1011 	return NULL;
  1012 }
  1013 
  1014 static void
  1015 list_dir(struct razor_set *set, struct razor_entry *dir,
  1016 	 char *prefix, const char *pattern)
  1017 {
  1018 	struct razor_entry *e;
  1019 	const char *n, *pool = set->string_pool.data;
  1020 
  1021 	e = (struct razor_entry *) set->files.data + dir->start;
  1022 	do {
  1023 		n = pool + e->name;
  1024 		if (pattern && pattern[0] && fnmatch(pattern, n, 0) != 0)
  1025 			continue;
  1026 		printf("%s/%s\n", prefix, n);
  1027 		if (e->start) {
  1028 			char *sub = prefix + strlen (prefix);
  1029 			*sub = '/';
  1030 			strcpy (sub + 1, n);
  1031 			list_dir(set, e, prefix, pattern);
  1032 			*sub = '\0';
  1033 		}
  1034 	} while (!((e++)->flags & RAZOR_ENTRY_LAST));
  1035 }
  1036 
  1037 void
  1038 razor_set_list_files(struct razor_set *set, const char *pattern)
  1039 {
  1040 	struct razor_entry *e;
  1041 	char buffer[512], *p, *base;
  1042 
  1043 	if (pattern == NULL || !strcmp (pattern, "/")) {
  1044 		buffer[0] = '\0';
  1045 		list_dir(set, set->files.data, buffer, NULL);
  1046 		return;
  1047 	}
  1048 
  1049 	strcpy(buffer, pattern);
  1050 	e = find_entry(set, set->files.data, buffer);
  1051 	if (e && e->start > 0) {
  1052 		base = NULL;
  1053 	} else {
  1054 		p = strrchr(buffer, '/');
  1055 		if (p) {
  1056 			*p = '\0';
  1057 			base = p + 1;
  1058 		} else {
  1059 			base = NULL;
  1060 		}
  1061 	}
  1062 	e = find_entry(set, set->files.data, buffer);
  1063 	if (e->start != 0)
  1064 		list_dir(set, e, buffer, base);
  1065 }
  1066 
  1067 struct razor_package_iterator *
  1068 razor_package_iterator_create_for_file(struct razor_set *set,
  1069 				       const char *filename)
  1070 {
  1071 	struct razor_entry *entry;
  1072 	struct list *index;
  1073 
  1074 	entry = find_entry(set, set->files.data, filename);
  1075 	if (entry == NULL)
  1076 		return NULL;
  1077 
  1078 	index = list_first(&entry->packages, &set->package_pool);
  1079 	return razor_package_iterator_create_with_index(set, index);
  1080 }
  1081 
  1082 static struct list *
  1083 list_package_files(struct razor_set *set, struct list *r,
  1084 		   struct razor_entry *dir, uint32_t end,
  1085 		   char *prefix)
  1086 {
  1087 	struct razor_entry *e, *f, *entries;
  1088 	uint32_t next, file;
  1089 	char *pool;
  1090 	int len;
  1091 
  1092 	entries = (struct razor_entry *) set->files.data;
  1093 	pool = set->string_pool.data;
  1094 
  1095 	e = entries + dir->start;
  1096 	do {
  1097 		if (entries + r->data == e) {
  1098 			printf("%s/%s\n", prefix, pool + e->name);
  1099 			r = list_next(r);
  1100 			if (!r)
  1101 				return NULL;
  1102 			if (r->data >= end)
  1103 				return r;
  1104 		}
  1105 	} while (!((e++)->flags & RAZOR_ENTRY_LAST));
  1106 
  1107 	e = entries + dir->start;
  1108 	do {
  1109 		if (e->start == 0)
  1110 			continue;
  1111 
  1112 		if (e->flags & RAZOR_ENTRY_LAST)
  1113 			next = end;
  1114 		else {
  1115 			f = e + 1;
  1116 			while (f->start == 0 && !(f->flags & RAZOR_ENTRY_LAST))
  1117 				f++;
  1118 			if (f->start == 0)
  1119 				next = end;
  1120 			else
  1121 				next = f->start;
  1122 		}
  1123 
  1124 		file = r->data;
  1125 		if (e->start <= file && file < next) {
  1126 			len = strlen(prefix);
  1127 			prefix[len] = '/';
  1128 			strcpy(prefix + len + 1, pool + e->name);
  1129 			r = list_package_files(set, r, e, next, prefix);
  1130 			prefix[len] = '\0';
  1131 		}
  1132 	} while (!((e++)->flags & RAZOR_ENTRY_LAST) && r != NULL);
  1133 
  1134 	return r;
  1135 }
  1136 
  1137 void
  1138 razor_set_list_package_files(struct razor_set *set, const char *name)
  1139 {
  1140 	struct razor_package *package;
  1141 	struct list *r;
  1142 	uint32_t end;
  1143 	char buffer[512];
  1144 
  1145 	package = razor_set_get_package(set, name);
  1146 
  1147 	r = list_first(&package->files, &set->file_pool);
  1148 	end = set->files.size / sizeof (struct razor_entry);
  1149 	buffer[0] = '\0';
  1150 	list_package_files(set, r, set->files.data, end, buffer);
  1151 }
  1152 
  1153 #define UPSTREAM_SOURCE 0x80
  1154 
  1155 struct source {
  1156 	struct razor_set *set;
  1157 	uint32_t *property_map;
  1158 	uint32_t *file_map;
  1159 };
  1160 
  1161 struct razor_merger {
  1162 	struct razor_set *set;
  1163 	struct hashtable table;
  1164 	struct source source1;
  1165 	struct source source2;
  1166 };
  1167 
  1168 static struct razor_merger *
  1169 razor_merger_create(struct razor_set *set1, struct razor_set *set2)
  1170 {
  1171 	struct razor_merger *merger;
  1172 	int count;
  1173 	size_t size;
  1174 
  1175 	merger = zalloc(sizeof *merger);
  1176 	merger->set = razor_set_create();
  1177 	hashtable_init(&merger->table, &merger->set->string_pool);
  1178 
  1179 	merger->source1.set = set1;
  1180 	count = set1->properties.size / sizeof (struct razor_property);
  1181 	size = count * sizeof merger->source1.property_map[0];
  1182 	merger->source1.property_map = zalloc(size);
  1183 	count = set1->files.size / sizeof (struct razor_entry);
  1184 	size = count * sizeof merger->source1.file_map[0];
  1185 	merger->source1.file_map = zalloc(size);
  1186 
  1187 	merger->source2.set = set2;
  1188 	count = set2->properties.size / sizeof (struct razor_property);
  1189 	size = count * sizeof merger->source2.property_map[0];
  1190 	merger->source2.property_map = zalloc(size);
  1191 	count = set2->files.size / sizeof (struct razor_entry);
  1192 	size = count * sizeof merger->source2.file_map[0];
  1193 	merger->source2.file_map = zalloc(size);
  1194 
  1195 	return merger;
  1196 }
  1197 
  1198 static void
  1199 razor_merger_add_package(struct razor_merger *merger,
  1200 			 struct razor_package *package)
  1201 {
  1202 	char *pool;
  1203 	struct list *r;
  1204 	struct razor_package *p;
  1205 	struct razor_set *set1;
  1206 	struct source *source;
  1207 	uint32_t flags;
  1208 
  1209 	set1 = merger->source1.set;
  1210 	if (set1->packages.data <= (void *) package &&
  1211 	    (void *) package < set1->packages.data + set1->packages.size) {
  1212 		source = &merger->source1;
  1213 		flags = 0;
  1214 	} else {
  1215 		source = &merger->source2;
  1216 		flags = UPSTREAM_SOURCE;
  1217 	}
  1218 
  1219 	pool = source->set->string_pool.data;
  1220 	p = array_add(&merger->set->packages, sizeof *p);
  1221 	p->name = hashtable_tokenize(&merger->table, &pool[package->name]);
  1222 	p->flags = flags;
  1223 	p->version = hashtable_tokenize(&merger->table,
  1224 					&pool[package->version]);
  1225 	p->arch = hashtable_tokenize(&merger->table,
  1226 				     &pool[package->arch]);
  1227 
  1228 	p->properties = package->properties;
  1229 	r = list_first(&package->properties, &source->set->property_pool);
  1230 	while (r) {
  1231 		source->property_map[r->data] = 1;
  1232 		r = list_next(r);
  1233 	}
  1234 
  1235 	p->files = package->files;
  1236 	r = list_first(&package->files, &source->set->file_pool);
  1237 	while (r) {
  1238 		source->file_map[r->data] = 1;
  1239 		r = list_next(r);
  1240 	}
  1241 }
  1242 
  1243 static uint32_t
  1244 add_property(struct razor_merger *merger,
  1245 	     const char *name, enum razor_version_relation relation,
  1246 	     const char *version, int type)
  1247 {
  1248 	struct razor_property *p;
  1249 
  1250 	p = array_add(&merger->set->properties, sizeof *p);
  1251 	p->name = hashtable_tokenize(&merger->table, name);
  1252 	p->flags = 0;
  1253 	p->type = type;
  1254 	p->relation = relation;
  1255 	p->version = hashtable_tokenize(&merger->table, version);
  1256 
  1257 	return p - (struct razor_property *) merger->set->properties.data;
  1258 }
  1259 
  1260 static void
  1261 merge_properties(struct razor_merger *merger)
  1262 {
  1263 	struct razor_property *p1, *p2;
  1264 	struct razor_set *set1, *set2;
  1265 	uint32_t *map1, *map2;
  1266 	int i, j, cmp, count1, count2;
  1267 	char *pool1, *pool2;
  1268 
  1269 	set1 = merger->source1.set;
  1270 	set2 = merger->source2.set;
  1271 	map1 = merger->source1.property_map;
  1272 	map2 = merger->source2.property_map;
  1273 
  1274 	i = 0;
  1275 	j = 0;
  1276 	pool1 = set1->string_pool.data;
  1277 	pool2 = set2->string_pool.data;
  1278 
  1279 	count1 = set1->properties.size / sizeof *p1;
  1280 	count2 = set2->properties.size / sizeof *p2;
  1281 	while (i < count1 || j < count2) {
  1282 		if (i < count1 && map1[i] == 0) {
  1283 			i++;
  1284 			continue;
  1285 		}
  1286 		if (j < count2 && map2[j] == 0) {
  1287 			j++;
  1288 			continue;
  1289 		}
  1290 		p1 = (struct razor_property *) set1->properties.data + i;
  1291 		p2 = (struct razor_property *) set2->properties.data + j;
  1292 		if (i < count1 && j < count2)
  1293 			cmp = strcmp(&pool1[p1->name], &pool2[p2->name]);
  1294 		else if (i < count1)
  1295 			cmp = -1;
  1296 		else
  1297 			cmp = 1;
  1298 		if (cmp == 0)
  1299 			cmp = p1->type - p2->type;
  1300 		if (cmp == 0)
  1301 			cmp = p1->relation - p2->relation;
  1302 		if (cmp == 0)
  1303 			cmp = versioncmp(&pool1[p1->version],
  1304 					 &pool2[p2->version]);
  1305 		if (cmp < 0) {
  1306 			map1[i++] = add_property(merger,
  1307 						 &pool1[p1->name],
  1308 						 p1->relation,
  1309 						 &pool1[p1->version],
  1310 						 p1->type);
  1311 		} else if (cmp > 0) {
  1312 			map2[j++] = add_property(merger,
  1313 						 &pool2[p2->name],
  1314 						 p2->relation,
  1315 						 &pool2[p2->version],
  1316 						 p2->type);
  1317 		} else  {
  1318 			map1[i++] = map2[j++] = add_property(merger,
  1319 							     &pool1[p1->name],
  1320 							     p1->relation,
  1321 							     &pool1[p1->version],
  1322 							     p1->type);
  1323 		}
  1324 	}
  1325 }
  1326 
  1327 static void
  1328 emit_properties(struct list_head *properties, struct array *source_pool,
  1329 		uint32_t *map, struct array *pool)
  1330 {
  1331 	uint32_t r;
  1332 	struct list *p, *q;
  1333 
  1334 	r = pool->size / sizeof *q;
  1335 	p = list_first(properties, source_pool);
  1336 	while (p) {
  1337 		q = array_add(pool, sizeof *q);
  1338 		q->data = map[p->data];
  1339 		q->flags = p->flags;
  1340 		p = list_next(p);
  1341 	}
  1342 
  1343 	list_set_ptr(properties, r);
  1344 }
  1345 
  1346 static uint32_t
  1347 add_file(struct razor_merger *merger, const char *name)
  1348 {
  1349 	struct razor_entry *e;
  1350 
  1351 	e = array_add(&merger->set->files, sizeof *e);
  1352 	e->name = hashtable_tokenize(&merger->table, name);
  1353 	e->flags = 0;
  1354 	e->start = 0;
  1355 
  1356 	return e - (struct razor_entry *)merger->set->files.data;
  1357 }
  1358 
  1359 /* FIXME. Blah */
  1360 static int
  1361 fix_file_map(uint32_t *map,
  1362 	     struct razor_entry *files,
  1363 	     struct razor_entry *top)
  1364 {
  1365 	uint32_t e;
  1366 	int found_file = 0;
  1367 
  1368 	e = top->start;
  1369 	do {
  1370 		if (files[e].start)
  1371 			fix_file_map(map, files, &files[e]);
  1372 		if (map[e])
  1373 			found_file = 1;
  1374 	} while (!(files[e++].flags & RAZOR_ENTRY_LAST));
  1375 
  1376 	if (found_file)
  1377 		map[top - files] = 1;
  1378 	return found_file;
  1379 }
  1380 
  1381 struct merge_directory {
  1382 	uint32_t merged, dir1, dir2;
  1383 };
  1384 
  1385 static void
  1386 merge_one_directory(struct razor_merger *merger, struct merge_directory *md)
  1387 {
  1388 	struct razor_entry *root1, *root2, *mroot, *e1, *e2;
  1389 	struct razor_set *set1, *set2;
  1390 	struct array merge_stack;
  1391 	struct merge_directory *child_md, *end_md;
  1392 	uint32_t *map1, *map2, start, last;
  1393 	int cmp;
  1394 	char *pool1, *pool2;
  1395 
  1396 	set1 = merger->source1.set;
  1397 	set2 = merger->source2.set;
  1398 	map1 = merger->source1.file_map;
  1399 	map2 = merger->source2.file_map;
  1400 	pool1 = set1->string_pool.data;
  1401 	pool2 = set2->string_pool.data;
  1402 	root1 = (struct razor_entry *) set1->files.data;
  1403 	root2 = (struct razor_entry *) set2->files.data;
  1404 
  1405 	array_init(&merge_stack);
  1406 
  1407 	start = merger->set->files.size / sizeof (struct razor_entry);
  1408 	last = 0;
  1409 	e1 = md->dir1 ? root1 + md->dir1 : NULL;
  1410 	e2 = md->dir2 ? root2 + md->dir2 : NULL;
  1411 	while (e1 || e2) {
  1412 		if (!e2 && !map1[e1 - root1]) {
  1413 			if ((e1++)->flags & RAZOR_ENTRY_LAST)
  1414 				e1 = NULL;
  1415 			continue;
  1416 		}
  1417 		if (!e1 && !map2[e2 - root2]) {
  1418 			if ((e2++)->flags & RAZOR_ENTRY_LAST)
  1419 				e2 = NULL;
  1420 			continue;
  1421 		}
  1422 		if (e1 && !map1[e1 - root1] &&
  1423 		    e2 && !map1[e2 - root2]) {
  1424 			if ((e1++)->flags & RAZOR_ENTRY_LAST)
  1425 				e1 = NULL;
  1426 			if ((e2++)->flags & RAZOR_ENTRY_LAST)
  1427 				e2 = NULL;
  1428 			continue;
  1429 		}
  1430 
  1431 		if (!e1)
  1432 			cmp = 1;
  1433 		else if (!e2)
  1434 			cmp = -1;
  1435 		else {
  1436 			cmp = strcmp (&pool1[e1->name],
  1437 				      &pool2[e2->name]);
  1438 		}
  1439 
  1440 		if (cmp < 0) {
  1441 			if (map1[e1 - root1]) {
  1442 				map1[e1 - root1] = last =
  1443 					add_file(merger, &pool1[e1->name]);
  1444 				if (e1->start) {
  1445 					child_md = array_add(&merge_stack, sizeof (struct merge_directory));
  1446 					child_md->merged = last;
  1447 					child_md->dir1 = e1->start;
  1448 					child_md->dir2 = 0;
  1449 				}
  1450 			}
  1451 			if ((e1++)->flags & RAZOR_ENTRY_LAST)
  1452 				e1 = NULL;
  1453 		} else if (cmp > 0) {
  1454 			if (map2[e2 - root2]) {
  1455 				map2[e2 - root2] = last =
  1456 					add_file(merger, &pool2[e2->name]);
  1457 				if (e2->start) {
  1458 					child_md = array_add(&merge_stack, sizeof (struct merge_directory));
  1459 					child_md->merged = last;
  1460 					child_md->dir1 = 0;
  1461 					child_md->dir2 = e2->start;
  1462 				}
  1463 			}
  1464 			if ((e2++)->flags & RAZOR_ENTRY_LAST)
  1465 				e2 = NULL;
  1466 		} else {
  1467 			map1[e1 - root1] = map2[e2- root2] = last =
  1468 				add_file(merger, &pool1[e1->name]);
  1469 			if (e1->start || e2->start) {
  1470 				child_md = array_add(&merge_stack, sizeof (struct merge_directory));
  1471 				child_md->merged = last;
  1472 				child_md->dir1 = e1->start;
  1473 				child_md->dir2 = e2->start;
  1474 			}
  1475 			if ((e1++)->flags & RAZOR_ENTRY_LAST)
  1476 				e1 = NULL;
  1477 			if ((e2++)->flags & RAZOR_ENTRY_LAST)
  1478 				e2 = NULL;
  1479 		}
  1480 	}
  1481 
  1482 	mroot = (struct razor_entry *)merger->set->files.data;
  1483 	if (last) {
  1484 		mroot[last].flags = RAZOR_ENTRY_LAST;
  1485 		mroot[md->merged].start = start;
  1486 	} else
  1487 		mroot[md->merged].start = 0;
  1488 
  1489 	end_md = merge_stack.data + merge_stack.size;
  1490 	for (child_md = merge_stack.data; child_md < end_md; child_md++)
  1491 		merge_one_directory(merger, child_md);
  1492 	array_release(&merge_stack);
  1493 }
  1494 
  1495 static void
  1496 merge_files(struct razor_merger *merger)
  1497 {
  1498 	struct razor_entry *root;
  1499 	struct merge_directory md;
  1500 	uint32_t *map1, *map2;
  1501 
  1502 	map1 = merger->source1.file_map;
  1503 	map2 = merger->source2.file_map;
  1504 
  1505 	md.merged = 0;
  1506 
  1507 	if (merger->source1.set->files.size) {
  1508 		root = (struct razor_entry *) merger->source1.set->files.data;
  1509 		if (root->start)
  1510 			fix_file_map(map1, root, root);
  1511 		md.dir1 = root->start;
  1512 	} else
  1513 		md.dir1 = 0;
  1514 
  1515 	if (merger->source2.set->files.size) {
  1516 		root = (struct razor_entry *) merger->source2.set->files.data;
  1517 		if (root->start)
  1518 			fix_file_map(map2, root, root);
  1519 		md.dir2 = root->start;
  1520 	} else
  1521 		md.dir2 = 0;
  1522 
  1523 	merge_one_directory(merger, &md);
  1524 }
  1525 
  1526 static void
  1527 emit_files(struct list_head *files, struct array *source_pool,
  1528 	   uint32_t *map, struct array *pool)
  1529 {
  1530 	uint32_t r;
  1531 	struct list *p, *q;
  1532 
  1533 	r = pool->size / sizeof *q;
  1534 	p = list_first(files, source_pool);
  1535 	while (p) {
  1536 		q = array_add(pool, sizeof *q);
  1537 		q->data = map[p->data];
  1538 		q->flags = p->flags;
  1539 		p = list_next(p);
  1540 	}
  1541 
  1542 	list_set_ptr(files, r);
  1543 }
  1544 
  1545 /* Rebuild property->packages maps.  We can't just remap these, as a
  1546  * property may have lost or gained a number of packages.  Allocate an
  1547  * array per property and loop through the packages and add them to
  1548  * the arrays for their properties. */
  1549 static void
  1550 rebuild_property_package_lists(struct razor_set *set)
  1551 {
  1552 	struct array *pkgs, *a;
  1553 	struct razor_package *pkg, *pkg_end;
  1554 	struct razor_property *prop, *prop_end;
  1555 	struct list *r;
  1556 	uint32_t *q;
  1557 	int count;
  1558 
  1559 	count = set->properties.size / sizeof (struct razor_property);
  1560 	pkgs = zalloc(count * sizeof *pkgs);
  1561 	pkg_end = set->packages.data + set->packages.size;
  1562 
  1563 	for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
  1564 		r = list_first(&pkg->properties, &set->property_pool);
  1565 		while (r) {
  1566 			q = array_add(&pkgs[r->data], sizeof *q);
  1567 			*q = pkg - (struct razor_package *) set->packages.data;
  1568 			r = list_next(r);
  1569 		}
  1570 	}
  1571 
  1572 	prop_end = set->properties.data + set->properties.size;
  1573 	a = pkgs;
  1574 	for (prop = set->properties.data; prop < prop_end; prop++, a++) {
  1575 		list_set_array(&prop->packages, &set->package_pool, a, 0);
  1576 		array_release(a);
  1577 	}
  1578 	free(pkgs);
  1579 }
  1580 
  1581 static void
  1582 rebuild_file_package_lists(struct razor_set *set)
  1583 {
  1584 	struct array *pkgs, *a;
  1585 	struct razor_package *pkg, *pkg_end;
  1586 	struct razor_entry *entry, *entry_end;
  1587 	struct list *r;
  1588 	uint32_t *q;
  1589 	int count;
  1590 
  1591 	count = set->files.size / sizeof (struct razor_entry);
  1592 	pkgs = zalloc(count * sizeof *pkgs);
  1593 	pkg_end = set->packages.data + set->packages.size;
  1594 
  1595 	for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
  1596 		r = list_first(&pkg->files, &set->file_pool);
  1597 		while (r) {
  1598 			q = array_add(&pkgs[r->data], sizeof *q);
  1599 			*q = pkg - (struct razor_package *) set->packages.data;
  1600 			r = list_next(r);
  1601 		}
  1602 	}
  1603 
  1604 	entry_end = set->files.data + set->files.size;
  1605 	a = pkgs;
  1606 	for (entry = set->files.data; entry < entry_end; entry++, a++) {
  1607 		list_set_array(&entry->packages, &set->package_pool, a, 0);
  1608 		array_release(a);
  1609 	}
  1610 	free(pkgs);
  1611 }
  1612 
  1613 static struct razor_set *
  1614 razor_merger_finish(struct razor_merger *merger)
  1615 {
  1616 	struct razor_set *result;
  1617 	struct razor_package *p, *pend;
  1618 
  1619 	/* As we built the package list, we filled out a bitvector of
  1620 	 * the properties that are referenced by the packages in the
  1621 	 * new set.  Now we do a parallel loop through the properties
  1622 	 * and emit those marked in the bit vector to the new set.  In
  1623 	 * the process, we update the bit vector to actually map from
  1624 	 * indices in the old property list to indices in the new
  1625 	 * property list for both sets. */
  1626 
  1627 	merge_properties(merger);
  1628 	merge_files(merger);
  1629 
  1630 	/* Now we loop through the packages again and emit the
  1631 	 * property lists, remapped to point to the new properties. */
  1632 
  1633 	pend = merger->set->packages.data + merger->set->packages.size;
  1634 	for (p = merger->set->packages.data; p < pend; p++) {
  1635 		struct source *src;
  1636 
  1637 		if (p->flags & UPSTREAM_SOURCE)
  1638 			src = &merger->source2;
  1639 		else
  1640 			src = &merger->source1;
  1641 
  1642 		emit_properties(&p->properties,
  1643 				&src->set->property_pool,
  1644 				src->property_map,
  1645 				&merger->set->property_pool);
  1646 		emit_files(&p->files,
  1647 			   &src->set->file_pool,
  1648 			   src->file_map,
  1649 			   &merger->set->file_pool);
  1650 		p->flags &= ~UPSTREAM_SOURCE;
  1651 	}
  1652 
  1653 	rebuild_property_package_lists(merger->set);
  1654 	rebuild_file_package_lists(merger->set);
  1655 
  1656 	result = merger->set;
  1657 	hashtable_release(&merger->table);
  1658 	free(merger);
  1659 
  1660 	return result;
  1661 }
  1662 
  1663 /* The diff order matters.  We should sort the packages so that a
  1664  * REMOVE of a package comes before the INSTALL, and so that all
  1665  * requires for a package have been installed before the package.
  1666  **/
  1667 
  1668 void
  1669 razor_set_diff(struct razor_set *set, struct razor_set *upstream,
  1670 	       razor_package_callback_t callback, void *data)
  1671 {
  1672  	struct razor_package_iterator *pi1, *pi2;
  1673  	struct razor_package *p1, *p2;
  1674 	const char *name1, *name2, *version1, *version2, *arch1, *arch2;
  1675 	int res;
  1676 
  1677 	pi1 = razor_package_iterator_create(set);
  1678 	pi2 = razor_package_iterator_create(upstream);
  1679 
  1680 	razor_package_iterator_next(pi1, &p1, &name1, &version1, &arch1);
  1681 	razor_package_iterator_next(pi2, &p2, &name2, &version2, &arch2);
  1682 
  1683 	while (p1 || p2) {
  1684 		if (p1 && p2) {
  1685 			res = strcmp(name1, name2);
  1686 			if (res == 0)
  1687 				res = versioncmp(version1, version2);
  1688 		} else {
  1689 			res = 0;
  1690 		}
  1691 
  1692 		if (p2 == NULL || res < 0)
  1693 			callback(name1, version1, NULL, arch1, data);
  1694 		else if (p1 == NULL || res > 0)
  1695 			callback(name2, NULL, version2, arch2, data);
  1696 
  1697 		if (p1 != NULL && res <= 0)
  1698 			razor_package_iterator_next(pi1, &p1,
  1699 						    &name1, &version1, &arch1);
  1700 		if (p2 != NULL && res >= 0)
  1701 			razor_package_iterator_next(pi2, &p2,
  1702 						    &name2, &version2, &arch2);
  1703 	}
  1704 
  1705 	razor_package_iterator_destroy(pi1);
  1706 	razor_package_iterator_destroy(pi2);
  1707 }
  1708 
  1709 static int
  1710 provider_satisfies_requirement(struct razor_property *provider,
  1711 			       const char *provider_strings,
  1712 			       enum razor_version_relation relation,
  1713 			       const char *required)
  1714 {
  1715 	int cmp, len;
  1716 	const char *provided = &provider_strings[provider->version];
  1717 
  1718 	if (!*required)
  1719 		return 1;
  1720 	if (!*provided) {
  1721 		if (relation >= RAZOR_VERSION_EQUAL)
  1722 			return 1;
  1723 		else
  1724 			return 0;
  1725 	}
  1726 
  1727 	cmp = versioncmp(provided, required);
  1728 
  1729 	switch (relation) {
  1730 	case RAZOR_VERSION_LESS:
  1731 		return cmp < 0;
  1732 
  1733 	case RAZOR_VERSION_LESS_OR_EQUAL:
  1734 		if (cmp <= 0)
  1735 			return 1;
  1736 		/* fall through: FIXME, make sure this is correct */
  1737 
  1738 	case RAZOR_VERSION_EQUAL:
  1739 		if (cmp == 0)
  1740 			return 1;
  1741 
  1742 		/* "foo == 1.1" is satisfied by "foo 1.1-2" */
  1743 		len = strlen(required);
  1744 		if (!strncmp(required, provided, len) && provided[len] == '-')
  1745 			return 1;
  1746 		return 0;
  1747 
  1748 	case RAZOR_VERSION_GREATER_OR_EQUAL:
  1749 		return cmp >= 0;
  1750 
  1751 	case RAZOR_VERSION_GREATER:
  1752 		return cmp > 0;
  1753 	}
  1754 
  1755 	/* shouldn't happen */
  1756 	return 0;
  1757 }
  1758 
  1759 #define TRANS_PACKAGE_PRESENT		1
  1760 #define TRANS_PACKAGE_UPDATE		2
  1761 #define TRANS_PROPERTY_SATISFIED	0x80000000
  1762 
  1763 struct transaction_set {
  1764 	struct razor_set *set;
  1765 	uint32_t *packages;
  1766 	uint32_t *properties;
  1767 };
  1768 
  1769 struct razor_transaction {
  1770 	int package_count, errors;
  1771 	struct transaction_set system, upstream;
  1772 	int changes;
  1773 };
  1774 
  1775 static void
  1776 transaction_set_init(struct transaction_set *ts, struct razor_set *set)
  1777 {
  1778 	int count;
  1779 
  1780 	ts->set = set;
  1781 	count = set->packages.size / sizeof (struct razor_package);
  1782 	ts->packages = zalloc(count * sizeof *ts->packages);
  1783 	count = set->properties.size / sizeof (struct razor_property);
  1784 	ts->properties = zalloc(count * sizeof *ts->properties);
  1785 }
  1786 
  1787 static void
  1788 transaction_set_release(struct transaction_set *ts)
  1789 {
  1790 	free(ts->packages);
  1791 	free(ts->properties);
  1792 }
  1793 
  1794 static void
  1795 transaction_set_install_package(struct transaction_set *ts,
  1796 				struct razor_package *package)
  1797 {
  1798 	struct razor_package *pkgs;
  1799 	struct list *prop;
  1800 	int i;
  1801 
  1802 	pkgs = ts->set->packages.data;
  1803 	i = package - pkgs;
  1804 	if (ts->packages[i] == TRANS_PACKAGE_PRESENT)
  1805 		return;
  1806 
  1807 	ts->packages[i] = TRANS_PACKAGE_PRESENT;
  1808 
  1809 	prop = list_first(&package->properties, &ts->set->property_pool);
  1810 	while (prop) {
  1811 		ts->properties[prop->data]++;
  1812 		prop = list_next(prop);
  1813 	}
  1814 }
  1815 
  1816 static void
  1817 transaction_set_remove_package(struct transaction_set *ts,
  1818 			       struct razor_package *package)
  1819 {
  1820 	struct razor_package *pkgs;
  1821 	struct list *prop;
  1822 	int i;
  1823 
  1824 	pkgs = ts->set->packages.data;
  1825 	i = package - pkgs;
  1826 	if (ts->packages[i] == 0)
  1827 		return;
  1828 
  1829 	ts->packages[i] = 0;
  1830 
  1831 	prop = list_first(&package->properties, &ts->set->property_pool);
  1832 	while (prop) {
  1833 		ts->properties[prop->data]--;
  1834 		prop = list_next(prop);
  1835 	}
  1836 }
  1837 
  1838 struct razor_transaction *
  1839 razor_transaction_create(struct razor_set *system, struct razor_set *upstream)
  1840 {
  1841 	struct razor_transaction *trans;
  1842 	struct razor_package *p, *spkgs, *pend;
  1843 
  1844 	trans = zalloc(sizeof *trans);
  1845 	transaction_set_init(&trans->system, system);
  1846 	transaction_set_init(&trans->upstream, upstream);
  1847 
  1848 	spkgs = trans->system.set->packages.data;
  1849 	pend = trans->system.set->packages.data +
  1850 		trans->system.set->packages.size;
  1851 	for (p = spkgs; p < pend; p++)
  1852 		transaction_set_install_package(&trans->system, p);
  1853 
  1854 	return trans;
  1855 }
  1856 
  1857 void
  1858 razor_transaction_install_package(struct razor_transaction *trans,
  1859 				  struct razor_package *package)
  1860 {
  1861 	transaction_set_install_package(&trans->upstream, package);
  1862 	trans->changes++;
  1863 }
  1864 
  1865 void
  1866 razor_transaction_remove_package(struct razor_transaction *trans,
  1867 				 struct razor_package *package)
  1868 {
  1869 	transaction_set_remove_package(&trans->system, package);
  1870 	trans->changes++;
  1871 }
  1872 
  1873 void
  1874 razor_transaction_update_package(struct razor_transaction *trans,
  1875 				  struct razor_package *package)
  1876 {
  1877 	struct razor_package *spkgs, *upkgs, *end;
  1878 
  1879 	spkgs = trans->system.set->packages.data;
  1880 	upkgs = trans->upstream.set->packages.data;
  1881 	end = trans->system.set->packages.data +
  1882 		trans->system.set->packages.size;
  1883 	if (spkgs <= package && package < end)
  1884 		trans->system.packages[package - spkgs] |= TRANS_PACKAGE_UPDATE;
  1885 	else
  1886 		trans->upstream.packages[package - upkgs] |= TRANS_PACKAGE_UPDATE;
  1887 }
  1888 
  1889 struct prop_iter {
  1890 	struct razor_property *p, *start, *end;
  1891 	const char *pool;
  1892 	uint32_t *present;
  1893 };
  1894 
  1895 static void
  1896 prop_iter_init(struct prop_iter *pi, struct transaction_set *ts)
  1897 {
  1898 	pi->p = ts->set->properties.data;
  1899 	pi->start = ts->set->properties.data;
  1900 	pi->end = ts->set->properties.data + ts->set->properties.size;
  1901 	pi->pool = ts->set->string_pool.data;
  1902 	pi->present = ts->properties;
  1903 }
  1904 
  1905 static int
  1906 prop_iter_next(struct prop_iter *pi,
  1907 	       enum razor_property_type type, struct razor_property **p)
  1908 {
  1909 	while (pi->p < pi->end) {
  1910 		if ((pi->present[pi->p - pi->start] & ~TRANS_PROPERTY_SATISFIED) &&
  1911 		    pi->p->type == type) {
  1912 			*p = pi->p++;
  1913 			return 1;
  1914 		}
  1915 		pi->p++;
  1916 	}
  1917 
  1918 	return 0;
  1919 }
  1920 
  1921 static struct razor_property *
  1922 prop_iter_seek_to(struct prop_iter *pi,
  1923 		  enum razor_property_type type, const char *match)
  1924 {
  1925 	uint32_t name;
  1926 
  1927 	while (pi->p < pi->end && strcmp(&pi->pool[pi->p->name], match) < 0)
  1928 		pi->p++;
  1929 
  1930 	if (pi->p == pi->end || strcmp(&pi->pool[pi->p->name], match) > 0)
  1931 		return NULL;
  1932 
  1933 	name = pi->p->name;
  1934 	while (pi->p < pi->end &&
  1935 	       pi->p->name == name &&
  1936 	       pi->p->type != type)
  1937 		pi->p++;
  1938 
  1939 	if (pi->p == pi->end || pi->p->name != name)
  1940 		return NULL;
  1941 
  1942 	return pi->p;
  1943 }
  1944 
  1945 /* Remove packages from set that provide any of the matching (same
  1946  * name and type) providers from ppi onwards that match the
  1947  * requirement that rpi points to. */
  1948 static void
  1949 remove_matching_providers(struct razor_transaction *trans,
  1950 			  struct prop_iter *ppi,
  1951 			  enum razor_version_relation relation,
  1952 			  const char *version)
  1953 {
  1954 	struct razor_property *p;
  1955 	struct razor_package *pkg, *pkgs;
  1956 	struct razor_package_iterator pkg_iter;
  1957 	struct razor_set *set;
  1958 	const char *n, *v, *a;
  1959 
  1960 	if (ppi->present == trans->system.properties)
  1961 		set = trans->system.set;
  1962 	else
  1963 		set = trans->upstream.set;
  1964 
  1965 	pkgs = (struct razor_package *) set->packages.data;
  1966 	for (p = ppi->p;
  1967 	     p < ppi->end &&
  1968 	     p->name == ppi->p->name &&
  1969 	     p->type == ppi->p->type;
  1970 	     p++) {
  1971 		if (!ppi->present[p - ppi->start])
  1972 			continue;
  1973 		if (!provider_satisfies_requirement(p, ppi->pool,
  1974 						    relation, version))
  1975 			continue;
  1976 
  1977 		razor_package_iterator_init_for_property(&pkg_iter, set, p);
  1978 		while (razor_package_iterator_next(&pkg_iter,
  1979 						   &pkg, &n, &v, &a)) {
  1980 			fprintf(stderr, "removing %s-%s\n", n, v);
  1981 			razor_transaction_remove_package(trans, pkg);
  1982 		}
  1983 	}
  1984 }
  1985 
  1986 static void
  1987 flag_matching_providers(struct razor_transaction *trans,
  1988 			struct prop_iter *ppi,
  1989 			struct razor_property *r,
  1990 			struct prop_iter *rpi,
  1991 			unsigned int flag)
  1992 {
  1993 	struct razor_property *p;
  1994 	struct razor_package *pkg, *pkgs;
  1995 	struct razor_package_iterator pkg_iter;
  1996 	struct razor_set *set;
  1997 	const char *name, *version, *arch;
  1998 	uint32_t *flags;
  1999 
  2000 	if (ppi->present == trans->system.properties) {
  2001 		set = trans->system.set;
  2002 		flags = trans->system.packages;
  2003 	} else {
  2004 		set = trans->upstream.set;
  2005 		flags = trans->upstream.packages;
  2006 	}
  2007 
  2008 	pkgs = (struct razor_package *) set->packages.data;
  2009 	for (p = ppi->p;
  2010 	     p < ppi->end &&
  2011 		     p->name == ppi->p->name &&
  2012 		     p->type == ppi->p->type;
  2013 	     p++) {
  2014 		if (!ppi->present[p - ppi->start])
  2015 			continue;
  2016 		if (!provider_satisfies_requirement(p, ppi->pool,
  2017 						    r->relation,
  2018 						    &rpi->pool[r->version]))
  2019 			continue;
  2020 
  2021 		razor_package_iterator_init_for_property(&pkg_iter, set, p);
  2022 		while (razor_package_iterator_next(&pkg_iter, &pkg,
  2023 						   &name, &version, &arch)) {
  2024 
  2025 			fprintf(stderr, "flagging %s-%s for providing %s matching %s %s\n",
  2026 				name, version,
  2027 				ppi->pool + p->name,
  2028 				rpi->pool + r->name,
  2029 				rpi->pool + r->version);
  2030 			flags[pkg - pkgs] |= flag;
  2031 		}
  2032 	}
  2033 }
  2034 
  2035 static struct razor_package *
  2036 pick_matching_provider(struct razor_set *set,
  2037 		       struct prop_iter *ppi,
  2038 		       enum razor_version_relation relation,
  2039 		       const char *version)
  2040 {
  2041 	struct razor_property *p;
  2042 	struct razor_package *pkgs;
  2043 	struct list *i;
  2044 
  2045 	/* This is where we decide which pkgs to pull in to satisfy a
  2046 	 * requirement.  There may be several different providers
  2047 	 * (different versions) and each version of a provider may
  2048 	 * come from a number of packages.  We pick the first package
  2049 	 * from the first provider that matches. */
  2050 
  2051 	pkgs = set->packages.data;
  2052 	for (p = ppi->p;
  2053 	     p < ppi->end &&
  2054 		     p->name == ppi->p->name &&
  2055 		     p->type == ppi->p->type &&
  2056 		     ppi->present[p - ppi->start] == 0;
  2057 	     p++) {
  2058 		if (!provider_satisfies_requirement(p, ppi->pool,
  2059 						    relation, version))
  2060 			continue;
  2061 
  2062 		i = list_first(&p->packages, &set->package_pool);
  2063 
  2064 		return &pkgs[i->data];
  2065 	}
  2066 
  2067 	return NULL;
  2068 }
  2069 
  2070 static void
  2071 remove_obsoleted_packages(struct razor_transaction *trans)
  2072 {
  2073 	struct razor_property *up;
  2074 	struct razor_package *spkgs;
  2075 	struct prop_iter spi, upi;
  2076 
  2077 	spkgs = trans->system.set->packages.data;
  2078 	prop_iter_init(&spi, &trans->system);
  2079 	prop_iter_init(&upi, &trans->upstream);
  2080 
  2081 	while (prop_iter_next(&upi, RAZOR_PROPERTY_OBSOLETES, &up)) {
  2082 		if (!prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
  2083 				       &upi.pool[up->name]))
  2084 			continue;
  2085 		remove_matching_providers(trans, &spi, up->relation,
  2086 					  &upi.pool[up->version]);
  2087 	}
  2088 }
  2089 
  2090 static int
  2091 any_provider_satisfies_requirement(struct prop_iter *ppi,
  2092 				   enum razor_version_relation relation,
  2093 				   const char *version)
  2094 {
  2095 	struct razor_property *p;
  2096 
  2097 	for (p = ppi->p;
  2098 	     p < ppi->end &&
  2099 		     p->name == ppi->p->name &&
  2100 		     p->type == ppi->p->type;
  2101 	     p++) {
  2102 		if (ppi->present[p - ppi->start] > 0 &&
  2103 		    provider_satisfies_requirement(p, ppi->pool,
  2104 						   relation, version))
  2105 			return 1;
  2106 	}
  2107 
  2108 	return 0;
  2109 }
  2110 
  2111 static void
  2112 clear_requires_flags(struct transaction_set *ts)
  2113 {
  2114 	struct razor_property *p;
  2115 	const char *pool;
  2116 	int i, count;
  2117 
  2118 	count = ts->set->properties.size / sizeof *p;
  2119 	p = ts->set->properties.data;
  2120 	pool = ts->set->string_pool.data;
  2121 	for (i = 0; i < count; i++) {
  2122 		ts->properties[i] &= ~TRANS_PROPERTY_SATISFIED;
  2123 		if (strncmp(&pool[p[i].name], "rpmlib(", 7) == 0)
  2124 			ts->properties[i] |= TRANS_PROPERTY_SATISFIED;
  2125 	}
  2126 }
  2127 
  2128 static const char *relation_string[] = { "<", "<=", "=", ">=", ">" };
  2129 
  2130 static void
  2131 mark_satisfied_requires(struct razor_transaction *trans,
  2132 			struct transaction_set *rts,
  2133 			struct transaction_set *pts)
  2134 {
  2135 	struct prop_iter rpi, ppi;
  2136 	struct razor_property *rp;
  2137 
  2138 	prop_iter_init(&rpi, rts);
  2139 	prop_iter_init(&ppi, pts);
  2140 
  2141 	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
  2142 		if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES,
  2143 				       &rpi.pool[rp->name]))
  2144 			continue;
  2145 
  2146 		if (any_provider_satisfies_requirement(&ppi, rp->relation,
  2147 						       &rpi.pool[rp->version]))
  2148 			rpi.present[rp - rpi.start] |= TRANS_PROPERTY_SATISFIED;
  2149 	}
  2150 }
  2151 
  2152 static void
  2153 mark_all_satisfied_requires(struct razor_transaction *trans)
  2154 {
  2155 	clear_requires_flags(&trans->system);
  2156 	clear_requires_flags(&trans->upstream);
  2157 	mark_satisfied_requires(trans, &trans->system, &trans->system);
  2158 	mark_satisfied_requires(trans, &trans->system, &trans->upstream);
  2159 	mark_satisfied_requires(trans, &trans->upstream, &trans->system);
  2160 	mark_satisfied_requires(trans, &trans->upstream, &trans->upstream);
  2161 }
  2162 
  2163 static void
  2164 update_unsatisfied_packages(struct razor_transaction *trans)
  2165 {
  2166 	struct razor_package *spkgs, *pkg;
  2167 	struct razor_property *sp;
  2168 	struct prop_iter spi;
  2169 	struct razor_package_iterator pkg_iter;
  2170 	const char *name, *version, *arch;
  2171 
  2172 	spkgs = trans->system.set->packages.data;
  2173 	prop_iter_init(&spi, &trans->system);
  2174 
  2175 	while (prop_iter_next(&spi, RAZOR_PROPERTY_REQUIRES, &sp)) {
  2176 		if (spi.present[sp - spi.start] & TRANS_PROPERTY_SATISFIED)
  2177 			continue;
  2178 
  2179 		razor_package_iterator_init_for_property(&pkg_iter,
  2180 							 trans->system.set,
  2181 							 sp);
  2182 		while (razor_package_iterator_next(&pkg_iter, &pkg,
  2183 						   &name, &version, &arch)) {
  2184 			fprintf(stderr, "updating %s because %s %s %s "
  2185 				"isn't satisfied\n",
  2186 				name, spi.pool + sp->name,
  2187 				relation_string[sp->relation],
  2188 				spi.pool + sp->version);
  2189 			trans->system.packages[pkg - spkgs] |=
  2190 				TRANS_PACKAGE_UPDATE;
  2191 		}
  2192 	}
  2193 }
  2194 
  2195 void
  2196 razor_transaction_update_all(struct razor_transaction *trans)
  2197 {
  2198 	struct razor_package *p;
  2199 	int i, count;
  2200 
  2201 	count = trans->system.set->packages.size / sizeof *p;
  2202 	for (i = 0; i < count; i++)
  2203 		trans->system.packages[i] |= TRANS_PACKAGE_UPDATE;
  2204 }
  2205 
  2206 static void
  2207 update_conflicted_packages(struct razor_transaction *trans)
  2208 {
  2209 	struct razor_package *pkg, *spkgs;
  2210 	struct razor_property *up, *sp;
  2211 	struct prop_iter spi, upi;
  2212 	struct razor_package_iterator pkg_iter;
  2213 	const char *name, *version, *arch;
  2214 
  2215 	spkgs = trans->system.set->packages.data;
  2216 	prop_iter_init(&spi, &trans->system);
  2217 	prop_iter_init(&upi, &trans->upstream);
  2218 
  2219 	while (prop_iter_next(&spi, RAZOR_PROPERTY_CONFLICTS, &sp)) {
  2220 		if (!prop_iter_seek_to(&upi, RAZOR_PROPERTY_PROVIDES,
  2221 				       &spi.pool[sp->name]))
  2222 			continue;
  2223 
  2224 		if (!any_provider_satisfies_requirement(&upi, sp->relation,
  2225 							&spi.pool[sp->version]))
  2226 			continue;
  2227 
  2228 		razor_package_iterator_init_for_property(&pkg_iter,
  2229 							 trans->system.set,
  2230 							 sp);
  2231 		while (razor_package_iterator_next(&pkg_iter, &pkg,
  2232 						   &name, &version, &arch)) {
  2233 			fprintf(stderr, "updating %s %s because it conflicts with %s",
  2234 				name, version, spi.pool + sp->name);
  2235 			trans->system.packages[pkg - spkgs] |=
  2236 				TRANS_PACKAGE_UPDATE;
  2237 		}
  2238 	}
  2239 
  2240 	prop_iter_init(&spi, &trans->system);
  2241 	prop_iter_init(&upi, &trans->upstream);
  2242 
  2243 	while (prop_iter_next(&upi, RAZOR_PROPERTY_CONFLICTS, &up)) {
  2244 		sp = prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
  2245 				       &upi.pool[upi.p->name]);
  2246 
  2247 		if (sp)
  2248 			flag_matching_providers(trans, &spi, up, &upi,
  2249 						TRANS_PACKAGE_UPDATE);
  2250 	}
  2251 }
  2252 
  2253 static void
  2254 pull_in_requirements(struct razor_transaction *trans,
  2255 		     struct prop_iter *rpi, struct prop_iter *ppi)
  2256 {
  2257 	struct razor_property *rp, *pp;
  2258 	struct razor_package *pkg, *upkgs;
  2259 
  2260 	upkgs = trans->upstream.set->packages.data;
  2261 	while (prop_iter_next(rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
  2262 		if (rpi->present[rp - rpi->start] & TRANS_PROPERTY_SATISFIED)
  2263 			continue;
  2264 
  2265 		pp = prop_iter_seek_to(ppi, RAZOR_PROPERTY_PROVIDES,
  2266 				       &rpi->pool[rp->name]);
  2267 		if (pp == NULL)
  2268 			continue;
  2269 		pkg = pick_matching_provider(trans->upstream.set,
  2270 					     ppi, rp->relation,
  2271 					     &rpi->pool[rp->version]);
  2272 		if (pkg == NULL)
  2273 			continue;
  2274 
  2275 		rpi->present[rp - rpi->start] |= TRANS_PROPERTY_SATISFIED;
  2276 
  2277 		fprintf(stderr, "pulling in %s which provides %s %s %s "
  2278 			"to satisfy %s %s %s\n",
  2279 			ppi->pool + pkg->name,
  2280 			ppi->pool + pp->name,
  2281 			relation_string[pp->relation],
  2282 			ppi->pool + pp->version,
  2283 			&rpi->pool[rp->name],
  2284 			relation_string[rp->relation],
  2285 			&rpi->pool[rp->version]);
  2286 
  2287 		trans->upstream.packages[pkg - upkgs] |= TRANS_PACKAGE_UPDATE;
  2288 	}
  2289 }
  2290 
  2291 static void
  2292 pull_in_all_requirements(struct razor_transaction *trans)
  2293 {
  2294 	struct prop_iter rpi, ppi;
  2295 
  2296 	prop_iter_init(&rpi, &trans->system);
  2297 	prop_iter_init(&ppi, &trans->upstream);
  2298 	pull_in_requirements(trans, &rpi, &ppi);
  2299 
  2300 	prop_iter_init(&rpi, &trans->upstream);
  2301 	prop_iter_init(&ppi, &trans->upstream);
  2302 	pull_in_requirements(trans, &rpi, &ppi);
  2303 }
  2304 
  2305 static void
  2306 flush_scheduled_system_updates(struct razor_transaction *trans)
  2307 {
  2308  	struct razor_package_iterator *pi;
  2309  	struct razor_package *p, *pkg, *spkgs;
  2310 	struct prop_iter ppi;
  2311 	const char *name, *version, *arch;
  2312 
  2313 	spkgs = trans->system.set->packages.data;
  2314 	pi = razor_package_iterator_create(trans->system.set);
  2315 	prop_iter_init(&ppi, &trans->upstream);
  2316 
  2317 	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
  2318 		if (!(trans->system.packages[p - spkgs] & TRANS_PACKAGE_UPDATE))
  2319 			continue;
  2320 
  2321 		if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES, name))
  2322 			continue;
  2323 
  2324 		pkg = pick_matching_provider(trans->upstream.set, &ppi,
  2325 					     RAZOR_VERSION_GREATER, version);
  2326 		if (pkg == NULL)
  2327 			continue;
  2328 
  2329 		fprintf(stderr, "updating %s-%s to %s-%s\n",
  2330 			name, version,
  2331 			&ppi.pool[pkg->name], &ppi.pool[pkg->version]);
  2332 
  2333 		razor_transaction_remove_package(trans, p);
  2334 		razor_transaction_install_package(trans, pkg);
  2335 	}
  2336 
  2337 	razor_package_iterator_destroy(pi);
  2338 }
  2339 
  2340 static void
  2341 flush_scheduled_upstream_updates(struct razor_transaction *trans)
  2342 {
  2343  	struct razor_package_iterator *pi;
  2344  	struct razor_package *p, *upkgs;
  2345 	struct prop_iter spi;
  2346 	const char *name, *version, *arch;
  2347 
  2348 	upkgs = trans->upstream.set->packages.data;
  2349 	pi = razor_package_iterator_create(trans->upstream.set);
  2350 	prop_iter_init(&spi, &trans->system);
  2351 
  2352 	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
  2353 		if (!(trans->upstream.packages[p - upkgs] & TRANS_PACKAGE_UPDATE))
  2354 			continue;
  2355 
  2356 		if (prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES, name))
  2357 			remove_matching_providers(trans, &spi,
  2358 						  RAZOR_VERSION_LESS, version);
  2359 		razor_transaction_install_package(trans, p);
  2360 		fprintf(stderr, "installing %s-%s\n", name, version);
  2361 	}
  2362 }
  2363 
  2364 int
  2365 razor_transaction_resolve(struct razor_transaction *trans)
  2366 {
  2367 	int last = 0;
  2368 
  2369 	flush_scheduled_system_updates(trans);
  2370 	flush_scheduled_upstream_updates(trans);
  2371 
  2372 	while (last < trans->changes) {
  2373 		last = trans->changes;
  2374 		remove_obsoleted_packages(trans);
  2375 		mark_all_satisfied_requires(trans);
  2376 		update_unsatisfied_packages(trans);
  2377 		update_conflicted_packages(trans);
  2378 		pull_in_all_requirements(trans);
  2379 		flush_scheduled_system_updates(trans);
  2380 		flush_scheduled_upstream_updates(trans);
  2381 	}
  2382 
  2383 	return trans->changes;
  2384 }
  2385 
  2386 static void
  2387 describe_unsatisfied(struct razor_set *set, struct razor_property *rp)
  2388 {
  2389 	struct razor_package_iterator pi;
  2390 	struct razor_package *pkg;
  2391 	const char *name, *version, *arch, *pool;
  2392 
  2393 	pool = set->string_pool.data;
  2394 	if (pool[rp->version] == '\0') {
  2395 		razor_package_iterator_init_for_property(&pi, set, rp);
  2396 		while (razor_package_iterator_next(&pi, &pkg,
  2397 						   &name, &version, &arch))
  2398 			fprintf(stderr, "%s is needed by %s-%s.%s\n",
  2399 				&pool[rp->name],
  2400 				name, version, arch);
  2401 	} else {
  2402 		razor_package_iterator_init_for_property(&pi, set, rp);
  2403 		while (razor_package_iterator_next(&pi, &pkg,
  2404 						   &name, &version, &arch))
  2405 			fprintf(stderr, "%s %s %s is needed by %s-%s.%s\n",
  2406 				&pool[rp->name],
  2407 				relation_string[rp->relation],
  2408 				&pool[rp->version],
  2409 				name, version, arch);
  2410 	}
  2411 }
  2412 
  2413 int
  2414 razor_transaction_describe(struct razor_transaction *trans)
  2415 {
  2416 	struct prop_iter rpi;
  2417 	struct razor_property *rp;
  2418 	int unsatisfied;
  2419 
  2420 	flush_scheduled_system_updates(trans);
  2421 	flush_scheduled_upstream_updates(trans);
  2422 	mark_all_satisfied_requires(trans);
  2423 
  2424 	unsatisfied = 0;
  2425 	prop_iter_init(&rpi, &trans->system);
  2426 	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
  2427 		if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
  2428 			describe_unsatisfied(trans->system.set, rp);
  2429 		        unsatisfied++;
  2430 		}
  2431 	}
  2432 
  2433 	prop_iter_init(&rpi, &trans->upstream);
  2434 	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
  2435 		if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
  2436 			describe_unsatisfied(trans->upstream.set, rp);
  2437 			unsatisfied++;
  2438 		}
  2439 	}
  2440 
  2441 	return unsatisfied;
  2442 }
  2443 
  2444 int
  2445 razor_transaction_unsatisfied_property(struct razor_transaction *trans,
  2446 				       const char *name,
  2447 				       enum razor_version_relation rel,
  2448 				       const char *version,
  2449 				       enum razor_property_type type)
  2450 {
  2451 	struct prop_iter pi;
  2452 	struct razor_property *p;
  2453 
  2454 	prop_iter_init(&pi, &trans->system);
  2455 	while (prop_iter_next(&pi, type, &p)) {
  2456 		if (!(trans->system.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
  2457 		    p->relation == rel &&
  2458 		    strcmp(&pi.pool[p->name], name) == 0 &&
  2459 		    strcmp(&pi.pool[p->version], version) == 0)
  2460 
  2461 			return 1;
  2462 	}
  2463 
  2464 	prop_iter_init(&pi, &trans->upstream);
  2465 	while (prop_iter_next(&pi, type, &p)) {
  2466 		if (!(trans->upstream.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
  2467 		    p->relation == rel &&
  2468 		    strcmp(&pi.pool[p->name], name) == 0 &&
  2469 		    strcmp(&pi.pool[p->version], version) == 0)
  2470 
  2471 			return 1;
  2472 	}
  2473 
  2474 	return 0;
  2475 }
  2476 
  2477 struct razor_set *
  2478 razor_transaction_finish(struct razor_transaction *trans)
  2479 {
  2480 	struct razor_merger *merger;
  2481 	struct razor_package *u, *uend, *upkgs, *s, *send, *spkgs;
  2482 	char *upool, *spool;
  2483 	int cmp;
  2484 
  2485 	s = trans->system.set->packages.data;
  2486 	spkgs = trans->system.set->packages.data;
  2487 	send = trans->system.set->packages.data +
  2488 		trans->system.set->packages.size;
  2489 	spool = trans->system.set->string_pool.data;
  2490 
  2491 	u = trans->upstream.set->packages.data;
  2492 	upkgs = trans->upstream.set->packages.data;
  2493 	uend = trans->upstream.set->packages.data +
  2494 		trans->upstream.set->packages.size;
  2495 	upool = trans->upstream.set->string_pool.data;
  2496 
  2497 	merger = razor_merger_create(trans->system.set, trans->upstream.set);
  2498 	while (s < send || u < uend) {
  2499 		if (s < send && u < uend)
  2500 			cmp = strcmp(&spool[s->name], &upool[u->name]);
  2501 		else if (s < send)
  2502 			cmp = -1;
  2503 		else
  2504 			cmp = 1;
  2505 
  2506 		if (cmp < 0) {
  2507 			if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
  2508 				razor_merger_add_package(merger, s);
  2509 			s++;
  2510 		} else if (cmp == 0) {
  2511 			if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
  2512 				razor_merger_add_package(merger, s);
  2513 			if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
  2514 				razor_merger_add_package(merger, u);
  2515 
  2516 			s++;
  2517 			u++;
  2518 		} else {
  2519 			if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
  2520 				razor_merger_add_package(merger, u);
  2521 			u++;
  2522 		}
  2523 	}
  2524 
  2525 	razor_transaction_destroy(trans);
  2526 
  2527 	return razor_merger_finish(merger);
  2528 }
  2529 
  2530 void
  2531 razor_transaction_destroy(struct razor_transaction *trans)
  2532 {
  2533 	transaction_set_release(&trans->system);
  2534 	transaction_set_release(&trans->upstream);
  2535 	free(trans);
  2536 }
  2537 
  2538 struct razor_package_query {
  2539 	struct razor_set *set;
  2540 	char *vector;
  2541 	int count;
  2542 };
  2543 
  2544 struct razor_package_query *
  2545 razor_package_query_create(struct razor_set *set)
  2546 {
  2547 	struct razor_package_query *pq;
  2548 	int count;
  2549 
  2550 	pq = zalloc(sizeof *pq);
  2551 	pq->set = set;
  2552 	count = set->packages.size / sizeof(struct razor_package);
  2553 	pq->vector = zalloc(count * sizeof(char));
  2554 
  2555 	return pq;
  2556 }
  2557 
  2558 void
  2559 razor_package_query_add_package(struct razor_package_query *pq,
  2560 				struct razor_package *p)
  2561 {
  2562 	struct razor_package *packages;
  2563 
  2564 	packages = pq->set->packages.data;
  2565 	pq->count += pq->vector[p - packages] ^ 1;
  2566 	pq->vector[p - packages] = 1;
  2567 }
  2568 
  2569 void
  2570 razor_package_query_add_iterator(struct razor_package_query *pq,
  2571 				 struct razor_package_iterator *pi)
  2572 {
  2573 	struct razor_package *packages, *p;
  2574 	const char *name, *version, *arch;
  2575 
  2576 	packages = pq->set->packages.data;
  2577 	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
  2578 		pq->count += pq->vector[p - packages] ^ 1;
  2579 		pq->vector[p - packages] = 1;
  2580 	}
  2581 }
  2582 
  2583 struct razor_package_iterator *
  2584 razor_package_query_finish(struct razor_package_query *pq)
  2585 {
  2586 	struct razor_package_iterator *pi;
  2587 	struct razor_set *set;
  2588 	struct list *index;
  2589 	int i, j, count;
  2590 
  2591 	set = pq->set;
  2592 	count = set->packages.size / sizeof(struct razor_package);
  2593 	index = zalloc(pq->count * sizeof *index);
  2594 
  2595 	for (i = 0, j = 0; i < count; i++) {
  2596 		if (!pq->vector[i])
  2597 			continue;
  2598 
  2599 		index[j].data = i;
  2600 		if (j == pq->count - 1)
  2601 			index[j].flags = 0x80;
  2602 		j++;
  2603 	}
  2604 
  2605 	free(pq);
  2606 
  2607 	pi = razor_package_iterator_create_with_index(set, index);
  2608 	pi->free_index = 1;
  2609 
  2610 	return pi;
  2611 }