Introduce install/remove iterators.
These iterator constructors lets you pass in two sets and creates
an iterator for the packages to remove or the packages to install.
The iterators will step through the packages in a sequence that respects
the pre, post, preun and postun modifiers.
Right now, the install order isn't actually implemented, this patch just
implements the API changes and updates the applications.
2 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
3 * Copyright (C) 2008 Red Hat, Inc
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include <sys/types.h>
36 #include "razor-internal.h"
50 struct razor_set_section razor_sections[] = {
51 { RAZOR_STRING_POOL, offsetof(struct razor_set, string_pool) },
52 { RAZOR_PACKAGES, offsetof(struct razor_set, packages) },
53 { RAZOR_PROPERTIES, offsetof(struct razor_set, properties) },
54 { RAZOR_FILES, offsetof(struct razor_set, files) },
55 { RAZOR_PACKAGE_POOL, offsetof(struct razor_set, package_pool) },
56 { RAZOR_PROPERTY_POOL, offsetof(struct razor_set, property_pool) },
57 { RAZOR_FILE_POOL, offsetof(struct razor_set, file_pool) },
61 razor_set_create(void)
63 struct razor_set *set;
64 struct razor_entry *e;
67 set = zalloc(sizeof *set);
69 e = array_add(&set->files, sizeof *e);
70 empty = array_add(&set->string_pool, 1);
73 e->flags = RAZOR_ENTRY_LAST;
75 list_set_empty(&e->packages);
81 razor_set_open(const char *filename)
83 struct razor_set *set;
84 struct razor_set_section *s;
89 set = zalloc(sizeof *set);
90 fd = open(filename, O_RDONLY);
91 if (fstat(fd, &stat) < 0)
93 set->header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
94 if (set->header == MAP_FAILED) {
99 for (s = set->header->sections; ~s->type; s++) {
100 if (s->type >= ARRAY_SIZE(razor_sections))
102 if (s->type != razor_sections[s->type].type)
104 array = (void *) set + razor_sections[s->type].offset;
105 array->data = (void *) set->header + s->offset;
106 array->size = s->size;
107 array->alloc = s->size;
115 razor_set_destroy(struct razor_set *set)
122 for (i = 0; set->header->sections[i].type; i++)
124 size = set->header->sections[i].type;
125 munmap(set->header, size);
127 for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
128 a = (void *) set + razor_sections[i].offset;
137 razor_set_write_to_fd(struct razor_set *set, int fd)
140 struct razor_set_header *header = (struct razor_set_header *) data;
145 memset(data, 0, sizeof data);
146 header->magic = RAZOR_MAGIC;
147 header->version = RAZOR_VERSION;
148 offset = sizeof data;
150 for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
151 if (razor_sections[i].type != i)
153 a = (void *) set + razor_sections[i].offset;
154 header->sections[i].type = i;
155 header->sections[i].offset = offset;
156 header->sections[i].size = a->size;
157 offset += ALIGN(a->size, 4096);
160 header->sections[i].type = ~0;
161 header->sections[i].offset = 0;
162 header->sections[i].size = 0;
164 razor_write(fd, data, sizeof data);
165 memset(data, 0, sizeof data);
166 for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
167 if (razor_sections[i].type != i)
169 a = (void *) set + razor_sections[i].offset;
170 razor_write(fd, a->data, a->size);
171 razor_write(fd, data, ALIGN(a->size, 4096) - a->size);
178 razor_set_write(struct razor_set *set, const char *filename)
182 fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
186 status = razor_set_write_to_fd(set, fd);
196 razor_build_evr(char *evr_buf, int size, const char *epoch,
197 const char *version, const char *release)
201 if (!version || !*version) {
206 if (epoch && *epoch && strcmp(epoch, "0") != 0) {
207 len = snprintf(evr_buf, size, "%s:", epoch);
211 len = snprintf(evr_buf, size, "%s", version);
214 if (release && *release)
215 snprintf(evr_buf, size, "-%s", release);
219 razor_versioncmp(const char *s1, const char *s2)
225 n1 = strtol(s1, (char **) &p1, 10);
226 n2 = strtol(s2, (char **) &p2, 10);
228 /* Epoch; if one but not the other has an epoch set, default
229 * the epoch-less version to 0. */
230 res = (*p1 == ':') - (*p2 == ':');
235 } else if (res > 0) {
248 if (isdigit(*p1) && isdigit(*p2))
249 return razor_versioncmp(p1, p2);
255 struct razor_package *
256 razor_set_get_package(struct razor_set *set, const char *package)
258 struct razor_package_iterator *pi;
259 struct razor_package *p;
260 const char *name, *version, *arch;
262 pi = razor_package_iterator_create(set);
263 while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
264 if (strcmp(package, name) == 0)
267 razor_package_iterator_destroy(pi);
273 razor_set_find_entry(struct razor_set *set,
274 struct razor_entry *dir, const char *pattern)
276 struct razor_entry *e;
277 const char *n, *pool = set->string_pool.data;
280 e = (struct razor_entry *) set->files.data + dir->start;
283 if (strcmp(pattern + 1, n) == 0)
286 if (e->start != 0 && strncmp(pattern + 1, n, len) == 0 &&
287 pattern[len + 1] == '/') {
288 return razor_set_find_entry(set, e, pattern + len + 1);
290 } while (!((e++)->flags & RAZOR_ENTRY_LAST));
296 list_dir(struct razor_set *set, struct razor_entry *dir,
297 char *prefix, const char *pattern)
299 struct razor_entry *e;
300 const char *n, *pool = set->string_pool.data;
302 e = (struct razor_entry *) set->files.data + dir->start;
305 if (pattern && pattern[0] && fnmatch(pattern, n, 0) != 0)
307 printf("%s/%s\n", prefix, n);
309 char *sub = prefix + strlen (prefix);
312 list_dir(set, e, prefix, pattern);
315 } while (!((e++)->flags & RAZOR_ENTRY_LAST));
319 razor_set_list_files(struct razor_set *set, const char *pattern)
321 struct razor_entry *e;
322 char buffer[512], *p, *base;
324 if (pattern == NULL || !strcmp (pattern, "/")) {
326 list_dir(set, set->files.data, buffer, NULL);
330 strcpy(buffer, pattern);
331 e = razor_set_find_entry(set, set->files.data, buffer);
332 if (e && e->start > 0) {
335 p = strrchr(buffer, '/');
343 e = razor_set_find_entry(set, set->files.data, buffer);
345 list_dir(set, e, buffer, base);
349 list_package_files(struct razor_set *set, struct list *r,
350 struct razor_entry *dir, uint32_t end,
353 struct razor_entry *e, *f, *entries;
358 entries = (struct razor_entry *) set->files.data;
359 pool = set->string_pool.data;
361 e = entries + dir->start;
363 if (entries + r->data == e) {
364 printf("%s/%s\n", prefix, pool + e->name);
371 } while (!((e++)->flags & RAZOR_ENTRY_LAST));
373 e = entries + dir->start;
378 if (e->flags & RAZOR_ENTRY_LAST)
382 while (f->start == 0 && !(f->flags & RAZOR_ENTRY_LAST))
391 if (e->start <= file && file < next) {
392 len = strlen(prefix);
394 strcpy(prefix + len + 1, pool + e->name);
395 r = list_package_files(set, r, e, next, prefix);
398 } while (!((e++)->flags & RAZOR_ENTRY_LAST) && r != NULL);
404 razor_set_list_package_files(struct razor_set *set, const char *name)
406 struct razor_package *package;
411 package = razor_set_get_package(set, name);
413 r = list_first(&package->files, &set->file_pool);
414 end = set->files.size / sizeof (struct razor_entry);
416 list_package_files(set, r, set->files.data, end, buffer);
419 /* The diff order matters. We should sort the packages so that a
420 * REMOVE of a package comes before the INSTALL, and so that all
421 * requires for a package have been installed before the package.
425 razor_set_diff(struct razor_set *set, struct razor_set *upstream,
426 razor_diff_callback_t callback, void *data)
428 struct razor_package_iterator *pi1, *pi2;
429 struct razor_package *p1, *p2;
430 const char *name1, *name2, *version1, *version2, *arch1, *arch2;
433 pi1 = razor_package_iterator_create(set);
434 pi2 = razor_package_iterator_create(upstream);
436 razor_package_iterator_next(pi1, &p1, &name1, &version1, &arch1);
437 razor_package_iterator_next(pi2, &p2, &name2, &version2, &arch2);
441 res = strcmp(name1, name2);
443 res = razor_versioncmp(version1, version2);
448 if (p2 == NULL || res < 0)
449 callback(RAZOR_DIFF_ACTION_REMOVE,
450 p1, name1, version1, arch1, data);
451 else if (p1 == NULL || res > 0)
452 callback(RAZOR_DIFF_ACTION_ADD,
453 p2, name2, version2, arch2, data);
455 if (p1 != NULL && res <= 0)
456 razor_package_iterator_next(pi1, &p1,
457 &name1, &version1, &arch1);
458 if (p2 != NULL && res >= 0)
459 razor_package_iterator_next(pi2, &p2,
460 &name2, &version2, &arch2);
463 razor_package_iterator_destroy(pi1);
464 razor_package_iterator_destroy(pi2);
468 add_new_package(enum razor_diff_action action,
469 struct razor_package *package,
475 if (action == RAZOR_DIFF_ACTION_ADD)
476 razor_package_query_add_package(data, package);
479 struct razor_package_iterator *
480 razor_set_create_remove_iterator(struct razor_set *set,
481 struct razor_set *next)
483 struct razor_package_query *query;
484 struct razor_package_iterator *pi;
486 query = razor_package_query_create(set);
487 razor_set_diff(next, set, add_new_package, query);
489 pi = razor_package_query_finish(query);
491 /* FIXME: We need to figure out the right install order here,
492 * so the post and pre scripts can run. */
499 struct razor_package_iterator *
500 razor_set_create_install_iterator(struct razor_set *set,
501 struct razor_set *next)
503 struct razor_package_query *query;
504 struct razor_package_iterator *pi;
506 query = razor_package_query_create(next);
507 razor_set_diff(set, next, add_new_package, query);
509 pi = razor_package_query_finish(query);
511 /* FIXME: We need to figure out the right install order here,
512 * so the post and pre scripts can run. */