Add support for preloading lua modules. This is useful both when
providing lua bindings to applications based on librazor and when
producing static binaries using librazor (where otherwise the lua
POSIX library would need to be included as an additional dynamic
object).
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.
30 #include <sys/types.h>
39 #include "razor-internal.h"
57 struct razor_set_section_index {
62 struct razor_set_section_index razor_sections[] = {
63 { RAZOR_STRING_POOL, offsetof(struct razor_set, string_pool) },
64 { RAZOR_PACKAGES, offsetof(struct razor_set, packages) },
65 { RAZOR_PROPERTIES, offsetof(struct razor_set, properties) },
66 { RAZOR_PACKAGE_POOL, offsetof(struct razor_set, package_pool) },
67 { RAZOR_PROPERTY_POOL, offsetof(struct razor_set, property_pool) },
70 struct razor_set_section_index razor_files_sections[] = {
71 { RAZOR_FILES, offsetof(struct razor_set, files) },
72 { RAZOR_FILE_POOL, offsetof(struct razor_set, file_pool) },
73 { RAZOR_FILE_STRING_POOL, offsetof(struct razor_set, file_string_pool) },
76 struct razor_set_section_index razor_details_sections[] = {
77 { RAZOR_DETAILS_STRING_POOL, offsetof(struct razor_set, details_string_pool) },
80 RAZOR_EXPORT struct razor_set *
81 razor_set_create(void)
83 struct razor_set *set;
84 struct razor_entry *e;
87 set = zalloc(sizeof *set);
89 e = array_add(&set->files, sizeof *e);
90 empty = array_add(&set->string_pool, 1);
93 e->flags = RAZOR_ENTRY_LAST;
95 list_set_empty(&e->packages);
101 razor_set_bind_sections(struct razor_set *set,
102 struct razor_set_header **header,
104 struct razor_set_section_index section_index[],
105 int section_index_size,
106 const char *filename)
108 struct razor_set_section *s, *sections;
113 *header = razor_file_get_contents(filename, header_size);
117 sections = (void *) *header + sizeof **header;
118 pool = (void *) sections + (*header)->num_sections * sizeof *sections;
120 for (i = 0; i < (*header)->num_sections; i++) {
123 for (j = 0; j < section_index_size; j++)
124 if (!strcmp(section_index[j].name,
127 if (j == section_index_size)
129 array = (void *) set + section_index[j].offset;
130 array->data = (void *) *header + s->offset;
131 array->size = s->size;
132 array->alloc = s->size;
138 RAZOR_EXPORT struct razor_set *
139 razor_set_open(const char *filename)
141 struct razor_set *set;
143 set = zalloc(sizeof *set);
144 if (razor_set_bind_sections(set, &set->header, &set->header_size,
145 razor_sections, ARRAY_SIZE(razor_sections),
154 razor_set_open_details(struct razor_set *set, const char *filename)
156 return razor_set_bind_sections(set, &set->details_header,
157 &set->details_header_size,
158 razor_details_sections,
159 ARRAY_SIZE(razor_details_sections),
164 razor_set_open_files(struct razor_set *set, const char *filename)
166 return razor_set_bind_sections(set, &set->files_header,
167 &set->files_header_size,
168 razor_files_sections,
169 ARRAY_SIZE(razor_files_sections),
174 razor_set_destroy(struct razor_set *set)
179 assert (set != NULL);
182 razor_file_free_contents(set->header, set->header_size);
184 for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
185 a = (void *) set + razor_sections[i].offset;
190 if (set->details_header) {
191 razor_file_free_contents(set->details_header,
192 set->details_header_size);
194 for (i = 0; i < ARRAY_SIZE(razor_details_sections); i++) {
195 a = (void *) set + razor_details_sections[i].offset;
200 if (set->files_header) {
201 razor_file_free_contents(set->files_header,
202 set->files_header_size);
204 for (i = 0; i < ARRAY_SIZE(razor_files_sections); i++) {
205 a = (void *) set + razor_files_sections[i].offset;
214 razor_set_write_sections_to_fd(struct razor_set *set, int fd,
215 struct razor_set_section_index *sections,
218 struct razor_set_header header;
219 struct razor_set_section *out_sections =
220 malloc(array_size * sizeof *out_sections);
221 struct hashtable table;
222 struct array *a, pool;
226 header.magic = RAZOR_MAGIC;
227 header.version = RAZOR_VERSION;
228 header.num_sections = array_size;
229 offset = sizeof header + array_size * sizeof *out_sections;
232 hashtable_init(&table, &pool);
234 for (i = 0; i < array_size; i++)
235 out_sections[i].name =
236 hashtable_tokenize(&table, sections[i].name);
240 for (i = 0; i < array_size; i++) {
241 a = (void *) set + sections[i].offset;
242 out_sections[i].offset = offset;
243 out_sections[i].size = a->size;
247 razor_write(fd, &header, sizeof header);
248 razor_write(fd, out_sections, array_size * sizeof *out_sections);
249 razor_write(fd, pool.data, pool.size);
251 for (i = 0; i < array_size; i++) {
252 a = (void *) set + sections[i].offset;
253 razor_write(fd, a->data, a->size);
262 razor_set_write_to_fd(struct razor_set *set, int fd,
263 enum razor_repo_file_type type)
266 case RAZOR_REPO_FILE_MAIN:
267 return razor_set_write_sections_to_fd(set, fd,
269 ARRAY_SIZE(razor_sections));
271 case RAZOR_REPO_FILE_DETAILS:
272 return razor_set_write_sections_to_fd(set, fd,
273 razor_details_sections,
274 ARRAY_SIZE(razor_details_sections));
275 case RAZOR_REPO_FILE_FILES:
276 return razor_set_write_sections_to_fd(set, fd,
277 razor_files_sections,
278 ARRAY_SIZE(razor_files_sections));
285 razor_set_write(struct razor_set *set, const char *filename,
286 enum razor_repo_file_type type)
290 fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, 0666);
294 status = razor_set_write_to_fd(set, fd, type);
304 razor_build_evr(char *evr_buf, int size, const char *epoch,
305 const char *version, const char *release)
309 if (!version || !*version) {
314 if (epoch && *epoch && strcmp(epoch, "0") != 0) {
315 len = snprintf(evr_buf, size, "%s:", epoch);
319 len = snprintf(evr_buf, size, "%s", version);
322 if (release && *release)
323 snprintf(evr_buf, size, "-%s", release);
327 razor_versioncmp(const char *s1, const char *s2)
336 n1 = strtol(s1, (char **) &p1, 10);
337 n2 = strtol(s2, (char **) &p2, 10);
339 /* Epoch; if one but not the other has an epoch set, default
340 * the epoch-less version to 0. */
341 res = (*p1 == ':') - (*p2 == ':');
346 } else if (res > 0) {
359 if (isdigit(*p1) && isdigit(*p2))
360 return razor_versioncmp(p1, p2);
367 razor_package_get_details_type(struct razor_set *set,
368 struct razor_package *package,
369 enum razor_detail_type type)
374 case RAZOR_DETAIL_NAME:
375 pool = set->string_pool.data;
376 return &pool[package->name];
378 case RAZOR_DETAIL_VERSION:
379 pool = set->string_pool.data;
380 return &pool[package->version];
382 case RAZOR_DETAIL_ARCH:
383 pool = set->string_pool.data;
384 return &pool[package->arch];
386 case RAZOR_DETAIL_SUMMARY:
387 pool = set->details_string_pool.data;
388 return &pool[package->summary];
390 case RAZOR_DETAIL_DESCRIPTION:
391 pool = set->details_string_pool.data;
392 return &pool[package->description];
394 case RAZOR_DETAIL_URL:
395 pool = set->details_string_pool.data;
396 return &pool[package->url];
398 case RAZOR_DETAIL_LICENSE:
399 pool = set->details_string_pool.data;
400 return &pool[package->license];
403 fprintf(stderr, "type %u not found\n", type);
409 * razor_package_get_details_varg:
411 * @package: a %razor_package
412 * @args: a va_list of arguments to set
415 razor_package_get_details_varg(struct razor_set *set,
416 struct razor_package *package,
420 enum razor_detail_type type;
423 for (i = 0;; i += 2) {
424 type = va_arg(args, enum razor_detail_type);
425 if (type == RAZOR_DETAIL_LAST)
427 data = va_arg(args, const char **);
428 *data = razor_package_get_details_type(set, package, type);
434 * razor_package_get_details:
436 * @package: a %razor_package
438 * Gets details about a package using a varg interface
439 * The vararg must be terminated with %RAZOR_DETAIL_LAST.
441 * Example: razor_package_get_details (set, package,
442 * RAZOR_DETAIL_URL, &url,
443 * RAZOR_DETAIL_LAST);
446 razor_package_get_details(struct razor_set *set, struct razor_package *package, ...)
450 assert (set != NULL);
451 assert (package != NULL);
453 va_start(args, NULL);
454 razor_package_get_details_varg (set, package, args);
458 RAZOR_EXPORT const char *
459 razor_property_relation_to_string(struct razor_property *p)
463 switch (p->flags & RAZOR_PROPERTY_RELATION_MASK) {
464 case RAZOR_PROPERTY_LESS:
467 case RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL:
470 case RAZOR_PROPERTY_EQUAL:
473 case RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL:
476 case RAZOR_PROPERTY_GREATER:
484 RAZOR_EXPORT const char *
485 razor_property_type_to_string(struct razor_property *p)
489 switch (p->flags & RAZOR_PROPERTY_TYPE_MASK) {
490 case RAZOR_PROPERTY_REQUIRES:
492 case RAZOR_PROPERTY_PROVIDES:
494 case RAZOR_PROPERTY_CONFLICTS:
496 case RAZOR_PROPERTY_OBSOLETES:
503 RAZOR_EXPORT struct razor_entry *
504 razor_set_find_entry(struct razor_set *set,
505 struct razor_entry *dir, const char *pattern)
507 struct razor_entry *e, *subdir;
508 const char *n, *pool = set->file_string_pool.data;
511 assert (set != NULL);
512 assert (dir != NULL);
513 assert (pattern != NULL);
518 if (strcmp(pattern, n) == 0)
521 if (e->start != 0 && strncmp(pattern, n, len) == 0 &&
522 pattern[len] == '/') {
523 subdir = (struct razor_entry *) set->files.data +
525 return razor_set_find_entry(set, subdir,
528 } while (!((e++)->flags & RAZOR_ENTRY_LAST));
534 list_dir(struct razor_set *set, struct razor_entry *dir,
535 char *prefix, const char *pattern)
537 struct razor_entry *e, *subdir;
538 const char *n, *pool = set->file_string_pool.data;
543 if (pattern && pattern[0] && fnmatch(pattern, n, 0) != 0)
545 printf("%s/%s\n", prefix, n);
547 char *sub = prefix + strlen (prefix);
550 subdir = (struct razor_entry *) set->files.data +
552 list_dir(set, subdir, prefix, pattern);
555 } while (!((e++)->flags & RAZOR_ENTRY_LAST));
559 razor_set_list_files(struct razor_set *set, const char *pattern)
561 struct razor_entry *root, *e;
562 char buffer[512], *p, *base;
564 assert (set != NULL);
566 root = (struct razor_entry *) set->files.data;
568 if (pattern == NULL) {
569 p = set->file_string_pool.data;
573 strcpy(buffer, p + e->name);
574 list_dir(set, root + e->start, buffer, NULL);
576 } while (!((e++)->flags & RAZOR_ENTRY_LAST));
580 strcpy(buffer, pattern);
581 e = razor_set_find_entry(set, root, buffer);
585 p = strrchr(buffer, '/');
593 e = razor_set_find_entry(set, root, buffer);
595 list_dir(set, root + e->start, buffer, base);
599 razor_set_list_package_files(struct razor_set *set,
600 struct razor_package *package)
602 struct razor_file_iterator *fi;
605 assert (set != NULL);
606 assert (package != NULL);
608 fi = razor_file_iterator_create(set, package);
610 while (razor_file_iterator_next(fi, &name))
611 printf("%s\n", name);
613 razor_file_iterator_destroy(fi);
616 /* The diff order matters. We should sort the packages so that a
617 * REMOVE of a package comes before the INSTALL, and so that all
618 * requires for a package have been installed before the package.
622 razor_set_diff(struct razor_set *set, struct razor_set *upstream,
623 razor_diff_callback_t callback, void *data)
625 struct razor_package_iterator *pi1, *pi2;
626 struct razor_package *p1, *p2;
627 const char *name1, *name2, *version1, *version2, *arch1, *arch2;
630 assert (set != NULL);
631 assert (upstream != NULL);
633 pi1 = razor_package_iterator_create(set);
634 pi2 = razor_package_iterator_create(upstream);
636 razor_package_iterator_next(pi1, &p1,
637 RAZOR_DETAIL_NAME, &name1,
638 RAZOR_DETAIL_VERSION, &version1,
639 RAZOR_DETAIL_ARCH, &arch1,
641 razor_package_iterator_next(pi2, &p2,
642 RAZOR_DETAIL_NAME, &name2,
643 RAZOR_DETAIL_VERSION, &version2,
644 RAZOR_DETAIL_ARCH, &arch2,
649 res = strcmp(name1, name2);
651 res = razor_versioncmp(version1, version2);
656 if (p2 == NULL || res < 0)
657 callback(RAZOR_DIFF_ACTION_REMOVE,
658 p1, name1, version1, arch1, data);
659 else if (p1 == NULL || res > 0)
660 callback(RAZOR_DIFF_ACTION_ADD,
661 p2, name2, version2, arch2, data);
663 if (p1 != NULL && res <= 0)
664 razor_package_iterator_next(pi1, &p1,
665 RAZOR_DETAIL_NAME, &name1,
666 RAZOR_DETAIL_VERSION, &version1,
667 RAZOR_DETAIL_ARCH, &arch1,
669 if (p2 != NULL && res >= 0)
670 razor_package_iterator_next(pi2, &p2,
671 RAZOR_DETAIL_NAME, &name2,
672 RAZOR_DETAIL_VERSION, &version2,
673 RAZOR_DETAIL_ARCH, &arch2,
677 razor_package_iterator_destroy(pi1);
678 razor_package_iterator_destroy(pi2);
681 struct install_action {
682 enum razor_install_action action;
683 struct razor_package *package;
686 struct razor_install_iterator {
687 struct razor_set *set;
688 struct razor_set *next;
689 struct array actions;
690 struct install_action *a, *end;
694 add_action(enum razor_diff_action action,
695 struct razor_package *package,
701 struct razor_install_iterator *ii = data;
702 struct install_action *a;
704 a = array_add(&ii->actions, sizeof *a);
705 a->package = package;
708 case RAZOR_DIFF_ACTION_ADD:
709 a->action = RAZOR_INSTALL_ACTION_ADD;
711 case RAZOR_DIFF_ACTION_REMOVE:
712 a->action = RAZOR_INSTALL_ACTION_REMOVE;
717 RAZOR_EXPORT struct razor_install_iterator *
718 razor_set_create_install_iterator(struct razor_set *set,
719 struct razor_set *next)
721 struct razor_install_iterator *ii;
723 assert (set != NULL);
724 assert (next != NULL);
726 ii = zalloc(sizeof *ii);
730 razor_set_diff(set, next, add_action, ii);
732 ii->a = ii->actions.data;
733 ii->end = ii->actions.data + ii->actions.size;
735 /* FIXME: We need to figure out the right install order here,
736 * so the post and pre scripts can run. */
742 razor_install_iterator_next(struct razor_install_iterator *ii,
743 struct razor_set **set,
744 struct razor_package **package,
745 enum razor_install_action *action,
748 if (ii->a == ii->end)
751 switch (ii->a->action) {
752 case RAZOR_INSTALL_ACTION_ADD:
755 case RAZOR_INSTALL_ACTION_REMOVE:
760 *package = ii->a->package;
761 *action = ii->a->action;
769 razor_install_iterator_destroy(struct razor_install_iterator *ii)
771 array_release(&ii->actions);