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