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