Only export symbols starting with razor_ in dynamic library.
Apart from being good practice to avoid clashes with higher-level
libraries and the application, this also fixes an obscure bug: The
gnulib library is used both by librazor (the dynamic library) and
by razor (the executable). In doing so, we want to have two separate
copies of the library despite the code duplication this involves.
Without the explicit limit to export only razor_ symbols, the razor
executable under mingw64 was picking up the getopt_long function
from librazor and the optind variable from libgnu which meant that
it did not see optind changing. Hiding librazor's copy of getopt
causes the linker to find libgnu's copy and everything works.
Note that under mingw librazor-#.dll still contains undocumented
(private) razor_ symbols but these will do no harm as long as nobody
tries to use them.
2 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
3 * Copyright (C) 2008 Red Hat, Inc
4 * Copyright (C) 2009-2011 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.
24 #include "razor-internal.h"
27 #define UPSTREAM_SOURCE 0x80
30 struct razor_set *set;
31 uint32_t *property_map;
37 struct razor_set *set;
38 struct hashtable table;
39 struct hashtable file_table;
40 struct hashtable details_table;
41 struct source source1;
42 struct source source2;
46 razor_merger_create(struct razor_set *set1, struct razor_set *set2)
48 struct razor_merger *merger;
51 uint32_t header_version;
53 merger = zalloc(sizeof *merger);
54 merger->set = razor_set_create();
55 if (set1->packages.size) {
56 header_version = razor_set_get_header_version(set1);
57 if (set2->packages.size &&
58 razor_set_get_header_version(set2) > header_version)
59 header_version = razor_set_get_header_version(set2);
61 header_version = razor_set_get_header_version(set2);
62 razor_set_set_header_version(merger->set, header_version);
63 hashtable_init(&merger->table, &merger->set->string_pool);
64 hashtable_init(&merger->file_table, &merger->set->file_string_pool);
65 hashtable_init(&merger->details_table,
66 &merger->set->details_string_pool);
68 merger->source1.set = set1;
69 count = set1->properties.size / sizeof (struct razor_property);
70 size = count * sizeof merger->source1.property_map[0];
71 merger->source1.property_map = zalloc(size);
72 count = set1->files.size / sizeof (struct razor_entry);
73 size = count * sizeof merger->source1.file_map[0];
74 merger->source1.file_map = zalloc(size);
76 merger->source2.set = set2;
77 count = set2->properties.size / sizeof (struct razor_property);
78 size = count * sizeof merger->source2.property_map[0];
79 merger->source2.property_map = zalloc(size);
80 count = set2->files.size / sizeof (struct razor_entry);
81 size = count * sizeof merger->source2.file_map[0];
82 merger->source2.file_map = zalloc(size);
88 razor_merger_add_package(struct razor_merger *merger,
89 struct razor_package *package)
91 char *pool, *details_pool, *s;
93 struct razor_package *p;
94 struct razor_set *set1;
95 struct source *source;
96 uint32_t flags, *prefix;
97 struct array install_prefixes;
99 assert(merger->committed == 0);
101 set1 = merger->source1.set;
102 if (set1->packages.data <= (void *) package &&
103 (void *) package < set1->packages.data + set1->packages.size) {
104 source = &merger->source1;
107 source = &merger->source2;
108 flags = UPSTREAM_SOURCE;
111 pool = source->set->string_pool.data;
112 details_pool = source->set->details_string_pool.data;
113 p = array_add(&merger->set->packages, sizeof *p);
114 p->name = hashtable_tokenize(&merger->table, &pool[package->name]);
116 p->version = hashtable_tokenize(&merger->table,
117 &pool[package->version]);
118 p->arch = hashtable_tokenize(&merger->table,
119 &pool[package->arch]);
120 if (source->set->details_string_pool.size) {
121 p->summary = hashtable_tokenize(&merger->details_table,
122 &details_pool[package->summary]);
123 p->description = hashtable_tokenize(&merger->details_table,
124 &details_pool[package->description]);
125 p->url = hashtable_tokenize(&merger->details_table,
126 &details_pool[package->url]);
127 p->license = hashtable_tokenize(&merger->details_table,
128 &details_pool[package->license]);
130 p->summary = hashtable_tokenize(&merger->details_table, "");
131 p->description = hashtable_tokenize(&merger->details_table, "");
132 p->url = hashtable_tokenize(&merger->details_table, "");
133 p->license = hashtable_tokenize(&merger->details_table, "");
136 p->properties = package->properties;
137 r = list_first(&package->properties, &source->set->property_pool);
139 source->property_map[r->data] = 1;
143 p->files = package->files;
144 r = list_first(&package->files, &source->set->file_pool);
146 source->file_map[r->data] = 1;
150 array_init(&install_prefixes);
151 r = list_first(&package->install_prefixes, &source->set->prefix_pool);
153 s = (char *)source->set->string_pool.data + r->data;
154 prefix = array_add(&install_prefixes, sizeof *prefix);
155 *prefix = hashtable_tokenize(&merger->table, s);
158 list_set_array(&p->install_prefixes, &merger->set->prefix_pool,
159 &install_prefixes, 0);
160 array_release(&install_prefixes);
162 p->preun.program = hashtable_tokenize(&merger->table,
163 &pool[package->preun.program]);
164 p->preun.body = hashtable_tokenize(&merger->table,
165 &pool[package->preun.body]);
166 p->postun.program = hashtable_tokenize(&merger->table,
167 &pool[package->postun.program]);
168 p->postun.body = hashtable_tokenize(&merger->table,
169 &pool[package->postun.body]);
173 add_property(struct razor_merger *merger,
174 const char *name, uint32_t flags, const char *version)
176 struct razor_property *p;
178 p = array_add(&merger->set->properties, sizeof *p);
179 p->name = hashtable_tokenize(&merger->table, name);
181 p->version = hashtable_tokenize(&merger->table, version);
183 return p - (struct razor_property *) merger->set->properties.data;
187 merge_properties(struct razor_merger *merger)
189 struct razor_property *p1, *p2;
190 struct razor_set *set1, *set2;
191 uint32_t *map1, *map2;
192 int i, j, cmp, count1, count2;
195 set1 = merger->source1.set;
196 set2 = merger->source2.set;
197 map1 = merger->source1.property_map;
198 map2 = merger->source2.property_map;
202 pool1 = set1->string_pool.data;
203 pool2 = set2->string_pool.data;
205 count1 = set1->properties.size / sizeof *p1;
206 count2 = set2->properties.size / sizeof *p2;
207 while (i < count1 || j < count2) {
208 if (i < count1 && map1[i] == 0) {
212 if (j < count2 && map2[j] == 0) {
216 p1 = (struct razor_property *) set1->properties.data + i;
217 p2 = (struct razor_property *) set2->properties.data + j;
218 if (i < count1 && j < count2)
219 cmp = strcmp(&pool1[p1->name], &pool2[p2->name]);
225 cmp = p1->flags - p2->flags;
227 cmp = razor_versioncmp(&pool1[p1->version],
228 &pool2[p2->version]);
230 map1[i++] = add_property(merger,
233 &pool1[p1->version]);
234 } else if (cmp > 0) {
235 map2[j++] = add_property(merger,
238 &pool2[p2->version]);
240 map1[i++] = map2[j++] =
244 &pool1[p1->version]);
250 emit_properties(struct list_head *properties, struct array *source_pool,
251 uint32_t *map, struct array *pool)
256 r = pool->size / sizeof *q;
257 p = list_first(properties, source_pool);
259 q = array_add(pool, sizeof *q);
260 q->data = map[p->data];
265 list_set_ptr(properties, r);
269 add_file(struct razor_merger *merger, const char *name)
271 struct razor_entry *e;
273 e = array_add(&merger->set->files, sizeof *e);
274 e->name = hashtable_tokenize(&merger->file_table, name);
278 return e - (struct razor_entry *)merger->set->files.data;
283 fix_file_map(uint32_t *map,
284 struct razor_entry *files,
285 struct razor_entry *top)
292 if (files[e].start &&
293 fix_file_map(map, files, &files[files[e].start]))
297 } while (!(files[e++].flags & RAZOR_ENTRY_LAST));
302 struct merge_directory {
303 uint32_t merged, dir1, dir2;
307 merge_one_directory(struct razor_merger *merger, struct merge_directory *md)
309 struct razor_entry *root1, *root2, *mroot, *e1, *e2;
310 struct razor_set *set1, *set2;
311 struct array merge_stack;
312 struct merge_directory *child_md, *end_md;
313 uint32_t *map1, *map2, start, last;
317 set1 = merger->source1.set;
318 set2 = merger->source2.set;
319 map1 = merger->source1.file_map;
320 map2 = merger->source2.file_map;
321 pool1 = set1->file_string_pool.data;
322 pool2 = set2->file_string_pool.data;
323 root1 = (struct razor_entry *) set1->files.data;
324 root2 = (struct razor_entry *) set2->files.data;
326 array_init(&merge_stack);
328 start = merger->set->files.size / sizeof (struct razor_entry);
330 e1 = md->dir1 != 0xFFFFFFFF ? root1 + md->dir1 : NULL;
331 e2 = md->dir2 != 0xFFFFFFFF ? root2 + md->dir2 : NULL;
333 if (!e2 && !map1[e1 - root1]) {
334 if ((e1++)->flags & RAZOR_ENTRY_LAST)
338 if (!e1 && !map2[e2 - root2]) {
339 if ((e2++)->flags & RAZOR_ENTRY_LAST)
343 if (e1 && !map1[e1 - root1] &&
344 e2 && !map2[e2 - root2]) {
345 if ((e1++)->flags & RAZOR_ENTRY_LAST)
347 if ((e2++)->flags & RAZOR_ENTRY_LAST)
357 cmp = strcmp (&pool1[e1->name],
362 if (map1[e1 - root1]) {
363 map1[e1 - root1] = last =
364 add_file(merger, &pool1[e1->name]);
366 child_md = array_add(&merge_stack, sizeof (struct merge_directory));
367 child_md->merged = last;
368 child_md->dir1 = e1->start;
369 child_md->dir2 = 0xFFFFFFFF;
372 if ((e1++)->flags & RAZOR_ENTRY_LAST)
374 } else if (cmp > 0) {
375 if (map2[e2 - root2]) {
376 map2[e2 - root2] = last =
377 add_file(merger, &pool2[e2->name]);
379 child_md = array_add(&merge_stack, sizeof (struct merge_directory));
380 child_md->merged = last;
381 child_md->dir1 = 0xFFFFFFFF;
382 child_md->dir2 = e2->start;
385 if ((e2++)->flags & RAZOR_ENTRY_LAST)
388 map1[e1 - root1] = map2[e2- root2] = last =
389 add_file(merger, &pool1[e1->name]);
390 if (e1->start || e2->start) {
391 child_md = array_add(&merge_stack, sizeof (struct merge_directory));
392 child_md->merged = last;
393 child_md->dir1 = e1->start ? e1->start : 0xFFFFFFFF;
394 child_md->dir2 = e2->start ? e2->start : 0xFFFFFFFF;
396 if ((e1++)->flags & RAZOR_ENTRY_LAST)
398 if ((e2++)->flags & RAZOR_ENTRY_LAST)
403 mroot = (struct razor_entry *)merger->set->files.data;
404 if (last != 0xFFFFFFFF) {
405 mroot[last].flags = RAZOR_ENTRY_LAST;
406 mroot[md->merged].start = start;
409 end_md = merge_stack.data + merge_stack.size;
410 for (child_md = merge_stack.data; child_md < end_md; child_md++)
411 merge_one_directory(merger, child_md);
412 array_release(&merge_stack);
416 merge_files(struct razor_merger *merger)
418 struct razor_entry *root;
419 struct merge_directory md;
420 uint32_t *map1, *map2;
422 map1 = merger->source1.file_map;
423 map2 = merger->source2.file_map;
427 if (merger->source1.set->files.size) {
428 root = (struct razor_entry *) merger->source1.set->files.data;
430 fix_file_map(map1, root, root);
433 md.dir1 = 0xFFFFFFFF;
436 if (merger->source2.set->files.size) {
437 root = (struct razor_entry *) merger->source2.set->files.data;
439 fix_file_map(map2, root, root);
442 md.dir2 = 0xFFFFFFFF;
445 /* Remove the unnamed root which razor_set_create() added */
446 array_release(&merger->set->files);
447 array_init(&merger->set->files);
449 merge_one_directory(merger, &md);
453 emit_files(struct list_head *files, struct array *source_pool,
454 uint32_t *map, struct array *pool)
459 r = pool->size / sizeof *q;
460 p = list_first(files, source_pool);
462 q = array_add(pool, sizeof *q);
463 q->data = map[p->data];
468 list_set_ptr(files, r);
471 /* Rebuild property->packages maps. We can't just remap these, as a
472 * property may have lost or gained a number of packages. Allocate an
473 * array per property and loop through the packages and add them to
474 * the arrays for their properties. */
476 rebuild_property_package_lists(struct razor_set *set)
478 struct array *pkgs, *a;
479 struct razor_package *pkg, *pkg_end;
480 struct razor_property *prop, *prop_end;
485 count = set->properties.size / sizeof (struct razor_property);
486 pkgs = zalloc(count * sizeof *pkgs);
487 pkg_end = set->packages.data + set->packages.size;
489 for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
490 r = list_first(&pkg->properties, &set->property_pool);
492 q = array_add(&pkgs[r->data], sizeof *q);
493 *q = pkg - (struct razor_package *) set->packages.data;
498 prop_end = set->properties.data + set->properties.size;
500 for (prop = set->properties.data; prop < prop_end; prop++, a++) {
501 list_set_array(&prop->packages, &set->package_pool, a, 0);
508 rebuild_file_package_lists(struct razor_set *set)
510 struct array *pkgs, *a;
511 struct razor_package *pkg, *pkg_end;
512 struct razor_entry *entry, *entry_end;
517 count = set->files.size / sizeof (struct razor_entry);
518 pkgs = zalloc(count * sizeof *pkgs);
519 pkg_end = set->packages.data + set->packages.size;
521 for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
522 r = list_first(&pkg->files, &set->file_pool);
524 q = array_add(&pkgs[r->data], sizeof *q);
525 *q = pkg - (struct razor_package *) set->packages.data;
530 entry_end = set->files.data + set->files.size;
532 for (entry = set->files.data; entry < entry_end; entry++, a++) {
533 list_set_array(&entry->packages, &set->package_pool, a, 0);
540 razor_merger_commit(struct razor_merger *merger)
542 struct razor_package *p, *pend;
544 /* As we built the package list, we filled out a bitvector of
545 * the properties that are referenced by the packages in the
546 * new set. Now we do a parallel loop through the properties
547 * and emit those marked in the bit vector to the new set. In
548 * the process, we update the bit vector to actually map from
549 * indices in the old property list to indices in the new
550 * property list for both sets. */
552 merge_properties(merger);
555 /* Now we loop through the packages again and emit the
556 * property lists, remapped to point to the new properties. */
558 pend = merger->set->packages.data + merger->set->packages.size;
559 for (p = merger->set->packages.data; p < pend; p++) {
562 if (p->flags & UPSTREAM_SOURCE)
563 src = &merger->source2;
565 src = &merger->source1;
567 emit_properties(&p->properties,
568 &src->set->property_pool,
570 &merger->set->property_pool);
571 emit_files(&p->files,
572 &src->set->file_pool,
574 &merger->set->file_pool);
575 p->flags &= ~UPSTREAM_SOURCE;
578 rebuild_property_package_lists(merger->set);
579 rebuild_file_package_lists(merger->set);
581 merger->committed = 1;
587 razor_merger_package_add_script(struct razor_merger *merger,
588 struct razor_package *package,
589 enum razor_property_flags script,
590 const char *program, const char *body)
594 struct razor_set *set = merger->set;
595 assert ((void *)package >= set->packages.data && \
596 (void *)package < set->packages.data + set->packages.size);
598 p = hashtable_tokenize(&merger->table, program);
599 b = hashtable_tokenize(&merger->table, body);
601 pool = merger->set->string_pool.data;
604 case RAZOR_PROPERTY_PREUN:
605 if (package->preun.program != p) {
606 assert(pool[package->preun.program] == '\0');
607 package->preun.program = p;
609 if (package->preun.body != b) {
610 assert(pool[package->preun.body] == '\0');
611 package->preun.body = b;
614 case RAZOR_PROPERTY_POSTUN:
615 if (package->postun.program != p) {
616 assert(pool[package->postun.program] == '\0');
617 package->postun.program = p;
619 if (package->postun.body != b) {
620 assert(pool[package->postun.body] == '\0');
621 package->postun.body = b;
629 void razor_merger_destroy(struct razor_merger *merger)
631 hashtable_release(&merger->table);
632 hashtable_release(&merger->file_table);
633 hashtable_release(&merger->details_table);