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