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