Remove INTLLIBS from librazor_la_LIBADD.
This partially reverts 611c84a3f4b4538a65d186050608c17adbf17770.
It's not clear what motivated the initial inclusion of INTLLIBS
here since the net effect is only seen in librazor.la and not
in razor.pc and librazor.la is not normally packaged. Certainly
neither the static nor the dynamic versions of librazor currently
use libintl. At best this would cause the linker to search a
static libintl for undefined symbols without finding any; at worse
it causes a static build of plover using librazor.la to fail if
no static version of libintl is installed.
2 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
3 * Copyright (C) 2008 Red Hat, Inc
4 * Copyright (C) 2009-2012 J. Ali Harlow <ali@juiblex.co.uk>
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.
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.
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.
31 #include <sys/types.h>
44 #include "razor-internal.h"
51 struct razor_set_section_index {
57 #define MAIN(type, field) \
58 { type, offsetof(struct razor_set, field), RAZOR_SECTION_MAIN }
59 #define FILES(type, field) \
60 { type, offsetof(struct razor_set, field), RAZOR_SECTION_FILES }
61 #define DETAILS(type, field) \
62 { type, offsetof(struct razor_set, field), RAZOR_SECTION_DETAILS }
64 struct razor_set_section_index razor_sections[] = {
65 MAIN(RAZOR_STRING_POOL, string_pool),
66 MAIN(RAZOR_PACKAGES, packages),
67 MAIN(RAZOR_PROPERTIES, properties),
68 MAIN(RAZOR_PACKAGE_POOL, package_pool),
69 MAIN(RAZOR_PROPERTY_POOL, property_pool),
70 MAIN(RAZOR_PREFIX_POOL, prefix_pool),
71 FILES(RAZOR_FILES, files),
72 FILES(RAZOR_FILE_POOL, file_pool),
73 FILES(RAZOR_FILE_STRING_POOL, file_string_pool),
74 DETAILS(RAZOR_DETAILS_STRING_POOL, details_string_pool)
77 RAZOR_EXPORT struct razor_set *
78 razor_set_create_without_root(void)
80 struct razor_set *set;
83 set = zalloc(sizeof *set);
86 empty = array_add(&set->string_pool, 1);
93 set->header_version = RAZOR_HEADER_VERSION;
95 set->flags = RAZOR_SET_PRIVATE;
101 RAZOR_EXPORT struct razor_set *
102 razor_set_create(void)
104 struct razor_set *set;
105 struct razor_entry *e;
107 set = razor_set_create_without_root();
109 e = array_add(&set->files, sizeof *e);
111 e->flags = RAZOR_ENTRY_LAST;
113 list_set_empty(&e->packages);
118 RAZOR_EXPORT uint32_t
119 razor_set_get_header_version(struct razor_set *set)
121 return set->header_version;
125 razor_set_set_header_version(struct razor_set *set, uint32_t header_version)
127 if (header_version<RAZOR_HEADER_VERSION_MIN ||
128 header_version>RAZOR_HEADER_VERSION)
131 set->header_version = header_version;
136 struct razor_mapped_file {
137 struct razor_set_header *header;
139 struct razor_mapped_file *next;
143 razor_set_bind_sections(struct razor_set *set, const char *filename,
144 enum razor_set_flags flags, struct razor_error **error)
146 struct razor_set_section *s, *sections;
147 struct razor_mapped_file *file;
148 const char *pool, *reason;
152 file = zalloc(sizeof *file);
154 razor_set_error(error, NULL, "Not enough memory");
158 file->header = razor_file_get_contents(filename, &file->size,
159 flags & RAZOR_SET_PRIVATE,
166 if (file->size < sizeof *file->header)
167 reason = "Premature EOF";
168 else if (file->header->magic != RAZOR_MAGIC)
169 reason = "Bad magic number";
170 else if (file->header->version < RAZOR_HEADER_VERSION_MIN ||
171 file->header->version > RAZOR_HEADER_VERSION)
172 reason = "Incompatible file version";
177 razor_set_error(error, filename, reason);
178 razor_file_free_contents(file->header, file->size);
183 set->flags = flags & RAZOR_SET_PRIVATE;
185 set->header_version = file->header->version;
187 if (set->mapped_files == NULL) {
188 for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
189 array = (void *) set + razor_sections[i].offset;
190 array_release(array);
194 file->next = set->mapped_files;
195 set->mapped_files = file;
197 sections = (void *) file->header + sizeof *file->header;
198 pool = (void *) sections +
199 file->header->num_sections * sizeof *sections;
201 for (i = 0; i < file->header->num_sections; i++) {
203 for (j = 0; j < ARRAY_SIZE(razor_sections); j++)
204 if (!strcmp(razor_sections[j].name, &pool[s->name]))
206 if (j == ARRAY_SIZE(razor_sections))
208 array = (void *) set + razor_sections[j].offset;
209 array->data = (void *) file->header + s->offset;
210 array->size = s->size;
211 array->alloc = s->size;
217 RAZOR_EXPORT struct razor_set *
218 razor_set_open(const char *filename, enum razor_set_flags flags,
219 struct razor_error **error)
221 struct razor_set *set;
223 set = zalloc(sizeof *set);
225 razor_set_error(error, NULL, "Not enough memory");
231 if (razor_set_bind_sections(set, filename, flags, error)) {
239 razor_set_aquire_lock(struct razor_set *set, const char *path, int exclusive)
245 fd = open(path, O_CREAT | O_RDWR | O_TRUNC | O_BINARY, 0666);
253 DWORD flags = LOCKFILE_FAIL_IMMEDIATELY;
254 OVERLAPPED lock = {0};
257 flags |= LOCKFILE_EXCLUSIVE_LOCK;
258 if (fd >= 0 && !LockFileEx((HANDLE)_get_osfhandle(fd), flags, 0, 1, 0,
263 if (set->lock_fd >= 0)
264 (void)UnlockFile((HANDLE)_get_osfhandle(set->lock_fd), 0, 0, 1,
267 struct flock lock = {0};
269 lock.l_type = exclusive ? F_WRLCK : F_RDLCK;
270 lock.l_whence = SEEK_SET;
273 if (fd >= 0 && fcntl(fd, F_SETLK, &lock) < 0) {
277 if (set->lock_fd >= 0) {
278 lock.l_type = F_UNLCK;
279 (void)fcntl(set->lock_fd, F_SETLK, &lock);
283 if (set->lock_fd >= 0)
291 razor_set_destroy(struct razor_set *set)
293 struct razor_mapped_file *file, *next;
297 assert (set != NULL);
299 if (set->mapped_files == NULL) {
300 for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
301 array = (void *) set + razor_sections[i].offset;
302 array_release(array);
305 for (file = set->mapped_files; file != NULL; file = next) {
307 razor_file_free_contents(file->header, file->size);
312 razor_set_aquire_lock(set, NULL, 0);
317 razor_set_unref(struct razor_set *set)
319 if (set && !--set->ref_count)
320 razor_set_destroy(set);
323 RAZOR_EXPORT struct razor_set *
324 razor_set_ref(struct razor_set *set)
332 razor_set_write_to_handle(struct razor_set *set, struct razor_atomic *atomic,
333 int handle, uint32_t section_mask)
335 struct razor_set_header header;
336 struct razor_set_section sections[ARRAY_SIZE(razor_sections)];
337 struct hashtable table;
338 struct array pool, *arrays[ARRAY_SIZE(razor_sections)];
341 static const char padding[4];
344 hashtable_init(&table, &pool);
347 for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
348 if ((razor_sections[i].flags & section_mask) == 0)
351 arrays[j] = (void *) set + razor_sections[i].offset;
353 hashtable_tokenize(&table, razor_sections[i].name);
358 header.magic = RAZOR_MAGIC;
359 header.version = set->header_version;
360 header.num_sections = count;
361 offset = sizeof header + count * sizeof *sections + ALIGN(pool.size, 4);
363 for (i = 0; i < count; i++) {
364 sections[i].offset = offset;
365 sections[i].size = arrays[i]->size;
366 offset += ALIGN(arrays[i]->size, 4);
369 razor_atomic_write(atomic, handle, &header, sizeof header);
370 razor_atomic_write(atomic, handle, sections, count * sizeof *sections);
371 razor_atomic_write(atomic, handle, pool.data, pool.size);
372 razor_atomic_write(atomic, handle, padding, PADDING(pool.size, 4));
374 for (i = 0; i < count; i++) {
375 razor_atomic_write(atomic, handle, arrays[i]->data,
377 razor_atomic_write(atomic, handle, padding,
378 PADDING(arrays[i]->size, 4));
381 array_release(&pool);
382 hashtable_release(&table);
386 razor_set_write(struct razor_set *set, struct razor_atomic *atomic,
387 const char *filename, uint32_t sections)
391 h = razor_atomic_create_file(atomic, filename,
392 S_IRWXU | S_IRWXG | S_IRWXO);
396 razor_set_write_to_handle(set, atomic, h, sections);
398 return razor_atomic_close(atomic, h);
402 razor_build_evr(char *evr_buf, int size, const char *epoch,
403 const char *version, const char *release)
407 if (!version || !*version) {
412 if (epoch && *epoch && strcmp(epoch, "0") != 0) {
413 len = snprintf(evr_buf, size, "%s:", epoch);
417 len = snprintf(evr_buf, size, "%s", version);
420 if (release && *release)
421 snprintf(evr_buf, size, "-%s", release);
425 razor_versioncmp(const char *s1, const char *s2)
434 n1 = strtol(s1, (char **) &p1, 10);
435 n2 = strtol(s2, (char **) &p2, 10);
437 /* Epoch; if one but not the other has an epoch set, default
438 * the epoch-less version to 0. */
439 res = (*p1 == ':') - (*p2 == ':');
444 } else if (res > 0) {
457 if (isdigit(*p1) && isdigit(*p2))
458 return razor_versioncmp(p1, p2);
465 razor_package_get_details_string(struct razor_set *set,
466 struct razor_package *package,
467 enum razor_detail_type type)
472 case RAZOR_DETAIL_NAME:
473 pool = set->string_pool.data;
474 return &pool[package->name];
476 case RAZOR_DETAIL_VERSION:
477 pool = set->string_pool.data;
478 return &pool[package->version];
480 case RAZOR_DETAIL_ARCH:
481 pool = set->string_pool.data;
482 return &pool[package->arch];
484 case RAZOR_DETAIL_SUMMARY:
485 if (!set->details_string_pool.size)
487 pool = set->details_string_pool.data;
488 return &pool[package->summary];
490 case RAZOR_DETAIL_DESCRIPTION:
491 if (!set->details_string_pool.size)
493 pool = set->details_string_pool.data;
494 return &pool[package->description];
496 case RAZOR_DETAIL_URL:
497 if (!set->details_string_pool.size)
499 pool = set->details_string_pool.data;
500 return &pool[package->url];
502 case RAZOR_DETAIL_LICENSE:
503 if (!set->details_string_pool.size)
505 pool = set->details_string_pool.data;
506 return &pool[package->license];
508 case RAZOR_DETAIL_PREUNPROG:
509 pool = set->string_pool.data;
510 return &pool[package->preun.program];
512 case RAZOR_DETAIL_PREUN:
513 pool = set->string_pool.data;
514 return &pool[package->preun.body];
516 case RAZOR_DETAIL_POSTUNPROG:
517 pool = set->string_pool.data;
518 return &pool[package->postun.program];
520 case RAZOR_DETAIL_POSTUN:
521 pool = set->string_pool.data;
522 return &pool[package->postun.body];
525 fprintf(stderr, "type %u not found\n", type);
530 static const char *const *
531 razor_package_get_details_array(struct razor_set *set,
532 struct razor_package *package,
533 enum razor_detail_type type)
536 case RAZOR_DETAIL_PREFIXES:
537 /* We don't track prefixes in packages. Install prefixes
538 * are tracked, but we don't provide an API to get them.
543 fprintf(stderr, "type %u not found\n", type);
549 * razor_package_get_details_varg:
551 * @package: a %razor_package
552 * @args: a va_list of arguments to set
555 razor_package_get_details_varg(struct razor_set *set,
556 struct razor_package *package,
560 enum razor_detail_type type;
562 const char *const **array;
564 for (i = 0;; i += 2) {
565 type = va_arg(args, enum razor_detail_type);
566 if (type == RAZOR_DETAIL_LAST)
568 if (type == RAZOR_DETAIL_PREFIXES) {
569 array = va_arg(args, const char *const **);
570 *array = razor_package_get_details_array(set, package,
573 string = va_arg(args, const char **);
574 *string = razor_package_get_details_string(set, package,
582 * razor_package_get_details:
584 * @package: a %razor_package
586 * Gets details about a package using a varg interface
587 * The vararg must be terminated with %RAZOR_DETAIL_LAST.
589 * Example: razor_package_get_details (set, package,
590 * RAZOR_DETAIL_URL, &url,
591 * RAZOR_DETAIL_LAST);
594 razor_package_get_details(struct razor_set *set, struct razor_package *package, ...)
598 assert (set != NULL);
599 assert (package != NULL);
601 va_start(args, NULL);
602 razor_package_get_details_varg (set, package, args);
607 * razor_package_remove:
608 * @prev: The %razor_set before the current transaction
609 * @next: The %razor_set after the current transaction is applied
610 * @package: a %razor_package
611 * @root: the root into which the package is currently installed
612 * @install_count: the value to pass to uninstall scripts
613 * @stage: Limit the removal to just the scripts or the files
615 * Removes an installed package.
618 razor_package_remove(struct razor_set *prev, struct razor_set *next,
619 struct razor_atomic *atomic, struct razor_package *package,
620 const char *root, int install_count,
621 enum razor_stage_type stage)
623 struct razor_file_iterator *fi;
624 struct razor_package_iterator *pi;
625 struct razor_package *p;
626 char *buffer, buf[32];
627 const char *name, *program, *script;
628 int i, count, retval = 0;
629 struct environment env;
633 if (stage & RAZOR_STAGE_SCRIPTS) {
634 environment_init(&env);
635 link = list_first(&package->install_prefixes,
637 for (i = 0; link; i++) {
638 prefix = (const char *)prev->string_pool.data +
640 sprintf(buf, "RPM_INSTALL_PREFIX%d", i);
641 environment_add_variable(&env, buf, prefix);
642 link = list_next(link);
644 environment_set(&env);
647 if (stage & RAZOR_STAGE_SCRIPTS_PRE) {
648 razor_package_get_details(prev, package,
649 RAZOR_DETAIL_PREUNPROG, &program,
650 RAZOR_DETAIL_PREUN, &script,
653 retval = razor_run_script(root, RAZOR_PROPERTY_PREUN, program,
654 script, install_count);
657 if (!retval && (stage & RAZOR_STAGE_FILES)) {
658 fi = razor_file_iterator_create(prev, package, 1);
660 while (razor_file_iterator_next(fi, &name)) {
661 pi = razor_package_iterator_create_for_file(next, name);
663 while (razor_package_iterator_next(pi, &p,
666 razor_package_iterator_destroy(pi);
668 buffer = razor_concat(root, name, NULL);
669 razor_atomic_remove(atomic, buffer);
674 razor_file_iterator_destroy(fi);
676 retval = razor_atomic_in_error_state(atomic);
679 if (!retval && (stage & RAZOR_STAGE_SCRIPTS_POST)) {
680 razor_package_get_details(prev, package,
681 RAZOR_DETAIL_POSTUNPROG, &program,
682 RAZOR_DETAIL_POSTUN, &script,
685 retval |= razor_run_script(root, RAZOR_PROPERTY_POSTUN, program,
686 script, install_count);
689 if (stage & RAZOR_STAGE_SCRIPTS) {
690 environment_unset(&env);
691 environment_release(&env);
697 RAZOR_EXPORT const char *
698 razor_property_relation_to_string(struct razor_property *p)
702 switch (p->flags & RAZOR_PROPERTY_RELATION_MASK) {
703 case RAZOR_PROPERTY_LESS:
706 case RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL:
709 case RAZOR_PROPERTY_EQUAL:
712 case RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL:
715 case RAZOR_PROPERTY_GREATER:
723 RAZOR_EXPORT const char *
724 razor_property_type_to_string(struct razor_property *p)
728 switch (p->flags & RAZOR_PROPERTY_TYPE_MASK) {
729 case RAZOR_PROPERTY_REQUIRES:
731 case RAZOR_PROPERTY_PROVIDES:
733 case RAZOR_PROPERTY_CONFLICTS:
735 case RAZOR_PROPERTY_OBSOLETES:
742 RAZOR_EXPORT struct razor_entry *
743 razor_set_find_entry(struct razor_set *set,
744 struct razor_entry *dir, const char *pattern)
746 struct razor_entry *e, *subdir;
747 const char *n, *pool = set->file_string_pool.data;
750 assert (set != NULL);
751 assert (pattern != NULL);
759 if (strcmp(pattern, n) == 0)
762 if (e->start != 0 && strncmp(pattern, n, len) == 0 &&
763 pattern[len] == '/') {
764 subdir = (struct razor_entry *) set->files.data +
766 return razor_set_find_entry(set, subdir,
769 } while (!((e++)->flags & RAZOR_ENTRY_LAST));
775 list_dir(struct razor_set *set, struct razor_entry *dir,
776 char *prefix, const char *pattern)
778 struct razor_entry *e, *subdir;
779 const char *n, *pool = set->file_string_pool.data;
784 if (pattern && pattern[0] && fnmatch(pattern, n, 0) != 0)
786 printf("%s/%s\n", prefix, n);
788 char *sub = prefix + strlen (prefix);
791 subdir = (struct razor_entry *) set->files.data +
793 list_dir(set, subdir, prefix, pattern);
796 } while (!((e++)->flags & RAZOR_ENTRY_LAST));
800 razor_set_list_files(struct razor_set *set, const char *pattern)
802 struct razor_entry *root, *e;
803 char buffer[512], *p, *base;
805 assert (set != NULL);
807 root = (struct razor_entry *) set->files.data;
809 if (pattern == NULL) {
810 p = set->file_string_pool.data;
814 strcpy(buffer, p + e->name);
815 list_dir(set, root + e->start, buffer, NULL);
817 } while (!((e++)->flags & RAZOR_ENTRY_LAST));
821 strcpy(buffer, pattern);
822 e = razor_set_find_entry(set, root, buffer);
826 p = strrchr(buffer, '/');
834 e = razor_set_find_entry(set, root, buffer);
836 list_dir(set, root + e->start, buffer, base);
840 razor_set_list_package_files(struct razor_set *set,
841 struct razor_package *package)
843 struct razor_file_iterator *fi;
846 assert (set != NULL);
847 assert (package != NULL);
849 fi = razor_file_iterator_create(set, package, 0);
851 while (razor_file_iterator_next(fi, &name))
852 printf("%s\n", name);
854 razor_file_iterator_destroy(fi);
858 * Package data can potentially come from two places. The so-called
859 * metadata (eg., from comps.xml) and from an RPM file. We consider
860 * a package which has additional data from an RPM file as "fixed".
861 * If a package needs fixing, then razor_transaction_fixup_package()
862 * will do so. When considering what packages to add and to remove
863 * we need to take this into account since we always want to add
864 * unfixed packages (otherwise we have a potential conflict between
865 * the existing package data and that present in the RPM).
868 razor_package_is_fixed(struct razor_set *set, struct razor_package *p)
870 const char *preunprog, *preun, *postunprog, *postun;
874 razor_package_get_details(set, p,
875 RAZOR_DETAIL_PREUNPROG, &preunprog,
876 RAZOR_DETAIL_PREUN, &preun,
877 RAZOR_DETAIL_POSTUNPROG, &postunprog,
878 RAZOR_DETAIL_POSTUN, &postun,
880 return *preunprog || *preun || *postunprog || *postun;
884 razor_set_diff(struct razor_set *set, struct razor_set *upstream,
885 razor_diff_callback_t callback, void *data)
887 struct razor_package_iterator *pi1, *pi2;
888 struct razor_package *p1, *p2;
889 const char *name1, *name2, *version1, *version2, *arch1, *arch2;
890 int res, is_fixed1, is_fixed2;
892 assert (set != NULL);
893 assert (upstream != NULL);
895 pi1 = razor_package_iterator_create(set);
896 pi2 = razor_package_iterator_create(upstream);
898 razor_package_iterator_next(pi1, &p1,
899 RAZOR_DETAIL_NAME, &name1,
900 RAZOR_DETAIL_VERSION, &version1,
901 RAZOR_DETAIL_ARCH, &arch1,
903 is_fixed1 = razor_package_is_fixed(set, p1);
904 razor_package_iterator_next(pi2, &p2,
905 RAZOR_DETAIL_NAME, &name2,
906 RAZOR_DETAIL_VERSION, &version2,
907 RAZOR_DETAIL_ARCH, &arch2,
909 is_fixed2 = razor_package_is_fixed(upstream, p2);
913 res = strcmp(name1, name2);
915 res = razor_versioncmp(version1, version2);
917 res = is_fixed1 - is_fixed2;
922 if (p2 == NULL || res < 0)
923 callback(RAZOR_DIFF_ACTION_REMOVE,
924 p1, name1, version1, arch1, data);
925 else if (p1 == NULL || res > 0)
926 callback(RAZOR_DIFF_ACTION_ADD,
927 p2, name2, version2, arch2, data);
929 if (p1 != NULL && res <= 0) {
930 razor_package_iterator_next(pi1, &p1,
931 RAZOR_DETAIL_NAME, &name1,
932 RAZOR_DETAIL_VERSION, &version1,
933 RAZOR_DETAIL_ARCH, &arch1,
935 is_fixed1 = razor_package_is_fixed(set, p1);
937 if (p2 != NULL && res >= 0) {
938 razor_package_iterator_next(pi2, &p2,
939 RAZOR_DETAIL_NAME, &name2,
940 RAZOR_DETAIL_VERSION, &version2,
941 RAZOR_DETAIL_ARCH, &arch2,
943 is_fixed2 = razor_package_is_fixed(upstream, p2);
947 razor_package_iterator_destroy(pi1);
948 razor_package_iterator_destroy(pi2);
951 struct install_action {
952 enum razor_install_action action;
953 struct razor_package *package;
956 struct razor_install_iterator {
957 struct razor_set *set;
958 struct razor_set *next;
959 struct array actions;
960 struct deque *order, *left;
964 add_action(enum razor_diff_action action,
965 struct razor_package *package,
971 struct razor_install_iterator *ii = data;
972 struct install_action *a;
974 a = array_add(&ii->actions, sizeof *a);
975 a->package = package;
978 case RAZOR_DIFF_ACTION_ADD:
979 a->action = RAZOR_INSTALL_ACTION_ADD;
981 case RAZOR_DIFF_ACTION_REMOVE:
982 a->action = RAZOR_INSTALL_ACTION_REMOVE;
988 * Does <package> have a requirement for <script> which is
989 * satisfied by <provider> ?
990 * Note: We already know that <provider> is to be added as part of this install
991 * so there is no need to check the relation.
994 package_script_requires(struct razor_set *set, struct razor_package *package,
995 enum razor_property_flags script,
996 struct razor_package *provider)
999 struct razor_property *prop;
1001 link = list_first(&package->properties, &set->property_pool);
1002 for(; link; link = list_next(link)) {
1003 prop = set->properties.data;
1005 if ((prop->flags & RAZOR_PROPERTY_SCRIPT_MASK) & script &&
1006 (prop->flags & RAZOR_PROPERTY_TYPE_MASK) == RAZOR_PROPERTY_REQUIRES &&
1007 provider->name == prop->name)
1013 RAZOR_EXPORT struct razor_install_iterator *
1014 razor_set_create_install_iterator(struct razor_set *set,
1015 struct razor_set *next)
1017 struct razor_install_iterator *ii;
1018 struct razor_property *prop;
1019 /* A graph of the actions to be perfomed where
1020 * A->B means action A should follow action B.
1022 struct graph follows;
1023 struct install_action *actions, *ai, *aj, *an;
1024 int i, j, count, vertex_added;
1026 struct razor_set *rs;
1027 struct deque *order;
1030 assert (set != NULL);
1031 assert (next != NULL);
1033 ii = zalloc(sizeof *ii);
1037 razor_set_diff(set, next, add_action, ii);
1039 actions = ii->actions.data;
1040 count = ii->actions.size / sizeof (struct install_action);
1042 graph_init(&follows);
1044 for(i = 0; i < count; i++) {
1046 rs = ai->action == RAZOR_INSTALL_ACTION_ADD ? next : set;
1048 link = list_first(&ai->package->properties, &rs->property_pool);
1049 for(; link; link = list_next(link)) {
1050 prop = rs->properties.data;
1052 switch(prop->flags & RAZOR_PROPERTY_TYPE_MASK) {
1053 case RAZOR_PROPERTY_REQUIRES:
1054 case RAZOR_PROPERTY_CONFLICTS:
1055 for(j = 0; j < count; j++) {
1059 if (aj->package->name == prop->name) {
1061 RAZOR_INSTALL_ACTION_ADD)
1062 graph_add_edge(&follows,
1065 graph_add_edge(&follows,
1073 if (ai->action == RAZOR_INSTALL_ACTION_ADD) {
1074 for(j = 0; j < count; j++) {
1078 if (aj->package == ai->package &&
1079 aj->action == RAZOR_INSTALL_ACTION_REMOVE) {
1080 graph_add_edge(&follows, i, j);
1086 graph_add_edge(&follows, i, i);
1090 * Because files are installed and removed using razor_atomic,
1091 * but scripts are run with no regard for these, we need some
1092 * means for synchronisation between the two. We support this
1093 * via transaction barriers which are points where
1094 * razor_atomic_commit() should be called so that scripts can
1095 * rely on the files they need being present.
1098 * 1) Transaction barriers never occur within a dependency
1099 * loop. Since we can't guarantee any ordering of actions
1100 * within such a loop, they make no sense.
1101 * 2) Otherwise the following table applies:
1102 * Action I Action J Barrier between I and J iff
1103 * ADD P ADD Q %pre(Q) requires P
1104 * ADD P REMOVE Q %preun(Q) requires P
1105 * REMOVE P ADD Q never
1106 * REMOVE P REMOVE Q %postun(P) requires Q
1109 * This should take account of conflicts somehow.
1111 order = graph_sort(&follows);
1112 ii->order = deque_new(0);
1113 if (!deque_empty(order)) {
1114 j = deque_pop(order);
1115 deque_unshift(ii->order, j);
1117 while (!deque_empty(order)) {
1119 j = deque_pop(order);
1122 if (graph_is_connected(&follows, i, j) &&
1123 graph_is_connected(&follows, j, i))
1125 else if (ai->action == RAZOR_INSTALL_ACTION_ADD &&
1126 aj->action == RAZOR_INSTALL_ACTION_ADD &&
1127 package_script_requires(next, aj->package,
1131 else if (ai->action == RAZOR_INSTALL_ACTION_ADD &&
1132 aj->action == RAZOR_INSTALL_ACTION_REMOVE &&
1133 package_script_requires(set, aj->package,
1134 RAZOR_PROPERTY_PREUN,
1137 else if (ai->action == RAZOR_INSTALL_ACTION_REMOVE &&
1138 aj->action == RAZOR_INSTALL_ACTION_REMOVE &&
1139 package_script_requires(set, ai->package,
1140 RAZOR_PROPERTY_POSTUN,
1145 if (barrier_needed) {
1146 an = array_add(&ii->actions, sizeof *an);
1147 actions = ii->actions.data;
1149 an->action = RAZOR_INSTALL_ACTION_COMMIT;
1150 deque_unshift(ii->order, an - actions);
1152 deque_unshift(ii->order, j);
1156 ii->left = deque_dup(ii->order);
1157 graph_release(&follows);
1163 razor_install_iterator_next(struct razor_install_iterator *ii,
1164 struct razor_package **package,
1165 enum razor_install_action *action,
1168 struct install_action *a;
1169 struct razor_package_iterator *pi;
1170 struct razor_package *pkg;
1171 const char *removing, *name;
1173 if (deque_empty(ii->left))
1176 a = (struct install_action *)ii->actions.data + deque_pop(ii->left);
1177 *package = a->package;
1178 *action = a->action;
1181 if (a->action == RAZOR_INSTALL_ACTION_REMOVE) {
1182 razor_package_get_details(ii->set, a->package,
1183 RAZOR_DETAIL_NAME, &removing,
1186 pi = razor_package_iterator_create(ii->next);
1187 while (razor_package_iterator_next(pi, &pkg,
1188 RAZOR_DETAIL_NAME, &name,
1189 RAZOR_DETAIL_LAST)) {
1190 if (!strcmp(name, removing))
1193 razor_package_iterator_destroy(pi);
1194 } else if (a->action == RAZOR_INSTALL_ACTION_ADD)
1201 action_is_included(struct razor_install_iterator *ii, struct deque *done,
1202 struct razor_package *package,
1203 enum razor_install_action action)
1206 struct install_action *a;
1209 t = deque_dup(done);
1211 while(!deque_empty(t)) {
1212 a = (struct install_action *)ii->actions.data + deque_pop(t);
1213 if (a->package == package && a->action == action)
1216 retval = !deque_empty(t);
1223 RAZOR_EXPORT struct razor_set *
1224 razor_install_iterator_commit_set(struct razor_install_iterator *ii)
1226 struct razor_merger *merger;
1227 struct razor_set *set;
1228 struct razor_package *n, *nend, *npkgs, *s, *send, *spkgs;
1231 char *npool, *spool;
1234 done = deque_dup(ii->order);
1235 pos = razor_install_iterator_tell(ii);
1236 while(deque_length(done) > pos)
1239 s = ii->set->packages.data;
1240 spkgs = ii->set->packages.data;
1241 send = ii->set->packages.data + ii->set->packages.size;
1242 spool = ii->set->string_pool.data;
1244 n = ii->next->packages.data;
1245 npkgs = ii->next->packages.data;
1246 nend = ii->next->packages.data + ii->next->packages.size;
1247 npool = ii->next->string_pool.data;
1249 merger = razor_merger_create(ii->set, ii->next);
1250 while (s < send || n < nend) {
1251 if (s < send && n < nend)
1252 cmp = strcmp(&spool[s->name], &npool[n->name]);
1259 if (!action_is_included(ii, done, s,
1260 RAZOR_INSTALL_ACTION_REMOVE))
1261 razor_merger_add_package(merger, s);
1263 } else if (cmp == 0) {
1264 if (!action_is_included(ii, done, s,
1265 RAZOR_INSTALL_ACTION_REMOVE))
1266 razor_merger_add_package(merger, s);
1267 if (action_is_included(ii, done, n,
1268 RAZOR_INSTALL_ACTION_ADD))
1269 razor_merger_add_package(merger, n);
1274 if (action_is_included(ii, done, n,
1275 RAZOR_INSTALL_ACTION_ADD))
1276 razor_merger_add_package(merger, n);
1281 set = razor_merger_commit(merger);
1282 razor_merger_destroy(merger);
1288 razor_install_iterator_rewind(struct razor_install_iterator *ii)
1290 deque_free(ii->left);
1291 ii->left=deque_dup(ii->order);
1295 razor_install_iterator_tell(struct razor_install_iterator *ii)
1297 return deque_length(ii->order) - deque_length(ii->left);
1301 razor_install_iterator_seek(struct razor_install_iterator *ii, size_t pos)
1305 if (pos > deque_length(ii->order))
1306 pos = deque_length(ii->order);
1308 current_pos = razor_install_iterator_tell(ii);
1310 if (pos < current_pos) {
1311 razor_install_iterator_rewind(ii);
1315 while(current_pos < pos) {
1316 (void) deque_pop(ii->left);
1324 razor_install_iterator_destroy(struct razor_install_iterator *ii)
1326 array_release(&ii->actions);
1327 deque_free(ii->order);
1328 deque_free(ii->left);