9ba44e82eafa71493952f3132bae8ea2f844fe57
[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              return;
513      }
514
515      free(file_name);
516
517      if (pkg_parse_from_stream(pkg, fp, PFM_ESSENTIAL)) {
518         opkg_message(conf, OPKG_DEBUG, "unable to read control file for %s. May be empty\n", pkg->name);
519      }
520
521      fclose(fp);
522
523      return;
524 }
525
526 void pkg_formatted_field(FILE *fp, pkg_t *pkg, const char *field)
527 {
528      int i;
529
530      if (strlen(field) < PKG_MINIMUM_FIELD_NAME_LEN) {
531           goto UNKNOWN_FMT_FIELD;
532      }
533
534      switch (field[0])
535      {
536      case 'a':
537      case 'A':
538           if (strcasecmp(field, "Architecture") == 0) {
539                if (pkg->architecture) {
540                    fprintf(fp, "Architecture: %s\n", pkg->architecture);
541                }
542           } else if (strcasecmp(field, "Auto-Installed") == 0) {
543                 if (pkg->auto_installed)
544                     fprintf(fp, "Auto-Installed: yes\n");
545           } else {
546                goto UNKNOWN_FMT_FIELD;
547           }
548           break;
549      case 'c':
550      case 'C':
551           if (strcasecmp(field, "Conffiles") == 0) {
552                conffile_list_elt_t *iter;
553
554                if (nv_pair_list_empty(&pkg->conffiles))
555                     return;
556
557                fprintf(fp, "Conffiles:\n");
558                for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
559                     if (((conffile_t *)iter->data)->name && ((conffile_t *)iter->data)->value) {
560                          fprintf(fp, " %s %s\n", 
561                                  ((conffile_t *)iter->data)->name, 
562                                  ((conffile_t *)iter->data)->value);
563                     }
564                }
565           } else if (strcasecmp(field, "Conflicts") == 0) {
566                if (pkg->conflicts_count) {
567                     fprintf(fp, "Conflicts:");
568                     for(i = 0; i < pkg->conflicts_count; i++) {
569                         fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->conflicts_str[i]);
570                     }
571                     fprintf(fp, "\n");
572                }
573           } else {
574                goto UNKNOWN_FMT_FIELD;
575           }
576           break;
577      case 'd':
578      case 'D':
579           if (strcasecmp(field, "Depends") == 0) {
580                if (pkg->depends_count) {
581                     fprintf(fp, "Depends:");
582                     for(i = 0; i < pkg->depends_count; i++) {
583                         fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->depends_str[i]);
584                     }
585                     fprintf(fp, "\n");
586                }
587           } else if (strcasecmp(field, "Description") == 0) {
588                if (pkg->description) {
589                    fprintf(fp, "Description: %s\n", pkg->description);
590                }
591           } else {
592                goto UNKNOWN_FMT_FIELD;
593           }
594           break;
595      case 'e':
596      case 'E':
597           if (pkg->essential) {
598               fprintf(fp, "Essential: yes\n");
599           }
600           break;
601      case 'f':
602      case 'F':
603           if (pkg->filename) {
604               fprintf(fp, "Filename: %s\n", pkg->filename);
605           }
606           break;
607      case 'i':
608      case 'I':
609           if (strcasecmp(field, "Installed-Size") == 0) {
610                fprintf(fp, "Installed-Size: %s\n", pkg->installed_size);
611           } else if (strcasecmp(field, "Installed-Time") == 0 && pkg->installed_time) {
612                fprintf(fp, "Installed-Time: %lu\n", pkg->installed_time);
613           }
614           break;
615      case 'm':
616      case 'M':
617           if (strcasecmp(field, "Maintainer") == 0) {
618                if (pkg->maintainer) {
619                    fprintf(fp, "maintainer: %s\n", pkg->maintainer);
620                }
621           } else if (strcasecmp(field, "MD5sum") == 0) {
622                if (pkg->md5sum) {
623                    fprintf(fp, "MD5Sum: %s\n", pkg->md5sum);
624                }
625           } else {
626                goto UNKNOWN_FMT_FIELD;
627           }
628           break;
629      case 'p':
630      case 'P':
631           if (strcasecmp(field, "Package") == 0) {
632                fprintf(fp, "Package: %s\n", pkg->name);
633           } else if (strcasecmp(field, "Priority") == 0) {
634                fprintf(fp, "Priority: %s\n", pkg->priority);
635           } else if (strcasecmp(field, "Provides") == 0) {
636                if (pkg->provides_count) {
637                   fprintf(fp, "Provides:");
638                   for(i = 0; i < pkg->provides_count-1; i++) {
639                       fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->provides_str[i]);
640                   }
641                   fprintf(fp, "\n");
642                }
643           } else {
644                goto UNKNOWN_FMT_FIELD;
645           }
646           break;
647      case 'r':
648      case 'R':
649           if (strcasecmp (field, "Replaces") == 0) {
650                if (pkg->replaces_count) {
651                     fprintf(fp, "Replaces:");
652                     for (i = 0; i < pkg->replaces_count; i++) {
653                         fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->replaces_str[i]);
654                     }
655                     fprintf(fp, "\n");
656                }
657           } else if (strcasecmp (field, "Recommends") == 0) {
658                if (pkg->recommends_count) {
659                     fprintf(fp, "Recommends:");
660                     for(i = 0; i < pkg->recommends_count; i++) {
661                         fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->recommends_str[i]);
662                     }
663                     fprintf(fp, "\n");
664                }
665           } else {
666                goto UNKNOWN_FMT_FIELD;
667           }
668           break;
669      case 's':
670      case 'S':
671           if (strcasecmp(field, "Section") == 0) {
672                if (pkg->section) {
673                    fprintf(fp, "Section: %s\n", pkg->section);
674                }
675 #if defined HAVE_SHA256
676           } else if (strcasecmp(field, "SHA256sum") == 0) {
677                if (pkg->sha256sum) {
678                    fprintf(fp, "SHA256sum: %s\n", pkg->sha256sum);
679                }
680 #endif
681           } else if (strcasecmp(field, "Size") == 0) {
682                if (pkg->size) {
683                    fprintf(fp, "Size: %s\n", pkg->size);
684                }
685           } else if (strcasecmp(field, "Source") == 0) {
686                if (pkg->source) {
687                    fprintf(fp, "Source: %s\n", pkg->source);
688                }
689           } else if (strcasecmp(field, "Status") == 0) {
690                char *pflag = pkg_state_flag_to_str(pkg->state_flag);
691                char *pstat = pkg_state_status_to_str(pkg->state_status);
692                char *pwant = pkg_state_want_to_str(pkg->state_want);
693
694                if (pflag == NULL || pstat == NULL || pwant == NULL)
695                        return;
696
697                fprintf(fp, "Status: %s %s %s\n", pwant, pflag, pstat);
698
699                free(pflag);
700                free(pwant);
701                free(pstat);
702           } else if (strcasecmp(field, "Suggests") == 0) {
703                if (pkg->suggests_count) {
704                     fprintf(fp, "Suggests:");
705                     for(i = 0; i < pkg->suggests_count; i++) {
706                         fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->suggests_str[i]);
707                     }
708                     fprintf(fp, "\n");
709                }
710           } else {
711                goto UNKNOWN_FMT_FIELD;
712           }
713           break;
714      case 't':
715      case 'T':
716           if (strcasecmp(field, "Tags") == 0) {
717                if (pkg->tags) {
718                    fprintf(fp, "Tags: %s\n", pkg->tags);
719                }
720           }
721           break;
722      case 'v':
723      case 'V':
724           {
725                char *version = pkg_version_str_alloc(pkg);
726                if (version == NULL)
727                     return;
728                fprintf(fp, "Version: %s\n", version);
729                free(version);
730           }
731           break;
732      default:
733           goto UNKNOWN_FMT_FIELD;
734      }
735
736      return;
737
738 UNKNOWN_FMT_FIELD:
739      fprintf(stderr, "%s: ERROR: Unknown field name: %s\n", __FUNCTION__, field);
740 }
741
742 void pkg_formatted_info(FILE *fp, pkg_t *pkg)
743 {
744         pkg_formatted_field(fp, pkg, "Package");
745         pkg_formatted_field(fp, pkg, "Version");
746         pkg_formatted_field(fp, pkg, "Depends");
747         pkg_formatted_field(fp, pkg, "Recommends");
748         pkg_formatted_field(fp, pkg, "Suggests");
749         pkg_formatted_field(fp, pkg, "Provides");
750         pkg_formatted_field(fp, pkg, "Replaces");
751         pkg_formatted_field(fp, pkg, "Conflicts");
752         pkg_formatted_field(fp, pkg, "Status");
753         pkg_formatted_field(fp, pkg, "Section");
754         pkg_formatted_field(fp, pkg, "Essential");
755         pkg_formatted_field(fp, pkg, "Architecture");
756         pkg_formatted_field(fp, pkg, "Maintainer");
757         pkg_formatted_field(fp, pkg, "MD5sum");
758         pkg_formatted_field(fp, pkg, "Size");
759         pkg_formatted_field(fp, pkg, "Filename");
760         pkg_formatted_field(fp, pkg, "Conffiles");
761         pkg_formatted_field(fp, pkg, "Source");
762         pkg_formatted_field(fp, pkg, "Description");
763         pkg_formatted_field(fp, pkg, "Installed-Time");
764         pkg_formatted_field(fp, pkg, "Tags");
765         fputs("\n", fp);
766 }
767
768 void pkg_print_status(pkg_t * pkg, FILE * file)
769 {
770      if (pkg == NULL) {
771           return;
772      }
773
774      /* XXX: QUESTION: Do we actually want more fields here? The
775         original idea was to save space by installing only what was
776         needed for actual computation, (package, version, status,
777         essential, conffiles). The assumption is that all other fields
778         can be found in th available file.
779
780         But, someone proposed the idea to make it possible to
781         reconstruct a .opk from an installed package, (ie. for beaming
782         from one handheld to another). So, maybe we actually want a few
783         more fields here, (depends, suggests, etc.), so that that would
784         be guaranteed to work even in the absence of more information
785         from the available file.
786
787         28-MAR-03: kergoth and I discussed this yesterday.  We think
788         the essential info needs to be here for all installed packages
789         because they may not appear in the Packages files on various
790         feeds.  Furthermore, one should be able to install from URL or
791         local storage without requiring a Packages file from any feed.
792         -Jamey
793      */
794      pkg_formatted_field(file, pkg, "Package");
795      pkg_formatted_field(file, pkg, "Version");
796      pkg_formatted_field(file, pkg, "Depends");
797      pkg_formatted_field(file, pkg, "Recommends");
798      pkg_formatted_field(file, pkg, "Suggests");
799      pkg_formatted_field(file, pkg, "Provides");
800      pkg_formatted_field(file, pkg, "Replaces");
801      pkg_formatted_field(file, pkg, "Conflicts");
802      pkg_formatted_field(file, pkg, "Status");
803      pkg_formatted_field(file, pkg, "Essential");
804      pkg_formatted_field(file, pkg, "Architecture");
805      pkg_formatted_field(file, pkg, "Conffiles");
806      pkg_formatted_field(file, pkg, "Installed-Time");
807      pkg_formatted_field(file, pkg, "Auto-Installed");
808      fputs("\n", file);
809 }
810
811 /*
812  * libdpkg - Debian packaging suite library routines
813  * vercmp.c - comparison of version numbers
814  *
815  * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
816  */
817 int pkg_compare_versions(const pkg_t *pkg, const pkg_t *ref_pkg)
818 {
819      int r;
820
821      if (pkg->epoch > ref_pkg->epoch) {
822           return 1;
823      }
824
825      if (pkg->epoch < ref_pkg->epoch) {
826           return -1;
827      }
828
829      r = verrevcmp(pkg->version, ref_pkg->version);
830      if (r) {
831           return r;
832      }
833
834      r = verrevcmp(pkg->revision, ref_pkg->revision);
835      if (r) {
836           return r;
837      }
838
839      return r;
840 }
841
842 /* assume ascii; warning: evaluates x multiple times! */
843 #define order(x) ((x) == '~' ? -1 \
844                 : isdigit((x)) ? 0 \
845                 : !(x) ? 0 \
846                 : isalpha((x)) ? (x) \
847                 : (x) + 256)
848
849 static int verrevcmp(const char *val, const char *ref) {
850   if (!val) val= "";
851   if (!ref) ref= "";
852
853   while (*val || *ref) {
854     int first_diff= 0;
855
856     while ( (*val && !isdigit(*val)) || (*ref && !isdigit(*ref)) ) {
857       int vc= order(*val), rc= order(*ref);
858       if (vc != rc) return vc - rc;
859       val++; ref++;
860     }
861
862     while ( *val == '0' ) val++;
863     while ( *ref == '0' ) ref++;
864     while (isdigit(*val) && isdigit(*ref)) {
865       if (!first_diff) first_diff= *val - *ref;
866       val++; ref++;
867     }
868     if (isdigit(*val)) return 1;
869     if (isdigit(*ref)) return -1;
870     if (first_diff) return first_diff;
871   }
872   return 0;
873 }
874
875 int pkg_version_satisfied(pkg_t *it, pkg_t *ref, const char *op)
876 {
877      int r;
878
879      r = pkg_compare_versions(it, ref);
880
881      if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0) {
882           return r <= 0;
883      }
884
885      if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0) {
886           return r >= 0;
887      }
888
889      if (strcmp(op, "<<") == 0) {
890           return r < 0;
891      }
892
893      if (strcmp(op, ">>") == 0) {
894           return r > 0;
895      }
896
897      if (strcmp(op, "=") == 0) {
898           return r == 0;
899      }
900
901      fprintf(stderr, "unknown operator: %s", op);
902      return 0;
903 }
904
905 int pkg_name_version_and_architecture_compare(const void *p1, const void *p2)
906 {
907      const pkg_t *a = *(const pkg_t**) p1;
908      const pkg_t *b = *(const pkg_t**) p2;
909      int namecmp;
910      int vercmp;
911      if (!a->name || !b->name) {
912        fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->name=%p b=%p b->name=%p\n",
913                a, a->name, b, b->name);
914        return 0;
915      }
916        
917      namecmp = strcmp(a->name, b->name);
918      if (namecmp)
919           return namecmp;
920      vercmp = pkg_compare_versions(a, b);
921      if (vercmp)
922           return vercmp;
923      if (!a->arch_priority || !b->arch_priority) {
924        fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->arch_priority=%i b=%p b->arch_priority=%i\n",
925                a, a->arch_priority, b, b->arch_priority);
926        return 0;
927      }
928      if (a->arch_priority > b->arch_priority)
929           return 1;
930      if (a->arch_priority < b->arch_priority)
931           return -1;
932      return 0;
933 }
934
935 int abstract_pkg_name_compare(const void *p1, const void *p2)
936 {
937      const abstract_pkg_t *a = *(const abstract_pkg_t **)p1;
938      const abstract_pkg_t *b = *(const abstract_pkg_t **)p2;
939      if (!a->name || !b->name) {
940        fprintf(stderr, "abstract_pkg_name_compare: a=%p a->name=%p b=%p b->name=%p\n",
941                a, a->name, b, b->name);
942        return 0;
943      }
944      return strcmp(a->name, b->name);
945 }
946
947
948 char *
949 pkg_version_str_alloc(pkg_t *pkg)
950 {
951         char *version;
952
953         if (pkg->epoch) {
954                 if (pkg->revision)
955                         sprintf_alloc(&version, "%d:%s-%s",
956                                 pkg->epoch, pkg->version, pkg->revision);
957                 else
958                         sprintf_alloc(&version, "%d:%s",
959                                 pkg->epoch, pkg->version);
960         } else {
961                 if (pkg->revision)
962                         sprintf_alloc(&version, "%s-%s",
963                                 pkg->version, pkg->revision);
964                 else
965                         version = xstrdup(pkg->version);
966         }
967
968         return version;
969 }
970
971 str_list_t *pkg_get_installed_files(pkg_t *pkg)
972 {
973      int err;
974      char *list_file_name = NULL;
975      FILE *list_file = NULL;
976      char *line;
977      char *installed_file_name;
978      int rootdirlen;
979
980      pkg->installed_files_ref_cnt++;
981
982      if (pkg->installed_files) {
983           return pkg->installed_files;
984      }
985
986      pkg->installed_files = str_list_alloc();
987
988      /* For uninstalled packages, get the file list directly from the package.
989         For installed packages, look at the package.list file in the database.
990      */
991      if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
992           if (pkg->local_filename == NULL) {
993                return pkg->installed_files;
994           }
995           /* XXX: CLEANUP: Maybe rewrite this to avoid using a temporary
996              file. In other words, change deb_extract so that it can
997              simply return the file list as a char *[] rather than
998              insisting on writing in to a FILE * as it does now. */
999           list_file = tmpfile();
1000           err = pkg_extract_data_file_names_to_stream(pkg, list_file);
1001           if (err) {
1002                fclose(list_file);
1003                fprintf(stderr, "%s: Error extracting file list from %s: %s\n",
1004                        __FUNCTION__, pkg->local_filename, strerror(err));
1005                return pkg->installed_files;
1006           }
1007           rewind(list_file);
1008      } else {
1009           sprintf_alloc(&list_file_name, "%s/%s.list",
1010                         pkg->dest->info_dir, pkg->name);
1011           if (! file_exists(list_file_name)) {
1012                free(list_file_name);
1013                return pkg->installed_files;
1014           }
1015
1016           list_file = fopen(list_file_name, "r");
1017           if (list_file == NULL) {
1018                fprintf(stderr, "WARNING: Cannot open %s: %s\n",
1019                        list_file_name, strerror(errno));
1020                free(list_file_name);
1021                return pkg->installed_files;
1022           }
1023           free(list_file_name);
1024      }
1025
1026      rootdirlen = strlen( pkg->dest->root_dir );
1027      while (1) {
1028           char *file_name;
1029         
1030           line = file_read_line_alloc(list_file);
1031           if (line == NULL) {
1032                break;
1033           }
1034           str_chomp(line);
1035           file_name = line;
1036
1037           /* Take pains to avoid uglies like "/./" in the middle of file_name. */
1038           if( strncmp( pkg->dest->root_dir, 
1039                        file_name, 
1040                        rootdirlen ) ) {
1041                if (*file_name == '.') {
1042                     file_name++;
1043                }
1044                if (*file_name == '/') {
1045                     file_name++;
1046                }
1047
1048                /* Freed in pkg_free_installed_files */
1049                sprintf_alloc(&installed_file_name, "%s%s", pkg->dest->root_dir, file_name);
1050           } else {
1051                // already contains root_dir as header -> ABSOLUTE
1052                sprintf_alloc(&installed_file_name, "%s", file_name);
1053           }
1054           str_list_append(pkg->installed_files, installed_file_name);
1055           free(installed_file_name);
1056           free(line);
1057      }
1058
1059      fclose(list_file);
1060
1061      return pkg->installed_files;
1062 }
1063
1064 /* XXX: CLEANUP: This function and it's counterpart,
1065    (pkg_get_installed_files), do not match our init/deinit naming
1066    convention. Nor the alloc/free convention. But, then again, neither
1067    of these conventions currrently fit the way these two functions
1068    work. */
1069 int pkg_free_installed_files(pkg_t *pkg)
1070 {
1071      pkg->installed_files_ref_cnt--;
1072
1073      if (pkg->installed_files_ref_cnt > 0)
1074           return 0;
1075
1076      if (pkg->installed_files) {
1077          str_list_purge(pkg->installed_files);
1078      }
1079
1080      pkg->installed_files = NULL;
1081
1082      return 0;
1083 }
1084
1085 int pkg_remove_installed_files_list(opkg_conf_t *conf, pkg_t *pkg)
1086 {
1087      int err;
1088      char *list_file_name;
1089
1090      //I don't think pkg_free_installed_files should be called here. Jamey
1091      //pkg_free_installed_files(pkg);
1092
1093      sprintf_alloc(&list_file_name, "%s/%s.list",
1094                    pkg->dest->info_dir, pkg->name);
1095      if (!conf->noaction) {
1096           err = unlink(list_file_name);
1097           free(list_file_name);
1098
1099           if (err) {
1100                return errno;
1101           }
1102      }
1103      return 0;
1104 }
1105
1106 conffile_t *pkg_get_conffile(pkg_t *pkg, const char *file_name)
1107 {
1108      conffile_list_elt_t *iter;
1109      conffile_t *conffile;
1110
1111      if (pkg == NULL) {
1112           return NULL;
1113      }
1114
1115      for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
1116           conffile = (conffile_t *)iter->data;
1117
1118           if (strcmp(conffile->name, file_name) == 0) {
1119                return conffile;
1120           }
1121      }
1122
1123      return NULL;
1124 }
1125
1126 int pkg_run_script(opkg_conf_t *conf, pkg_t *pkg,
1127                    const char *script, const char *args)
1128 {
1129      int err;
1130      char *path;
1131      char *cmd;
1132
1133      if (conf->noaction)
1134              return 0;
1135
1136      /* XXX: CLEANUP: There must be a better way to handle maintainer
1137         scripts when running with offline_root mode and/or a dest other
1138         than '/'. I've been playing around with some clever chroot
1139         tricks and I might come up with something workable. */
1140      /*
1141       * Attempt to provide a restricted environment for offline operation
1142       * Need the following set as a minimum:
1143       * OPKG_OFFLINE_ROOT = absolute path to root dir
1144       * D                 = absolute path to root dir (for OE generated postinst)
1145       * PATH              = something safe (a restricted set of utilities)
1146       */
1147
1148      if (conf->offline_root) {
1149           if (conf->offline_root_path) {
1150             setenv("PATH", conf->offline_root_path, 1);
1151           } else {
1152             opkg_message(conf, OPKG_NOTICE, 
1153                 "(offline root mode: not running %s.%s)\n", pkg->name, script);
1154             return 0;
1155           }
1156           setenv("OPKG_OFFLINE_ROOT", conf->offline_root, 1);
1157           setenv("D", conf->offline_root, 1);
1158      }
1159
1160      /* XXX: FEATURE: When conf->offline_root is set, we should run the
1161         maintainer script within a chroot environment. */
1162
1163      /* Installed packages have scripts in pkg->dest->info_dir, uninstalled packages
1164         have scripts in pkg->tmp_unpack_dir. */
1165      if (pkg->state_status == SS_INSTALLED || pkg->state_status == SS_UNPACKED) {
1166           if (pkg->dest == NULL) {
1167                fprintf(stderr, "%s: ERROR: installed package %s has a NULL dest\n",
1168                        __FUNCTION__, pkg->name);
1169                return EINVAL;
1170           }
1171           sprintf_alloc(&path, "%s/%s.%s", pkg->dest->info_dir, pkg->name, script);
1172      } else {
1173           if (pkg->tmp_unpack_dir == NULL) {
1174                fprintf(stderr, "%s: ERROR: uninstalled package %s has a NULL tmp_unpack_dir\n",
1175                        __FUNCTION__, pkg->name);
1176                return EINVAL;
1177           }
1178           sprintf_alloc(&path, "%s/%s", pkg->tmp_unpack_dir, script);
1179      }
1180
1181      opkg_message(conf, OPKG_INFO, "Running script %s\n", path);
1182
1183      setenv("PKG_ROOT",
1184             pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir, 1);
1185
1186      if (! file_exists(path)) {
1187           free(path);
1188           return 0;
1189      }
1190
1191      sprintf_alloc(&cmd, "%s %s", path, args);
1192      free(path);
1193
1194      err = xsystem(cmd);
1195      free(cmd);
1196
1197      if (err) {
1198           fprintf(stderr, "%s script returned status %d\n", script, err);
1199           return err;
1200      }
1201
1202      return 0;
1203 }
1204
1205 char *pkg_state_want_to_str(pkg_state_want_t sw)
1206 {
1207      int i;
1208
1209      for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1210           if (pkg_state_want_map[i].value == sw) {
1211                return xstrdup(pkg_state_want_map[i].str);
1212           }
1213      }
1214
1215      fprintf(stderr, "%s: ERROR: Illegal value for state_want: %d\n",
1216              __FUNCTION__, sw);
1217      return xstrdup("<STATE_WANT_UNKNOWN>");
1218 }
1219
1220 pkg_state_want_t pkg_state_want_from_str(char *str)
1221 {
1222      int i;
1223
1224      for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1225           if (strcmp(str, pkg_state_want_map[i].str) == 0) {
1226                return pkg_state_want_map[i].value;
1227           }
1228      }
1229
1230      fprintf(stderr, "%s: ERROR: Illegal value for state_want string: %s\n",
1231              __FUNCTION__, str);
1232      return SW_UNKNOWN;
1233 }
1234
1235 char *pkg_state_flag_to_str(pkg_state_flag_t sf)
1236 {
1237      int i;
1238      int len = 3; /* ok\000 is minimum */
1239      char *str = NULL;
1240
1241      /* clear the temporary flags before converting to string */
1242      sf &= SF_NONVOLATILE_FLAGS;
1243
1244      if (sf == 0) {
1245           return xstrdup("ok");
1246      } else {
1247
1248           for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1249                if (sf & pkg_state_flag_map[i].value) {
1250                     len += strlen(pkg_state_flag_map[i].str) + 1;
1251                }
1252           }
1253           str = xmalloc(len);
1254           str[0] = 0;
1255           for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1256                if (sf & pkg_state_flag_map[i].value) {
1257                     strcat(str, pkg_state_flag_map[i].str);
1258                     strcat(str, ",");
1259                }
1260           }
1261           len = strlen(str);
1262           str[len-1] = 0; /* squash last comma */
1263           return str;
1264      }
1265 }
1266
1267 pkg_state_flag_t pkg_state_flag_from_str(const char *str)
1268 {
1269      int i;
1270      int sf = SF_OK;
1271
1272      if (strcmp(str, "ok") == 0) {
1273           return SF_OK;
1274      }
1275      for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1276           const char *sfname = pkg_state_flag_map[i].str;
1277           int sfname_len = strlen(sfname);
1278           if (strncmp(str, sfname, sfname_len) == 0) {
1279                sf |= pkg_state_flag_map[i].value;
1280                str += sfname_len;
1281                if (str[0] == ',') {
1282                     str++;
1283                } else {
1284                     break;
1285                }
1286           }
1287      }
1288
1289      return sf;
1290 }
1291
1292 char *pkg_state_status_to_str(pkg_state_status_t ss)
1293 {
1294      int i;
1295
1296      for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1297           if (pkg_state_status_map[i].value == ss) {
1298                return xstrdup(pkg_state_status_map[i].str);
1299           }
1300      }
1301
1302      fprintf(stderr, "%s: ERROR: Illegal value for state_status: %d\n",
1303              __FUNCTION__, ss);
1304      return xstrdup("<STATE_STATUS_UNKNOWN>");
1305 }
1306
1307 pkg_state_status_t pkg_state_status_from_str(const char *str)
1308 {
1309      int i;
1310
1311      for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1312           if (strcmp(str, pkg_state_status_map[i].str) == 0) {
1313                return pkg_state_status_map[i].value;
1314           }
1315      }
1316
1317      fprintf(stderr, "%s: ERROR: Illegal value for state_status string: %s\n",
1318              __FUNCTION__, str);
1319      return SS_NOT_INSTALLED;
1320 }
1321
1322 int pkg_arch_supported(opkg_conf_t *conf, pkg_t *pkg)
1323 {
1324      nv_pair_list_elt_t *l;
1325
1326      if (!pkg->architecture)
1327           return 1;
1328
1329      list_for_each_entry(l , &conf->arch_list.head, node) {
1330           nv_pair_t *nv = (nv_pair_t *)l->data;
1331           if (strcmp(nv->name, pkg->architecture) == 0) {
1332                opkg_message(conf, OPKG_DEBUG, "arch %s (priority %s) supported for pkg %s\n", nv->name, nv->value, pkg->name);
1333                return 1;
1334           }
1335      }
1336
1337      opkg_message(conf, OPKG_DEBUG, "arch %s unsupported for pkg %s\n", pkg->architecture, pkg->name);
1338      return 0;
1339 }
1340
1341 int pkg_get_arch_priority(opkg_conf_t *conf, const char *archname)
1342 {
1343      nv_pair_list_elt_t *l;
1344
1345      list_for_each_entry(l , &conf->arch_list.head, node) {
1346           nv_pair_t *nv = (nv_pair_t *)l->data;
1347           if (strcmp(nv->name, archname) == 0) {
1348                int priority = strtol(nv->value, NULL, 0);
1349                return priority;
1350           }
1351      }
1352      return 0;
1353 }
1354
1355 int pkg_info_preinstall_check(opkg_conf_t *conf)
1356 {
1357      int i;
1358      hash_table_t *pkg_hash = &conf->pkg_hash;
1359      pkg_vec_t *available_pkgs = pkg_vec_alloc();
1360      pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1361
1362      opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: updating arch priority for each package\n");
1363      pkg_hash_fetch_available(pkg_hash, available_pkgs);
1364      /* update arch_priority for each package */
1365      for (i = 0; i < available_pkgs->len; i++) {
1366           pkg_t *pkg = available_pkgs->pkgs[i];
1367           int arch_priority = 1;
1368           if (!pkg)
1369                continue;
1370           // opkg_message(conf, OPKG_DEBUG2, " package %s version=%s arch=%p:", pkg->name, pkg->version, pkg->architecture);
1371           if (pkg->architecture) 
1372                arch_priority = pkg_get_arch_priority(conf, pkg->architecture);
1373           else 
1374                opkg_message(conf, OPKG_ERROR, "pkg_info_preinstall_check: no architecture for package %s\n", pkg->name);
1375           // opkg_message(conf, OPKG_DEBUG2, "%s arch_priority=%d\n", pkg->architecture, arch_priority);
1376           pkg->arch_priority = arch_priority;
1377      }
1378
1379      for (i = 0; i < available_pkgs->len; i++) {
1380           pkg_t *pkg = available_pkgs->pkgs[i];
1381           if (!pkg->arch_priority && (pkg->state_flag || (pkg->state_want != SW_UNKNOWN))) {
1382                /* clear flags and want for any uninstallable package */
1383                opkg_message(conf, OPKG_DEBUG, "Clearing state_want and state_flag for pkg=%s (arch_priority=%d flag=%d want=%d)\n", 
1384                             pkg->name, pkg->arch_priority, pkg->state_flag, pkg->state_want);
1385                pkg->state_want = SW_UNKNOWN;
1386                pkg->state_flag = 0;
1387           }
1388      }
1389      pkg_vec_free(available_pkgs);
1390
1391      /* update the file owner data structure */
1392      opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: update file owner list\n");
1393      pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1394      for (i = 0; i < installed_pkgs->len; i++) {
1395           pkg_t *pkg = installed_pkgs->pkgs[i];
1396           str_list_t *installed_files = pkg_get_installed_files(pkg); /* this causes installed_files to be cached */
1397           str_list_elt_t *iter, *niter;
1398           if (installed_files == NULL) {
1399                opkg_message(conf, OPKG_ERROR, "No installed files for pkg %s\n", pkg->name);
1400                break;
1401           }
1402           for (iter = str_list_first(installed_files), niter = str_list_next(installed_files, iter); 
1403                   iter; 
1404                   iter = niter, niter = str_list_next(installed_files, iter)) {
1405                char *installed_file = (char *) iter->data;
1406                // opkg_message(conf, OPKG_DEBUG2, "pkg %s: file=%s\n", pkg->name, installed_file);
1407                file_hash_set_file_owner(conf, installed_file, pkg);
1408           }
1409           pkg_free_installed_files(pkg);
1410      }
1411      pkg_vec_free(installed_pkgs);
1412
1413      return 0;
1414 }
1415
1416 struct pkg_write_filelist_data {
1417      opkg_conf_t *conf;
1418      pkg_t *pkg;
1419      FILE *stream;
1420 };
1421
1422 void pkg_write_filelist_helper(const char *key, void *entry_, void *data_)
1423 {
1424      struct pkg_write_filelist_data *data = data_;
1425      pkg_t *entry = entry_;
1426      if (entry == data->pkg) {
1427           fprintf(data->stream, "%s\n", key);
1428      }
1429 }
1430
1431 int pkg_write_filelist(opkg_conf_t *conf, pkg_t *pkg)
1432 {
1433      struct pkg_write_filelist_data data;
1434      char *list_file_name = NULL;
1435      int err = 0;
1436
1437      if (!pkg) {
1438           opkg_message(conf, OPKG_ERROR, "Null pkg\n");
1439           return -EINVAL;
1440      }
1441      opkg_message(conf, OPKG_INFO,
1442                   "    creating %s.list file\n", pkg->name);
1443      sprintf_alloc(&list_file_name, "%s/%s.list", pkg->dest->info_dir, pkg->name);
1444      if (!list_file_name) {
1445           opkg_message(conf, OPKG_ERROR, "Failed to alloc list_file_name\n");
1446           return -ENOMEM;
1447      }
1448      opkg_message(conf, OPKG_INFO,
1449                   "    creating %s file for pkg %s\n", list_file_name, pkg->name);
1450      data.stream = fopen(list_file_name, "w");
1451      if (!data.stream) {
1452           opkg_message(conf, OPKG_ERROR, "Could not open %s for writing: %s\n",
1453                        list_file_name, strerror(errno));
1454                        return errno;
1455      }
1456      data.pkg = pkg;
1457      data.conf = conf;
1458      hash_table_foreach(&conf->file_hash, pkg_write_filelist_helper, &data);
1459      fclose(data.stream);
1460      free(list_file_name);
1461
1462      pkg->state_flag &= ~SF_FILELIST_CHANGED;
1463
1464      return err;
1465 }
1466
1467 int pkg_write_changed_filelists(opkg_conf_t *conf)
1468 {
1469      pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1470      hash_table_t *pkg_hash = &conf->pkg_hash;
1471      int i;
1472      int err;
1473      if (conf->noaction)
1474           return 0;
1475
1476      opkg_message(conf, OPKG_INFO, "%s: saving changed filelists\n", __FUNCTION__);
1477      pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1478      for (i = 0; i < installed_pkgs->len; i++) {
1479           pkg_t *pkg = installed_pkgs->pkgs[i];
1480           if (pkg->state_flag & SF_FILELIST_CHANGED) {
1481                opkg_message(conf, OPKG_DEBUG, "Calling pkg_write_filelist for pkg=%s from %s\n", pkg->name, __FUNCTION__);
1482                err = pkg_write_filelist(conf, pkg);
1483                if (err)
1484                     opkg_message(conf, OPKG_NOTICE, "pkg_write_filelist pkg=%s returned %d\n", pkg->name, err);
1485           }
1486      }
1487      pkg_vec_free (installed_pkgs);
1488      return 0;
1489 }