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