libopkg: work-around yet another dependency checking problem
[project/opkg-lede.git] / libopkg / pkg_hash.c
1 /* opkg_hash.c - the opkg package management system
2
3 Steven M. Ayer
4
5 Copyright (C) 2002 Compaq Computer Corporation
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2, or (at
10 your option) any later version.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16 */
17
18 #include <stdio.h>
19
20 #include "hash_table.h"
21 #include "pkg.h"
22 #include "opkg_message.h"
23 #include "pkg_depends.h"
24 #include "pkg_vec.h"
25 #include "pkg_hash.h"
26 #include "parse_util.h"
27 #include "pkg_parse.h"
28 #include "opkg_utils.h"
29 #include "sprintf_alloc.h"
30 #include "file_util.h"
31 #include "libbb/libbb.h"
32 #include "libbb/gzip.h"
33
34 void pkg_hash_init(void)
35 {
36 hash_table_init("pkg-hash", &conf->pkg_hash,
37 OPKG_CONF_DEFAULT_HASH_LEN);
38 }
39
40 static void free_pkgs(const char *key, void *entry, void *data)
41 {
42 int i;
43 abstract_pkg_t *ab_pkg;
44
45 /* Each entry in the hash table is an abstract package, which contains
46 * a list of packages that provide the abstract package.
47 */
48
49 ab_pkg = (abstract_pkg_t *) entry;
50
51 if (ab_pkg->pkgs) {
52 for (i = 0; i < ab_pkg->pkgs->len; i++) {
53 pkg_deinit(ab_pkg->pkgs->pkgs[i]);
54 free(ab_pkg->pkgs->pkgs[i]);
55 }
56 }
57
58 abstract_pkg_vec_free(ab_pkg->provided_by);
59 abstract_pkg_vec_free(ab_pkg->replaced_by);
60 pkg_vec_free(ab_pkg->pkgs);
61 free(ab_pkg->depended_upon_by);
62 free(ab_pkg->name);
63 free(ab_pkg);
64 }
65
66 void pkg_hash_deinit(void)
67 {
68 hash_table_foreach(&conf->pkg_hash, free_pkgs, NULL);
69 hash_table_deinit(&conf->pkg_hash);
70 }
71
72 int dist_hash_add_from_file(const char *lists_dir, pkg_src_t * dist)
73 {
74 nv_pair_list_elt_t *l;
75 char *list_file, *subname;
76
77 list_for_each_entry(l, &conf->arch_list.head, node) {
78 nv_pair_t *nv = (nv_pair_t *) l->data;
79 sprintf_alloc(&subname, "%s-%s", dist->name, nv->name);
80 sprintf_alloc(&list_file, "%s/%s", lists_dir, subname);
81
82 if (file_exists(list_file)) {
83 if (pkg_hash_add_from_file(list_file, dist, NULL, 0, 0, NULL, NULL)) {
84 free(list_file);
85 return -1;
86 }
87 pkg_src_list_append(&conf->pkg_src_list, subname,
88 dist->value, "__dummy__", 0);
89 }
90
91 free(list_file);
92 }
93
94 return 0;
95 }
96
97 int
98 pkg_hash_add_from_file(const char *file_name,
99 pkg_src_t * src, pkg_dest_t * dest, int is_status_file, int state_flags,
100 void (*cb)(pkg_t *, void *), void *priv)
101 {
102 pkg_t *pkg;
103 FILE *fp;
104 char *buf;
105 const size_t len = 4096;
106 int ret = 0;
107 struct gzip_handle zh;
108
109 if (src && src->gzip) {
110 fp = gzip_fdopen(&zh, file_name);
111 } else {
112 fp = fopen(file_name, "r");
113 }
114
115 if (fp == NULL) {
116 opkg_perror(ERROR, "Failed to open %s", file_name);
117 return -1;
118 }
119
120 buf = xmalloc(len);
121
122 do {
123 pkg = pkg_new();
124 pkg->src = src;
125 pkg->dest = dest;
126 pkg->state_flag |= state_flags;
127
128 ret = parse_from_stream_nomalloc(pkg_parse_line, pkg, fp, 0,
129 &buf, len);
130
131 if (pkg->name == NULL) {
132 /* probably just a blank line */
133 ret = 1;
134 }
135
136 if (ret) {
137 pkg_deinit(pkg);
138 free(pkg);
139 if (ret == -1)
140 break;
141 if (ret == 1)
142 /* Probably a blank line, continue parsing. */
143 ret = 0;
144 continue;
145 }
146
147 if (!(pkg->state_flag & SF_NEED_DETAIL)) {
148 //opkg_msg(DEBUG, "Package %s is unrelated, ignoring.\n", pkg->name);
149 pkg_deinit(pkg);
150 free(pkg);
151 continue;
152 }
153
154 if (!pkg_get_architecture(pkg) || !pkg_get_arch_priority(pkg)) {
155 char *version_str = pkg_version_str_alloc(pkg);
156 opkg_msg(NOTICE, "Package %s version %s has no "
157 "valid architecture, ignoring.\n",
158 pkg->name, version_str);
159 free(version_str);
160 continue;
161 }
162
163 if (cb)
164 cb(pkg, priv);
165 else
166 hash_insert_pkg(pkg, is_status_file);
167
168 } while (!feof(fp));
169
170 free(buf);
171 fclose(fp);
172
173 if (src && src->gzip)
174 gzip_close(&zh);
175
176 return ret;
177 }
178
179 /*
180 * Load in feed files from the cached "src" and/or "src/gz" locations.
181 */
182 int pkg_hash_load_feeds(int state_flags, void (*cb)(pkg_t *, void *), void *priv)
183 {
184 pkg_src_list_elt_t *iter;
185 pkg_src_t *src;
186 char *list_file, *lists_dir;
187
188 opkg_msg(INFO, "\n");
189
190 lists_dir = conf->restrict_to_default_dest ?
191 conf->default_dest->lists_dir : conf->lists_dir;
192
193 for (iter = void_list_first(&conf->pkg_src_list); iter;
194 iter = void_list_next(&conf->pkg_src_list, iter)) {
195
196 src = (pkg_src_t *) iter->data;
197
198 sprintf_alloc(&list_file, "%s/%s", lists_dir, src->name);
199
200 if (file_exists(list_file)) {
201 if (pkg_hash_add_from_file(list_file, src, NULL, 0, state_flags, cb, priv)) {
202 free(list_file);
203 return -1;
204 }
205 }
206 free(list_file);
207 }
208
209 return 0;
210 }
211
212 /*
213 * Load in status files from the configured "dest"s.
214 */
215 int pkg_hash_load_status_files(void (*cb)(pkg_t *, void *), void *priv)
216 {
217 pkg_dest_list_elt_t *iter;
218 pkg_dest_t *dest;
219
220 opkg_msg(INFO, "\n");
221
222 for (iter = void_list_first(&conf->pkg_dest_list); iter;
223 iter = void_list_next(&conf->pkg_dest_list, iter)) {
224
225 dest = (pkg_dest_t *) iter->data;
226
227 if (file_exists(dest->status_file_name)) {
228 if (pkg_hash_add_from_file
229 (dest->status_file_name, NULL, dest, 1, SF_NEED_DETAIL, cb, priv))
230 return -1;
231 }
232 }
233
234 return 0;
235 }
236
237 static void
238 pkg_hash_load_package_details_helper(const char *pkg_name, void *entry, void *data)
239 {
240 int *count = data;
241 abstract_pkg_t *ab_pkg = (abstract_pkg_t *) entry;
242
243 if (ab_pkg->state_flag & SF_NEED_DETAIL) {
244 if (ab_pkg->state_flag & SF_MARKED) {
245 opkg_msg(DEBUG, "skipping already seen flagged abpkg %s\n",
246 ab_pkg->name);
247 return;
248 }
249
250 opkg_msg(DEBUG, "found yet incomplete flagged abpkg %s\n",
251 ab_pkg->name);
252
253 (*count)++;
254 ab_pkg->state_flag |= SF_MARKED;
255 }
256 }
257
258 int pkg_hash_load_package_details(void)
259 {
260 int n_need_detail;
261
262 while (1) {
263 pkg_hash_load_feeds(0, NULL, NULL);
264
265 n_need_detail = 0;
266 hash_table_foreach(&conf->pkg_hash, pkg_hash_load_package_details_helper, &n_need_detail);
267
268 if (n_need_detail > 0)
269 opkg_msg(DEBUG, "Found %d packages requiring details, reloading feeds\n", n_need_detail);
270 else
271 break;
272 }
273
274 return 0;
275 }
276
277 static int
278 pkg_hash_check_unresolved(pkg_t *maybe)
279 {
280 char **unresolved = NULL;
281 char **tmp;
282 pkg_vec_t *depends, *all;
283 int i, res = 0;
284
285 depends = pkg_vec_alloc();
286 all = pkg_vec_alloc();
287 pkg_hash_fetch_available(all);
288 /* backup dependencies_checked marks, they get destroyed by pkg_hash_fetch_unsatisfied_dependencies */
289 for (i = 0; i < all->len; i++)
290 all->pkgs[i]->parent->prev_dependencies_checked = all->pkgs[i]->parent->dependencies_checked;
291
292 pkg_hash_fetch_unsatisfied_dependencies(maybe, depends, &unresolved);
293
294 if (unresolved) {
295 res = 1;
296 tmp = unresolved;
297 while (tmp)
298 free(*(tmp++));
299 free(unresolved);
300 }
301 pkg_vec_free(depends);
302
303 /* restore dependencies_checked marks */
304 for (i = 0; i < all->len; i++)
305 all->pkgs[i]->parent->dependencies_checked = all->pkgs[i]->parent->prev_dependencies_checked;
306
307 pkg_vec_free(all);
308
309 return res;
310 }
311
312 pkg_t *pkg_hash_fetch_best_installation_candidate(abstract_pkg_t * apkg,
313 int (*constraint_fcn) (pkg_t *
314 pkg,
315 void
316 *cdata),
317 void *cdata, int quiet)
318 {
319 int i, j;
320 int nprovides = 0;
321 int nmatching = 0;
322 int wrong_arch_found = 0;
323 int arch_priority;
324 pkg_vec_t *matching_pkgs;
325 abstract_pkg_vec_t *matching_apkgs;
326 abstract_pkg_vec_t *provided_apkg_vec;
327 abstract_pkg_t **provided_apkgs;
328 abstract_pkg_vec_t *providers;
329 pkg_t *latest_installed_parent = NULL;
330 pkg_t *latest_matching = NULL;
331 pkg_t *priorized_matching = NULL;
332 pkg_t *held_pkg = NULL;
333 pkg_t *good_pkg_by_name = NULL;
334
335 if (apkg == NULL || apkg->provided_by == NULL
336 || (apkg->provided_by->len == 0))
337 return NULL;
338
339 matching_pkgs = pkg_vec_alloc();
340 matching_apkgs = abstract_pkg_vec_alloc();
341 providers = abstract_pkg_vec_alloc();
342
343 opkg_msg(DEBUG, "Best installation candidate for %s:\n", apkg->name);
344
345 provided_apkg_vec = apkg->provided_by;
346 nprovides = provided_apkg_vec->len;
347 provided_apkgs = provided_apkg_vec->pkgs;
348 if (nprovides > 1)
349 opkg_msg(DEBUG, "apkg=%s nprovides=%d.\n", apkg->name,
350 nprovides);
351
352 /* accumulate all the providers */
353 for (i = 0; i < nprovides; i++) {
354 abstract_pkg_t *provider_apkg = provided_apkgs[i];
355 opkg_msg(DEBUG, "Adding %s to providers.\n",
356 provider_apkg->name);
357 abstract_pkg_vec_insert(providers, provider_apkg);
358 }
359 nprovides = providers->len;
360
361 for (i = 0; i < nprovides; i++) {
362 abstract_pkg_t *provider_apkg =
363 abstract_pkg_vec_get(providers, i);
364 abstract_pkg_t *replacement_apkg = NULL;
365 pkg_vec_t *vec;
366
367 if (provider_apkg->replaced_by
368 && provider_apkg->replaced_by->len) {
369 replacement_apkg = provider_apkg->replaced_by->pkgs[0];
370 if (provider_apkg->replaced_by->len > 1) {
371 opkg_msg(NOTICE, "Multiple replacers for %s, "
372 "using first one (%s).\n",
373 provider_apkg->name,
374 replacement_apkg->name);
375 }
376 }
377
378 if (replacement_apkg)
379 opkg_msg(DEBUG,
380 "replacement_apkg=%s for provider_apkg=%s.\n",
381 replacement_apkg->name, provider_apkg->name);
382
383 if (replacement_apkg && (replacement_apkg != provider_apkg)) {
384 if (abstract_pkg_vec_contains
385 (providers, replacement_apkg))
386 continue;
387 else
388 provider_apkg = replacement_apkg;
389 }
390
391 if (!(vec = provider_apkg->pkgs)) {
392 opkg_msg(DEBUG, "No pkgs for provider_apkg %s.\n",
393 provider_apkg->name);
394 continue;
395 }
396
397 /* now check for supported architecture */
398 {
399 int max_count = 0;
400
401 /* count packages matching max arch priority and keep track of last one */
402 for (j = 0; j < vec->len; j++) {
403 pkg_t *maybe = vec->pkgs[j];
404 arch_priority = pkg_get_arch_priority(maybe);
405
406 opkg_msg(DEBUG,
407 "%s arch=%s arch_priority=%d version=%s.\n",
408 maybe->name, pkg_get_architecture(maybe),
409 arch_priority, pkg_get_string(maybe, PKG_VERSION));
410 /* We make sure not to add the same package twice. Need to search for the reason why
411 they show up twice sometimes. */
412 if ((arch_priority > 0)
413 &&
414 (!pkg_vec_contains(matching_pkgs, maybe))
415 &&
416 (!pkg_hash_check_unresolved(maybe))) {
417 max_count++;
418 abstract_pkg_vec_insert(matching_apkgs,
419 maybe->parent);
420 pkg_vec_insert(matching_pkgs, maybe);
421 }
422 }
423
424 if (vec->len > 0 && matching_pkgs->len < 1)
425 wrong_arch_found = 1;
426 }
427 }
428
429 if (matching_pkgs->len < 1) {
430 if (wrong_arch_found)
431 opkg_msg(ERROR, "Packages for %s found, but"
432 " incompatible with the architectures configured\n",
433 apkg->name);
434 pkg_vec_free(matching_pkgs);
435 abstract_pkg_vec_free(matching_apkgs);
436 abstract_pkg_vec_free(providers);
437 return NULL;
438 }
439
440 if (matching_pkgs->len > 1)
441 pkg_vec_sort(matching_pkgs,
442 pkg_name_version_and_architecture_compare);
443 if (matching_apkgs->len > 1)
444 abstract_pkg_vec_sort(matching_apkgs, abstract_pkg_name_compare);
445
446 for (i = 0; i < matching_pkgs->len; i++) {
447 pkg_t *matching = matching_pkgs->pkgs[i];
448 if (constraint_fcn(matching, cdata)) {
449 opkg_msg(DEBUG, "Candidate: %s %s.\n",
450 matching->name, pkg_get_string(matching, PKG_VERSION));
451 good_pkg_by_name = matching;
452 /* It has been provided by hand, so it is what user want */
453 if (matching->provided_by_hand == 1)
454 break;
455 }
456 }
457
458 for (i = 0; i < matching_pkgs->len; i++) {
459 pkg_t *matching = matching_pkgs->pkgs[i];
460 latest_matching = matching;
461 if (matching->parent->state_status == SS_INSTALLED
462 || matching->parent->state_status == SS_UNPACKED)
463 latest_installed_parent = matching;
464 if (matching->state_flag & (SF_HOLD | SF_PREFER)) {
465 if (held_pkg)
466 opkg_msg(NOTICE,
467 "Multiple packages (%s and %s) providing"
468 " same name marked HOLD or PREFER. "
469 "Using latest.\n", held_pkg->name,
470 matching->name);
471 held_pkg = matching;
472 }
473 }
474
475 if (!good_pkg_by_name && !held_pkg && !latest_installed_parent
476 && matching_apkgs->len > 1 && !quiet) {
477 int prio = 0;
478 for (i = 0; i < matching_pkgs->len; i++) {
479 pkg_t *matching = matching_pkgs->pkgs[i];
480 arch_priority = pkg_get_arch_priority(matching);
481 if (arch_priority > prio) {
482 priorized_matching = matching;
483 prio = arch_priority;
484 opkg_msg(DEBUG, "Match %s with priority %i.\n",
485 matching->name, prio);
486 }
487 }
488
489 }
490
491 if (conf->verbosity >= INFO && matching_apkgs->len > 1) {
492 opkg_msg(INFO, "%d matching pkgs for apkg=%s:\n",
493 matching_pkgs->len, apkg->name);
494 for (i = 0; i < matching_pkgs->len; i++) {
495 pkg_t *matching = matching_pkgs->pkgs[i];
496 opkg_msg(INFO, "%s %s %s\n",
497 matching->name, pkg_get_string(matching, PKG_VERSION),
498 pkg_get_architecture(matching));
499 }
500 }
501
502 nmatching = matching_apkgs->len;
503
504 pkg_vec_free(matching_pkgs);
505 abstract_pkg_vec_free(matching_apkgs);
506 abstract_pkg_vec_free(providers);
507
508 if (good_pkg_by_name) { /* We found a good candidate, we will install it */
509 return good_pkg_by_name;
510 }
511 if (held_pkg) {
512 opkg_msg(INFO, "Using held package %s.\n", held_pkg->name);
513 return held_pkg;
514 }
515 if (latest_installed_parent) {
516 opkg_msg(INFO,
517 "Using latest version of installed package %s.\n",
518 latest_installed_parent->name);
519 return latest_installed_parent;
520 }
521 if (priorized_matching) {
522 opkg_msg(INFO, "Using priorized matching %s %s %s.\n",
523 priorized_matching->name, pkg_get_string(priorized_matching, PKG_VERSION),
524 pkg_get_architecture(priorized_matching));
525 return priorized_matching;
526 }
527 if (nmatching > 1) {
528 opkg_msg(INFO, "No matching pkg out of %d matching_apkgs.\n",
529 nmatching);
530 return NULL;
531 }
532 if (latest_matching) {
533 opkg_msg(INFO, "Using latest matching %s %s %s.\n",
534 latest_matching->name, pkg_get_string(latest_matching, PKG_VERSION),
535 pkg_get_architecture(latest_matching));
536 return latest_matching;
537 }
538 return NULL;
539 }
540
541 static int pkg_name_constraint_fcn(pkg_t * pkg, void *cdata)
542 {
543 const char *name = (const char *)cdata;
544
545 if (strcmp(pkg->name, name) == 0)
546 return 1;
547 else
548 return 0;
549 }
550
551 static pkg_vec_t *pkg_vec_fetch_by_name(const char *pkg_name)
552 {
553 abstract_pkg_t *ab_pkg;
554
555 if (!(ab_pkg = abstract_pkg_fetch_by_name(pkg_name)))
556 return NULL;
557
558 if (ab_pkg->pkgs)
559 return ab_pkg->pkgs;
560
561 if (ab_pkg->provided_by) {
562 abstract_pkg_t *abpkg =
563 abstract_pkg_vec_get(ab_pkg->provided_by, 0);
564 if (abpkg != NULL)
565 return abpkg->pkgs;
566 else
567 return ab_pkg->pkgs;
568 }
569
570 return NULL;
571 }
572
573 pkg_t *pkg_hash_fetch_best_installation_candidate_by_name(const char *name)
574 {
575 abstract_pkg_t *apkg = NULL;
576
577 if (!(apkg = abstract_pkg_fetch_by_name(name)))
578 return NULL;
579
580 return pkg_hash_fetch_best_installation_candidate(apkg,
581 pkg_name_constraint_fcn,
582 apkg->name, 0);
583 }
584
585 pkg_t *pkg_hash_fetch_by_name_version(const char *pkg_name, const char *version)
586 {
587 pkg_vec_t *vec;
588 int i;
589 char *version_str = NULL;
590
591 if (!(vec = pkg_vec_fetch_by_name(pkg_name)))
592 return NULL;
593
594 for (i = 0; i < vec->len; i++) {
595 version_str = pkg_version_str_alloc(vec->pkgs[i]);
596 if (!strcmp(version_str, version)) {
597 free(version_str);
598 break;
599 }
600 free(version_str);
601 }
602
603 if (i == vec->len)
604 return NULL;
605
606 return vec->pkgs[i];
607 }
608
609 pkg_t *pkg_hash_fetch_installed_by_name_dest(const char *pkg_name,
610 pkg_dest_t * dest)
611 {
612 pkg_vec_t *vec;
613 int i;
614
615 if (!(vec = pkg_vec_fetch_by_name(pkg_name))) {
616 return NULL;
617 }
618
619 for (i = 0; i < vec->len; i++)
620 if ((vec->pkgs[i]->state_status == SS_INSTALLED
621 || vec->pkgs[i]->state_status == SS_UNPACKED)
622 && vec->pkgs[i]->dest == dest) {
623 return vec->pkgs[i];
624 }
625
626 return NULL;
627 }
628
629 pkg_t *pkg_hash_fetch_installed_by_name(const char *pkg_name)
630 {
631 pkg_vec_t *vec;
632 int i;
633
634 if (!(vec = pkg_vec_fetch_by_name(pkg_name))) {
635 return NULL;
636 }
637
638 for (i = 0; i < vec->len; i++) {
639 if (vec->pkgs[i]->state_status == SS_INSTALLED
640 || vec->pkgs[i]->state_status == SS_UNPACKED) {
641 return vec->pkgs[i];
642 }
643 }
644
645 return NULL;
646 }
647
648 static void
649 pkg_hash_fetch_available_helper(const char *pkg_name, void *entry, void *data)
650 {
651 int j;
652 abstract_pkg_t *ab_pkg = (abstract_pkg_t *) entry;
653 pkg_vec_t *all = (pkg_vec_t *) data;
654 pkg_vec_t *pkg_vec = ab_pkg->pkgs;
655
656 if (!pkg_vec)
657 return;
658
659 for (j = 0; j < pkg_vec->len; j++) {
660 pkg_t *pkg = pkg_vec->pkgs[j];
661 pkg_vec_insert(all, pkg);
662 }
663 }
664
665 void pkg_hash_fetch_available(pkg_vec_t * all)
666 {
667 hash_table_foreach(&conf->pkg_hash, pkg_hash_fetch_available_helper,
668 all);
669 }
670
671 static void
672 pkg_hash_fetch_all_installed_helper(const char *pkg_name, void *entry,
673 void *data)
674 {
675 abstract_pkg_t *ab_pkg = (abstract_pkg_t *) entry;
676 pkg_vec_t *all = (pkg_vec_t *) data;
677 pkg_vec_t *pkg_vec = ab_pkg->pkgs;
678 int j;
679
680 if (!pkg_vec)
681 return;
682
683 for (j = 0; j < pkg_vec->len; j++) {
684 pkg_t *pkg = pkg_vec->pkgs[j];
685 if (pkg->state_status == SS_INSTALLED
686 || pkg->state_status == SS_UNPACKED)
687 pkg_vec_insert(all, pkg);
688 }
689 }
690
691 void pkg_hash_fetch_all_installed(pkg_vec_t * all)
692 {
693 hash_table_foreach(&conf->pkg_hash, pkg_hash_fetch_all_installed_helper,
694 all);
695 }
696
697 /*
698 * This assumes that the abstract pkg doesn't exist.
699 */
700 static abstract_pkg_t *add_new_abstract_pkg_by_name(const char *pkg_name)
701 {
702 abstract_pkg_t *ab_pkg;
703
704 ab_pkg = abstract_pkg_new();
705
706 ab_pkg->name = xstrdup(pkg_name);
707 hash_table_insert(&conf->pkg_hash, pkg_name, ab_pkg);
708
709 return ab_pkg;
710 }
711
712 abstract_pkg_t *ensure_abstract_pkg_by_name(const char *pkg_name)
713 {
714 abstract_pkg_t *ab_pkg;
715
716 if (!(ab_pkg = abstract_pkg_fetch_by_name(pkg_name)))
717 ab_pkg = add_new_abstract_pkg_by_name(pkg_name);
718
719 return ab_pkg;
720 }
721
722 void hash_insert_pkg(pkg_t * pkg, int set_status)
723 {
724 abstract_pkg_t *ab_pkg;
725
726 ab_pkg = ensure_abstract_pkg_by_name(pkg->name);
727 if (!ab_pkg->pkgs)
728 ab_pkg->pkgs = pkg_vec_alloc();
729
730 if (pkg->state_status == SS_INSTALLED) {
731 ab_pkg->state_status = SS_INSTALLED;
732 } else if (pkg->state_status == SS_UNPACKED) {
733 ab_pkg->state_status = SS_UNPACKED;
734 }
735
736 buildDepends(pkg);
737
738 buildProvides(ab_pkg, pkg);
739
740 init_providelist(pkg, NULL);
741
742 /* Need to build the conflicts graph before replaces for correct
743 * calculation of replaced_by relation.
744 */
745 buildConflicts(pkg);
746
747 buildReplaces(ab_pkg, pkg);
748
749 buildDependedUponBy(pkg, ab_pkg);
750
751 pkg_vec_insert_merge(ab_pkg->pkgs, pkg, set_status);
752 pkg->parent = ab_pkg;
753 }
754
755 static const char *strip_offline_root(const char *file_name)
756 {
757 unsigned int len;
758
759 if (conf->offline_root) {
760 len = strlen(conf->offline_root);
761 if (strncmp(file_name, conf->offline_root, len) == 0)
762 file_name += len;
763 }
764
765 return file_name;
766 }
767
768 void file_hash_remove(const char *file_name)
769 {
770 file_name = strip_offline_root(file_name);
771 hash_table_remove(&conf->file_hash, file_name);
772 }
773
774 pkg_t *file_hash_get_file_owner(const char *file_name)
775 {
776 file_name = strip_offline_root(file_name);
777 return hash_table_get(&conf->file_hash, file_name);
778 }
779
780 void file_hash_set_file_owner(const char *file_name, pkg_t * owning_pkg)
781 {
782 pkg_t *old_owning_pkg;
783 int file_name_len = strlen(file_name);
784
785 if (file_name[file_name_len - 1] == '/')
786 return;
787
788 file_name = strip_offline_root(file_name);
789
790 old_owning_pkg = hash_table_get(&conf->file_hash, file_name);
791 hash_table_insert(&conf->file_hash, file_name, owning_pkg);
792
793 if (old_owning_pkg) {
794 pkg_get_installed_files(old_owning_pkg);
795 str_list_remove_elt(old_owning_pkg->installed_files, file_name);
796 pkg_free_installed_files(old_owning_pkg);
797
798 /* mark this package to have its filelist written */
799 old_owning_pkg->state_flag |= SF_FILELIST_CHANGED;
800 owning_pkg->state_flag |= SF_FILELIST_CHANGED;
801 }
802 }