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