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