librazor/razor.c
author James Bowes <jbowes@redhat.com>
Thu Jun 26 19:11:36 2008 -0400 (2008-06-26)
changeset 292 4af421a011b4
parent 283 a510dcb8e019
child 298 ddc35bb593ef
permissions -rw-r--r--
Add 'search' command
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>
rhughes@241
    26
#include <string.h>
rhughes@241
    27
#include <sys/types.h>
rhughes@241
    28
#include <sys/stat.h>
rhughes@241
    29
#include <sys/mman.h>
rhughes@241
    30
#include <unistd.h>
rhughes@241
    31
#include <fcntl.h>
rhughes@241
    32
#include <errno.h>
rhughes@241
    33
#include <ctype.h>
rhughes@241
    34
#include <fnmatch.h>
rhughes@241
    35
krh@253
    36
#include "razor-internal.h"
rhughes@241
    37
#include "razor.h"
rhughes@241
    38
krh@248
    39
void *
rhughes@241
    40
zalloc(size_t size)
rhughes@241
    41
{
rhughes@241
    42
	void *p;
rhughes@241
    43
rhughes@241
    44
	p = malloc(size);
rhughes@241
    45
	memset(p, 0, size);
rhughes@241
    46
rhughes@241
    47
	return p;
rhughes@241
    48
}
rhughes@241
    49
rhughes@241
    50
struct razor_set_section razor_sections[] = {
rhughes@241
    51
	{ RAZOR_STRING_POOL,	offsetof(struct razor_set, string_pool) },
rhughes@241
    52
	{ RAZOR_PACKAGES,	offsetof(struct razor_set, packages) },
rhughes@241
    53
	{ RAZOR_PROPERTIES,	offsetof(struct razor_set, properties) },
rhughes@241
    54
	{ RAZOR_PACKAGE_POOL,	offsetof(struct razor_set, package_pool) },
rhughes@241
    55
	{ RAZOR_PROPERTY_POOL,	offsetof(struct razor_set, property_pool) },
rhughes@241
    56
};
rhughes@241
    57
jbowes@258
    58
struct razor_set_section razor_files_sections[] = {
jbowes@258
    59
	{ RAZOR_FILES,			offsetof(struct razor_set, files) },
jbowes@258
    60
	{ RAZOR_FILE_POOL,		offsetof(struct razor_set, file_pool) },
jbowes@258
    61
	{ RAZOR_FILE_STRING_POOL,	offsetof(struct razor_set, file_string_pool) },
jbowes@258
    62
};
jbowes@258
    63
jbowes@258
    64
struct razor_set_section razor_details_sections[] = {
jbowes@258
    65
	{ RAZOR_DETAILS_STRING_POOL,	offsetof(struct razor_set, details_string_pool) },
jbowes@258
    66
};
krh@262
    67
krh@269
    68
RAZOR_EXPORT struct razor_set *
rhughes@241
    69
razor_set_create(void)
rhughes@241
    70
{
rhughes@241
    71
	struct razor_set *set;
rhughes@241
    72
	struct razor_entry *e;
rhughes@241
    73
	char *empty;
rhughes@241
    74
rhughes@241
    75
	set = zalloc(sizeof *set);
rhughes@241
    76
rhughes@241
    77
	e = array_add(&set->files, sizeof *e);
rhughes@241
    78
	empty = array_add(&set->string_pool, 1);
rhughes@241
    79
	*empty = '\0';
rhughes@241
    80
	e->name = 0;
rhughes@241
    81
	e->flags = RAZOR_ENTRY_LAST;
rhughes@241
    82
	e->start = 0;
rhughes@241
    83
	list_set_empty(&e->packages);
rhughes@241
    84
rhughes@241
    85
	return set;
rhughes@241
    86
}
rhughes@241
    87
krh@269
    88
RAZOR_EXPORT struct razor_set *
rhughes@241
    89
razor_set_open(const char *filename)
rhughes@241
    90
{
rhughes@241
    91
	struct razor_set *set;
rhughes@241
    92
	struct razor_set_section *s;
rhughes@241
    93
	struct stat stat;
rhughes@241
    94
	struct array *array;
rhughes@241
    95
	int fd;
rhughes@241
    96
rhughes@241
    97
	set = zalloc(sizeof *set);
rhughes@241
    98
	fd = open(filename, O_RDONLY);
rhughes@241
    99
	if (fstat(fd, &stat) < 0)
rhughes@241
   100
		return NULL;
rhughes@241
   101
	set->header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
rhughes@241
   102
	if (set->header == MAP_FAILED) {
rhughes@241
   103
		free(set);
rhughes@241
   104
		return NULL;
rhughes@241
   105
	}
rhughes@241
   106
rhughes@241
   107
	for (s = set->header->sections; ~s->type; s++) {
rhughes@241
   108
		if (s->type >= ARRAY_SIZE(razor_sections))
rhughes@241
   109
			continue;
rhughes@241
   110
		if (s->type != razor_sections[s->type].type)
rhughes@241
   111
			continue;
rhughes@241
   112
		array = (void *) set + razor_sections[s->type].offset;
rhughes@241
   113
		array->data = (void *) set->header + s->offset;
rhughes@241
   114
		array->size = s->size;
rhughes@241
   115
		array->alloc = s->size;
rhughes@241
   116
	}
rhughes@241
   117
	close(fd);
rhughes@241
   118
rhughes@241
   119
	return set;
rhughes@241
   120
}
rhughes@241
   121
jbowes@288
   122
RAZOR_EXPORT int
jbowes@258
   123
razor_set_open_details(struct razor_set *set, const char *filename)
jbowes@258
   124
{
jbowes@258
   125
	struct razor_set_section *s;
jbowes@258
   126
	struct stat stat;
jbowes@258
   127
	struct array *array;
jbowes@258
   128
	int fd;
jbowes@258
   129
jbowes@258
   130
	fd = open(filename, O_RDONLY);
jbowes@258
   131
	if (fstat(fd, &stat) < 0)
jbowes@288
   132
		return -1;
jbowes@258
   133
	set->details_header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
jbowes@258
   134
	if (set->details_header == MAP_FAILED)
jbowes@288
   135
		return -1;
jbowes@258
   136
jbowes@258
   137
	for (s = set->details_header->sections; ~s->type; s++) {
jbowes@258
   138
		if (s->type >= ARRAY_SIZE(razor_details_sections))
jbowes@258
   139
			continue;
jbowes@258
   140
		if (s->type != razor_details_sections[s->type].type)
jbowes@258
   141
			continue;
jbowes@258
   142
		array = (void *) set + razor_details_sections[s->type].offset;
jbowes@258
   143
		array->data = (void *) set->details_header + s->offset;
jbowes@258
   144
		array->size = s->size;
jbowes@258
   145
		array->alloc = s->size;
jbowes@258
   146
	}
jbowes@258
   147
	close(fd);
jbowes@288
   148
jbowes@288
   149
	return 0;
jbowes@258
   150
}
jbowes@258
   151
jbowes@288
   152
RAZOR_EXPORT int
jbowes@258
   153
razor_set_open_files(struct razor_set *set, const char *filename)
jbowes@258
   154
{
jbowes@258
   155
	struct razor_set_section *s;
jbowes@258
   156
	struct stat stat;
jbowes@258
   157
	struct array *array;
jbowes@258
   158
	int fd;
jbowes@258
   159
jbowes@258
   160
	fd = open(filename, O_RDONLY);
jbowes@258
   161
	if (fstat(fd, &stat) < 0)
jbowes@288
   162
		return -1;
jbowes@258
   163
	set->files_header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
jbowes@258
   164
	if (set->files_header == MAP_FAILED)
jbowes@288
   165
		return -1;
jbowes@258
   166
jbowes@258
   167
	for (s = set->files_header->sections; ~s->type; s++) {
jbowes@258
   168
		if (s->type >= ARRAY_SIZE(razor_files_sections))
jbowes@258
   169
			continue;
jbowes@258
   170
		if (s->type != razor_files_sections[s->type].type)
jbowes@258
   171
			continue;
jbowes@258
   172
		array = (void *) set + razor_files_sections[s->type].offset;
jbowes@258
   173
		array->data = (void *) set->files_header + s->offset;
jbowes@258
   174
		array->size = s->size;
jbowes@258
   175
		array->alloc = s->size;
jbowes@258
   176
	}
jbowes@258
   177
	close(fd);
jbowes@288
   178
jbowes@288
   179
	return 0;
jbowes@258
   180
}
jbowes@258
   181
krh@269
   182
RAZOR_EXPORT void
rhughes@241
   183
razor_set_destroy(struct razor_set *set)
rhughes@241
   184
{
rhughes@241
   185
	unsigned int size;
rhughes@241
   186
	struct array *a;
rhughes@241
   187
	int i;
rhughes@241
   188
rhughes@241
   189
	if (set->header) {
rhughes@241
   190
		for (i = 0; set->header->sections[i].type; i++)
rhughes@241
   191
			;
rhughes@241
   192
		size = set->header->sections[i].type;
rhughes@241
   193
		munmap(set->header, size);
rhughes@241
   194
	} else {
rhughes@241
   195
		for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
rhughes@241
   196
			a = (void *) set + razor_sections[i].offset;
rhughes@241
   197
			free(a->data);
rhughes@241
   198
		}
rhughes@241
   199
	}
rhughes@241
   200
jbowes@258
   201
	if (set->details_header) {
jbowes@258
   202
		for (i = 0; set->details_header->sections[i].type; i++)
jbowes@258
   203
			;
jbowes@258
   204
		size = set->details_header->sections[i].type;
jbowes@258
   205
		munmap(set->details_header, size);
jbowes@258
   206
	} else {
jbowes@258
   207
		for (i = 0; i < ARRAY_SIZE(razor_details_sections); i++) {
jbowes@258
   208
			a = (void *) set + razor_details_sections[i].offset;
jbowes@258
   209
			free(a->data);
jbowes@258
   210
		}
jbowes@258
   211
	}
jbowes@258
   212
jbowes@258
   213
	if (set->files_header) {
jbowes@258
   214
		for (i = 0; set->files_header->sections[i].type; i++)
jbowes@258
   215
			;
jbowes@258
   216
		size = set->files_header->sections[i].type;
jbowes@258
   217
		munmap(set->files_header, size);
jbowes@258
   218
	} else {
jbowes@258
   219
		for (i = 0; i < ARRAY_SIZE(razor_files_sections); i++) {
jbowes@258
   220
			a = (void *) set + razor_files_sections[i].offset;
jbowes@258
   221
			free(a->data);
jbowes@258
   222
		}
jbowes@258
   223
	}
jbowes@258
   224
rhughes@241
   225
	free(set);
rhughes@241
   226
}
rhughes@241
   227
jbowes@258
   228
static int
jbowes@258
   229
razor_set_write_sections_to_fd(struct razor_set *set, int fd, int magic,
jbowes@258
   230
			       struct razor_set_section *sections,
jbowes@258
   231
			       size_t array_size)
rhughes@241
   232
{
rhughes@241
   233
	char data[4096];
rhughes@241
   234
	struct razor_set_header *header = (struct razor_set_header *) data;
rhughes@241
   235
	struct array *a;
rhughes@241
   236
	uint32_t offset;
rhughes@241
   237
	int i;
rhughes@241
   238
rhughes@241
   239
	memset(data, 0, sizeof data);
jbowes@258
   240
	header->magic = magic;
rhughes@241
   241
	header->version = RAZOR_VERSION;
rhughes@241
   242
	offset = sizeof data;
rhughes@241
   243
jbowes@258
   244
	for (i = 0; i < array_size; i++) {
jbowes@258
   245
		if (sections[i].type != i)
rhughes@241
   246
			continue;
jbowes@258
   247
		a = (void *) set + sections[i].offset;
rhughes@241
   248
		header->sections[i].type = i;
rhughes@241
   249
		header->sections[i].offset = offset;
rhughes@241
   250
		header->sections[i].size = a->size;
rhughes@241
   251
		offset += ALIGN(a->size, 4096);
rhughes@241
   252
	}
rhughes@241
   253
rhughes@241
   254
	header->sections[i].type = ~0;
rhughes@241
   255
	header->sections[i].offset = 0;
rhughes@241
   256
	header->sections[i].size = 0;
rhughes@241
   257
rhughes@241
   258
	razor_write(fd, data, sizeof data);
rhughes@241
   259
	memset(data, 0, sizeof data);
jbowes@258
   260
	for (i = 0; i < array_size; i++) {
jbowes@258
   261
		if (sections[i].type != i)
rhughes@241
   262
			continue;
jbowes@258
   263
		a = (void *) set + sections[i].offset;
rhughes@241
   264
		razor_write(fd, a->data, a->size);
rhughes@241
   265
		razor_write(fd, data, ALIGN(a->size, 4096) - a->size);
rhughes@241
   266
	}
rhughes@241
   267
rhughes@241
   268
	return 0;
rhughes@241
   269
}
rhughes@241
   270
krh@269
   271
RAZOR_EXPORT int
jbowes@258
   272
razor_set_write_to_fd(struct razor_set *set, int fd,
jbowes@258
   273
		      enum razor_repo_file_type type)
jbowes@258
   274
{
jbowes@258
   275
	switch (type) {
jbowes@258
   276
	case RAZOR_REPO_FILE_MAIN:
jbowes@258
   277
		return razor_set_write_sections_to_fd(set, fd, RAZOR_MAGIC,
jbowes@258
   278
						      razor_sections,
jbowes@258
   279
						      ARRAY_SIZE(razor_sections));
jbowes@258
   280
jbowes@258
   281
	case RAZOR_REPO_FILE_DETAILS:
jbowes@258
   282
		return razor_set_write_sections_to_fd(set, fd, RAZOR_DETAILS_MAGIC,
jbowes@258
   283
						      razor_details_sections,
jbowes@258
   284
						      ARRAY_SIZE(razor_details_sections));
jbowes@258
   285
	case RAZOR_REPO_FILE_FILES:
jbowes@258
   286
		return razor_set_write_sections_to_fd(set, fd, RAZOR_FILES_MAGIC,
jbowes@258
   287
						      razor_files_sections,
jbowes@258
   288
						      ARRAY_SIZE(razor_files_sections));
jbowes@258
   289
	default:
jbowes@258
   290
		return -1;
jbowes@258
   291
	}
jbowes@258
   292
}
jbowes@258
   293
krh@269
   294
RAZOR_EXPORT int
jbowes@258
   295
razor_set_write(struct razor_set *set, const char *filename,
jbowes@258
   296
		enum razor_repo_file_type type)
rhughes@241
   297
{
rhughes@241
   298
	int fd, status;
rhughes@241
   299
rhughes@241
   300
	fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
rhughes@241
   301
	if (fd < 0)
rhughes@241
   302
		return -1;
rhughes@241
   303
jbowes@258
   304
	status = razor_set_write_to_fd(set, fd, type);
rhughes@241
   305
	if (status) {
rhughes@241
   306
	    close(fd);
rhughes@241
   307
	    return status;
rhughes@241
   308
	}
rhughes@241
   309
rhughes@241
   310
	return close(fd);
rhughes@241
   311
}
krh@269
   312
krh@269
   313
RAZOR_EXPORT void
rhughes@241
   314
razor_build_evr(char *evr_buf, int size, const char *epoch,
rhughes@241
   315
		const char *version, const char *release)
rhughes@241
   316
{
rhughes@241
   317
	int len;
rhughes@241
   318
rhughes@241
   319
	if (!version || !*version) {
rhughes@241
   320
		*evr_buf = '\0';
rhughes@241
   321
		return;
rhughes@241
   322
	}
rhughes@241
   323
rhughes@241
   324
	if (epoch && *epoch && strcmp(epoch, "0") != 0) {
rhughes@241
   325
		len = snprintf(evr_buf, size, "%s:", epoch);
rhughes@241
   326
		evr_buf += len;
rhughes@241
   327
		size -= len;
rhughes@241
   328
	}
rhughes@241
   329
	len = snprintf(evr_buf, size, "%s", version);
rhughes@241
   330
	evr_buf += len;
rhughes@241
   331
	size -= len;
rhughes@241
   332
	if (release && *release)
rhughes@241
   333
		snprintf(evr_buf, size, "-%s", release);
rhughes@241
   334
}
rhughes@241
   335
krh@269
   336
RAZOR_EXPORT int
krh@248
   337
razor_versioncmp(const char *s1, const char *s2)
rhughes@241
   338
{
rhughes@241
   339
	const char *p1, *p2;
rhughes@241
   340
	long n1, n2;
rhughes@241
   341
	int res;
rhughes@241
   342
rhughes@241
   343
	n1 = strtol(s1, (char **) &p1, 10);
rhughes@241
   344
	n2 = strtol(s2, (char **) &p2, 10);
rhughes@241
   345
rhughes@241
   346
	/* Epoch; if one but not the other has an epoch set, default
rhughes@241
   347
	 * the epoch-less version to 0. */
rhughes@241
   348
	res = (*p1 == ':') - (*p2 == ':');
rhughes@241
   349
	if (res < 0) {
rhughes@241
   350
		n1 = 0;
rhughes@241
   351
		p1 = s1;
rhughes@241
   352
		p2++;
rhughes@241
   353
	} else if (res > 0) {
rhughes@241
   354
		p1++;
rhughes@241
   355
		n2 = 0;
rhughes@241
   356
		p2 = s2;
rhughes@241
   357
	}
rhughes@241
   358
rhughes@241
   359
	if (n1 != n2)
rhughes@241
   360
		return n1 - n2;
rhughes@241
   361
	while (*p1 && *p2) {
rhughes@241
   362
		if (*p1 != *p2)
rhughes@241
   363
			return *p1 - *p2;
rhughes@241
   364
		p1++;
rhughes@241
   365
		p2++;
rhughes@241
   366
		if (isdigit(*p1) && isdigit(*p2))
krh@248
   367
			return razor_versioncmp(p1, p2);
rhughes@241
   368
	}
rhughes@241
   369
rhughes@241
   370
	return *p1 - *p2;
rhughes@241
   371
}
rhughes@241
   372
krh@269
   373
RAZOR_EXPORT struct razor_package *
rhughes@241
   374
razor_set_get_package(struct razor_set *set, const char *package)
rhughes@241
   375
{
rhughes@241
   376
	struct razor_package_iterator *pi;
rhughes@241
   377
	struct razor_package *p;
rhughes@241
   378
	const char *name, *version, *arch;
rhughes@241
   379
rhughes@241
   380
	pi = razor_package_iterator_create(set);
rhughes@241
   381
	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
rhughes@241
   382
		if (strcmp(package, name) == 0)
rhughes@241
   383
			break;
rhughes@241
   384
	}
rhughes@241
   385
	razor_package_iterator_destroy(pi);
rhughes@241
   386
rhughes@241
   387
	return p;
rhughes@241
   388
}
rhughes@241
   389
krh@269
   390
RAZOR_EXPORT void
krh@269
   391
razor_package_get_details(struct razor_set *set,
krh@269
   392
			  struct razor_package *package,
jbowes@258
   393
			  const char **summary, const char **description,
jbowes@258
   394
			  const char **url, const char **license)
jbowes@258
   395
{
jbowes@258
   396
	const char *pool = set->details_string_pool.data;
jbowes@258
   397
jbowes@258
   398
	*summary = &pool[package->summary];
jbowes@258
   399
	*description = &pool[package->description];
jbowes@258
   400
	*url = &pool[package->url];
jbowes@258
   401
	*license = &pool[package->license];
jbowes@258
   402
}
jbowes@258
   403
krh@270
   404
RAZOR_EXPORT const char *
krh@270
   405
razor_property_relation_to_string(struct razor_property *p)
krh@270
   406
{
krh@270
   407
	switch (p->flags & RAZOR_PROPERTY_RELATION_MASK) {
krh@270
   408
	case RAZOR_PROPERTY_LESS:
krh@270
   409
		return "<";
krh@270
   410
krh@270
   411
	case RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL:
krh@270
   412
		return "<=";
krh@270
   413
krh@270
   414
	case RAZOR_PROPERTY_EQUAL:
krh@270
   415
		return "=";
krh@270
   416
krh@270
   417
	case RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL:
krh@270
   418
		return ">=";
krh@270
   419
krh@270
   420
	case RAZOR_PROPERTY_GREATER:
krh@270
   421
		return ">";
krh@270
   422
krh@270
   423
	default:
krh@270
   424
		return "?";
krh@270
   425
	}
krh@270
   426
}
krh@270
   427
krh@270
   428
RAZOR_EXPORT const char *
krh@270
   429
razor_property_type_to_string(struct razor_property *p)
krh@270
   430
{
krh@270
   431
	switch (p->flags & RAZOR_PROPERTY_TYPE_MASK) {
krh@270
   432
	case RAZOR_PROPERTY_REQUIRES:
krh@270
   433
		return "requires";
krh@270
   434
	case RAZOR_PROPERTY_PROVIDES:
krh@270
   435
		return "provides";
krh@270
   436
	case RAZOR_PROPERTY_CONFLICTS:
krh@270
   437
		return "conflicts";
krh@270
   438
	case RAZOR_PROPERTY_OBSOLETES:
krh@270
   439
		return "obsoletes";
krh@270
   440
	default:
krh@270
   441
		return NULL;
krh@270
   442
	}
krh@270
   443
}
krh@270
   444
krh@269
   445
RAZOR_EXPORT struct razor_entry *
krh@248
   446
razor_set_find_entry(struct razor_set *set,
krh@248
   447
		     struct razor_entry *dir, const char *pattern)
rhughes@241
   448
{
rhughes@241
   449
	struct razor_entry *e;
jbowes@264
   450
	const char *n, *pool = set->file_string_pool.data;
rhughes@241
   451
	int len;
rhughes@241
   452
rhughes@241
   453
	e = (struct razor_entry *) set->files.data + dir->start;
rhughes@241
   454
	do {
rhughes@241
   455
		n = pool + e->name;
rhughes@241
   456
		if (strcmp(pattern + 1, n) == 0)
rhughes@241
   457
			return e;
rhughes@241
   458
		len = strlen(n);
rhughes@241
   459
		if (e->start != 0 && strncmp(pattern + 1, n, len) == 0 &&
rhughes@241
   460
		    pattern[len + 1] == '/') {
krh@248
   461
			return razor_set_find_entry(set, e, pattern + len + 1);
rhughes@241
   462
		}
rhughes@241
   463
	} while (!((e++)->flags & RAZOR_ENTRY_LAST));
rhughes@241
   464
rhughes@241
   465
	return NULL;
rhughes@241
   466
}
rhughes@241
   467
rhughes@241
   468
static void
rhughes@241
   469
list_dir(struct razor_set *set, struct razor_entry *dir,
rhughes@241
   470
	 char *prefix, const char *pattern)
rhughes@241
   471
{
rhughes@241
   472
	struct razor_entry *e;
jbowes@274
   473
	const char *n, *pool = set->file_string_pool.data;
rhughes@241
   474
rhughes@241
   475
	e = (struct razor_entry *) set->files.data + dir->start;
rhughes@241
   476
	do {
rhughes@241
   477
		n = pool + e->name;
rhughes@241
   478
		if (pattern && pattern[0] && fnmatch(pattern, n, 0) != 0)
rhughes@241
   479
			continue;
rhughes@241
   480
		printf("%s/%s\n", prefix, n);
rhughes@241
   481
		if (e->start) {
rhughes@241
   482
			char *sub = prefix + strlen (prefix);
rhughes@241
   483
			*sub = '/';
rhughes@241
   484
			strcpy (sub + 1, n);
rhughes@241
   485
			list_dir(set, e, prefix, pattern);
rhughes@241
   486
			*sub = '\0';
rhughes@241
   487
		}
rhughes@241
   488
	} while (!((e++)->flags & RAZOR_ENTRY_LAST));
rhughes@241
   489
}
rhughes@241
   490
krh@269
   491
RAZOR_EXPORT void
rhughes@241
   492
razor_set_list_files(struct razor_set *set, const char *pattern)
rhughes@241
   493
{
rhughes@241
   494
	struct razor_entry *e;
rhughes@241
   495
	char buffer[512], *p, *base;
rhughes@241
   496
rhughes@241
   497
	if (pattern == NULL || !strcmp (pattern, "/")) {
rhughes@241
   498
		buffer[0] = '\0';
rhughes@241
   499
		list_dir(set, set->files.data, buffer, NULL);
rhughes@241
   500
		return;
rhughes@241
   501
	}
rhughes@241
   502
rhughes@241
   503
	strcpy(buffer, pattern);
krh@248
   504
	e = razor_set_find_entry(set, set->files.data, buffer);
rhughes@241
   505
	if (e && e->start > 0) {
rhughes@241
   506
		base = NULL;
rhughes@241
   507
	} else {
rhughes@241
   508
		p = strrchr(buffer, '/');
rhughes@241
   509
		if (p) {
rhughes@241
   510
			*p = '\0';
rhughes@241
   511
			base = p + 1;
rhughes@241
   512
		} else {
rhughes@241
   513
			base = NULL;
rhughes@241
   514
		}
rhughes@241
   515
	}
krh@248
   516
	e = razor_set_find_entry(set, set->files.data, buffer);
krh@283
   517
	if (e && e->start != 0)
rhughes@241
   518
		list_dir(set, e, buffer, base);
rhughes@241
   519
}
rhughes@241
   520
rhughes@241
   521
static struct list *
rhughes@241
   522
list_package_files(struct razor_set *set, struct list *r,
rhughes@241
   523
		   struct razor_entry *dir, uint32_t end,
rhughes@241
   524
		   char *prefix)
rhughes@241
   525
{
rhughes@241
   526
	struct razor_entry *e, *f, *entries;
rhughes@241
   527
	uint32_t next, file;
rhughes@241
   528
	char *pool;
rhughes@241
   529
	int len;
rhughes@241
   530
rhughes@241
   531
	entries = (struct razor_entry *) set->files.data;
jbowes@274
   532
	pool = set->file_string_pool.data;
rhughes@241
   533
rhughes@241
   534
	e = entries + dir->start;
rhughes@241
   535
	do {
rhughes@241
   536
		if (entries + r->data == e) {
rhughes@241
   537
			printf("%s/%s\n", prefix, pool + e->name);
rhughes@241
   538
			r = list_next(r);
rhughes@241
   539
			if (!r)
rhughes@241
   540
				return NULL;
rhughes@241
   541
			if (r->data >= end)
rhughes@241
   542
				return r;
rhughes@241
   543
		}
rhughes@241
   544
	} while (!((e++)->flags & RAZOR_ENTRY_LAST));
rhughes@241
   545
rhughes@241
   546
	e = entries + dir->start;
rhughes@241
   547
	do {
rhughes@241
   548
		if (e->start == 0)
rhughes@241
   549
			continue;
rhughes@241
   550
rhughes@241
   551
		if (e->flags & RAZOR_ENTRY_LAST)
rhughes@241
   552
			next = end;
rhughes@241
   553
		else {
rhughes@241
   554
			f = e + 1;
rhughes@241
   555
			while (f->start == 0 && !(f->flags & RAZOR_ENTRY_LAST))
rhughes@241
   556
				f++;
rhughes@241
   557
			if (f->start == 0)
rhughes@241
   558
				next = end;
rhughes@241
   559
			else
rhughes@241
   560
				next = f->start;
rhughes@241
   561
		}
rhughes@241
   562
rhughes@241
   563
		file = r->data;
rhughes@241
   564
		if (e->start <= file && file < next) {
rhughes@241
   565
			len = strlen(prefix);
rhughes@241
   566
			prefix[len] = '/';
rhughes@241
   567
			strcpy(prefix + len + 1, pool + e->name);
rhughes@241
   568
			r = list_package_files(set, r, e, next, prefix);
rhughes@241
   569
			prefix[len] = '\0';
rhughes@241
   570
		}
rhughes@241
   571
	} while (!((e++)->flags & RAZOR_ENTRY_LAST) && r != NULL);
rhughes@241
   572
rhughes@241
   573
	return r;
rhughes@241
   574
}
rhughes@241
   575
krh@269
   576
RAZOR_EXPORT void
rhughes@241
   577
razor_set_list_package_files(struct razor_set *set, const char *name)
rhughes@241
   578
{
rhughes@241
   579
	struct razor_package *package;
rhughes@241
   580
	struct list *r;
rhughes@241
   581
	uint32_t end;
rhughes@241
   582
	char buffer[512];
rhughes@241
   583
rhughes@241
   584
	package = razor_set_get_package(set, name);
richard@282
   585
	/* TODO: we should return the error to the caller */
richard@282
   586
	if (!package)
richard@282
   587
		return;
rhughes@241
   588
rhughes@241
   589
	r = list_first(&package->files, &set->file_pool);
rhughes@241
   590
	end = set->files.size / sizeof (struct razor_entry);
rhughes@241
   591
	buffer[0] = '\0';
rhughes@241
   592
	list_package_files(set, r, set->files.data, end, buffer);
rhughes@241
   593
}
rhughes@241
   594
rhughes@241
   595
/* The diff order matters.  We should sort the packages so that a
rhughes@241
   596
 * REMOVE of a package comes before the INSTALL, and so that all
rhughes@241
   597
 * requires for a package have been installed before the package.
rhughes@241
   598
 **/
rhughes@241
   599
krh@269
   600
RAZOR_EXPORT void
rhughes@241
   601
razor_set_diff(struct razor_set *set, struct razor_set *upstream,
krh@253
   602
	       razor_diff_callback_t callback, void *data)
rhughes@241
   603
{
rhughes@241
   604
 	struct razor_package_iterator *pi1, *pi2;
rhughes@241
   605
 	struct razor_package *p1, *p2;
rhughes@241
   606
	const char *name1, *name2, *version1, *version2, *arch1, *arch2;
rhughes@241
   607
	int res;
rhughes@241
   608
rhughes@241
   609
	pi1 = razor_package_iterator_create(set);
rhughes@241
   610
	pi2 = razor_package_iterator_create(upstream);
rhughes@241
   611
rhughes@241
   612
	razor_package_iterator_next(pi1, &p1, &name1, &version1, &arch1);
rhughes@241
   613
	razor_package_iterator_next(pi2, &p2, &name2, &version2, &arch2);
rhughes@241
   614
rhughes@241
   615
	while (p1 || p2) {
rhughes@241
   616
		if (p1 && p2) {
rhughes@241
   617
			res = strcmp(name1, name2);
rhughes@241
   618
			if (res == 0)
krh@248
   619
				res = razor_versioncmp(version1, version2);
rhughes@241
   620
		} else {
rhughes@241
   621
			res = 0;
rhughes@241
   622
		}
rhughes@241
   623
rhughes@241
   624
		if (p2 == NULL || res < 0)
krh@253
   625
			callback(RAZOR_DIFF_ACTION_REMOVE,
krh@253
   626
				 p1, name1, version1, arch1, data);
rhughes@241
   627
		else if (p1 == NULL || res > 0)
krh@253
   628
			callback(RAZOR_DIFF_ACTION_ADD,
krh@253
   629
				 p2, name2, version2, arch2, data);
rhughes@241
   630
rhughes@241
   631
		if (p1 != NULL && res <= 0)
rhughes@241
   632
			razor_package_iterator_next(pi1, &p1,
rhughes@241
   633
						    &name1, &version1, &arch1);
rhughes@241
   634
		if (p2 != NULL && res >= 0)
rhughes@241
   635
			razor_package_iterator_next(pi2, &p2,
rhughes@241
   636
						    &name2, &version2, &arch2);
rhughes@241
   637
	}
rhughes@241
   638
rhughes@241
   639
	razor_package_iterator_destroy(pi1);
rhughes@241
   640
	razor_package_iterator_destroy(pi2);
rhughes@241
   641
}
krh@254
   642
krh@254
   643
static void
krh@254
   644
add_new_package(enum razor_diff_action action,
krh@254
   645
		struct razor_package *package,
krh@254
   646
		const char *name,
krh@254
   647
		const char *version,
krh@254
   648
		const char *arch,
krh@254
   649
		void *data)
krh@254
   650
{
krh@254
   651
	if (action == RAZOR_DIFF_ACTION_ADD)
krh@254
   652
		razor_package_query_add_package(data, package);
krh@254
   653
}
krh@254
   654
krh@269
   655
RAZOR_EXPORT struct razor_package_iterator *
krh@254
   656
razor_set_create_remove_iterator(struct razor_set *set,
krh@254
   657
				 struct razor_set *next)
krh@254
   658
{
krh@254
   659
	struct razor_package_query *query;
krh@254
   660
	struct razor_package_iterator *pi;
krh@254
   661
krh@254
   662
	query = razor_package_query_create(set);
krh@254
   663
	razor_set_diff(next, set, add_new_package, query);
krh@254
   664
krh@254
   665
	pi = razor_package_query_finish(query);
krh@254
   666
krh@254
   667
	/* FIXME: We need to figure out the right install order here,
krh@254
   668
	 * so the post and pre scripts can run. */
krh@254
   669
krh@254
   670
	/* sort */
krh@254
   671
krh@254
   672
	return pi;
krh@254
   673
}
krh@254
   674
krh@269
   675
RAZOR_EXPORT struct razor_package_iterator *
krh@254
   676
razor_set_create_install_iterator(struct razor_set *set,
krh@254
   677
				  struct razor_set *next)
krh@254
   678
{
krh@254
   679
	struct razor_package_query *query;
krh@254
   680
	struct razor_package_iterator *pi;
krh@254
   681
krh@254
   682
	query = razor_package_query_create(next);
krh@254
   683
	razor_set_diff(set, next, add_new_package, query);
krh@254
   684
krh@254
   685
	pi = razor_package_query_finish(query);
krh@254
   686
krh@254
   687
	/* FIXME: We need to figure out the right install order here,
krh@254
   688
	 * so the post and pre scripts can run. */
krh@254
   689
krh@254
   690
	/* sort */
krh@254
   691
krh@254
   692
	return pi;
krh@254
   693
}