Merge commit 'grg' into HEAD
[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 "includes.h"
19 #include <errno.h>
20 #include <ctype.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include "hash_table.h"
25 #include "pkg.h"
26 #include "opkg_message.h"
27 #include "pkg_vec.h"
28 #include "pkg_hash.h"
29 #include "pkg_parse.h"
30 #include "opkg_utils.h"
31 #include "libbb/libbb.h"
32
33 void
34 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
41 free_pkgs(const char *key, void *entry, void *data)
42 {
43 int i;
44 abstract_pkg_t *ab_pkg;
45
46 /* Each entry in the hash table is an abstract package, which contains
47 * a list of packages that provide the abstract package.
48 */
49
50 ab_pkg = (abstract_pkg_t*) entry;
51
52 if (ab_pkg->pkgs) {
53 for (i = 0; i < ab_pkg->pkgs->len; i++) {
54 pkg_deinit (ab_pkg->pkgs->pkgs[i]);
55 free (ab_pkg->pkgs->pkgs[i]);
56 }
57 }
58
59 abstract_pkg_vec_free (ab_pkg->provided_by);
60 abstract_pkg_vec_free (ab_pkg->replaced_by);
61 pkg_vec_free (ab_pkg->pkgs);
62 free (ab_pkg->depended_upon_by);
63 free (ab_pkg->name);
64 free (ab_pkg);
65 }
66
67 void
68 pkg_hash_deinit(void)
69 {
70 hash_table_foreach(&conf->pkg_hash, free_pkgs, NULL);
71 hash_table_deinit(&conf->pkg_hash);
72 }
73
74 int
75 pkg_hash_add_from_file(const char *file_name,
76 pkg_src_t *src, pkg_dest_t *dest, int is_status_file)
77 {
78 pkg_t *pkg;
79 FILE *fp;
80 char *buf;
81 const size_t len = 4096;
82 int ret = 0;
83
84 fp = fopen(file_name, "r");
85 if (fp == NULL) {
86 opkg_perror(ERROR, "Failed to open %s", file_name);
87 return -1;
88 }
89
90 buf = xmalloc(len);
91
92 do {
93 pkg = pkg_new();
94 pkg->src = src;
95 pkg->dest = dest;
96
97 ret = pkg_parse_from_stream_nomalloc(pkg, fp, 0,
98 &buf, len);
99 if (ret) {
100 pkg_deinit (pkg);
101 free(pkg);
102 if (ret == -1)
103 break;
104 if (ret == 1)
105 /* Probably a blank line, continue parsing. */
106 ret = 0;
107 continue;
108 }
109
110 if (!pkg->architecture) {
111 char *version_str = pkg_version_str_alloc(pkg);
112 opkg_msg(ERROR, "Package %s version %s has no "
113 "architecture specified, ignoring.\n",
114 pkg->name, version_str);
115 free(version_str);
116 continue;
117 }
118
119 hash_insert_pkg(pkg, is_status_file);
120
121 } while (!feof(fp));
122
123 free(buf);
124 fclose(fp);
125
126 return ret;
127 }
128
129 static abstract_pkg_t *
130 abstract_pkg_fetch_by_name(const char * pkg_name)
131 {
132 return (abstract_pkg_t *)hash_table_get(&conf->pkg_hash, pkg_name);
133 }
134
135 pkg_t *
136 pkg_hash_fetch_best_installation_candidate(abstract_pkg_t *apkg,
137 int (*constraint_fcn)(pkg_t *pkg, void *cdata),
138 void *cdata, int quiet)
139 {
140 int i;
141 int nprovides = 0;
142 int nmatching = 0;
143 int wrong_arch_found = 0;
144 pkg_vec_t *matching_pkgs;
145 abstract_pkg_vec_t *matching_apkgs;
146 abstract_pkg_vec_t *provided_apkg_vec;
147 abstract_pkg_t **provided_apkgs;
148 abstract_pkg_vec_t *providers;
149 pkg_t *latest_installed_parent = NULL;
150 pkg_t *latest_matching = NULL;
151 pkg_t *priorized_matching = NULL;
152 pkg_t *held_pkg = NULL;
153 pkg_t *good_pkg_by_name = NULL;
154
155 if (apkg == NULL || apkg->provided_by == NULL || (apkg->provided_by->len == 0))
156 return NULL;
157
158 matching_pkgs = pkg_vec_alloc();
159 matching_apkgs = abstract_pkg_vec_alloc();
160 providers = abstract_pkg_vec_alloc();
161
162 opkg_msg(DEBUG, "Best installation candidate for %s:\n", apkg->name);
163
164 provided_apkg_vec = apkg->provided_by;
165 nprovides = provided_apkg_vec->len;
166 provided_apkgs = provided_apkg_vec->pkgs;
167 if (nprovides > 1)
168 opkg_msg(DEBUG, "apkg=%s nprovides=%d.\n", apkg->name, nprovides);
169
170 /* accumulate all the providers */
171 for (i = 0; i < nprovides; i++) {
172 abstract_pkg_t *provider_apkg = provided_apkgs[i];
173 opkg_msg(DEBUG, "Adding %s to providers.\n", provider_apkg->name);
174 abstract_pkg_vec_insert(providers, provider_apkg);
175 }
176 nprovides = providers->len;
177
178 for (i = 0; i < nprovides; i++) {
179 abstract_pkg_t *provider_apkg = abstract_pkg_vec_get(providers, i);
180 abstract_pkg_t *replacement_apkg = NULL;
181 pkg_vec_t *vec;
182
183 if (provider_apkg->replaced_by && provider_apkg->replaced_by->len) {
184 replacement_apkg = provider_apkg->replaced_by->pkgs[0];
185 if (provider_apkg->replaced_by->len > 1) {
186 opkg_msg(NOTICE, "Multiple replacers for %s, "
187 "using first one (%s).\n",
188 provider_apkg->name, replacement_apkg->name);
189 }
190 }
191
192 if (replacement_apkg)
193 opkg_msg(DEBUG, "replacement_apkg=%s for provider_apkg=%s.\n",
194 replacement_apkg->name, provider_apkg->name);
195
196 if (replacement_apkg && (replacement_apkg != provider_apkg)) {
197 if (abstract_pkg_vec_contains(providers, replacement_apkg))
198 continue;
199 else
200 provider_apkg = replacement_apkg;
201 }
202
203 if (!(vec = provider_apkg->pkgs)) {
204 opkg_msg(DEBUG, "No pkgs for provider_apkg %s.\n",
205 provider_apkg->name);
206 continue;
207 }
208
209
210 /* now check for supported architecture */
211 {
212 int max_count = 0;
213
214 /* count packages matching max arch priority and keep track of last one */
215 for (i = 0; i < vec->len; i++) {
216 pkg_t *maybe = vec->pkgs[i];
217 opkg_msg(DEBUG, "%s arch=%s arch_priority=%d version=%s.\n",
218 maybe->name, maybe->architecture,
219 maybe->arch_priority, maybe->version);
220 /* We make sure not to add the same package twice. Need to search for the reason why
221 they show up twice sometimes. */
222 if ((maybe->arch_priority > 0) && (! pkg_vec_contains(matching_pkgs, maybe))) {
223 max_count++;
224 abstract_pkg_vec_insert(matching_apkgs, maybe->parent);
225 pkg_vec_insert(matching_pkgs, maybe);
226 }
227 }
228
229 if (vec->len > 0 && matching_pkgs->len < 1)
230 wrong_arch_found = 1;
231 }
232 }
233
234 if (matching_pkgs->len < 1) {
235 if (wrong_arch_found)
236 opkg_msg(ERROR, "Packages for %s found, but"
237 " incompatible with the architectures configured\n",
238 apkg->name);
239 pkg_vec_free(matching_pkgs);
240 abstract_pkg_vec_free(matching_apkgs);
241 abstract_pkg_vec_free(providers);
242 return NULL;
243 }
244
245
246 if (matching_pkgs->len > 1)
247 pkg_vec_sort(matching_pkgs, pkg_name_version_and_architecture_compare);
248 if (matching_apkgs->len > 1)
249 abstract_pkg_vec_sort(matching_pkgs, abstract_pkg_name_compare);
250
251 for (i = 0; i < matching_pkgs->len; i++) {
252 pkg_t *matching = matching_pkgs->pkgs[i];
253 if (constraint_fcn(matching, cdata)) {
254 opkg_msg(DEBUG, "Candidate: %s %s.\n",
255 matching->name, matching->version) ;
256 good_pkg_by_name = matching;
257 /* It has been provided by hand, so it is what user want */
258 if (matching->provided_by_hand == 1)
259 break;
260 }
261 }
262
263
264 for (i = 0; i < matching_pkgs->len; i++) {
265 pkg_t *matching = matching_pkgs->pkgs[i];
266 latest_matching = matching;
267 if (matching->parent->state_status == SS_INSTALLED || matching->parent->state_status == SS_UNPACKED)
268 latest_installed_parent = matching;
269 if (matching->state_flag & (SF_HOLD|SF_PREFER)) {
270 if (held_pkg)
271 opkg_msg(NOTICE, "Multiple packages (%s and %s) providing"
272 " same name marked HOLD or PREFER. "
273 "Using latest.\n",
274 held_pkg->name, matching->name);
275 held_pkg = matching;
276 }
277 }
278
279 if (!good_pkg_by_name && !held_pkg && !latest_installed_parent && matching_apkgs->len > 1 && !quiet) {
280 int prio = 0;
281 for (i = 0; i < matching_pkgs->len; i++) {
282 pkg_t *matching = matching_pkgs->pkgs[i];
283 if (matching->arch_priority > prio) {
284 priorized_matching = matching;
285 prio = matching->arch_priority;
286 opkg_msg(DEBUG, "Match %s with priority %i.\n",
287 matching->name, prio);
288 }
289 }
290
291 }
292
293 if (conf->verbosity >= INFO && matching_apkgs->len > 1) {
294 opkg_msg(INFO, "%d matching pkgs for apkg=%s:\n",
295 matching_pkgs->len, apkg->name);
296 for (i = 0; i < matching_pkgs->len; i++) {
297 pkg_t *matching = matching_pkgs->pkgs[i];
298 opkg_msg(INFO, "%s %s %s\n",
299 matching->name, matching->version,
300 matching->architecture);
301 }
302 }
303
304 nmatching = matching_apkgs->len;
305
306 pkg_vec_free(matching_pkgs);
307 abstract_pkg_vec_free(matching_apkgs);
308 abstract_pkg_vec_free(providers);
309
310 if (good_pkg_by_name) { /* We found a good candidate, we will install it */
311 return good_pkg_by_name;
312 }
313 if (held_pkg) {
314 opkg_msg(INFO, "Using held package %s.\n", held_pkg->name);
315 return held_pkg;
316 }
317 if (latest_installed_parent) {
318 opkg_msg(INFO, "Using latest version of installed package %s.\n",
319 latest_installed_parent->name);
320 return latest_installed_parent;
321 }
322 if (priorized_matching) {
323 opkg_msg(INFO, "Using priorized matching %s %s %s.\n",
324 priorized_matching->name, priorized_matching->version,
325 priorized_matching->architecture);
326 return priorized_matching;
327 }
328 if (nmatching > 1) {
329 opkg_msg(INFO, "No matching pkg out of %d matching_apkgs.\n",
330 nmatching);
331 return NULL;
332 }
333 if (latest_matching) {
334 opkg_msg(INFO, "Using latest matching %s %s %s.\n",
335 latest_matching->name, latest_matching->version,
336 latest_matching->architecture);
337 return latest_matching;
338 }
339 return NULL;
340 }
341
342 static int
343 pkg_name_constraint_fcn(pkg_t *pkg, void *cdata)
344 {
345 const char *name = (const char *)cdata;
346
347 if (strcmp(pkg->name, name) == 0)
348 return 1;
349 else
350 return 0;
351 }
352
353 static pkg_vec_t *
354 pkg_vec_fetch_by_name(const char *pkg_name)
355 {
356 abstract_pkg_t * ab_pkg;
357
358 if(!(ab_pkg = abstract_pkg_fetch_by_name(pkg_name)))
359 return NULL;
360
361 if (ab_pkg->pkgs)
362 return ab_pkg->pkgs;
363
364 if (ab_pkg->provided_by) {
365 abstract_pkg_t *abpkg = abstract_pkg_vec_get(ab_pkg->provided_by, 0);
366 if (abpkg != NULL)
367 return abpkg->pkgs;
368 else
369 return ab_pkg->pkgs;
370 }
371
372 return NULL;
373 }
374
375
376 pkg_t *
377 pkg_hash_fetch_best_installation_candidate_by_name(const char *name)
378 {
379 abstract_pkg_t *apkg = NULL;
380
381 if (!(apkg = abstract_pkg_fetch_by_name(name)))
382 return NULL;
383
384 return pkg_hash_fetch_best_installation_candidate(apkg,
385 pkg_name_constraint_fcn, apkg->name, 0);
386 }
387
388
389 pkg_t *
390 pkg_hash_fetch_by_name_version(const char *pkg_name, const char * version)
391 {
392 pkg_vec_t * vec;
393 int i;
394 char *version_str = NULL;
395
396 if(!(vec = pkg_vec_fetch_by_name(pkg_name)))
397 return NULL;
398
399 for(i = 0; i < vec->len; i++) {
400 version_str = pkg_version_str_alloc(vec->pkgs[i]);
401 if(!strcmp(version_str, version)) {
402 free(version_str);
403 break;
404 }
405 free(version_str);
406 }
407
408 if(i == vec->len)
409 return NULL;
410
411 return vec->pkgs[i];
412 }
413
414 pkg_t *
415 pkg_hash_fetch_installed_by_name_dest(const char *pkg_name, pkg_dest_t *dest)
416 {
417 pkg_vec_t * vec;
418 int i;
419
420 if (!(vec = pkg_vec_fetch_by_name(pkg_name))) {
421 return NULL;
422 }
423
424 for (i = 0; i < vec->len; i++)
425 if((vec->pkgs[i]->state_status == SS_INSTALLED
426 || vec->pkgs[i]->state_status == SS_UNPACKED)
427 && vec->pkgs[i]->dest == dest) {
428 return vec->pkgs[i];
429 }
430
431 return NULL;
432 }
433
434 pkg_t *
435 pkg_hash_fetch_installed_by_name(const char *pkg_name)
436 {
437 pkg_vec_t * vec;
438 int i;
439
440 if (!(vec = pkg_vec_fetch_by_name(pkg_name))) {
441 return NULL;
442 }
443
444 for (i = 0; i < vec->len; i++) {
445 if (vec->pkgs[i]->state_status == SS_INSTALLED
446 || vec->pkgs[i]->state_status == SS_UNPACKED) {
447 return vec->pkgs[i];
448 }
449 }
450
451 return NULL;
452 }
453
454
455 static void
456 pkg_hash_fetch_available_helper(const char *pkg_name, void *entry, void *data)
457 {
458 int j;
459 abstract_pkg_t *ab_pkg = (abstract_pkg_t *)entry;
460 pkg_vec_t *all = (pkg_vec_t *)data;
461 pkg_vec_t *pkg_vec = ab_pkg->pkgs;
462
463 if (!pkg_vec)
464 return;
465
466 for (j = 0; j < pkg_vec->len; j++) {
467 pkg_t *pkg = pkg_vec->pkgs[j];
468 pkg_vec_insert(all, pkg);
469 }
470 }
471
472 void
473 pkg_hash_fetch_available(pkg_vec_t *all)
474 {
475 hash_table_foreach(&conf->pkg_hash, pkg_hash_fetch_available_helper,
476 all);
477 }
478
479 static void
480 pkg_hash_fetch_all_installed_helper(const char *pkg_name, void *entry, void *data)
481 {
482 abstract_pkg_t *ab_pkg = (abstract_pkg_t *)entry;
483 pkg_vec_t *all = (pkg_vec_t *)data;
484 pkg_vec_t *pkg_vec = ab_pkg->pkgs;
485 int j;
486
487 if (!pkg_vec)
488 return;
489
490 for (j = 0; j < pkg_vec->len; j++) {
491 pkg_t *pkg = pkg_vec->pkgs[j];
492 if (pkg->state_status == SS_INSTALLED
493 || pkg->state_status == SS_UNPACKED)
494 pkg_vec_insert(all, pkg);
495 }
496 }
497
498 void
499 pkg_hash_fetch_all_installed(pkg_vec_t *all)
500 {
501 hash_table_foreach(&conf->pkg_hash, pkg_hash_fetch_all_installed_helper,
502 all);
503 }
504
505 /*
506 * This assumes that the abstract pkg doesn't exist.
507 */
508 static abstract_pkg_t *
509 add_new_abstract_pkg_by_name(const char *pkg_name)
510 {
511 abstract_pkg_t *ab_pkg;
512
513 ab_pkg = abstract_pkg_new();
514
515 ab_pkg->name = xstrdup(pkg_name);
516 hash_table_insert(&conf->pkg_hash, pkg_name, ab_pkg);
517
518 return ab_pkg;
519 }
520
521
522 abstract_pkg_t *
523 ensure_abstract_pkg_by_name(const char *pkg_name)
524 {
525 abstract_pkg_t * ab_pkg;
526
527 if (!(ab_pkg = abstract_pkg_fetch_by_name(pkg_name)))
528 ab_pkg = add_new_abstract_pkg_by_name(pkg_name);
529
530 return ab_pkg;
531 }
532
533 void
534 hash_insert_pkg(pkg_t *pkg, int set_status)
535 {
536 abstract_pkg_t * ab_pkg;
537
538 ab_pkg = ensure_abstract_pkg_by_name(pkg->name);
539 if (!ab_pkg->pkgs)
540 ab_pkg->pkgs = pkg_vec_alloc();
541
542 if (pkg->state_status == SS_INSTALLED) {
543 ab_pkg->state_status = SS_INSTALLED;
544 } else if (pkg->state_status == SS_UNPACKED) {
545 ab_pkg->state_status = SS_UNPACKED;
546 }
547
548 buildDepends(pkg);
549
550 buildProvides(ab_pkg, pkg);
551
552 /* Need to build the conflicts graph before replaces for correct
553 * calculation of replaced_by relation.
554 */
555 buildConflicts(pkg);
556
557 buildReplaces(ab_pkg, pkg);
558
559 buildDependedUponBy(pkg, ab_pkg);
560
561 pkg_vec_insert_merge(ab_pkg->pkgs, pkg, set_status);
562 pkg->parent = ab_pkg;
563 }
564
565
566 pkg_t *
567 file_hash_get_file_owner(const char *file_name)
568 {
569 return hash_table_get(&conf->file_hash, file_name);
570 }
571
572 void
573 file_hash_set_file_owner(const char *file_name, pkg_t *owning_pkg)
574 {
575 pkg_t *old_owning_pkg = hash_table_get(&conf->file_hash, file_name);
576 int file_name_len = strlen(file_name);
577
578 if (file_name[file_name_len -1] == '/')
579 return;
580
581 if (conf->offline_root) {
582 unsigned int len = strlen(conf->offline_root);
583 if (strncmp(file_name, conf->offline_root, len) == 0) {
584 file_name += len;
585 }
586 }
587
588 hash_table_insert(&conf->file_hash, file_name, owning_pkg);
589
590 if (old_owning_pkg) {
591 pkg_get_installed_files(old_owning_pkg);
592 str_list_remove_elt(old_owning_pkg->installed_files, file_name);
593 pkg_free_installed_files(old_owning_pkg);
594
595 /* mark this package to have its filelist written */
596 old_owning_pkg->state_flag |= SF_FILELIST_CHANGED;
597 owning_pkg->state_flag |= SF_FILELIST_CHANGED;
598 }
599 }