librazor/iterator.c
author J. Ali Harlow <ali@juiblex.co.uk>
Thu Oct 09 17:27:41 2014 +0100 (2014-10-09)
changeset 455 df914f383f5c
parent 438 fab0b8a61dcb
child 458 3f841a46eab5
permissions -rw-r--r--
Support downloading from local repository even without libcurl

Using the --url option of the razor executable, it is possible
to specify a yum repository on the local machine (eg., on installation
media) and import from there, eg.,:

C> razor --url file:///d:/ import-yum

This will be handled by libcurl if available but if not, an internal
copy routine will be used.

Note that if Microsoft's KTM implementation of atomic transactions is
used, then the current directory must support atomic transactions
(also improve error messages for this, and other, cases).
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
ali@438
    23
#include "config.h"
richard@302
    24
#include <stdarg.h>
krh@248
    25
#include <string.h>
richard@301
    26
#include <assert.h>
ali@442
    27
#include <stdio.h>
richard@301
    28
krh@248
    29
#include "razor-internal.h"
krh@248
    30
#include "razor.h"
krh@248
    31
krh@248
    32
static struct razor_package_iterator *
krh@248
    33
razor_package_iterator_create_with_index(struct razor_set *set,
krh@248
    34
					 struct list *index)
krh@248
    35
{
krh@248
    36
	struct razor_package_iterator *pi;
krh@248
    37
krh@248
    38
	pi = zalloc(sizeof *pi);
krh@248
    39
	pi->set = set;
krh@248
    40
	pi->index = index;
krh@248
    41
krh@248
    42
	return pi;
krh@248
    43
}
krh@248
    44
jbowes@278
    45
static struct razor_package_iterator *
jbowes@278
    46
razor_package_iterator_create_empty(struct razor_set *set)
jbowes@278
    47
{
jbowes@278
    48
	struct razor_package_iterator *pi;
jbowes@278
    49
	return zalloc(sizeof *pi);
jbowes@278
    50
}
jbowes@278
    51
krh@269
    52
RAZOR_EXPORT struct razor_package_iterator *
krh@248
    53
razor_package_iterator_create(struct razor_set *set)
krh@248
    54
{
krh@248
    55
	struct razor_package_iterator *pi;
krh@248
    56
richard@301
    57
	assert (set != NULL);
richard@301
    58
krh@248
    59
	pi = zalloc(sizeof *pi);
krh@248
    60
	pi->set = set;
krh@248
    61
	pi->end = set->packages.data + set->packages.size;
krh@248
    62
	pi->package = set->packages.data;
krh@248
    63
krh@248
    64
	return pi;
krh@248
    65
}
krh@248
    66
krh@269
    67
RAZOR_EXPORT void
krh@248
    68
razor_package_iterator_init_for_property(struct razor_package_iterator *pi,
krh@248
    69
					 struct razor_set *set,
krh@248
    70
					 struct razor_property *property)
krh@248
    71
{
richard@301
    72
	assert (pi != NULL);
richard@301
    73
	assert (set != NULL);
richard@301
    74
	assert (property != NULL);
richard@301
    75
krh@248
    76
	memset(pi, 0, sizeof *pi);
krh@248
    77
	pi->set = set;
krh@248
    78
	pi->index = list_first(&property->packages, &set->package_pool);
krh@248
    79
}
krh@248
    80
krh@269
    81
RAZOR_EXPORT struct razor_package_iterator *
krh@248
    82
razor_package_iterator_create_for_property(struct razor_set *set,
krh@248
    83
					   struct razor_property *property)
krh@248
    84
{
krh@248
    85
	struct list *index;
krh@248
    86
richard@301
    87
	assert (set != NULL);
richard@301
    88
	assert (property != NULL);
richard@301
    89
krh@248
    90
	index = list_first(&property->packages, &set->package_pool);
krh@248
    91
	return razor_package_iterator_create_with_index(set, index);
krh@248
    92
}
krh@248
    93
krh@269
    94
RAZOR_EXPORT struct razor_package_iterator *
krh@248
    95
razor_package_iterator_create_for_file(struct razor_set *set,
krh@248
    96
				       const char *filename)
krh@248
    97
{
krh@248
    98
	struct razor_entry *entry;
krh@248
    99
	struct list *index;
krh@248
   100
richard@301
   101
	assert (set != NULL);
richard@301
   102
	assert (filename != NULL);
richard@301
   103
krh@248
   104
	entry = razor_set_find_entry(set, set->files.data, filename);
krh@248
   105
	if (entry == NULL)
jbowes@278
   106
		return razor_package_iterator_create_empty(set);
krh@248
   107
krh@248
   108
	index = list_first(&entry->packages, &set->package_pool);
krh@248
   109
	return razor_package_iterator_create_with_index(set, index);
krh@248
   110
}
krh@248
   111
richard@302
   112
/**
richard@302
   113
 * razor_package_iterator_next:
richard@302
   114
 * @pi: a %razor_package_iterator
richard@302
   115
 * @package: a %razor_package
richard@302
   116
 *
richard@302
   117
 * Gets the next iteratr along with any vararg data.
krh@308
   118
 * The vararg must be terminated with %RAZOR_DETAIL_LAST.
richard@302
   119
 *
richard@307
   120
 * Example: razor_package_iterator_next (pi, package,
richard@307
   121
 *					 RAZOR_DETAIL_NAME, &name,
richard@307
   122
 *					 RAZOR_DETAIL_LAST);
richard@302
   123
 **/
krh@269
   124
RAZOR_EXPORT int
krh@248
   125
razor_package_iterator_next(struct razor_package_iterator *pi,
richard@302
   126
			    struct razor_package **package, ...)
krh@248
   127
{
richard@302
   128
	va_list args;
krh@248
   129
	int valid;
krh@248
   130
	struct razor_package *p, *packages;
krh@248
   131
richard@301
   132
	assert (pi != NULL);
richard@301
   133
krh@248
   134
	if (pi->package) {
krh@248
   135
		p = pi->package++;
krh@248
   136
		valid = p < pi->end;
krh@248
   137
	} else if (pi->index) {
krh@248
   138
		packages = pi->set->packages.data;
krh@248
   139
		p = &packages[pi->index->data];
krh@248
   140
		pi->index = list_next(pi->index);
krh@248
   141
		valid = 1;
krh@248
   142
	} else
krh@248
   143
		valid = 0;
krh@248
   144
richard@302
   145
	if (valid == 0) {
krh@248
   146
		*package = NULL;
richard@302
   147
		goto out;
krh@248
   148
	}
krh@248
   149
richard@302
   150
	*package = p;
richard@302
   151
richard@302
   152
	va_start(args, NULL);
richard@302
   153
	razor_package_get_details_varg (pi->set, p, args);
richard@302
   154
	va_end (args);
richard@302
   155
out:
krh@248
   156
	return valid;
krh@248
   157
}
krh@248
   158
krh@269
   159
RAZOR_EXPORT void
krh@248
   160
razor_package_iterator_destroy(struct razor_package_iterator *pi)
krh@248
   161
{
richard@301
   162
	assert (pi != NULL);
richard@301
   163
krh@248
   164
	if (pi->free_index)
krh@248
   165
		free(pi->index);
krh@248
   166
krh@248
   167
	free(pi);
krh@248
   168
}
krh@248
   169
krh@269
   170
RAZOR_EXPORT struct razor_property_iterator *
krh@248
   171
razor_property_iterator_create(struct razor_set *set,
krh@248
   172
			       struct razor_package *package)
krh@248
   173
{
krh@248
   174
	struct razor_property_iterator *pi;
krh@248
   175
richard@301
   176
	assert (set != NULL);
richard@301
   177
krh@248
   178
	pi = zalloc(sizeof *pi);
krh@248
   179
	pi->set = set;
krh@248
   180
krh@248
   181
	if (package) {
krh@248
   182
		pi->index = list_first(&package->properties,
krh@248
   183
				       &set->property_pool);
krh@248
   184
	} else {
krh@248
   185
		pi->property = set->properties.data;
krh@248
   186
		pi->end = set->properties.data + set->properties.size;
krh@248
   187
	}
krh@248
   188
krh@248
   189
	return pi;
krh@248
   190
}
krh@248
   191
krh@269
   192
RAZOR_EXPORT int
krh@248
   193
razor_property_iterator_next(struct razor_property_iterator *pi,
krh@248
   194
			     struct razor_property **property,
krh@248
   195
			     const char **name,
krh@248
   196
			     uint32_t *flags,
krh@248
   197
			     const char **version)
krh@248
   198
{
krh@248
   199
	char *pool;
krh@248
   200
	int valid;
krh@248
   201
	struct razor_property *p, *properties;
krh@248
   202
richard@301
   203
	assert (pi != NULL);
richard@301
   204
krh@248
   205
	if (pi->property) {
krh@248
   206
		p = pi->property++;
krh@248
   207
		valid = p < pi->end;
krh@248
   208
	} else if (pi->index) {
krh@248
   209
		properties = pi->set->properties.data;
krh@248
   210
		p = &properties[pi->index->data];
krh@248
   211
		pi->index = list_next(pi->index);
krh@248
   212
		valid = 1;
krh@248
   213
	} else
krh@248
   214
		valid = 0;
krh@248
   215
krh@248
   216
	if (valid) {
krh@248
   217
		pool = pi->set->string_pool.data;
krh@248
   218
		*property = p;
krh@248
   219
		*name = &pool[p->name];
krh@248
   220
		*flags = p->flags;
krh@248
   221
		*version = &pool[p->version];
krh@248
   222
	} else {
krh@248
   223
		*property = NULL;
krh@248
   224
	}
krh@248
   225
krh@248
   226
	return valid;
krh@248
   227
}
krh@248
   228
krh@269
   229
RAZOR_EXPORT void
krh@248
   230
razor_property_iterator_destroy(struct razor_property_iterator *pi)
krh@248
   231
{
krh@248
   232
	free(pi);
krh@248
   233
}
krh@248
   234
ali@351
   235
RAZOR_EXPORT struct razor_file_iterator *
ali@377
   236
razor_file_iterator_create(struct razor_set *set, struct razor_package *package,
ali@377
   237
			   int post_order)
ali@351
   238
{
ali@351
   239
	struct razor_file_iterator *fi;
ali@351
   240
ali@351
   241
	assert (set != NULL);
ali@351
   242
	assert (package != NULL);
ali@351
   243
ali@351
   244
	fi = zalloc(sizeof *fi);
ali@351
   245
	fi->set = set;
ali@377
   246
	fi->post_order = post_order;
ali@377
   247
	if (post_order)
ali@377
   248
		fi->index = list_last(&package->files, &set->file_pool);
ali@377
   249
	else
ali@377
   250
		fi->index = list_first(&package->files, &set->file_pool);
ali@351
   251
	array_init(&fi->path);
ali@351
   252
ali@351
   253
	return fi;
ali@351
   254
}
ali@351
   255
ali@351
   256
RAZOR_EXPORT int
ali@351
   257
razor_file_iterator_next(struct razor_file_iterator *fi,
ali@351
   258
			 const char **name)
ali@351
   259
{
ali@351
   260
	struct razor_entry *e, *dir, *entries;
ali@351
   261
	char *pool, *s, *f;
ali@351
   262
ali@351
   263
	assert (fi != NULL);
ali@351
   264
ali@351
   265
	if (!fi->index) {
ali@351
   266
		*name = NULL;
ali@351
   267
		return 0;
ali@351
   268
	}
ali@351
   269
ali@351
   270
	entries = (struct razor_entry *) fi->set->files.data;
ali@351
   271
	pool = fi->set->file_string_pool.data;
ali@351
   272
ali@351
   273
	dir = entries;
ali@351
   274
	fi->path.size = 0;
ali@351
   275
	for(;;) {
ali@351
   276
		e = dir;
ali@351
   277
		do {
ali@351
   278
			if (entries + fi->index->data == e) {
ali@351
   279
				f = pool + e->name;
ali@351
   280
				s = array_add(&fi->path, strlen(f) + 1);
ali@351
   281
				strcpy(s, f);
ali@351
   282
				if (fi->path.size == 1) {
ali@351
   283
					array_add(&fi->path, 1);
ali@351
   284
					strcpy(fi->path.data, "/");
ali@351
   285
				}
ali@351
   286
				*name = fi->path.data;
ali@377
   287
				if (fi->post_order)
ali@377
   288
					fi->index = list_prev(fi->index);
ali@377
   289
				else
ali@377
   290
					fi->index = list_next(fi->index);
ali@351
   291
				return 1;
ali@351
   292
			}
ali@351
   293
		} while (!((e++)->flags & RAZOR_ENTRY_LAST));
ali@351
   294
		for(e--; e >= dir; e--)
ali@351
   295
			if (e->start && fi->index->data >= e->start)
ali@351
   296
				break;
ali@351
   297
		if (e < dir)
ali@351
   298
			break;
ali@351
   299
		f = pool + e->name;
ali@351
   300
		s = array_add(&fi->path, strlen(f) + 1);
ali@351
   301
		strcpy(s, f);
ali@351
   302
		s += strlen(f);
ali@351
   303
		*s = '/';
ali@351
   304
		dir = entries + e->start;
ali@351
   305
	}
ali@351
   306
ali@351
   307
	printf("file_iterator_next: Failed to find file %d\n",fi->index->data);
ali@351
   308
	*name = NULL;
ali@351
   309
	return 0;
ali@351
   310
}
ali@351
   311
ali@351
   312
RAZOR_EXPORT void razor_file_iterator_destroy(struct razor_file_iterator *fi)
ali@351
   313
{
ali@351
   314
	assert (fi != NULL);
ali@351
   315
ali@351
   316
	array_release(&fi->path);
ali@351
   317
	free(fi);
ali@351
   318
}
ali@351
   319
krh@248
   320
struct razor_package_query {
krh@248
   321
	struct razor_set *set;
krh@248
   322
	char *vector;
krh@248
   323
	int count;
krh@248
   324
};
krh@248
   325
krh@269
   326
RAZOR_EXPORT struct razor_package_query *
krh@248
   327
razor_package_query_create(struct razor_set *set)
krh@248
   328
{
krh@248
   329
	struct razor_package_query *pq;
krh@248
   330
	int count;
krh@248
   331
richard@301
   332
	assert (set != NULL);
richard@301
   333
krh@248
   334
	pq = zalloc(sizeof *pq);
krh@248
   335
	pq->set = set;
krh@248
   336
	count = set->packages.size / sizeof(struct razor_package);
krh@248
   337
	pq->vector = zalloc(count * sizeof(char));
krh@248
   338
krh@248
   339
	return pq;
krh@248
   340
}
krh@248
   341
krh@269
   342
RAZOR_EXPORT void
krh@248
   343
razor_package_query_add_package(struct razor_package_query *pq,
krh@248
   344
				struct razor_package *p)
krh@248
   345
{
krh@248
   346
	struct razor_package *packages;
krh@248
   347
richard@301
   348
	assert (pq != NULL);
richard@301
   349
	assert (p != NULL);
richard@301
   350
krh@248
   351
	packages = pq->set->packages.data;
krh@248
   352
	pq->count += pq->vector[p - packages] ^ 1;
krh@248
   353
	pq->vector[p - packages] = 1;
krh@248
   354
}
krh@248
   355
krh@269
   356
RAZOR_EXPORT void
krh@248
   357
razor_package_query_add_iterator(struct razor_package_query *pq,
krh@248
   358
				 struct razor_package_iterator *pi)
krh@248
   359
{
krh@248
   360
	struct razor_package *packages, *p;
krh@248
   361
richard@301
   362
	assert (pq != NULL);
richard@301
   363
	assert (pi != NULL);
richard@301
   364
krh@248
   365
	packages = pq->set->packages.data;
richard@307
   366
	while (razor_package_iterator_next(pi, &p, RAZOR_DETAIL_LAST)) {
krh@248
   367
		pq->count += pq->vector[p - packages] ^ 1;
krh@248
   368
		pq->vector[p - packages] = 1;
krh@248
   369
	}
krh@248
   370
}
krh@248
   371
krh@269
   372
RAZOR_EXPORT struct razor_package_iterator *
krh@248
   373
razor_package_query_finish(struct razor_package_query *pq)
krh@248
   374
{
krh@248
   375
	struct razor_package_iterator *pi;
krh@248
   376
	struct razor_set *set;
krh@248
   377
	struct list *index;
krh@251
   378
	int i, j;
krh@248
   379
richard@301
   380
	assert (pq != NULL);
richard@301
   381
krh@248
   382
	set = pq->set;
krh@251
   383
	if (pq->count > 0)
krh@251
   384
		index = zalloc(pq->count * sizeof *index);
krh@251
   385
	else
krh@251
   386
		index = NULL;
krh@248
   387
krh@267
   388
	for (i = 0, j = 0; j < pq->count; i++) {
krh@248
   389
		if (!pq->vector[i])
krh@248
   390
			continue;
krh@248
   391
krh@248
   392
		index[j].data = i;
krh@248
   393
		if (j == pq->count - 1)
krh@248
   394
			index[j].flags = 0x80;
krh@248
   395
		j++;
krh@248
   396
	}
krh@248
   397
krh@251
   398
	free(pq->vector);
krh@248
   399
	free(pq);
krh@248
   400
krh@248
   401
	pi = razor_package_iterator_create_with_index(set, index);
krh@248
   402
	pi->free_index = 1;
krh@248
   403
krh@248
   404
	return pi;
krh@248
   405
}