b0c2b69944129df17011c0222f14fe62a8ad6dcd
[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(opkg_conf_t *conf, 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 = 0;
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      if (conf->offline_root)
1028           rootdirlen = strlen(conf->offline_root);
1029
1030      while (1) {
1031           char *file_name;
1032         
1033           line = file_read_line_alloc(list_file);
1034           if (line == NULL) {
1035                break;
1036           }
1037           str_chomp(line);
1038           file_name = line;
1039
1040           if (pkg->state_status == SS_NOT_INSTALLED) {
1041                if (*file_name == '.') {
1042                     file_name++;
1043                }
1044                if (*file_name == '/') {
1045                     file_name++;
1046                }
1047                sprintf_alloc(&installed_file_name, "%s%s",
1048                                pkg->dest->root_dir, file_name);
1049           } else {
1050                if (conf->offline_root &&
1051                        strncmp(conf->offline_root, file_name, rootdirlen)) {
1052                     sprintf_alloc(&installed_file_name, "%s%s",
1053                                     conf->offline_root, file_name);
1054                } else {
1055                     // already contains root_dir as header -> ABSOLUTE
1056                     sprintf_alloc(&installed_file_name, "%s", file_name);
1057                }
1058           }
1059           str_list_append(pkg->installed_files, installed_file_name);
1060           free(installed_file_name);
1061           free(line);
1062      }
1063
1064      fclose(list_file);
1065
1066      return pkg->installed_files;
1067 }
1068
1069 /* XXX: CLEANUP: This function and it's counterpart,
1070    (pkg_get_installed_files), do not match our init/deinit naming
1071    convention. Nor the alloc/free convention. But, then again, neither
1072    of these conventions currrently fit the way these two functions
1073    work. */
1074 int pkg_free_installed_files(pkg_t *pkg)
1075 {
1076      pkg->installed_files_ref_cnt--;
1077
1078      if (pkg->installed_files_ref_cnt > 0)
1079           return 0;
1080
1081      if (pkg->installed_files) {
1082          str_list_purge(pkg->installed_files);
1083      }
1084
1085      pkg->installed_files = NULL;
1086
1087      return 0;
1088 }
1089
1090 int pkg_remove_installed_files_list(opkg_conf_t *conf, pkg_t *pkg)
1091 {
1092      int err;
1093      char *list_file_name;
1094
1095      //I don't think pkg_free_installed_files should be called here. Jamey
1096      //pkg_free_installed_files(pkg);
1097
1098      sprintf_alloc(&list_file_name, "%s/%s.list",
1099                    pkg->dest->info_dir, pkg->name);
1100      if (!conf->noaction) {
1101           err = unlink(list_file_name);
1102           free(list_file_name);
1103
1104           if (err) {
1105                return errno;
1106           }
1107      }
1108      return 0;
1109 }
1110
1111 conffile_t *pkg_get_conffile(pkg_t *pkg, const char *file_name)
1112 {
1113      conffile_list_elt_t *iter;
1114      conffile_t *conffile;
1115
1116      if (pkg == NULL) {
1117           return NULL;
1118      }
1119
1120      for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
1121           conffile = (conffile_t *)iter->data;
1122
1123           if (strcmp(conffile->name, file_name) == 0) {
1124                return conffile;
1125           }
1126      }
1127
1128      return NULL;
1129 }
1130
1131 int pkg_run_script(opkg_conf_t *conf, pkg_t *pkg,
1132                    const char *script, const char *args)
1133 {
1134      int err;
1135      char *path;
1136      char *cmd;
1137
1138      if (conf->noaction)
1139              return 0;
1140
1141      /* XXX: CLEANUP: There must be a better way to handle maintainer
1142         scripts when running with offline_root mode and/or a dest other
1143         than '/'. I've been playing around with some clever chroot
1144         tricks and I might come up with something workable. */
1145      /*
1146       * Attempt to provide a restricted environment for offline operation
1147       * Need the following set as a minimum:
1148       * OPKG_OFFLINE_ROOT = absolute path to root dir
1149       * D                 = absolute path to root dir (for OE generated postinst)
1150       * PATH              = something safe (a restricted set of utilities)
1151       */
1152
1153      if (conf->offline_root) {
1154           if (conf->offline_root_path) {
1155             setenv("PATH", conf->offline_root_path, 1);
1156           } else {
1157             opkg_message(conf, OPKG_NOTICE, 
1158                 "(offline root mode: not running %s.%s)\n", pkg->name, script);
1159             return 0;
1160           }
1161           setenv("OPKG_OFFLINE_ROOT", conf->offline_root, 1);
1162           setenv("D", conf->offline_root, 1);
1163      }
1164
1165      /* XXX: FEATURE: When conf->offline_root is set, we should run the
1166         maintainer script within a chroot environment. */
1167
1168      /* Installed packages have scripts in pkg->dest->info_dir, uninstalled packages
1169         have scripts in pkg->tmp_unpack_dir. */
1170      if (pkg->state_status == SS_INSTALLED || pkg->state_status == SS_UNPACKED) {
1171           if (pkg->dest == NULL) {
1172                fprintf(stderr, "%s: ERROR: installed package %s has a NULL dest\n",
1173                        __FUNCTION__, pkg->name);
1174                return EINVAL;
1175           }
1176           sprintf_alloc(&path, "%s/%s.%s", pkg->dest->info_dir, pkg->name, script);
1177      } else {
1178           if (pkg->tmp_unpack_dir == NULL) {
1179                fprintf(stderr, "%s: ERROR: uninstalled package %s has a NULL tmp_unpack_dir\n",
1180                        __FUNCTION__, pkg->name);
1181                return EINVAL;
1182           }
1183           sprintf_alloc(&path, "%s/%s", pkg->tmp_unpack_dir, script);
1184      }
1185
1186      opkg_message(conf, OPKG_INFO, "Running script %s\n", path);
1187
1188      setenv("PKG_ROOT",
1189             pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir, 1);
1190
1191      if (! file_exists(path)) {
1192           free(path);
1193           return 0;
1194      }
1195
1196      sprintf_alloc(&cmd, "%s %s", path, args);
1197      free(path);
1198      {
1199           const char *argv[] = {"sh", "-c", cmd, NULL};
1200           err = xsystem(argv);
1201      }
1202      free(cmd);
1203
1204      if (err) {
1205           fprintf(stderr, "%s script returned status %d\n", script, err);
1206           return err;
1207      }
1208
1209      return 0;
1210 }
1211
1212 char *pkg_state_want_to_str(pkg_state_want_t sw)
1213 {
1214      int i;
1215
1216      for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1217           if (pkg_state_want_map[i].value == sw) {
1218                return xstrdup(pkg_state_want_map[i].str);
1219           }
1220      }
1221
1222      fprintf(stderr, "%s: ERROR: Illegal value for state_want: %d\n",
1223              __FUNCTION__, sw);
1224      return xstrdup("<STATE_WANT_UNKNOWN>");
1225 }
1226
1227 pkg_state_want_t pkg_state_want_from_str(char *str)
1228 {
1229      int i;
1230
1231      for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1232           if (strcmp(str, pkg_state_want_map[i].str) == 0) {
1233                return pkg_state_want_map[i].value;
1234           }
1235      }
1236
1237      fprintf(stderr, "%s: ERROR: Illegal value for state_want string: %s\n",
1238              __FUNCTION__, str);
1239      return SW_UNKNOWN;
1240 }
1241
1242 char *pkg_state_flag_to_str(pkg_state_flag_t sf)
1243 {
1244      int i;
1245      int len = 3; /* ok\000 is minimum */
1246      char *str = NULL;
1247
1248      /* clear the temporary flags before converting to string */
1249      sf &= SF_NONVOLATILE_FLAGS;
1250
1251      if (sf == 0) {
1252           return xstrdup("ok");
1253      } else {
1254
1255           for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1256                if (sf & pkg_state_flag_map[i].value) {
1257                     len += strlen(pkg_state_flag_map[i].str) + 1;
1258                }
1259           }
1260           str = xmalloc(len);
1261           str[0] = 0;
1262           for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1263                if (sf & pkg_state_flag_map[i].value) {
1264                     strcat(str, pkg_state_flag_map[i].str);
1265                     strcat(str, ",");
1266                }
1267           }
1268           len = strlen(str);
1269           str[len-1] = 0; /* squash last comma */
1270           return str;
1271      }
1272 }
1273
1274 pkg_state_flag_t pkg_state_flag_from_str(const char *str)
1275 {
1276      int i;
1277      int sf = SF_OK;
1278
1279      if (strcmp(str, "ok") == 0) {
1280           return SF_OK;
1281      }
1282      for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1283           const char *sfname = pkg_state_flag_map[i].str;
1284           int sfname_len = strlen(sfname);
1285           if (strncmp(str, sfname, sfname_len) == 0) {
1286                sf |= pkg_state_flag_map[i].value;
1287                str += sfname_len;
1288                if (str[0] == ',') {
1289                     str++;
1290                } else {
1291                     break;
1292                }
1293           }
1294      }
1295
1296      return sf;
1297 }
1298
1299 char *pkg_state_status_to_str(pkg_state_status_t ss)
1300 {
1301      int i;
1302
1303      for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1304           if (pkg_state_status_map[i].value == ss) {
1305                return xstrdup(pkg_state_status_map[i].str);
1306           }
1307      }
1308
1309      fprintf(stderr, "%s: ERROR: Illegal value for state_status: %d\n",
1310              __FUNCTION__, ss);
1311      return xstrdup("<STATE_STATUS_UNKNOWN>");
1312 }
1313
1314 pkg_state_status_t pkg_state_status_from_str(const char *str)
1315 {
1316      int i;
1317
1318      for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1319           if (strcmp(str, pkg_state_status_map[i].str) == 0) {
1320                return pkg_state_status_map[i].value;
1321           }
1322      }
1323
1324      fprintf(stderr, "%s: ERROR: Illegal value for state_status string: %s\n",
1325              __FUNCTION__, str);
1326      return SS_NOT_INSTALLED;
1327 }
1328
1329 int pkg_arch_supported(opkg_conf_t *conf, pkg_t *pkg)
1330 {
1331      nv_pair_list_elt_t *l;
1332
1333      if (!pkg->architecture)
1334           return 1;
1335
1336      list_for_each_entry(l , &conf->arch_list.head, node) {
1337           nv_pair_t *nv = (nv_pair_t *)l->data;
1338           if (strcmp(nv->name, pkg->architecture) == 0) {
1339                opkg_message(conf, OPKG_DEBUG, "arch %s (priority %s) supported for pkg %s\n", nv->name, nv->value, pkg->name);
1340                return 1;
1341           }
1342      }
1343
1344      opkg_message(conf, OPKG_DEBUG, "arch %s unsupported for pkg %s\n", pkg->architecture, pkg->name);
1345      return 0;
1346 }
1347
1348 int pkg_get_arch_priority(opkg_conf_t *conf, const char *archname)
1349 {
1350      nv_pair_list_elt_t *l;
1351
1352      list_for_each_entry(l , &conf->arch_list.head, node) {
1353           nv_pair_t *nv = (nv_pair_t *)l->data;
1354           if (strcmp(nv->name, archname) == 0) {
1355                int priority = strtol(nv->value, NULL, 0);
1356                return priority;
1357           }
1358      }
1359      return 0;
1360 }
1361
1362 int pkg_info_preinstall_check(opkg_conf_t *conf)
1363 {
1364      int i;
1365      hash_table_t *pkg_hash = &conf->pkg_hash;
1366      pkg_vec_t *available_pkgs = pkg_vec_alloc();
1367      pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1368
1369      opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: updating arch priority for each package\n");
1370      pkg_hash_fetch_available(pkg_hash, available_pkgs);
1371      /* update arch_priority for each package */
1372      for (i = 0; i < available_pkgs->len; i++) {
1373           pkg_t *pkg = available_pkgs->pkgs[i];
1374           int arch_priority = 1;
1375           if (!pkg)
1376                continue;
1377           // opkg_message(conf, OPKG_DEBUG2, " package %s version=%s arch=%p:", pkg->name, pkg->version, pkg->architecture);
1378           if (pkg->architecture) 
1379                arch_priority = pkg_get_arch_priority(conf, pkg->architecture);
1380           else 
1381                opkg_message(conf, OPKG_ERROR, "pkg_info_preinstall_check: no architecture for package %s\n", pkg->name);
1382           // opkg_message(conf, OPKG_DEBUG2, "%s arch_priority=%d\n", pkg->architecture, arch_priority);
1383           pkg->arch_priority = arch_priority;
1384      }
1385
1386      for (i = 0; i < available_pkgs->len; i++) {
1387           pkg_t *pkg = available_pkgs->pkgs[i];
1388           if (!pkg->arch_priority && (pkg->state_flag || (pkg->state_want != SW_UNKNOWN))) {
1389                /* clear flags and want for any uninstallable package */
1390                opkg_message(conf, OPKG_DEBUG, "Clearing state_want and state_flag for pkg=%s (arch_priority=%d flag=%d want=%d)\n", 
1391                             pkg->name, pkg->arch_priority, pkg->state_flag, pkg->state_want);
1392                pkg->state_want = SW_UNKNOWN;
1393                pkg->state_flag = 0;
1394           }
1395      }
1396      pkg_vec_free(available_pkgs);
1397
1398      /* update the file owner data structure */
1399      opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: update file owner list\n");
1400      pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1401      for (i = 0; i < installed_pkgs->len; i++) {
1402           pkg_t *pkg = installed_pkgs->pkgs[i];
1403           str_list_t *installed_files = pkg_get_installed_files(conf, pkg); /* this causes installed_files to be cached */
1404           str_list_elt_t *iter, *niter;
1405           if (installed_files == NULL) {
1406                opkg_message(conf, OPKG_ERROR, "No installed files for pkg %s\n", pkg->name);
1407                break;
1408           }
1409           for (iter = str_list_first(installed_files), niter = str_list_next(installed_files, iter); 
1410                   iter; 
1411                   iter = niter, niter = str_list_next(installed_files, iter)) {
1412                char *installed_file = (char *) iter->data;
1413                // opkg_message(conf, OPKG_DEBUG2, "pkg %s: file=%s\n", pkg->name, installed_file);
1414                file_hash_set_file_owner(conf, installed_file, pkg);
1415           }
1416           pkg_free_installed_files(pkg);
1417      }
1418      pkg_vec_free(installed_pkgs);
1419
1420      return 0;
1421 }
1422
1423 struct pkg_write_filelist_data {
1424      opkg_conf_t *conf;
1425      pkg_t *pkg;
1426      FILE *stream;
1427 };
1428
1429 void pkg_write_filelist_helper(const char *key, void *entry_, void *data_)
1430 {
1431      struct pkg_write_filelist_data *data = data_;
1432      pkg_t *entry = entry_;
1433      if (entry == data->pkg) {
1434           fprintf(data->stream, "%s\n", key);
1435      }
1436 }
1437
1438 int pkg_write_filelist(opkg_conf_t *conf, pkg_t *pkg)
1439 {
1440      struct pkg_write_filelist_data data;
1441      char *list_file_name = NULL;
1442      int err = 0;
1443
1444      if (!pkg) {
1445           opkg_message(conf, OPKG_ERROR, "Null pkg\n");
1446           return -EINVAL;
1447      }
1448      opkg_message(conf, OPKG_INFO,
1449                   "    creating %s.list file\n", pkg->name);
1450      sprintf_alloc(&list_file_name, "%s/%s.list", pkg->dest->info_dir, pkg->name);
1451      if (!list_file_name) {
1452           opkg_message(conf, OPKG_ERROR, "Failed to alloc list_file_name\n");
1453           return -ENOMEM;
1454      }
1455      opkg_message(conf, OPKG_INFO,
1456                   "    creating %s file for pkg %s\n", list_file_name, pkg->name);
1457      data.stream = fopen(list_file_name, "w");
1458      if (!data.stream) {
1459           opkg_message(conf, OPKG_ERROR, "Could not open %s for writing: %s\n",
1460                        list_file_name, strerror(errno));
1461                        return errno;
1462      }
1463      data.pkg = pkg;
1464      data.conf = conf;
1465      hash_table_foreach(&conf->file_hash, pkg_write_filelist_helper, &data);
1466      fclose(data.stream);
1467      free(list_file_name);
1468
1469      pkg->state_flag &= ~SF_FILELIST_CHANGED;
1470
1471      return err;
1472 }
1473
1474 int pkg_write_changed_filelists(opkg_conf_t *conf)
1475 {
1476      pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1477      hash_table_t *pkg_hash = &conf->pkg_hash;
1478      int i;
1479      int err;
1480      if (conf->noaction)
1481           return 0;
1482
1483      opkg_message(conf, OPKG_INFO, "%s: saving changed filelists\n", __FUNCTION__);
1484      pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1485      for (i = 0; i < installed_pkgs->len; i++) {
1486           pkg_t *pkg = installed_pkgs->pkgs[i];
1487           if (pkg->state_flag & SF_FILELIST_CHANGED) {
1488                opkg_message(conf, OPKG_DEBUG, "Calling pkg_write_filelist for pkg=%s from %s\n", pkg->name, __FUNCTION__);
1489                err = pkg_write_filelist(conf, pkg);
1490                if (err)
1491                     opkg_message(conf, OPKG_NOTICE, "pkg_write_filelist pkg=%s returned %d\n", pkg->name, err);
1492           }
1493      }
1494      pkg_vec_free (installed_pkgs);
1495      return 0;
1496 }