Fix leak in error path.
[oweals/opkg-lede.git] / libopkg / pkg.c
1 /* pkg.c - the opkg package management system
2
3    Carl D. Worth
4
5    Copyright (C) 2001 University of Southern California
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 <ctype.h>
20 #include <alloca.h>
21 #include <string.h>
22 #include <stdbool.h>
23 #include <errno.h>
24
25 #include "pkg.h"
26
27 #include "pkg_parse.h"
28 #include "pkg_extract.h"
29 #include "opkg_message.h"
30 #include "opkg_utils.h"
31
32 #include "libbb/libbb.h"
33 #include "sprintf_alloc.h"
34 #include "file_util.h"
35 #include "str_util.h"
36 #include "xsystem.h"
37 #include "opkg_conf.h"
38
39 typedef struct enum_map enum_map_t;
40 struct enum_map
41 {
42      int value;
43      char *str;
44 };
45
46 static const enum_map_t pkg_state_want_map[] = {
47      { SW_UNKNOWN, "unknown"},
48      { SW_INSTALL, "install"},
49      { SW_DEINSTALL, "deinstall"},
50      { SW_PURGE, "purge"}
51 };
52
53 static const enum_map_t pkg_state_flag_map[] = {
54      { SF_OK, "ok"},
55      { SF_REINSTREQ, "reinstreq"},
56      { SF_HOLD, "hold"},
57      { SF_REPLACE, "replace"},
58      { SF_NOPRUNE, "noprune"},
59      { SF_PREFER, "prefer"},
60      { SF_OBSOLETE, "obsolete"},
61      { SF_USER, "user"},
62 };
63
64 static const enum_map_t pkg_state_status_map[] = {
65      { SS_NOT_INSTALLED, "not-installed" },
66      { SS_UNPACKED, "unpacked" },
67      { SS_HALF_CONFIGURED, "half-configured" },
68      { SS_INSTALLED, "installed" },
69      { SS_HALF_INSTALLED, "half-installed" },
70      { SS_CONFIG_FILES, "config-files" },
71      { SS_POST_INST_FAILED, "post-inst-failed" },
72      { SS_REMOVAL_FAILED, "removal-failed" }
73 };
74
75 static int verrevcmp(const char *val, const char *ref);
76
77
78 pkg_t *pkg_new(void)
79 {
80      pkg_t *pkg;
81
82      pkg = xcalloc(1, sizeof(pkg_t));
83      pkg_init(pkg);
84
85      return pkg;
86 }
87
88 int pkg_init(pkg_t *pkg)
89 {
90      pkg->name = NULL;
91      pkg->epoch = 0;
92      pkg->version = NULL;
93      pkg->revision = NULL;
94      pkg->dest = NULL;
95      pkg->src = NULL;
96      pkg->architecture = NULL;
97      pkg->maintainer = NULL;
98      pkg->section = NULL;
99      pkg->description = NULL;
100      pkg->state_want = SW_UNKNOWN;
101      pkg->state_flag = SF_OK;
102      pkg->state_status = SS_NOT_INSTALLED;
103      pkg->depends_str = NULL;
104      pkg->provides_str = NULL;
105      pkg->depends_count = 0;
106      pkg->depends = NULL;
107      pkg->suggests_str = NULL;
108      pkg->recommends_str = NULL;
109      pkg->suggests_count = 0;
110      pkg->recommends_count = 0;
111      
112      active_list_init(&pkg->list);
113
114      /* Abhaya: added init for conflicts fields */
115      pkg->conflicts = NULL;
116      pkg->conflicts_count = 0;
117
118      /* added for replaces.  Jamey 7/23/2002 */
119      pkg->replaces = NULL;
120      pkg->replaces_count = 0;
121     
122      pkg->pre_depends_count = 0;
123      pkg->pre_depends_str = NULL;
124      pkg->provides_count = 0;
125      pkg->provides = NULL;
126      pkg->filename = NULL;
127      pkg->local_filename = NULL;
128      pkg->tmp_unpack_dir = NULL;
129      pkg->md5sum = NULL;
130 #if defined HAVE_SHA256
131      pkg->sha256sum = NULL;
132 #endif
133      pkg->size = NULL;
134      pkg->installed_size = NULL;
135      pkg->priority = NULL;
136      pkg->source = NULL;
137      conffile_list_init(&pkg->conffiles);
138      pkg->installed_files = NULL;
139      pkg->installed_files_ref_cnt = 0;
140      pkg->essential = 0;
141      pkg->provided_by_hand = 0;
142
143      return 0;
144 }
145
146 void compound_depend_deinit (compound_depend_t *depends)
147 {
148     int i;
149     for (i = 0; i < depends->possibility_count; i++)
150     {
151         depend_t *d;
152         d = depends->possibilities[i];
153         free (d->version);
154         free (d);
155     }
156     free (depends->possibilities);
157 }
158
159 void pkg_deinit(pkg_t *pkg)
160 {
161         int i;
162
163         if (pkg->name)
164                 free(pkg->name);
165         pkg->name = NULL;
166
167         pkg->epoch = 0;
168
169         if (pkg->version)
170                 free(pkg->version);
171         pkg->version = NULL;
172         /* revision shares storage with version, so don't free */
173         pkg->revision = NULL;
174
175         /* owned by opkg_conf_t */
176         pkg->dest = NULL;
177         /* owned by opkg_conf_t */
178         pkg->src = NULL;
179
180         if (pkg->architecture)
181                 free(pkg->architecture);
182         pkg->architecture = NULL;
183
184         if (pkg->maintainer)
185                 free(pkg->maintainer);
186         pkg->maintainer = NULL;
187
188         if (pkg->section)
189                 free(pkg->section);
190         pkg->section = NULL;
191
192         if (pkg->description)
193                 free(pkg->description);
194         pkg->description = NULL;
195         
196         pkg->state_want = SW_UNKNOWN;
197         pkg->state_flag = SF_OK;
198         pkg->state_status = SS_NOT_INSTALLED;
199
200         active_list_clear(&pkg->list);
201
202         if (pkg->replaces)
203                 free (pkg->replaces);
204         pkg->replaces = NULL;
205
206         for (i = 0; i < pkg->depends_count; i++)
207                 free (pkg->depends_str[i]);
208         free(pkg->depends_str);
209         pkg->depends_str = NULL;
210
211         for (i = 0; i < pkg->provides_count-1; i++)
212                 free (pkg->provides_str[i]);
213         free(pkg->provides_str);
214         pkg->provides_str = NULL;
215
216         for (i = 0; i < pkg->conflicts_count; i++)
217                 free (pkg->conflicts_str[i]);
218         free(pkg->conflicts_str);
219         pkg->conflicts_str = NULL;
220
221         for (i = 0; i < pkg->replaces_count; i++)
222                 free (pkg->replaces_str[i]);
223         free(pkg->replaces_str);
224         pkg->replaces_str = NULL;
225
226         for (i = 0; i < pkg->recommends_count; i++)
227                 free (pkg->recommends_str[i]);
228         free(pkg->recommends_str);
229         pkg->recommends_str = NULL;
230
231         for (i = 0; i < pkg->suggests_count; i++)
232                 free (pkg->suggests_str[i]);
233         free(pkg->suggests_str);
234         pkg->suggests_str = NULL;
235
236         if (pkg->depends) {
237                 int count = pkg->pre_depends_count
238                                 + pkg->depends_count
239                                 + pkg->recommends_count
240                                 + pkg->suggests_count;
241
242                 for (i=0; i<count; i++)
243                         compound_depend_deinit (&pkg->depends[i]);
244                 free (pkg->depends);
245         }
246
247         if (pkg->conflicts) {
248                 for (i=0; i<pkg->conflicts_count; i++)
249                         compound_depend_deinit (&pkg->conflicts[i]);
250                 free (pkg->conflicts);
251         }
252
253         if (pkg->provides)
254                 free (pkg->provides);
255
256         pkg->pre_depends_count = 0;
257         if (pkg->pre_depends_str)
258                 free(pkg->pre_depends_str);
259         pkg->pre_depends_str = NULL;
260         
261         pkg->provides_count = 0;
262         
263         if (pkg->filename)
264                 free(pkg->filename);
265         pkg->filename = NULL;
266         
267         if (pkg->local_filename)
268                 free(pkg->local_filename);
269         pkg->local_filename = NULL;
270
271      /* CLEANUP: It'd be nice to pullin the cleanup function from
272         opkg_install.c here. See comment in
273         opkg_install.c:cleanup_temporary_files */
274         if (pkg->tmp_unpack_dir)
275                 free(pkg->tmp_unpack_dir);
276         pkg->tmp_unpack_dir = NULL;
277
278         if (pkg->md5sum)
279                 free(pkg->md5sum);
280         pkg->md5sum = NULL;
281
282 #if defined HAVE_SHA256
283         if (pkg->sha256sum)
284                 free(pkg->sha256sum);
285         pkg->sha256sum = NULL;
286 #endif
287
288         if (pkg->size)
289                 free(pkg->size);
290         pkg->size = NULL;
291
292         if (pkg->installed_size)
293                 free(pkg->installed_size);
294         pkg->installed_size = NULL;
295
296         if (pkg->priority)
297                 free(pkg->priority);
298         pkg->priority = NULL;
299
300         if (pkg->source)
301                 free(pkg->source);
302         pkg->source = NULL;
303
304         conffile_list_deinit(&pkg->conffiles);
305
306         /* XXX: QUESTION: Is forcing this to 1 correct? I suppose so,
307         since if they are calling deinit, they should know. Maybe do an
308         assertion here instead? */
309         pkg->installed_files_ref_cnt = 1;
310         pkg_free_installed_files(pkg);
311         pkg->essential = 0;
312
313         if (pkg->tags)
314                 free (pkg->tags);
315         pkg->tags = NULL;
316 }
317
318 int pkg_init_from_file(pkg_t *pkg, const char *filename)
319 {
320      int err;
321      FILE *control_file;
322
323      err = pkg_init(pkg);
324      if (err) { return err; }
325
326      pkg->local_filename = xstrdup(filename);
327     
328      control_file = tmpfile();
329      err = pkg_extract_control_file_to_stream(pkg, control_file);
330      if (err) { return err; }
331
332      rewind(control_file);
333      pkg_parse_from_stream(pkg, control_file, PFM_ALL);
334
335      fclose(control_file);
336
337      return 0;
338 }
339
340 /* Merge any new information in newpkg into oldpkg */
341 /* XXX: CLEANUP: This function shouldn't actually modify anything in
342    newpkg, but should leave it usable. This rework is so that
343    pkg_hash_insert doesn't clobber the pkg that you pass into it. */
344 /* 
345  * uh, i thought that i had originally written this so that it took 
346  * two pkgs and returned a new one?  we can do that again... -sma
347  */
348 int pkg_merge(pkg_t *oldpkg, pkg_t *newpkg, int set_status)
349 {
350      if (oldpkg == newpkg) {
351           return 0;
352      }
353
354      if (!oldpkg->src)
355           oldpkg->src = newpkg->src;
356      if (!oldpkg->dest)
357           oldpkg->dest = newpkg->dest;
358      if (!oldpkg->architecture)
359           oldpkg->architecture = xstrdup(newpkg->architecture);
360      if (!oldpkg->arch_priority)
361           oldpkg->arch_priority = newpkg->arch_priority;
362      if (!oldpkg->section)
363           oldpkg->section = xstrdup(newpkg->section);
364      if(!oldpkg->maintainer)
365           oldpkg->maintainer = xstrdup(newpkg->maintainer);
366      if(!oldpkg->description)
367           oldpkg->description = xstrdup(newpkg->description);
368      if (set_status) {
369           /* merge the state_flags from the new package */
370           oldpkg->state_want = newpkg->state_want;
371           oldpkg->state_status = newpkg->state_status;
372           oldpkg->state_flag = newpkg->state_flag;
373      } else {
374           if (oldpkg->state_want == SW_UNKNOWN)
375                oldpkg->state_want = newpkg->state_want;
376           if (oldpkg->state_status == SS_NOT_INSTALLED)
377                oldpkg->state_status = newpkg->state_status;
378           oldpkg->state_flag |= newpkg->state_flag;
379      }
380
381      if (!oldpkg->depends_str && !oldpkg->pre_depends_str && !oldpkg->recommends_str && !oldpkg->suggests_str) {
382           oldpkg->depends_str = newpkg->depends_str;
383           newpkg->depends_str = NULL;
384           oldpkg->depends_count = newpkg->depends_count;
385           newpkg->depends_count = 0;
386
387           oldpkg->depends = newpkg->depends;
388           newpkg->depends = NULL;
389
390           oldpkg->pre_depends_str = newpkg->pre_depends_str;
391           newpkg->pre_depends_str = NULL;
392           oldpkg->pre_depends_count = newpkg->pre_depends_count;
393           newpkg->pre_depends_count = 0;
394
395           oldpkg->recommends_str = newpkg->recommends_str;
396           newpkg->recommends_str = NULL;
397           oldpkg->recommends_count = newpkg->recommends_count;
398           newpkg->recommends_count = 0;
399
400           oldpkg->suggests_str = newpkg->suggests_str;
401           newpkg->suggests_str = NULL;
402           oldpkg->suggests_count = newpkg->suggests_count;
403           newpkg->suggests_count = 0;
404      }
405
406      if (!oldpkg->provides_str) {
407           oldpkg->provides_str = newpkg->provides_str;
408           newpkg->provides_str = NULL;
409           oldpkg->provides_count = newpkg->provides_count;
410           newpkg->provides_count = 0;
411
412           if (!oldpkg->provides) {
413                 oldpkg->provides = newpkg->provides;
414                 newpkg->provides = NULL;
415           }
416      }
417
418      if (!oldpkg->conflicts_str) {
419           oldpkg->conflicts_str = newpkg->conflicts_str;
420           newpkg->conflicts_str = NULL;
421           oldpkg->conflicts_count = newpkg->conflicts_count;
422           newpkg->conflicts_count = 0;
423
424           oldpkg->conflicts = newpkg->conflicts;
425           newpkg->conflicts = NULL;
426      }
427
428      if (!oldpkg->replaces_str) {
429           oldpkg->replaces_str = newpkg->replaces_str;
430           newpkg->replaces_str = NULL;
431           oldpkg->replaces_count = newpkg->replaces_count;
432           newpkg->replaces_count = 0;
433
434           oldpkg->replaces = newpkg->replaces;
435           newpkg->replaces = NULL;
436      }
437
438      if (!oldpkg->filename)
439           oldpkg->filename = xstrdup(newpkg->filename);
440      if (!oldpkg->local_filename)
441           oldpkg->local_filename = xstrdup(newpkg->local_filename);
442      if (!oldpkg->tmp_unpack_dir)
443           oldpkg->tmp_unpack_dir = xstrdup(newpkg->tmp_unpack_dir);
444      if (!oldpkg->md5sum)
445           oldpkg->md5sum = xstrdup(newpkg->md5sum);
446 #if defined HAVE_SHA256
447      if (!oldpkg->sha256sum)
448           oldpkg->sha256sum = xstrdup(newpkg->sha256sum);
449 #endif
450      if (!oldpkg->size)
451           oldpkg->size = xstrdup(newpkg->size);
452      if (!oldpkg->installed_size)
453           oldpkg->installed_size = xstrdup(newpkg->installed_size);
454      if (!oldpkg->priority)
455           oldpkg->priority = xstrdup(newpkg->priority);
456      if (!oldpkg->source)
457           oldpkg->source = xstrdup(newpkg->source);
458      if (nv_pair_list_empty(&oldpkg->conffiles)){
459           list_splice_init(&newpkg->conffiles.head, &oldpkg->conffiles.head);
460           conffile_list_init(&newpkg->conffiles);
461      }
462      if (!oldpkg->installed_files){
463           oldpkg->installed_files = newpkg->installed_files;
464           oldpkg->installed_files_ref_cnt = newpkg->installed_files_ref_cnt;
465           newpkg->installed_files = NULL;
466      }
467      if (!oldpkg->essential)
468           oldpkg->essential = newpkg->essential;
469
470      return 0;
471 }
472
473 abstract_pkg_t *abstract_pkg_new(void)
474 {
475      abstract_pkg_t * ab_pkg;
476
477      ab_pkg = xcalloc(1, sizeof(abstract_pkg_t));
478
479      if (ab_pkg == NULL) {
480           fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
481           return NULL;
482      }
483
484      if ( abstract_pkg_init(ab_pkg) < 0 ) 
485         return NULL;
486
487      return ab_pkg;
488 }
489
490 int abstract_pkg_init(abstract_pkg_t *ab_pkg)
491 {
492      ab_pkg->provided_by = abstract_pkg_vec_alloc();
493      if (ab_pkg->provided_by==NULL){
494         return -1;
495      }
496      ab_pkg->dependencies_checked = 0;
497      ab_pkg->state_status = SS_NOT_INSTALLED;
498
499      return 0;
500 }
501
502 void set_flags_from_control(opkg_conf_t *conf, pkg_t *pkg){
503      char *file_name;
504      FILE *fp;
505
506      sprintf_alloc(&file_name,"%s/%s.control", pkg->dest->info_dir, pkg->name);
507
508      fp = fopen(file_name, "r");
509      if (fp == NULL) {
510              opkg_message(conf, OPKG_ERROR, "fopen(%s): %s\n",
511                              file_name, strerror(errno));
512              free(file_name);
513              return;
514      }
515
516      free(file_name);
517
518      if (pkg_parse_from_stream(pkg, fp, PFM_ESSENTIAL)) {
519         opkg_message(conf, OPKG_DEBUG, "unable to read control file for %s. May be empty\n", pkg->name);
520      }
521
522      fclose(fp);
523
524      return;
525 }
526
527 void pkg_formatted_field(FILE *fp, pkg_t *pkg, const char *field)
528 {
529      int i;
530
531      if (strlen(field) < PKG_MINIMUM_FIELD_NAME_LEN) {
532           goto UNKNOWN_FMT_FIELD;
533      }
534
535      switch (field[0])
536      {
537      case 'a':
538      case 'A':
539           if (strcasecmp(field, "Architecture") == 0) {
540                if (pkg->architecture) {
541                    fprintf(fp, "Architecture: %s\n", pkg->architecture);
542                }
543           } else if (strcasecmp(field, "Auto-Installed") == 0) {
544                 if (pkg->auto_installed)
545                     fprintf(fp, "Auto-Installed: yes\n");
546           } else {
547                goto UNKNOWN_FMT_FIELD;
548           }
549           break;
550      case 'c':
551      case 'C':
552           if (strcasecmp(field, "Conffiles") == 0) {
553                conffile_list_elt_t *iter;
554
555                if (nv_pair_list_empty(&pkg->conffiles))
556                     return;
557
558                fprintf(fp, "Conffiles:\n");
559                for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
560                     if (((conffile_t *)iter->data)->name && ((conffile_t *)iter->data)->value) {
561                          fprintf(fp, " %s %s\n", 
562                                  ((conffile_t *)iter->data)->name, 
563                                  ((conffile_t *)iter->data)->value);
564                     }
565                }
566           } else if (strcasecmp(field, "Conflicts") == 0) {
567                if (pkg->conflicts_count) {
568                     fprintf(fp, "Conflicts:");
569                     for(i = 0; i < pkg->conflicts_count; i++) {
570                         fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->conflicts_str[i]);
571                     }
572                     fprintf(fp, "\n");
573                }
574           } else {
575                goto UNKNOWN_FMT_FIELD;
576           }
577           break;
578      case 'd':
579      case 'D':
580           if (strcasecmp(field, "Depends") == 0) {
581                if (pkg->depends_count) {
582                     fprintf(fp, "Depends:");
583                     for(i = 0; i < pkg->depends_count; i++) {
584                         fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->depends_str[i]);
585                     }
586                     fprintf(fp, "\n");
587                }
588           } else if (strcasecmp(field, "Description") == 0) {
589                if (pkg->description) {
590                    fprintf(fp, "Description: %s\n", pkg->description);
591                }
592           } else {
593                goto UNKNOWN_FMT_FIELD;
594           }
595           break;
596      case 'e':
597      case 'E':
598           if (pkg->essential) {
599               fprintf(fp, "Essential: yes\n");
600           }
601           break;
602      case 'f':
603      case 'F':
604           if (pkg->filename) {
605               fprintf(fp, "Filename: %s\n", pkg->filename);
606           }
607           break;
608      case 'i':
609      case 'I':
610           if (strcasecmp(field, "Installed-Size") == 0) {
611                fprintf(fp, "Installed-Size: %s\n", pkg->installed_size);
612           } else if (strcasecmp(field, "Installed-Time") == 0 && pkg->installed_time) {
613                fprintf(fp, "Installed-Time: %lu\n", pkg->installed_time);
614           }
615           break;
616      case 'm':
617      case 'M':
618           if (strcasecmp(field, "Maintainer") == 0) {
619                if (pkg->maintainer) {
620                    fprintf(fp, "maintainer: %s\n", pkg->maintainer);
621                }
622           } else if (strcasecmp(field, "MD5sum") == 0) {
623                if (pkg->md5sum) {
624                    fprintf(fp, "MD5Sum: %s\n", pkg->md5sum);
625                }
626           } else {
627                goto UNKNOWN_FMT_FIELD;
628           }
629           break;
630      case 'p':
631      case 'P':
632           if (strcasecmp(field, "Package") == 0) {
633                fprintf(fp, "Package: %s\n", pkg->name);
634           } else if (strcasecmp(field, "Priority") == 0) {
635                fprintf(fp, "Priority: %s\n", pkg->priority);
636           } else if (strcasecmp(field, "Provides") == 0) {
637                if (pkg->provides_count) {
638                   fprintf(fp, "Provides:");
639                   for(i = 0; i < pkg->provides_count-1; i++) {
640                       fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->provides_str[i]);
641                   }
642                   fprintf(fp, "\n");
643                }
644           } else {
645                goto UNKNOWN_FMT_FIELD;
646           }
647           break;
648      case 'r':
649      case 'R':
650           if (strcasecmp (field, "Replaces") == 0) {
651                if (pkg->replaces_count) {
652                     fprintf(fp, "Replaces:");
653                     for (i = 0; i < pkg->replaces_count; i++) {
654                         fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->replaces_str[i]);
655                     }
656                     fprintf(fp, "\n");
657                }
658           } else if (strcasecmp (field, "Recommends") == 0) {
659                if (pkg->recommends_count) {
660                     fprintf(fp, "Recommends:");
661                     for(i = 0; i < pkg->recommends_count; i++) {
662                         fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->recommends_str[i]);
663                     }
664                     fprintf(fp, "\n");
665                }
666           } else {
667                goto UNKNOWN_FMT_FIELD;
668           }
669           break;
670      case 's':
671      case 'S':
672           if (strcasecmp(field, "Section") == 0) {
673                if (pkg->section) {
674                    fprintf(fp, "Section: %s\n", pkg->section);
675                }
676 #if defined HAVE_SHA256
677           } else if (strcasecmp(field, "SHA256sum") == 0) {
678                if (pkg->sha256sum) {
679                    fprintf(fp, "SHA256sum: %s\n", pkg->sha256sum);
680                }
681 #endif
682           } else if (strcasecmp(field, "Size") == 0) {
683                if (pkg->size) {
684                    fprintf(fp, "Size: %s\n", pkg->size);
685                }
686           } else if (strcasecmp(field, "Source") == 0) {
687                if (pkg->source) {
688                    fprintf(fp, "Source: %s\n", pkg->source);
689                }
690           } else if (strcasecmp(field, "Status") == 0) {
691                char *pflag = pkg_state_flag_to_str(pkg->state_flag);
692                char *pstat = pkg_state_status_to_str(pkg->state_status);
693                char *pwant = pkg_state_want_to_str(pkg->state_want);
694
695                if (pflag == NULL || pstat == NULL || pwant == NULL)
696                        return;
697
698                fprintf(fp, "Status: %s %s %s\n", pwant, pflag, pstat);
699
700                free(pflag);
701                free(pwant);
702                free(pstat);
703           } else if (strcasecmp(field, "Suggests") == 0) {
704                if (pkg->suggests_count) {
705                     fprintf(fp, "Suggests:");
706                     for(i = 0; i < pkg->suggests_count; i++) {
707                         fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->suggests_str[i]);
708                     }
709                     fprintf(fp, "\n");
710                }
711           } else {
712                goto UNKNOWN_FMT_FIELD;
713           }
714           break;
715      case 't':
716      case 'T':
717           if (strcasecmp(field, "Tags") == 0) {
718                if (pkg->tags) {
719                    fprintf(fp, "Tags: %s\n", pkg->tags);
720                }
721           }
722           break;
723      case 'v':
724      case 'V':
725           {
726                char *version = pkg_version_str_alloc(pkg);
727                if (version == NULL)
728                     return;
729                fprintf(fp, "Version: %s\n", version);
730                free(version);
731           }
732           break;
733      default:
734           goto UNKNOWN_FMT_FIELD;
735      }
736
737      return;
738
739 UNKNOWN_FMT_FIELD:
740      fprintf(stderr, "%s: ERROR: Unknown field name: %s\n", __FUNCTION__, field);
741 }
742
743 void pkg_formatted_info(FILE *fp, pkg_t *pkg)
744 {
745         pkg_formatted_field(fp, pkg, "Package");
746         pkg_formatted_field(fp, pkg, "Version");
747         pkg_formatted_field(fp, pkg, "Depends");
748         pkg_formatted_field(fp, pkg, "Recommends");
749         pkg_formatted_field(fp, pkg, "Suggests");
750         pkg_formatted_field(fp, pkg, "Provides");
751         pkg_formatted_field(fp, pkg, "Replaces");
752         pkg_formatted_field(fp, pkg, "Conflicts");
753         pkg_formatted_field(fp, pkg, "Status");
754         pkg_formatted_field(fp, pkg, "Section");
755         pkg_formatted_field(fp, pkg, "Essential");
756         pkg_formatted_field(fp, pkg, "Architecture");
757         pkg_formatted_field(fp, pkg, "Maintainer");
758         pkg_formatted_field(fp, pkg, "MD5sum");
759         pkg_formatted_field(fp, pkg, "Size");
760         pkg_formatted_field(fp, pkg, "Filename");
761         pkg_formatted_field(fp, pkg, "Conffiles");
762         pkg_formatted_field(fp, pkg, "Source");
763         pkg_formatted_field(fp, pkg, "Description");
764         pkg_formatted_field(fp, pkg, "Installed-Time");
765         pkg_formatted_field(fp, pkg, "Tags");
766         fputs("\n", fp);
767 }
768
769 void pkg_print_status(pkg_t * pkg, FILE * file)
770 {
771      if (pkg == NULL) {
772           return;
773      }
774
775      /* XXX: QUESTION: Do we actually want more fields here? The
776         original idea was to save space by installing only what was
777         needed for actual computation, (package, version, status,
778         essential, conffiles). The assumption is that all other fields
779         can be found in th available file.
780
781         But, someone proposed the idea to make it possible to
782         reconstruct a .opk from an installed package, (ie. for beaming
783         from one handheld to another). So, maybe we actually want a few
784         more fields here, (depends, suggests, etc.), so that that would
785         be guaranteed to work even in the absence of more information
786         from the available file.
787
788         28-MAR-03: kergoth and I discussed this yesterday.  We think
789         the essential info needs to be here for all installed packages
790         because they may not appear in the Packages files on various
791         feeds.  Furthermore, one should be able to install from URL or
792         local storage without requiring a Packages file from any feed.
793         -Jamey
794      */
795      pkg_formatted_field(file, pkg, "Package");
796      pkg_formatted_field(file, pkg, "Version");
797      pkg_formatted_field(file, pkg, "Depends");
798      pkg_formatted_field(file, pkg, "Recommends");
799      pkg_formatted_field(file, pkg, "Suggests");
800      pkg_formatted_field(file, pkg, "Provides");
801      pkg_formatted_field(file, pkg, "Replaces");
802      pkg_formatted_field(file, pkg, "Conflicts");
803      pkg_formatted_field(file, pkg, "Status");
804      pkg_formatted_field(file, pkg, "Essential");
805      pkg_formatted_field(file, pkg, "Architecture");
806      pkg_formatted_field(file, pkg, "Conffiles");
807      pkg_formatted_field(file, pkg, "Installed-Time");
808      pkg_formatted_field(file, pkg, "Auto-Installed");
809      fputs("\n", file);
810 }
811
812 /*
813  * libdpkg - Debian packaging suite library routines
814  * vercmp.c - comparison of version numbers
815  *
816  * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
817  */
818 int pkg_compare_versions(const pkg_t *pkg, const pkg_t *ref_pkg)
819 {
820      int r;
821
822      if (pkg->epoch > ref_pkg->epoch) {
823           return 1;
824      }
825
826      if (pkg->epoch < ref_pkg->epoch) {
827           return -1;
828      }
829
830      r = verrevcmp(pkg->version, ref_pkg->version);
831      if (r) {
832           return r;
833      }
834
835      r = verrevcmp(pkg->revision, ref_pkg->revision);
836      if (r) {
837           return r;
838      }
839
840      return r;
841 }
842
843 /* assume ascii; warning: evaluates x multiple times! */
844 #define order(x) ((x) == '~' ? -1 \
845                 : isdigit((x)) ? 0 \
846                 : !(x) ? 0 \
847                 : isalpha((x)) ? (x) \
848                 : (x) + 256)
849
850 static int verrevcmp(const char *val, const char *ref) {
851   if (!val) val= "";
852   if (!ref) ref= "";
853
854   while (*val || *ref) {
855     int first_diff= 0;
856
857     while ( (*val && !isdigit(*val)) || (*ref && !isdigit(*ref)) ) {
858       int vc= order(*val), rc= order(*ref);
859       if (vc != rc) return vc - rc;
860       val++; ref++;
861     }
862
863     while ( *val == '0' ) val++;
864     while ( *ref == '0' ) ref++;
865     while (isdigit(*val) && isdigit(*ref)) {
866       if (!first_diff) first_diff= *val - *ref;
867       val++; ref++;
868     }
869     if (isdigit(*val)) return 1;
870     if (isdigit(*ref)) return -1;
871     if (first_diff) return first_diff;
872   }
873   return 0;
874 }
875
876 int pkg_version_satisfied(pkg_t *it, pkg_t *ref, const char *op)
877 {
878      int r;
879
880      r = pkg_compare_versions(it, ref);
881
882      if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0) {
883           return r <= 0;
884      }
885
886      if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0) {
887           return r >= 0;
888      }
889
890      if (strcmp(op, "<<") == 0) {
891           return r < 0;
892      }
893
894      if (strcmp(op, ">>") == 0) {
895           return r > 0;
896      }
897
898      if (strcmp(op, "=") == 0) {
899           return r == 0;
900      }
901
902      fprintf(stderr, "unknown operator: %s", op);
903      return 0;
904 }
905
906 int pkg_name_version_and_architecture_compare(const void *p1, const void *p2)
907 {
908      const pkg_t *a = *(const pkg_t**) p1;
909      const pkg_t *b = *(const pkg_t**) p2;
910      int namecmp;
911      int vercmp;
912      if (!a->name || !b->name) {
913        fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->name=%p b=%p b->name=%p\n",
914                a, a->name, b, b->name);
915        return 0;
916      }
917        
918      namecmp = strcmp(a->name, b->name);
919      if (namecmp)
920           return namecmp;
921      vercmp = pkg_compare_versions(a, b);
922      if (vercmp)
923           return vercmp;
924      if (!a->arch_priority || !b->arch_priority) {
925        fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->arch_priority=%i b=%p b->arch_priority=%i\n",
926                a, a->arch_priority, b, b->arch_priority);
927        return 0;
928      }
929      if (a->arch_priority > b->arch_priority)
930           return 1;
931      if (a->arch_priority < b->arch_priority)
932           return -1;
933      return 0;
934 }
935
936 int abstract_pkg_name_compare(const void *p1, const void *p2)
937 {
938      const abstract_pkg_t *a = *(const abstract_pkg_t **)p1;
939      const abstract_pkg_t *b = *(const abstract_pkg_t **)p2;
940      if (!a->name || !b->name) {
941        fprintf(stderr, "abstract_pkg_name_compare: a=%p a->name=%p b=%p b->name=%p\n",
942                a, a->name, b, b->name);
943        return 0;
944      }
945      return strcmp(a->name, b->name);
946 }
947
948
949 char *
950 pkg_version_str_alloc(pkg_t *pkg)
951 {
952         char *version;
953
954         if (pkg->epoch) {
955                 if (pkg->revision)
956                         sprintf_alloc(&version, "%d:%s-%s",
957                                 pkg->epoch, pkg->version, pkg->revision);
958                 else
959                         sprintf_alloc(&version, "%d:%s",
960                                 pkg->epoch, pkg->version);
961         } else {
962                 if (pkg->revision)
963                         sprintf_alloc(&version, "%s-%s",
964                                 pkg->version, pkg->revision);
965                 else
966                         version = xstrdup(pkg->version);
967         }
968
969         return version;
970 }
971
972 str_list_t *pkg_get_installed_files(pkg_t *pkg)
973 {
974      int err;
975      char *list_file_name = NULL;
976      FILE *list_file = NULL;
977      char *line;
978      char *installed_file_name;
979      int rootdirlen;
980
981      pkg->installed_files_ref_cnt++;
982
983      if (pkg->installed_files) {
984           return pkg->installed_files;
985      }
986
987      pkg->installed_files = str_list_alloc();
988
989      /* For uninstalled packages, get the file list directly from the package.
990         For installed packages, look at the package.list file in the database.
991      */
992      if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
993           if (pkg->local_filename == NULL) {
994                return pkg->installed_files;
995           }
996           /* XXX: CLEANUP: Maybe rewrite this to avoid using a temporary
997              file. In other words, change deb_extract so that it can
998              simply return the file list as a char *[] rather than
999              insisting on writing in to a FILE * as it does now. */
1000           list_file = tmpfile();
1001           err = pkg_extract_data_file_names_to_stream(pkg, list_file);
1002           if (err) {
1003                fclose(list_file);
1004                fprintf(stderr, "%s: Error extracting file list from %s: %s\n",
1005                        __FUNCTION__, pkg->local_filename, strerror(err));
1006                return pkg->installed_files;
1007           }
1008           rewind(list_file);
1009      } else {
1010           sprintf_alloc(&list_file_name, "%s/%s.list",
1011                         pkg->dest->info_dir, pkg->name);
1012           if (! file_exists(list_file_name)) {
1013                free(list_file_name);
1014                return pkg->installed_files;
1015           }
1016
1017           list_file = fopen(list_file_name, "r");
1018           if (list_file == NULL) {
1019                fprintf(stderr, "WARNING: Cannot open %s: %s\n",
1020                        list_file_name, strerror(errno));
1021                free(list_file_name);
1022                return pkg->installed_files;
1023           }
1024           free(list_file_name);
1025      }
1026
1027      rootdirlen = strlen( pkg->dest->root_dir );
1028      while (1) {
1029           char *file_name;
1030         
1031           line = file_read_line_alloc(list_file);
1032           if (line == NULL) {
1033                break;
1034           }
1035           str_chomp(line);
1036           file_name = line;
1037
1038           /* Take pains to avoid uglies like "/./" in the middle of file_name. */
1039           if( strncmp( pkg->dest->root_dir, 
1040                        file_name, 
1041                        rootdirlen ) ) {
1042                if (*file_name == '.') {
1043                     file_name++;
1044                }
1045                if (*file_name == '/') {
1046                     file_name++;
1047                }
1048
1049                /* Freed in pkg_free_installed_files */
1050                sprintf_alloc(&installed_file_name, "%s%s", pkg->dest->root_dir, file_name);
1051           } else {
1052                // already contains root_dir as header -> ABSOLUTE
1053                sprintf_alloc(&installed_file_name, "%s", file_name);
1054           }
1055           str_list_append(pkg->installed_files, installed_file_name);
1056           free(installed_file_name);
1057           free(line);
1058      }
1059
1060      fclose(list_file);
1061
1062      return pkg->installed_files;
1063 }
1064
1065 /* XXX: CLEANUP: This function and it's counterpart,
1066    (pkg_get_installed_files), do not match our init/deinit naming
1067    convention. Nor the alloc/free convention. But, then again, neither
1068    of these conventions currrently fit the way these two functions
1069    work. */
1070 int pkg_free_installed_files(pkg_t *pkg)
1071 {
1072      pkg->installed_files_ref_cnt--;
1073
1074      if (pkg->installed_files_ref_cnt > 0)
1075           return 0;
1076
1077      if (pkg->installed_files) {
1078          str_list_purge(pkg->installed_files);
1079      }
1080
1081      pkg->installed_files = NULL;
1082
1083      return 0;
1084 }
1085
1086 int pkg_remove_installed_files_list(opkg_conf_t *conf, pkg_t *pkg)
1087 {
1088      int err;
1089      char *list_file_name;
1090
1091      //I don't think pkg_free_installed_files should be called here. Jamey
1092      //pkg_free_installed_files(pkg);
1093
1094      sprintf_alloc(&list_file_name, "%s/%s.list",
1095                    pkg->dest->info_dir, pkg->name);
1096      if (!conf->noaction) {
1097           err = unlink(list_file_name);
1098           free(list_file_name);
1099
1100           if (err) {
1101                return errno;
1102           }
1103      }
1104      return 0;
1105 }
1106
1107 conffile_t *pkg_get_conffile(pkg_t *pkg, const char *file_name)
1108 {
1109      conffile_list_elt_t *iter;
1110      conffile_t *conffile;
1111
1112      if (pkg == NULL) {
1113           return NULL;
1114      }
1115
1116      for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
1117           conffile = (conffile_t *)iter->data;
1118
1119           if (strcmp(conffile->name, file_name) == 0) {
1120                return conffile;
1121           }
1122      }
1123
1124      return NULL;
1125 }
1126
1127 int pkg_run_script(opkg_conf_t *conf, pkg_t *pkg,
1128                    const char *script, const char *args)
1129 {
1130      int err;
1131      char *path;
1132      char *cmd;
1133
1134      if (conf->noaction)
1135              return 0;
1136
1137      /* XXX: CLEANUP: There must be a better way to handle maintainer
1138         scripts when running with offline_root mode and/or a dest other
1139         than '/'. I've been playing around with some clever chroot
1140         tricks and I might come up with something workable. */
1141      /*
1142       * Attempt to provide a restricted environment for offline operation
1143       * Need the following set as a minimum:
1144       * OPKG_OFFLINE_ROOT = absolute path to root dir
1145       * D                 = absolute path to root dir (for OE generated postinst)
1146       * PATH              = something safe (a restricted set of utilities)
1147       */
1148
1149      if (conf->offline_root) {
1150           if (conf->offline_root_path) {
1151             setenv("PATH", conf->offline_root_path, 1);
1152           } else {
1153             opkg_message(conf, OPKG_NOTICE, 
1154                 "(offline root mode: not running %s.%s)\n", pkg->name, script);
1155             return 0;
1156           }
1157           setenv("OPKG_OFFLINE_ROOT", conf->offline_root, 1);
1158           setenv("D", conf->offline_root, 1);
1159      }
1160
1161      /* XXX: FEATURE: When conf->offline_root is set, we should run the
1162         maintainer script within a chroot environment. */
1163
1164      /* Installed packages have scripts in pkg->dest->info_dir, uninstalled packages
1165         have scripts in pkg->tmp_unpack_dir. */
1166      if (pkg->state_status == SS_INSTALLED || pkg->state_status == SS_UNPACKED) {
1167           if (pkg->dest == NULL) {
1168                fprintf(stderr, "%s: ERROR: installed package %s has a NULL dest\n",
1169                        __FUNCTION__, pkg->name);
1170                return EINVAL;
1171           }
1172           sprintf_alloc(&path, "%s/%s.%s", pkg->dest->info_dir, pkg->name, script);
1173      } else {
1174           if (pkg->tmp_unpack_dir == NULL) {
1175                fprintf(stderr, "%s: ERROR: uninstalled package %s has a NULL tmp_unpack_dir\n",
1176                        __FUNCTION__, pkg->name);
1177                return EINVAL;
1178           }
1179           sprintf_alloc(&path, "%s/%s", pkg->tmp_unpack_dir, script);
1180      }
1181
1182      opkg_message(conf, OPKG_INFO, "Running script %s\n", path);
1183
1184      setenv("PKG_ROOT",
1185             pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir, 1);
1186
1187      if (! file_exists(path)) {
1188           free(path);
1189           return 0;
1190      }
1191
1192      sprintf_alloc(&cmd, "%s %s", path, args);
1193      free(path);
1194
1195      err = xsystem(cmd);
1196      free(cmd);
1197
1198      if (err) {
1199           fprintf(stderr, "%s script returned status %d\n", script, err);
1200           return err;
1201      }
1202
1203      return 0;
1204 }
1205
1206 char *pkg_state_want_to_str(pkg_state_want_t sw)
1207 {
1208      int i;
1209
1210      for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1211           if (pkg_state_want_map[i].value == sw) {
1212                return xstrdup(pkg_state_want_map[i].str);
1213           }
1214      }
1215
1216      fprintf(stderr, "%s: ERROR: Illegal value for state_want: %d\n",
1217              __FUNCTION__, sw);
1218      return xstrdup("<STATE_WANT_UNKNOWN>");
1219 }
1220
1221 pkg_state_want_t pkg_state_want_from_str(char *str)
1222 {
1223      int i;
1224
1225      for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1226           if (strcmp(str, pkg_state_want_map[i].str) == 0) {
1227                return pkg_state_want_map[i].value;
1228           }
1229      }
1230
1231      fprintf(stderr, "%s: ERROR: Illegal value for state_want string: %s\n",
1232              __FUNCTION__, str);
1233      return SW_UNKNOWN;
1234 }
1235
1236 char *pkg_state_flag_to_str(pkg_state_flag_t sf)
1237 {
1238      int i;
1239      int len = 3; /* ok\000 is minimum */
1240      char *str = NULL;
1241
1242      /* clear the temporary flags before converting to string */
1243      sf &= SF_NONVOLATILE_FLAGS;
1244
1245      if (sf == 0) {
1246           return xstrdup("ok");
1247      } else {
1248
1249           for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1250                if (sf & pkg_state_flag_map[i].value) {
1251                     len += strlen(pkg_state_flag_map[i].str) + 1;
1252                }
1253           }
1254           str = xmalloc(len);
1255           str[0] = 0;
1256           for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1257                if (sf & pkg_state_flag_map[i].value) {
1258                     strcat(str, pkg_state_flag_map[i].str);
1259                     strcat(str, ",");
1260                }
1261           }
1262           len = strlen(str);
1263           str[len-1] = 0; /* squash last comma */
1264           return str;
1265      }
1266 }
1267
1268 pkg_state_flag_t pkg_state_flag_from_str(const char *str)
1269 {
1270      int i;
1271      int sf = SF_OK;
1272
1273      if (strcmp(str, "ok") == 0) {
1274           return SF_OK;
1275      }
1276      for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1277           const char *sfname = pkg_state_flag_map[i].str;
1278           int sfname_len = strlen(sfname);
1279           if (strncmp(str, sfname, sfname_len) == 0) {
1280                sf |= pkg_state_flag_map[i].value;
1281                str += sfname_len;
1282                if (str[0] == ',') {
1283                     str++;
1284                } else {
1285                     break;
1286                }
1287           }
1288      }
1289
1290      return sf;
1291 }
1292
1293 char *pkg_state_status_to_str(pkg_state_status_t ss)
1294 {
1295      int i;
1296
1297      for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1298           if (pkg_state_status_map[i].value == ss) {
1299                return xstrdup(pkg_state_status_map[i].str);
1300           }
1301      }
1302
1303      fprintf(stderr, "%s: ERROR: Illegal value for state_status: %d\n",
1304              __FUNCTION__, ss);
1305      return xstrdup("<STATE_STATUS_UNKNOWN>");
1306 }
1307
1308 pkg_state_status_t pkg_state_status_from_str(const char *str)
1309 {
1310      int i;
1311
1312      for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1313           if (strcmp(str, pkg_state_status_map[i].str) == 0) {
1314                return pkg_state_status_map[i].value;
1315           }
1316      }
1317
1318      fprintf(stderr, "%s: ERROR: Illegal value for state_status string: %s\n",
1319              __FUNCTION__, str);
1320      return SS_NOT_INSTALLED;
1321 }
1322
1323 int pkg_arch_supported(opkg_conf_t *conf, pkg_t *pkg)
1324 {
1325      nv_pair_list_elt_t *l;
1326
1327      if (!pkg->architecture)
1328           return 1;
1329
1330      list_for_each_entry(l , &conf->arch_list.head, node) {
1331           nv_pair_t *nv = (nv_pair_t *)l->data;
1332           if (strcmp(nv->name, pkg->architecture) == 0) {
1333                opkg_message(conf, OPKG_DEBUG, "arch %s (priority %s) supported for pkg %s\n", nv->name, nv->value, pkg->name);
1334                return 1;
1335           }
1336      }
1337
1338      opkg_message(conf, OPKG_DEBUG, "arch %s unsupported for pkg %s\n", pkg->architecture, pkg->name);
1339      return 0;
1340 }
1341
1342 int pkg_get_arch_priority(opkg_conf_t *conf, const char *archname)
1343 {
1344      nv_pair_list_elt_t *l;
1345
1346      list_for_each_entry(l , &conf->arch_list.head, node) {
1347           nv_pair_t *nv = (nv_pair_t *)l->data;
1348           if (strcmp(nv->name, archname) == 0) {
1349                int priority = strtol(nv->value, NULL, 0);
1350                return priority;
1351           }
1352      }
1353      return 0;
1354 }
1355
1356 int pkg_info_preinstall_check(opkg_conf_t *conf)
1357 {
1358      int i;
1359      hash_table_t *pkg_hash = &conf->pkg_hash;
1360      pkg_vec_t *available_pkgs = pkg_vec_alloc();
1361      pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1362
1363      opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: updating arch priority for each package\n");
1364      pkg_hash_fetch_available(pkg_hash, available_pkgs);
1365      /* update arch_priority for each package */
1366      for (i = 0; i < available_pkgs->len; i++) {
1367           pkg_t *pkg = available_pkgs->pkgs[i];
1368           int arch_priority = 1;
1369           if (!pkg)
1370                continue;
1371           // opkg_message(conf, OPKG_DEBUG2, " package %s version=%s arch=%p:", pkg->name, pkg->version, pkg->architecture);
1372           if (pkg->architecture) 
1373                arch_priority = pkg_get_arch_priority(conf, pkg->architecture);
1374           else 
1375                opkg_message(conf, OPKG_ERROR, "pkg_info_preinstall_check: no architecture for package %s\n", pkg->name);
1376           // opkg_message(conf, OPKG_DEBUG2, "%s arch_priority=%d\n", pkg->architecture, arch_priority);
1377           pkg->arch_priority = arch_priority;
1378      }
1379
1380      for (i = 0; i < available_pkgs->len; i++) {
1381           pkg_t *pkg = available_pkgs->pkgs[i];
1382           if (!pkg->arch_priority && (pkg->state_flag || (pkg->state_want != SW_UNKNOWN))) {
1383                /* clear flags and want for any uninstallable package */
1384                opkg_message(conf, OPKG_DEBUG, "Clearing state_want and state_flag for pkg=%s (arch_priority=%d flag=%d want=%d)\n", 
1385                             pkg->name, pkg->arch_priority, pkg->state_flag, pkg->state_want);
1386                pkg->state_want = SW_UNKNOWN;
1387                pkg->state_flag = 0;
1388           }
1389      }
1390      pkg_vec_free(available_pkgs);
1391
1392      /* update the file owner data structure */
1393      opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: update file owner list\n");
1394      pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1395      for (i = 0; i < installed_pkgs->len; i++) {
1396           pkg_t *pkg = installed_pkgs->pkgs[i];
1397           str_list_t *installed_files = pkg_get_installed_files(pkg); /* this causes installed_files to be cached */
1398           str_list_elt_t *iter, *niter;
1399           if (installed_files == NULL) {
1400                opkg_message(conf, OPKG_ERROR, "No installed files for pkg %s\n", pkg->name);
1401                break;
1402           }
1403           for (iter = str_list_first(installed_files), niter = str_list_next(installed_files, iter); 
1404                   iter; 
1405                   iter = niter, niter = str_list_next(installed_files, iter)) {
1406                char *installed_file = (char *) iter->data;
1407                // opkg_message(conf, OPKG_DEBUG2, "pkg %s: file=%s\n", pkg->name, installed_file);
1408                file_hash_set_file_owner(conf, installed_file, pkg);
1409           }
1410           pkg_free_installed_files(pkg);
1411      }
1412      pkg_vec_free(installed_pkgs);
1413
1414      return 0;
1415 }
1416
1417 struct pkg_write_filelist_data {
1418      opkg_conf_t *conf;
1419      pkg_t *pkg;
1420      FILE *stream;
1421 };
1422
1423 void pkg_write_filelist_helper(const char *key, void *entry_, void *data_)
1424 {
1425      struct pkg_write_filelist_data *data = data_;
1426      pkg_t *entry = entry_;
1427      if (entry == data->pkg) {
1428           fprintf(data->stream, "%s\n", key);
1429      }
1430 }
1431
1432 int pkg_write_filelist(opkg_conf_t *conf, pkg_t *pkg)
1433 {
1434      struct pkg_write_filelist_data data;
1435      char *list_file_name = NULL;
1436      int err = 0;
1437
1438      if (!pkg) {
1439           opkg_message(conf, OPKG_ERROR, "Null pkg\n");
1440           return -EINVAL;
1441      }
1442      opkg_message(conf, OPKG_INFO,
1443                   "    creating %s.list file\n", pkg->name);
1444      sprintf_alloc(&list_file_name, "%s/%s.list", pkg->dest->info_dir, pkg->name);
1445      if (!list_file_name) {
1446           opkg_message(conf, OPKG_ERROR, "Failed to alloc list_file_name\n");
1447           return -ENOMEM;
1448      }
1449      opkg_message(conf, OPKG_INFO,
1450                   "    creating %s file for pkg %s\n", list_file_name, pkg->name);
1451      data.stream = fopen(list_file_name, "w");
1452      if (!data.stream) {
1453           opkg_message(conf, OPKG_ERROR, "Could not open %s for writing: %s\n",
1454                        list_file_name, strerror(errno));
1455                        return errno;
1456      }
1457      data.pkg = pkg;
1458      data.conf = conf;
1459      hash_table_foreach(&conf->file_hash, pkg_write_filelist_helper, &data);
1460      fclose(data.stream);
1461      free(list_file_name);
1462
1463      pkg->state_flag &= ~SF_FILELIST_CHANGED;
1464
1465      return err;
1466 }
1467
1468 int pkg_write_changed_filelists(opkg_conf_t *conf)
1469 {
1470      pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1471      hash_table_t *pkg_hash = &conf->pkg_hash;
1472      int i;
1473      int err;
1474      if (conf->noaction)
1475           return 0;
1476
1477      opkg_message(conf, OPKG_INFO, "%s: saving changed filelists\n", __FUNCTION__);
1478      pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1479      for (i = 0; i < installed_pkgs->len; i++) {
1480           pkg_t *pkg = installed_pkgs->pkgs[i];
1481           if (pkg->state_flag & SF_FILELIST_CHANGED) {
1482                opkg_message(conf, OPKG_DEBUG, "Calling pkg_write_filelist for pkg=%s from %s\n", pkg->name, __FUNCTION__);
1483                err = pkg_write_filelist(conf, pkg);
1484                if (err)
1485                     opkg_message(conf, OPKG_NOTICE, "pkg_write_filelist pkg=%s returned %d\n", pkg->name, err);
1486           }
1487      }
1488      pkg_vec_free (installed_pkgs);
1489      return 0;
1490 }