librazor/iterator.c
author J. Ali Harlow <ali@juiblex.co.uk>
Thu Oct 01 19:54:03 2009 +0100 (2009-10-01)
changeset 387 ef9237601f24
parent 351 48b0adfe3059
child 438 fab0b8a61dcb
permissions -rw-r--r--
Fix bug causing multiple installs to abort
krh@248
     1
/*
krh@248
     2
 * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
krh@248
     3
 * Copyright (C) 2008  Red Hat, Inc
ali@351
     4
 * Copyright (C) 2009  J. Ali Harlow <ali@juiblex.co.uk>
krh@248
     5
 *
krh@248
     6
 * This program is free software; you can redistribute it and/or modify
krh@248
     7
 * it under the terms of the GNU General Public License as published by
krh@248
     8
 * the Free Software Foundation; either version 2 of the License, or
krh@248
     9
 * (at your option) any later version.
krh@248
    10
 *
krh@248
    11
 * This program is distributed in the hope that it will be useful,
krh@248
    12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
krh@248
    13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
krh@248
    14
 * GNU General Public License for more details.
krh@248
    15
 *
krh@248
    16
 * You should have received a copy of the GNU General Public License along
krh@248
    17
 * with this program; if not, write to the Free Software Foundation, Inc.,
krh@248
    18
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
krh@248
    19
 */
krh@248
    20
krh@248
    21
#define _GNU_SOURCE
krh@248
    22
richard@302
    23
#include <stdarg.h>
krh@248
    24
#include <string.h>
richard@301
    25
#include <assert.h>
richard@301
    26
krh@248
    27
#include "razor-internal.h"
krh@248
    28
#include "razor.h"
krh@248
    29
krh@248
    30
static struct razor_package_iterator *
krh@248
    31
razor_package_iterator_create_with_index(struct razor_set *set,
krh@248
    32
					 struct list *index)
krh@248
    33
{
krh@248
    34
	struct razor_package_iterator *pi;
krh@248
    35
krh@248
    36
	pi = zalloc(sizeof *pi);
krh@248
    37
	pi->set = set;
krh@248
    38
	pi->index = index;
krh@248
    39
krh@248
    40
	return pi;
krh@248
    41
}
krh@248
    42
jbowes@278
    43
static struct razor_package_iterator *
jbowes@278
    44
razor_package_iterator_create_empty(struct razor_set *set)
jbowes@278
    45
{
jbowes@278
    46
	struct razor_package_iterator *pi;
jbowes@278
    47
	return zalloc(sizeof *pi);
jbowes@278
    48
}
jbowes@278
    49
krh@269
    50
RAZOR_EXPORT struct razor_package_iterator *
krh@248
    51
razor_package_iterator_create(struct razor_set *set)
krh@248
    52
{
krh@248
    53
	struct razor_package_iterator *pi;
krh@248
    54
richard@301
    55
	assert (set != NULL);
richard@301
    56
krh@248
    57
	pi = zalloc(sizeof *pi);
krh@248
    58
	pi->set = set;
krh@248
    59
	pi->end = set->packages.data + set->packages.size;
krh@248
    60
	pi->package = set->packages.data;
krh@248
    61
krh@248
    62
	return pi;
krh@248
    63
}
krh@248
    64
krh@269
    65
RAZOR_EXPORT void
krh@248
    66
razor_package_iterator_init_for_property(struct razor_package_iterator *pi,
krh@248
    67
					 struct razor_set *set,
krh@248
    68
					 struct razor_property *property)
krh@248
    69
{
richard@301
    70
	assert (pi != NULL);
richard@301
    71
	assert (set != NULL);
richard@301
    72
	assert (property != NULL);
richard@301
    73
krh@248
    74
	memset(pi, 0, sizeof *pi);
krh@248
    75
	pi->set = set;
krh@248
    76
	pi->index = list_first(&property->packages, &set->package_pool);
krh@248
    77
}
krh@248
    78
krh@269
    79
RAZOR_EXPORT struct razor_package_iterator *
krh@248
    80
razor_package_iterator_create_for_property(struct razor_set *set,
krh@248
    81
					   struct razor_property *property)
krh@248
    82
{
krh@248
    83
	struct list *index;
krh@248
    84
richard@301
    85
	assert (set != NULL);
richard@301
    86
	assert (property != NULL);
richard@301
    87
krh@248
    88
	index = list_first(&property->packages, &set->package_pool);
krh@248
    89
	return razor_package_iterator_create_with_index(set, index);
krh@248
    90
}
krh@248
    91
krh@269
    92
RAZOR_EXPORT struct razor_package_iterator *
krh@248
    93
razor_package_iterator_create_for_file(struct razor_set *set,
krh@248
    94
				       const char *filename)
krh@248
    95
{
krh@248
    96
	struct razor_entry *entry;
krh@248
    97
	struct list *index;
krh@248
    98
richard@301
    99
	assert (set != NULL);
richard@301
   100
	assert (filename != NULL);
richard@301
   101
krh@248
   102
	entry = razor_set_find_entry(set, set->files.data, filename);
krh@248
   103
	if (entry == NULL)
jbowes@278
   104
		return razor_package_iterator_create_empty(set);
krh@248
   105
krh@248
   106
	index = list_first(&entry->packages, &set->package_pool);
krh@248
   107
	return razor_package_iterator_create_with_index(set, index);
krh@248
   108
}
krh@248
   109
richard@302
   110
/**
richard@302
   111
 * razor_package_iterator_next:
richard@302
   112
 * @pi: a %razor_package_iterator
richard@302
   113
 * @package: a %razor_package
richard@302
   114
 *
richard@302
   115
 * Gets the next iteratr along with any vararg data.
krh@308
   116
 * The vararg must be terminated with %RAZOR_DETAIL_LAST.
richard@302
   117
 *
richard@307
   118
 * Example: razor_package_iterator_next (pi, package,
richard@307
   119
 *					 RAZOR_DETAIL_NAME, &name,
richard@307
   120
 *					 RAZOR_DETAIL_LAST);
richard@302
   121
 **/
krh@269
   122
RAZOR_EXPORT int
krh@248
   123
razor_package_iterator_next(struct razor_package_iterator *pi,
richard@302
   124
			    struct razor_package **package, ...)
krh@248
   125
{
richard@302
   126
	va_list args;
krh@248
   127
	int valid;
krh@248
   128
	struct razor_package *p, *packages;
krh@248
   129
richard@301
   130
	assert (pi != NULL);
richard@301
   131
krh@248
   132
	if (pi->package) {
krh@248
   133
		p = pi->package++;
krh@248
   134
		valid = p < pi->end;
krh@248
   135
	} else if (pi->index) {
krh@248
   136
		packages = pi->set->packages.data;
krh@248
   137
		p = &packages[pi->index->data];
krh@248
   138
		pi->index = list_next(pi->index);
krh@248
   139
		valid = 1;
krh@248
   140
	} else
krh@248
   141
		valid = 0;
krh@248
   142
richard@302
   143
	if (valid == 0) {
krh@248
   144
		*package = NULL;
richard@302
   145
		goto out;
krh@248
   146
	}
krh@248
   147
richard@302
   148
	*package = p;
richard@302
   149
richard@302
   150
	va_start(args, NULL);
richard@302
   151
	razor_package_get_details_varg (pi->set, p, args);
richard@302
   152
	va_end (args);
richard@302
   153
out:
krh@248
   154
	return valid;
krh@248
   155
}
krh@248
   156
krh@269
   157
RAZOR_EXPORT void
krh@248
   158
razor_package_iterator_destroy(struct razor_package_iterator *pi)
krh@248
   159
{
richard@301
   160
	assert (pi != NULL);
richard@301
   161
krh@248
   162
	if (pi->free_index)
krh@248
   163
		free(pi->index);
krh@248
   164
krh@248
   165
	free(pi);
krh@248
   166
}
krh@248
   167
krh@269
   168
RAZOR_EXPORT struct razor_property_iterator *
krh@248
   169
razor_property_iterator_create(struct razor_set *set,
krh@248
   170
			       struct razor_package *package)
krh@248
   171
{
krh@248
   172
	struct razor_property_iterator *pi;
krh@248
   173
richard@301
   174
	assert (set != NULL);
richard@301
   175
krh@248
   176
	pi = zalloc(sizeof *pi);
krh@248
   177
	pi->set = set;
krh@248
   178
krh@248
   179
	if (package) {
krh@248
   180
		pi->index = list_first(&package->properties,
krh@248
   181
				       &set->property_pool);
krh@248
   182
	} else {
krh@248
   183
		pi->property = set->properties.data;
krh@248
   184
		pi->end = set->properties.data + set->properties.size;
krh@248
   185
	}
krh@248
   186
krh@248
   187
	return pi;
krh@248
   188
}
krh@248
   189
krh@269
   190
RAZOR_EXPORT int
krh@248
   191
razor_property_iterator_next(struct razor_property_iterator *pi,
krh@248
   192
			     struct razor_property **property,
krh@248
   193
			     const char **name,
krh@248
   194
			     uint32_t *flags,
krh@248
   195
			     const char **version)
krh@248
   196
{
krh@248
   197
	char *pool;
krh@248
   198
	int valid;
krh@248
   199
	struct razor_property *p, *properties;
krh@248
   200
richard@301
   201
	assert (pi != NULL);
richard@301
   202
krh@248
   203
	if (pi->property) {
krh@248
   204
		p = pi->property++;
krh@248
   205
		valid = p < pi->end;
krh@248
   206
	} else if (pi->index) {
krh@248
   207
		properties = pi->set->properties.data;
krh@248
   208
		p = &properties[pi->index->data];
krh@248
   209
		pi->index = list_next(pi->index);
krh@248
   210
		valid = 1;
krh@248
   211
	} else
krh@248
   212
		valid = 0;
krh@248
   213
krh@248
   214
	if (valid) {
krh@248
   215
		pool = pi->set->string_pool.data;
krh@248
   216
		*property = p;
krh@248
   217
		*name = &pool[p->name];
krh@248
   218
		*flags = p->flags;
krh@248
   219
		*version = &pool[p->version];
krh@248
   220
	} else {
krh@248
   221
		*property = NULL;
krh@248
   222
	}
krh@248
   223
krh@248
   224
	return valid;
krh@248
   225
}
krh@248
   226
krh@269
   227
RAZOR_EXPORT void
krh@248
   228
razor_property_iterator_destroy(struct razor_property_iterator *pi)
krh@248
   229
{
krh@248
   230
	free(pi);
krh@248
   231
}
krh@248
   232
ali@351
   233
RAZOR_EXPORT struct razor_file_iterator *
ali@377
   234
razor_file_iterator_create(struct razor_set *set, struct razor_package *package,
ali@377
   235
			   int post_order)
ali@351
   236
{
ali@351
   237
	struct razor_file_iterator *fi;
ali@351
   238
ali@351
   239
	assert (set != NULL);
ali@351
   240
	assert (package != NULL);
ali@351
   241
ali@351
   242
	fi = zalloc(sizeof *fi);
ali@351
   243
	fi->set = set;
ali@377
   244
	fi->post_order = post_order;
ali@377
   245
	if (post_order)
ali@377
   246
		fi->index = list_last(&package->files, &set->file_pool);
ali@377
   247
	else
ali@377
   248
		fi->index = list_first(&package->files, &set->file_pool);
ali@351
   249
	array_init(&fi->path);
ali@351
   250
ali@351
   251
	return fi;
ali@351
   252
}
ali@351
   253
ali@351
   254
RAZOR_EXPORT int
ali@351
   255
razor_file_iterator_next(struct razor_file_iterator *fi,
ali@351
   256
			 const char **name)
ali@351
   257
{
ali@351
   258
	struct razor_entry *e, *dir, *entries;
ali@351
   259
	char *pool, *s, *f;
ali@351
   260
ali@351
   261
	assert (fi != NULL);
ali@351
   262
ali@351
   263
	if (!fi->index) {
ali@351
   264
		*name = NULL;
ali@351
   265
		return 0;
ali@351
   266
	}
ali@351
   267
ali@351
   268
	entries = (struct razor_entry *) fi->set->files.data;
ali@351
   269
	pool = fi->set->file_string_pool.data;
ali@351
   270
ali@351
   271
	dir = entries;
ali@351
   272
	fi->path.size = 0;
ali@351
   273
	for(;;) {
ali@351
   274
		e = dir;
ali@351
   275
		do {
ali@351
   276
			if (entries + fi->index->data == e) {
ali@351
   277
				f = pool + e->name;
ali@351
   278
				s = array_add(&fi->path, strlen(f) + 1);
ali@351
   279
				strcpy(s, f);
ali@351
   280
				if (fi->path.size == 1) {
ali@351
   281
					array_add(&fi->path, 1);
ali@351
   282
					strcpy(fi->path.data, "/");
ali@351
   283
				}
ali@351
   284
				*name = fi->path.data;
ali@377
   285
				if (fi->post_order)
ali@377
   286
					fi->index = list_prev(fi->index);
ali@377
   287
				else
ali@377
   288
					fi->index = list_next(fi->index);
ali@351
   289
				return 1;
ali@351
   290
			}
ali@351
   291
		} while (!((e++)->flags & RAZOR_ENTRY_LAST));
ali@351
   292
		for(e--; e >= dir; e--)
ali@351
   293
			if (e->start && fi->index->data >= e->start)
ali@351
   294
				break;
ali@351
   295
		if (e < dir)
ali@351
   296
			break;
ali@351
   297
		f = pool + e->name;
ali@351
   298
		s = array_add(&fi->path, strlen(f) + 1);
ali@351
   299
		strcpy(s, f);
ali@351
   300
		s += strlen(f);
ali@351
   301
		*s = '/';
ali@351
   302
		dir = entries + e->start;
ali@351
   303
	}
ali@351
   304
ali@351
   305
	printf("file_iterator_next: Failed to find file %d\n",fi->index->data);
ali@351
   306
	*name = NULL;
ali@351
   307
	return 0;
ali@351
   308
}
ali@351
   309
ali@351
   310
RAZOR_EXPORT void razor_file_iterator_destroy(struct razor_file_iterator *fi)
ali@351
   311
{
ali@351
   312
	assert (fi != NULL);
ali@351
   313
ali@351
   314
	array_release(&fi->path);
ali@351
   315
	free(fi);
ali@351
   316
}
ali@351
   317
krh@248
   318
struct razor_package_query {
krh@248
   319
	struct razor_set *set;
krh@248
   320
	char *vector;
krh@248
   321
	int count;
krh@248
   322
};
krh@248
   323
krh@269
   324
RAZOR_EXPORT struct razor_package_query *
krh@248
   325
razor_package_query_create(struct razor_set *set)
krh@248
   326
{
krh@248
   327
	struct razor_package_query *pq;
krh@248
   328
	int count;
krh@248
   329
richard@301
   330
	assert (set != NULL);
richard@301
   331
krh@248
   332
	pq = zalloc(sizeof *pq);
krh@248
   333
	pq->set = set;
krh@248
   334
	count = set->packages.size / sizeof(struct razor_package);
krh@248
   335
	pq->vector = zalloc(count * sizeof(char));
krh@248
   336
krh@248
   337
	return pq;
krh@248
   338
}
krh@248
   339
krh@269
   340
RAZOR_EXPORT void
krh@248
   341
razor_package_query_add_package(struct razor_package_query *pq,
krh@248
   342
				struct razor_package *p)
krh@248
   343
{
krh@248
   344
	struct razor_package *packages;
krh@248
   345
richard@301
   346
	assert (pq != NULL);
richard@301
   347
	assert (p != NULL);
richard@301
   348
krh@248
   349
	packages = pq->set->packages.data;
krh@248
   350
	pq->count += pq->vector[p - packages] ^ 1;
krh@248
   351
	pq->vector[p - packages] = 1;
krh@248
   352
}
krh@248
   353
krh@269
   354
RAZOR_EXPORT void
krh@248
   355
razor_package_query_add_iterator(struct razor_package_query *pq,
krh@248
   356
				 struct razor_package_iterator *pi)
krh@248
   357
{
krh@248
   358
	struct razor_package *packages, *p;
krh@248
   359
richard@301
   360
	assert (pq != NULL);
richard@301
   361
	assert (pi != NULL);
richard@301
   362
krh@248
   363
	packages = pq->set->packages.data;
richard@307
   364
	while (razor_package_iterator_next(pi, &p, RAZOR_DETAIL_LAST)) {
krh@248
   365
		pq->count += pq->vector[p - packages] ^ 1;
krh@248
   366
		pq->vector[p - packages] = 1;
krh@248
   367
	}
krh@248
   368
}
krh@248
   369
krh@269
   370
RAZOR_EXPORT struct razor_package_iterator *
krh@248
   371
razor_package_query_finish(struct razor_package_query *pq)
krh@248
   372
{
krh@248
   373
	struct razor_package_iterator *pi;
krh@248
   374
	struct razor_set *set;
krh@248
   375
	struct list *index;
krh@251
   376
	int i, j;
krh@248
   377
richard@301
   378
	assert (pq != NULL);
richard@301
   379
krh@248
   380
	set = pq->set;
krh@251
   381
	if (pq->count > 0)
krh@251
   382
		index = zalloc(pq->count * sizeof *index);
krh@251
   383
	else
krh@251
   384
		index = NULL;
krh@248
   385
krh@267
   386
	for (i = 0, j = 0; j < pq->count; i++) {
krh@248
   387
		if (!pq->vector[i])
krh@248
   388
			continue;
krh@248
   389
krh@248
   390
		index[j].data = i;
krh@248
   391
		if (j == pq->count - 1)
krh@248
   392
			index[j].flags = 0x80;
krh@248
   393
		j++;
krh@248
   394
	}
krh@248
   395
krh@251
   396
	free(pq->vector);
krh@248
   397
	free(pq);
krh@248
   398
krh@248
   399
	pi = razor_package_iterator_create_with_index(set, index);
krh@248
   400
	pi->free_index = 1;
krh@248
   401
krh@248
   402
	return pi;
krh@248
   403
}