librazor/razor.c
author Kristian H?gsberg <krh@redhat.com>
Tue Jul 08 22:02:58 2008 -0400 (2008-07-08)
changeset 316 5ebed314390c
parent 308 f4761f529b9e
child 318 829d6711b316
permissions -rw-r--r--
Change the install iterator API to what we want.
rhughes@241
     1
/*
rhughes@241
     2
 * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
rhughes@241
     3
 * Copyright (C) 2008  Red Hat, Inc
rhughes@241
     4
 *
rhughes@241
     5
 * This program is free software; you can redistribute it and/or modify
rhughes@241
     6
 * it under the terms of the GNU General Public License as published by
rhughes@241
     7
 * the Free Software Foundation; either version 2 of the License, or
rhughes@241
     8
 * (at your option) any later version.
rhughes@241
     9
 *
rhughes@241
    10
 * This program is distributed in the hope that it will be useful,
rhughes@241
    11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
rhughes@241
    12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
rhughes@241
    13
 * GNU General Public License for more details.
rhughes@241
    14
 *
rhughes@241
    15
 * You should have received a copy of the GNU General Public License along
rhughes@241
    16
 * with this program; if not, write to the Free Software Foundation, Inc.,
rhughes@241
    17
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
rhughes@241
    18
 */
rhughes@241
    19
rhughes@241
    20
#define _GNU_SOURCE
rhughes@241
    21
rhughes@241
    22
#include <stdlib.h>
rhughes@241
    23
#include <stddef.h>
rhughes@241
    24
#include <stdint.h>
rhughes@241
    25
#include <stdio.h>
richard@302
    26
#include <stdarg.h>
rhughes@241
    27
#include <string.h>
rhughes@241
    28
#include <sys/types.h>
rhughes@241
    29
#include <sys/stat.h>
rhughes@241
    30
#include <sys/mman.h>
rhughes@241
    31
#include <unistd.h>
rhughes@241
    32
#include <fcntl.h>
rhughes@241
    33
#include <errno.h>
rhughes@241
    34
#include <ctype.h>
rhughes@241
    35
#include <fnmatch.h>
richard@301
    36
#include <assert.h>
rhughes@241
    37
krh@253
    38
#include "razor-internal.h"
rhughes@241
    39
#include "razor.h"
rhughes@241
    40
krh@248
    41
void *
rhughes@241
    42
zalloc(size_t size)
rhughes@241
    43
{
rhughes@241
    44
	void *p;
rhughes@241
    45
rhughes@241
    46
	p = malloc(size);
rhughes@241
    47
	memset(p, 0, size);
rhughes@241
    48
rhughes@241
    49
	return p;
rhughes@241
    50
}
rhughes@241
    51
rhughes@241
    52
struct razor_set_section razor_sections[] = {
rhughes@241
    53
	{ RAZOR_STRING_POOL,	offsetof(struct razor_set, string_pool) },
rhughes@241
    54
	{ RAZOR_PACKAGES,	offsetof(struct razor_set, packages) },
rhughes@241
    55
	{ RAZOR_PROPERTIES,	offsetof(struct razor_set, properties) },
rhughes@241
    56
	{ RAZOR_PACKAGE_POOL,	offsetof(struct razor_set, package_pool) },
rhughes@241
    57
	{ RAZOR_PROPERTY_POOL,	offsetof(struct razor_set, property_pool) },
rhughes@241
    58
};
rhughes@241
    59
jbowes@258
    60
struct razor_set_section razor_files_sections[] = {
jbowes@258
    61
	{ RAZOR_FILES,			offsetof(struct razor_set, files) },
jbowes@258
    62
	{ RAZOR_FILE_POOL,		offsetof(struct razor_set, file_pool) },
jbowes@258
    63
	{ RAZOR_FILE_STRING_POOL,	offsetof(struct razor_set, file_string_pool) },
jbowes@258
    64
};
jbowes@258
    65
jbowes@258
    66
struct razor_set_section razor_details_sections[] = {
jbowes@258
    67
	{ RAZOR_DETAILS_STRING_POOL,	offsetof(struct razor_set, details_string_pool) },
jbowes@258
    68
};
krh@262
    69
krh@269
    70
RAZOR_EXPORT struct razor_set *
rhughes@241
    71
razor_set_create(void)
rhughes@241
    72
{
rhughes@241
    73
	struct razor_set *set;
rhughes@241
    74
	struct razor_entry *e;
rhughes@241
    75
	char *empty;
rhughes@241
    76
rhughes@241
    77
	set = zalloc(sizeof *set);
rhughes@241
    78
rhughes@241
    79
	e = array_add(&set->files, sizeof *e);
rhughes@241
    80
	empty = array_add(&set->string_pool, 1);
rhughes@241
    81
	*empty = '\0';
rhughes@241
    82
	e->name = 0;
rhughes@241
    83
	e->flags = RAZOR_ENTRY_LAST;
rhughes@241
    84
	e->start = 0;
rhughes@241
    85
	list_set_empty(&e->packages);
rhughes@241
    86
rhughes@241
    87
	return set;
rhughes@241
    88
}
rhughes@241
    89
krh@269
    90
RAZOR_EXPORT struct razor_set *
rhughes@241
    91
razor_set_open(const char *filename)
rhughes@241
    92
{
rhughes@241
    93
	struct razor_set *set;
rhughes@241
    94
	struct razor_set_section *s;
rhughes@241
    95
	struct stat stat;
rhughes@241
    96
	struct array *array;
rhughes@241
    97
	int fd;
rhughes@241
    98
rhughes@241
    99
	set = zalloc(sizeof *set);
rhughes@241
   100
	fd = open(filename, O_RDONLY);
rhughes@241
   101
	if (fstat(fd, &stat) < 0)
rhughes@241
   102
		return NULL;
rhughes@241
   103
	set->header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
rhughes@241
   104
	if (set->header == MAP_FAILED) {
rhughes@241
   105
		free(set);
rhughes@241
   106
		return NULL;
rhughes@241
   107
	}
rhughes@241
   108
rhughes@241
   109
	for (s = set->header->sections; ~s->type; s++) {
rhughes@241
   110
		if (s->type >= ARRAY_SIZE(razor_sections))
rhughes@241
   111
			continue;
rhughes@241
   112
		if (s->type != razor_sections[s->type].type)
rhughes@241
   113
			continue;
rhughes@241
   114
		array = (void *) set + razor_sections[s->type].offset;
rhughes@241
   115
		array->data = (void *) set->header + s->offset;
rhughes@241
   116
		array->size = s->size;
rhughes@241
   117
		array->alloc = s->size;
rhughes@241
   118
	}
rhughes@241
   119
	close(fd);
rhughes@241
   120
rhughes@241
   121
	return set;
rhughes@241
   122
}
rhughes@241
   123
jbowes@288
   124
RAZOR_EXPORT int
jbowes@258
   125
razor_set_open_details(struct razor_set *set, const char *filename)
jbowes@258
   126
{
jbowes@258
   127
	struct razor_set_section *s;
jbowes@258
   128
	struct stat stat;
jbowes@258
   129
	struct array *array;
jbowes@258
   130
	int fd;
jbowes@258
   131
richard@301
   132
	assert (set != NULL);
richard@301
   133
	assert (filename != NULL);
richard@301
   134
jbowes@258
   135
	fd = open(filename, O_RDONLY);
jbowes@258
   136
	if (fstat(fd, &stat) < 0)
jbowes@288
   137
		return -1;
jbowes@258
   138
	set->details_header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
jbowes@258
   139
	if (set->details_header == MAP_FAILED)
jbowes@288
   140
		return -1;
jbowes@258
   141
jbowes@258
   142
	for (s = set->details_header->sections; ~s->type; s++) {
jbowes@258
   143
		if (s->type >= ARRAY_SIZE(razor_details_sections))
jbowes@258
   144
			continue;
jbowes@258
   145
		if (s->type != razor_details_sections[s->type].type)
jbowes@258
   146
			continue;
jbowes@258
   147
		array = (void *) set + razor_details_sections[s->type].offset;
jbowes@258
   148
		array->data = (void *) set->details_header + s->offset;
jbowes@258
   149
		array->size = s->size;
jbowes@258
   150
		array->alloc = s->size;
jbowes@258
   151
	}
jbowes@258
   152
	close(fd);
jbowes@288
   153
jbowes@288
   154
	return 0;
jbowes@258
   155
}
jbowes@258
   156
jbowes@288
   157
RAZOR_EXPORT int
jbowes@258
   158
razor_set_open_files(struct razor_set *set, const char *filename)
jbowes@258
   159
{
jbowes@258
   160
	struct razor_set_section *s;
jbowes@258
   161
	struct stat stat;
jbowes@258
   162
	struct array *array;
jbowes@258
   163
	int fd;
jbowes@258
   164
richard@301
   165
	assert (set != NULL);
richard@301
   166
	assert (filename != NULL);
richard@301
   167
jbowes@258
   168
	fd = open(filename, O_RDONLY);
jbowes@258
   169
	if (fstat(fd, &stat) < 0)
jbowes@288
   170
		return -1;
jbowes@258
   171
	set->files_header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
jbowes@258
   172
	if (set->files_header == MAP_FAILED)
jbowes@288
   173
		return -1;
jbowes@258
   174
jbowes@258
   175
	for (s = set->files_header->sections; ~s->type; s++) {
jbowes@258
   176
		if (s->type >= ARRAY_SIZE(razor_files_sections))
jbowes@258
   177
			continue;
jbowes@258
   178
		if (s->type != razor_files_sections[s->type].type)
jbowes@258
   179
			continue;
jbowes@258
   180
		array = (void *) set + razor_files_sections[s->type].offset;
jbowes@258
   181
		array->data = (void *) set->files_header + s->offset;
jbowes@258
   182
		array->size = s->size;
jbowes@258
   183
		array->alloc = s->size;
jbowes@258
   184
	}
jbowes@258
   185
	close(fd);
jbowes@288
   186
jbowes@288
   187
	return 0;
jbowes@258
   188
}
jbowes@258
   189
krh@269
   190
RAZOR_EXPORT void
rhughes@241
   191
razor_set_destroy(struct razor_set *set)
rhughes@241
   192
{
rhughes@241
   193
	unsigned int size;
rhughes@241
   194
	struct array *a;
rhughes@241
   195
	int i;
rhughes@241
   196
richard@301
   197
	assert (set != NULL);
richard@301
   198
rhughes@241
   199
	if (set->header) {
rhughes@241
   200
		for (i = 0; set->header->sections[i].type; i++)
rhughes@241
   201
			;
rhughes@241
   202
		size = set->header->sections[i].type;
rhughes@241
   203
		munmap(set->header, size);
rhughes@241
   204
	} else {
rhughes@241
   205
		for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
rhughes@241
   206
			a = (void *) set + razor_sections[i].offset;
rhughes@241
   207
			free(a->data);
rhughes@241
   208
		}
rhughes@241
   209
	}
rhughes@241
   210
jbowes@258
   211
	if (set->details_header) {
jbowes@258
   212
		for (i = 0; set->details_header->sections[i].type; i++)
jbowes@258
   213
			;
jbowes@258
   214
		size = set->details_header->sections[i].type;
jbowes@258
   215
		munmap(set->details_header, size);
jbowes@258
   216
	} else {
jbowes@258
   217
		for (i = 0; i < ARRAY_SIZE(razor_details_sections); i++) {
jbowes@258
   218
			a = (void *) set + razor_details_sections[i].offset;
jbowes@258
   219
			free(a->data);
jbowes@258
   220
		}
jbowes@258
   221
	}
jbowes@258
   222
jbowes@258
   223
	if (set->files_header) {
jbowes@258
   224
		for (i = 0; set->files_header->sections[i].type; i++)
jbowes@258
   225
			;
jbowes@258
   226
		size = set->files_header->sections[i].type;
jbowes@258
   227
		munmap(set->files_header, size);
jbowes@258
   228
	} else {
jbowes@258
   229
		for (i = 0; i < ARRAY_SIZE(razor_files_sections); i++) {
jbowes@258
   230
			a = (void *) set + razor_files_sections[i].offset;
jbowes@258
   231
			free(a->data);
jbowes@258
   232
		}
jbowes@258
   233
	}
jbowes@258
   234
rhughes@241
   235
	free(set);
rhughes@241
   236
}
rhughes@241
   237
jbowes@258
   238
static int
jbowes@258
   239
razor_set_write_sections_to_fd(struct razor_set *set, int fd, int magic,
jbowes@258
   240
			       struct razor_set_section *sections,
jbowes@258
   241
			       size_t array_size)
rhughes@241
   242
{
rhughes@241
   243
	char data[4096];
rhughes@241
   244
	struct razor_set_header *header = (struct razor_set_header *) data;
rhughes@241
   245
	struct array *a;
rhughes@241
   246
	uint32_t offset;
rhughes@241
   247
	int i;
rhughes@241
   248
rhughes@241
   249
	memset(data, 0, sizeof data);
jbowes@258
   250
	header->magic = magic;
rhughes@241
   251
	header->version = RAZOR_VERSION;
rhughes@241
   252
	offset = sizeof data;
rhughes@241
   253
jbowes@258
   254
	for (i = 0; i < array_size; i++) {
jbowes@258
   255
		if (sections[i].type != i)
rhughes@241
   256
			continue;
jbowes@258
   257
		a = (void *) set + sections[i].offset;
rhughes@241
   258
		header->sections[i].type = i;
rhughes@241
   259
		header->sections[i].offset = offset;
rhughes@241
   260
		header->sections[i].size = a->size;
rhughes@241
   261
		offset += ALIGN(a->size, 4096);
rhughes@241
   262
	}
rhughes@241
   263
rhughes@241
   264
	header->sections[i].type = ~0;
rhughes@241
   265
	header->sections[i].offset = 0;
rhughes@241
   266
	header->sections[i].size = 0;
rhughes@241
   267
rhughes@241
   268
	razor_write(fd, data, sizeof data);
rhughes@241
   269
	memset(data, 0, sizeof data);
jbowes@258
   270
	for (i = 0; i < array_size; i++) {
jbowes@258
   271
		if (sections[i].type != i)
rhughes@241
   272
			continue;
jbowes@258
   273
		a = (void *) set + sections[i].offset;
rhughes@241
   274
		razor_write(fd, a->data, a->size);
rhughes@241
   275
		razor_write(fd, data, ALIGN(a->size, 4096) - a->size);
rhughes@241
   276
	}
rhughes@241
   277
rhughes@241
   278
	return 0;
rhughes@241
   279
}
rhughes@241
   280
krh@269
   281
RAZOR_EXPORT int
jbowes@258
   282
razor_set_write_to_fd(struct razor_set *set, int fd,
jbowes@258
   283
		      enum razor_repo_file_type type)
jbowes@258
   284
{
jbowes@258
   285
	switch (type) {
jbowes@258
   286
	case RAZOR_REPO_FILE_MAIN:
jbowes@258
   287
		return razor_set_write_sections_to_fd(set, fd, RAZOR_MAGIC,
jbowes@258
   288
						      razor_sections,
jbowes@258
   289
						      ARRAY_SIZE(razor_sections));
jbowes@258
   290
jbowes@258
   291
	case RAZOR_REPO_FILE_DETAILS:
jbowes@258
   292
		return razor_set_write_sections_to_fd(set, fd, RAZOR_DETAILS_MAGIC,
jbowes@258
   293
						      razor_details_sections,
jbowes@258
   294
						      ARRAY_SIZE(razor_details_sections));
jbowes@258
   295
	case RAZOR_REPO_FILE_FILES:
jbowes@258
   296
		return razor_set_write_sections_to_fd(set, fd, RAZOR_FILES_MAGIC,
jbowes@258
   297
						      razor_files_sections,
jbowes@258
   298
						      ARRAY_SIZE(razor_files_sections));
jbowes@258
   299
	default:
jbowes@258
   300
		return -1;
jbowes@258
   301
	}
jbowes@258
   302
}
jbowes@258
   303
krh@269
   304
RAZOR_EXPORT int
jbowes@258
   305
razor_set_write(struct razor_set *set, const char *filename,
jbowes@258
   306
		enum razor_repo_file_type type)
rhughes@241
   307
{
rhughes@241
   308
	int fd, status;
rhughes@241
   309
rhughes@241
   310
	fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
rhughes@241
   311
	if (fd < 0)
rhughes@241
   312
		return -1;
rhughes@241
   313
jbowes@258
   314
	status = razor_set_write_to_fd(set, fd, type);
rhughes@241
   315
	if (status) {
rhughes@241
   316
	    close(fd);
rhughes@241
   317
	    return status;
rhughes@241
   318
	}
rhughes@241
   319
rhughes@241
   320
	return close(fd);
rhughes@241
   321
}
krh@269
   322
krh@269
   323
RAZOR_EXPORT void
rhughes@241
   324
razor_build_evr(char *evr_buf, int size, const char *epoch,
rhughes@241
   325
		const char *version, const char *release)
rhughes@241
   326
{
rhughes@241
   327
	int len;
rhughes@241
   328
rhughes@241
   329
	if (!version || !*version) {
rhughes@241
   330
		*evr_buf = '\0';
rhughes@241
   331
		return;
rhughes@241
   332
	}
rhughes@241
   333
rhughes@241
   334
	if (epoch && *epoch && strcmp(epoch, "0") != 0) {
rhughes@241
   335
		len = snprintf(evr_buf, size, "%s:", epoch);
rhughes@241
   336
		evr_buf += len;
rhughes@241
   337
		size -= len;
rhughes@241
   338
	}
rhughes@241
   339
	len = snprintf(evr_buf, size, "%s", version);
rhughes@241
   340
	evr_buf += len;
rhughes@241
   341
	size -= len;
rhughes@241
   342
	if (release && *release)
rhughes@241
   343
		snprintf(evr_buf, size, "-%s", release);
rhughes@241
   344
}
rhughes@241
   345
krh@269
   346
RAZOR_EXPORT int
krh@248
   347
razor_versioncmp(const char *s1, const char *s2)
rhughes@241
   348
{
rhughes@241
   349
	const char *p1, *p2;
rhughes@241
   350
	long n1, n2;
rhughes@241
   351
	int res;
rhughes@241
   352
richard@301
   353
	assert (s1 != NULL);
richard@301
   354
	assert (s2 != NULL);
richard@301
   355
rhughes@241
   356
	n1 = strtol(s1, (char **) &p1, 10);
rhughes@241
   357
	n2 = strtol(s2, (char **) &p2, 10);
rhughes@241
   358
rhughes@241
   359
	/* Epoch; if one but not the other has an epoch set, default
rhughes@241
   360
	 * the epoch-less version to 0. */
rhughes@241
   361
	res = (*p1 == ':') - (*p2 == ':');
rhughes@241
   362
	if (res < 0) {
rhughes@241
   363
		n1 = 0;
rhughes@241
   364
		p1 = s1;
rhughes@241
   365
		p2++;
rhughes@241
   366
	} else if (res > 0) {
rhughes@241
   367
		p1++;
rhughes@241
   368
		n2 = 0;
rhughes@241
   369
		p2 = s2;
rhughes@241
   370
	}
rhughes@241
   371
rhughes@241
   372
	if (n1 != n2)
rhughes@241
   373
		return n1 - n2;
rhughes@241
   374
	while (*p1 && *p2) {
rhughes@241
   375
		if (*p1 != *p2)
rhughes@241
   376
			return *p1 - *p2;
rhughes@241
   377
		p1++;
rhughes@241
   378
		p2++;
rhughes@241
   379
		if (isdigit(*p1) && isdigit(*p2))
krh@248
   380
			return razor_versioncmp(p1, p2);
rhughes@241
   381
	}
rhughes@241
   382
rhughes@241
   383
	return *p1 - *p2;
rhughes@241
   384
}
rhughes@241
   385
richard@302
   386
static const char *
richard@302
   387
razor_package_get_details_type(struct razor_set *set,
richard@302
   388
			       struct razor_package *package,
richard@302
   389
			       enum razor_detail_type type)
richard@302
   390
{
richard@302
   391
	const char *pool;
richard@302
   392
richard@302
   393
	switch (type) {
richard@302
   394
	case RAZOR_DETAIL_NAME:
richard@302
   395
		pool = set->string_pool.data;
richard@302
   396
		return &pool[package->name];
richard@302
   397
richard@302
   398
	case RAZOR_DETAIL_VERSION:
richard@302
   399
		pool = set->string_pool.data;
richard@302
   400
		return &pool[package->version];
richard@302
   401
richard@302
   402
	case RAZOR_DETAIL_ARCH:
richard@302
   403
		pool = set->string_pool.data;
richard@302
   404
		return &pool[package->arch];
richard@302
   405
richard@302
   406
	case RAZOR_DETAIL_SUMMARY:
richard@302
   407
		pool = set->details_string_pool.data;
richard@302
   408
		return &pool[package->summary];
richard@302
   409
richard@302
   410
	case RAZOR_DETAIL_DESCRIPTION:
richard@302
   411
		pool = set->details_string_pool.data;
richard@302
   412
		return &pool[package->description];
richard@302
   413
richard@302
   414
	case RAZOR_DETAIL_URL:
richard@302
   415
		pool = set->details_string_pool.data;
richard@302
   416
		return &pool[package->url];
richard@302
   417
richard@302
   418
	case RAZOR_DETAIL_LICENSE:
richard@302
   419
		pool = set->details_string_pool.data;
richard@302
   420
		return &pool[package->license];
richard@302
   421
richard@302
   422
	default:
richard@302
   423
		fprintf(stderr, "type %u not found\n", type);
richard@302
   424
		return NULL;
richard@302
   425
	}
richard@302
   426
}
richard@302
   427
richard@302
   428
/**
richard@302
   429
 * razor_package_get_details_varg:
richard@302
   430
 * @set: a %razor_set
richard@302
   431
 * @package: a %razor_package
richard@302
   432
 * @args: a va_list of arguments to set
richard@302
   433
 **/
richard@302
   434
void
richard@302
   435
razor_package_get_details_varg(struct razor_set *set,
richard@302
   436
			       struct razor_package *package,
richard@302
   437
			       va_list args)
richard@302
   438
{
richard@302
   439
	int i;
richard@302
   440
	enum razor_detail_type type;
richard@302
   441
	const char **data;
richard@302
   442
richard@302
   443
	for (i = 0;; i += 2) {
richard@302
   444
		type = va_arg(args, enum razor_detail_type);
richard@307
   445
		if (type == RAZOR_DETAIL_LAST)
richard@302
   446
			break;
richard@302
   447
		data = va_arg(args, const char **);
richard@302
   448
		*data = razor_package_get_details_type(set, package, type);
richard@302
   449
	}
richard@302
   450
richard@302
   451
}
richard@302
   452
richard@302
   453
/**
richard@302
   454
 * razor_package_get_details:
richard@302
   455
 * @set: a %razor_set
richard@302
   456
 * @package: a %razor_package
richard@302
   457
 *
richard@302
   458
 * Gets details about a package using a varg interface
krh@308
   459
 * The vararg must be terminated with %RAZOR_DETAIL_LAST.
richard@302
   460
 *
richard@307
   461
 * Example: razor_package_get_details (set, package,
richard@307
   462
 *				       RAZOR_DETAIL_URL, &url,
richard@307
   463
 *				       RAZOR_DETAIL_LAST);
richard@302
   464
 **/
krh@269
   465
RAZOR_EXPORT void
richard@302
   466
razor_package_get_details(struct razor_set *set, struct razor_package *package, ...)
jbowes@258
   467
{
richard@302
   468
	va_list args;
jbowes@258
   469
richard@301
   470
	assert (set != NULL);
richard@301
   471
	assert (package != NULL);
richard@301
   472
richard@302
   473
	va_start(args, NULL);
richard@302
   474
	razor_package_get_details_varg (set, package, args);
richard@302
   475
	va_end (args);
jbowes@258
   476
}
jbowes@258
   477
krh@270
   478
RAZOR_EXPORT const char *
krh@270
   479
razor_property_relation_to_string(struct razor_property *p)
krh@270
   480
{
richard@301
   481
	assert (p != NULL);
richard@301
   482
krh@270
   483
	switch (p->flags & RAZOR_PROPERTY_RELATION_MASK) {
krh@270
   484
	case RAZOR_PROPERTY_LESS:
krh@270
   485
		return "<";
krh@270
   486
krh@270
   487
	case RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL:
krh@270
   488
		return "<=";
krh@270
   489
krh@270
   490
	case RAZOR_PROPERTY_EQUAL:
krh@270
   491
		return "=";
krh@270
   492
krh@270
   493
	case RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL:
krh@270
   494
		return ">=";
krh@270
   495
krh@270
   496
	case RAZOR_PROPERTY_GREATER:
krh@270
   497
		return ">";
krh@270
   498
krh@270
   499
	default:
krh@270
   500
		return "?";
krh@270
   501
	}
krh@270
   502
}
krh@270
   503
krh@270
   504
RAZOR_EXPORT const char *
krh@270
   505
razor_property_type_to_string(struct razor_property *p)
krh@270
   506
{
richard@301
   507
	assert (p != NULL);
richard@301
   508
krh@270
   509
	switch (p->flags & RAZOR_PROPERTY_TYPE_MASK) {
krh@270
   510
	case RAZOR_PROPERTY_REQUIRES:
krh@270
   511
		return "requires";
krh@270
   512
	case RAZOR_PROPERTY_PROVIDES:
krh@270
   513
		return "provides";
krh@270
   514
	case RAZOR_PROPERTY_CONFLICTS:
krh@270
   515
		return "conflicts";
krh@270
   516
	case RAZOR_PROPERTY_OBSOLETES:
krh@270
   517
		return "obsoletes";
krh@270
   518
	default:
krh@270
   519
		return NULL;
krh@270
   520
	}
krh@270
   521
}
krh@270
   522
krh@269
   523
RAZOR_EXPORT struct razor_entry *
krh@248
   524
razor_set_find_entry(struct razor_set *set,
krh@248
   525
		     struct razor_entry *dir, const char *pattern)
rhughes@241
   526
{
rhughes@241
   527
	struct razor_entry *e;
jbowes@264
   528
	const char *n, *pool = set->file_string_pool.data;
rhughes@241
   529
	int len;
rhughes@241
   530
richard@301
   531
	assert (set != NULL);
richard@301
   532
	assert (dir != NULL);
richard@301
   533
	assert (pattern != NULL);
richard@301
   534
rhughes@241
   535
	e = (struct razor_entry *) set->files.data + dir->start;
rhughes@241
   536
	do {
rhughes@241
   537
		n = pool + e->name;
rhughes@241
   538
		if (strcmp(pattern + 1, n) == 0)
rhughes@241
   539
			return e;
rhughes@241
   540
		len = strlen(n);
rhughes@241
   541
		if (e->start != 0 && strncmp(pattern + 1, n, len) == 0 &&
rhughes@241
   542
		    pattern[len + 1] == '/') {
krh@248
   543
			return razor_set_find_entry(set, e, pattern + len + 1);
rhughes@241
   544
		}
rhughes@241
   545
	} while (!((e++)->flags & RAZOR_ENTRY_LAST));
rhughes@241
   546
rhughes@241
   547
	return NULL;
rhughes@241
   548
}
rhughes@241
   549
rhughes@241
   550
static void
rhughes@241
   551
list_dir(struct razor_set *set, struct razor_entry *dir,
rhughes@241
   552
	 char *prefix, const char *pattern)
rhughes@241
   553
{
rhughes@241
   554
	struct razor_entry *e;
jbowes@274
   555
	const char *n, *pool = set->file_string_pool.data;
rhughes@241
   556
rhughes@241
   557
	e = (struct razor_entry *) set->files.data + dir->start;
rhughes@241
   558
	do {
rhughes@241
   559
		n = pool + e->name;
rhughes@241
   560
		if (pattern && pattern[0] && fnmatch(pattern, n, 0) != 0)
rhughes@241
   561
			continue;
rhughes@241
   562
		printf("%s/%s\n", prefix, n);
rhughes@241
   563
		if (e->start) {
rhughes@241
   564
			char *sub = prefix + strlen (prefix);
rhughes@241
   565
			*sub = '/';
rhughes@241
   566
			strcpy (sub + 1, n);
rhughes@241
   567
			list_dir(set, e, prefix, pattern);
rhughes@241
   568
			*sub = '\0';
rhughes@241
   569
		}
rhughes@241
   570
	} while (!((e++)->flags & RAZOR_ENTRY_LAST));
rhughes@241
   571
}
rhughes@241
   572
krh@269
   573
RAZOR_EXPORT void
rhughes@241
   574
razor_set_list_files(struct razor_set *set, const char *pattern)
rhughes@241
   575
{
rhughes@241
   576
	struct razor_entry *e;
rhughes@241
   577
	char buffer[512], *p, *base;
rhughes@241
   578
richard@301
   579
	assert (set != NULL);
richard@301
   580
rhughes@241
   581
	if (pattern == NULL || !strcmp (pattern, "/")) {
rhughes@241
   582
		buffer[0] = '\0';
rhughes@241
   583
		list_dir(set, set->files.data, buffer, NULL);
rhughes@241
   584
		return;
rhughes@241
   585
	}
rhughes@241
   586
rhughes@241
   587
	strcpy(buffer, pattern);
krh@248
   588
	e = razor_set_find_entry(set, set->files.data, buffer);
rhughes@241
   589
	if (e && e->start > 0) {
rhughes@241
   590
		base = NULL;
rhughes@241
   591
	} else {
rhughes@241
   592
		p = strrchr(buffer, '/');
rhughes@241
   593
		if (p) {
rhughes@241
   594
			*p = '\0';
rhughes@241
   595
			base = p + 1;
rhughes@241
   596
		} else {
rhughes@241
   597
			base = NULL;
rhughes@241
   598
		}
rhughes@241
   599
	}
krh@248
   600
	e = razor_set_find_entry(set, set->files.data, buffer);
krh@283
   601
	if (e && e->start != 0)
rhughes@241
   602
		list_dir(set, e, buffer, base);
rhughes@241
   603
}
rhughes@241
   604
rhughes@241
   605
static struct list *
rhughes@241
   606
list_package_files(struct razor_set *set, struct list *r,
rhughes@241
   607
		   struct razor_entry *dir, uint32_t end,
rhughes@241
   608
		   char *prefix)
rhughes@241
   609
{
rhughes@241
   610
	struct razor_entry *e, *f, *entries;
rhughes@241
   611
	uint32_t next, file;
rhughes@241
   612
	char *pool;
rhughes@241
   613
	int len;
rhughes@241
   614
rhughes@241
   615
	entries = (struct razor_entry *) set->files.data;
jbowes@274
   616
	pool = set->file_string_pool.data;
rhughes@241
   617
rhughes@241
   618
	e = entries + dir->start;
rhughes@241
   619
	do {
rhughes@241
   620
		if (entries + r->data == e) {
rhughes@241
   621
			printf("%s/%s\n", prefix, pool + e->name);
rhughes@241
   622
			r = list_next(r);
rhughes@241
   623
			if (!r)
rhughes@241
   624
				return NULL;
rhughes@241
   625
			if (r->data >= end)
rhughes@241
   626
				return r;
rhughes@241
   627
		}
rhughes@241
   628
	} while (!((e++)->flags & RAZOR_ENTRY_LAST));
rhughes@241
   629
rhughes@241
   630
	e = entries + dir->start;
rhughes@241
   631
	do {
rhughes@241
   632
		if (e->start == 0)
rhughes@241
   633
			continue;
rhughes@241
   634
rhughes@241
   635
		if (e->flags & RAZOR_ENTRY_LAST)
rhughes@241
   636
			next = end;
rhughes@241
   637
		else {
rhughes@241
   638
			f = e + 1;
rhughes@241
   639
			while (f->start == 0 && !(f->flags & RAZOR_ENTRY_LAST))
rhughes@241
   640
				f++;
rhughes@241
   641
			if (f->start == 0)
rhughes@241
   642
				next = end;
rhughes@241
   643
			else
rhughes@241
   644
				next = f->start;
rhughes@241
   645
		}
rhughes@241
   646
rhughes@241
   647
		file = r->data;
rhughes@241
   648
		if (e->start <= file && file < next) {
rhughes@241
   649
			len = strlen(prefix);
rhughes@241
   650
			prefix[len] = '/';
rhughes@241
   651
			strcpy(prefix + len + 1, pool + e->name);
rhughes@241
   652
			r = list_package_files(set, r, e, next, prefix);
rhughes@241
   653
			prefix[len] = '\0';
rhughes@241
   654
		}
rhughes@241
   655
	} while (!((e++)->flags & RAZOR_ENTRY_LAST) && r != NULL);
rhughes@241
   656
rhughes@241
   657
	return r;
rhughes@241
   658
}
rhughes@241
   659
krh@269
   660
RAZOR_EXPORT void
krh@306
   661
razor_set_list_package_files(struct razor_set *set,
krh@306
   662
			     struct razor_package *package)
rhughes@241
   663
{
rhughes@241
   664
	struct list *r;
rhughes@241
   665
	uint32_t end;
rhughes@241
   666
	char buffer[512];
rhughes@241
   667
richard@301
   668
	assert (set != NULL);
krh@306
   669
	assert (package != NULL);
rhughes@241
   670
rhughes@241
   671
	r = list_first(&package->files, &set->file_pool);
rhughes@241
   672
	end = set->files.size / sizeof (struct razor_entry);
rhughes@241
   673
	buffer[0] = '\0';
rhughes@241
   674
	list_package_files(set, r, set->files.data, end, buffer);
rhughes@241
   675
}
rhughes@241
   676
rhughes@241
   677
/* The diff order matters.  We should sort the packages so that a
rhughes@241
   678
 * REMOVE of a package comes before the INSTALL, and so that all
rhughes@241
   679
 * requires for a package have been installed before the package.
rhughes@241
   680
 **/
rhughes@241
   681
krh@269
   682
RAZOR_EXPORT void
rhughes@241
   683
razor_set_diff(struct razor_set *set, struct razor_set *upstream,
krh@253
   684
	       razor_diff_callback_t callback, void *data)
rhughes@241
   685
{
rhughes@241
   686
 	struct razor_package_iterator *pi1, *pi2;
rhughes@241
   687
 	struct razor_package *p1, *p2;
rhughes@241
   688
	const char *name1, *name2, *version1, *version2, *arch1, *arch2;
rhughes@241
   689
	int res;
rhughes@241
   690
richard@301
   691
	assert (set != NULL);
richard@301
   692
	assert (upstream != NULL);
richard@301
   693
rhughes@241
   694
	pi1 = razor_package_iterator_create(set);
rhughes@241
   695
	pi2 = razor_package_iterator_create(upstream);
rhughes@241
   696
richard@302
   697
	razor_package_iterator_next(pi1, &p1,
richard@302
   698
				    RAZOR_DETAIL_NAME, &name1,
richard@302
   699
				    RAZOR_DETAIL_VERSION, &version1,
richard@302
   700
				    RAZOR_DETAIL_ARCH, &arch1,
richard@307
   701
				    RAZOR_DETAIL_LAST);
richard@302
   702
	razor_package_iterator_next(pi2, &p2,
richard@302
   703
				    RAZOR_DETAIL_NAME, &name2,
richard@302
   704
				    RAZOR_DETAIL_VERSION, &version2,
richard@302
   705
				    RAZOR_DETAIL_ARCH, &arch2,
richard@307
   706
				    RAZOR_DETAIL_LAST);
rhughes@241
   707
rhughes@241
   708
	while (p1 || p2) {
rhughes@241
   709
		if (p1 && p2) {
rhughes@241
   710
			res = strcmp(name1, name2);
rhughes@241
   711
			if (res == 0)
krh@248
   712
				res = razor_versioncmp(version1, version2);
rhughes@241
   713
		} else {
rhughes@241
   714
			res = 0;
rhughes@241
   715
		}
rhughes@241
   716
rhughes@241
   717
		if (p2 == NULL || res < 0)
krh@253
   718
			callback(RAZOR_DIFF_ACTION_REMOVE,
krh@253
   719
				 p1, name1, version1, arch1, data);
rhughes@241
   720
		else if (p1 == NULL || res > 0)
krh@253
   721
			callback(RAZOR_DIFF_ACTION_ADD,
krh@253
   722
				 p2, name2, version2, arch2, data);
rhughes@241
   723
rhughes@241
   724
		if (p1 != NULL && res <= 0)
rhughes@241
   725
			razor_package_iterator_next(pi1, &p1,
richard@302
   726
						    RAZOR_DETAIL_NAME, &name1,
richard@302
   727
						    RAZOR_DETAIL_VERSION, &version1,
richard@302
   728
						    RAZOR_DETAIL_ARCH, &arch1,
richard@307
   729
						    RAZOR_DETAIL_LAST);
rhughes@241
   730
		if (p2 != NULL && res >= 0)
rhughes@241
   731
			razor_package_iterator_next(pi2, &p2,
richard@302
   732
						    RAZOR_DETAIL_NAME, &name2,
richard@302
   733
						    RAZOR_DETAIL_VERSION, &version2,
richard@302
   734
						    RAZOR_DETAIL_ARCH, &arch2,
richard@307
   735
						    RAZOR_DETAIL_LAST);
rhughes@241
   736
	}
rhughes@241
   737
rhughes@241
   738
	razor_package_iterator_destroy(pi1);
rhughes@241
   739
	razor_package_iterator_destroy(pi2);
rhughes@241
   740
}
krh@254
   741
krh@316
   742
struct install_action {
krh@316
   743
	enum razor_install_action action;
krh@316
   744
	struct razor_package *package;
krh@316
   745
};
krh@316
   746
krh@316
   747
struct razor_install_iterator {
krh@316
   748
	struct razor_set *set;
krh@316
   749
	struct razor_set *next;
krh@316
   750
	struct array actions;
krh@316
   751
	struct install_action *a, *end;
krh@316
   752
};
krh@316
   753
krh@254
   754
static void
krh@316
   755
add_action(enum razor_diff_action action,
krh@316
   756
	   struct razor_package *package,
krh@316
   757
	   const char *name,
krh@316
   758
	   const char *version,
krh@316
   759
	   const char *arch,
krh@316
   760
	   void *data)
krh@254
   761
{
krh@316
   762
	struct razor_install_iterator *ii = data;
krh@316
   763
	struct install_action *a;
krh@316
   764
krh@316
   765
	a = array_add(&ii->actions, sizeof *a);
krh@316
   766
	a->package = package;
krh@316
   767
krh@316
   768
	switch (action) {
krh@316
   769
	case RAZOR_DIFF_ACTION_ADD:
krh@316
   770
		a->action = RAZOR_INSTALL_ACTION_ADD;
krh@316
   771
		break;
krh@316
   772
	case RAZOR_DIFF_ACTION_REMOVE:
krh@316
   773
		a->action = RAZOR_INSTALL_ACTION_REMOVE;
krh@316
   774
		break;
krh@316
   775
	}
krh@254
   776
}
krh@254
   777
krh@316
   778
RAZOR_EXPORT struct razor_install_iterator *
krh@316
   779
razor_set_create_install_iterator(struct razor_set *set,
krh@316
   780
				  struct razor_set *next)
krh@254
   781
{
krh@316
   782
	struct razor_install_iterator *ii;
krh@254
   783
richard@301
   784
	assert (set != NULL);
richard@301
   785
	assert (next != NULL);
richard@301
   786
krh@316
   787
	ii = zalloc(sizeof *ii);
krh@316
   788
	ii->set = set;
krh@316
   789
	ii->next = next;
krh@316
   790
	
krh@316
   791
	razor_set_diff(set, next, add_action, ii);
krh@254
   792
krh@316
   793
	ii->a = ii->actions.data;
krh@316
   794
	ii->end = ii->actions.data + ii->actions.size;
krh@254
   795
krh@254
   796
	/* FIXME: We need to figure out the right install order here,
krh@254
   797
	 * so the post and pre scripts can run. */
krh@254
   798
krh@316
   799
	return ii;
krh@254
   800
}
krh@254
   801
krh@316
   802
RAZOR_EXPORT int
krh@316
   803
razor_install_iterator_next(struct razor_install_iterator *ii,
krh@316
   804
			    struct razor_set **set,
krh@316
   805
			    struct razor_package **package,
krh@316
   806
			    enum razor_install_action *action,
krh@316
   807
			    int *count)
krh@254
   808
{
krh@316
   809
	if (ii->a == ii->end)
krh@316
   810
		return 0;
krh@254
   811
krh@316
   812
	switch (ii->a->action) {
krh@316
   813
	case RAZOR_INSTALL_ACTION_ADD:
krh@316
   814
		*set = ii->next;
krh@316
   815
		break;
krh@316
   816
	case RAZOR_INSTALL_ACTION_REMOVE:
krh@316
   817
		*set = ii->set;
krh@316
   818
		break;
krh@316
   819
	}
richard@301
   820
krh@316
   821
	*package = ii->a->package;
krh@316
   822
	*action = ii->a->action;
krh@316
   823
	*count = 0;
krh@316
   824
	ii->a++;
krh@254
   825
krh@316
   826
	return 1;
krh@316
   827
}
krh@254
   828
krh@316
   829
RAZOR_EXPORT void
krh@316
   830
razor_install_iterator_destroy(struct razor_install_iterator *ii)
krh@316
   831
{
krh@316
   832
	array_release(&ii->actions);
krh@316
   833
	free(ii);
krh@254
   834
}