Call exit() instead of just returning if child fails.
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. */