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