introduce the active_list for searching.
[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 <string.h>
21 #include <stdbool.h>
22 #include <errno.h>
23
24 #include "pkg.h"
25
26 #include "pkg_parse.h"
27 #include "pkg_extract.h"
28 #include "opkg_message.h"
29 #include "opkg_utils.h"
30
31 #include "sprintf_alloc.h"
32 #include "file_util.h"
33 #include "str_util.h"
34 #include "xsystem.h"
35 #include "opkg_conf.h"
36
37 typedef struct enum_map enum_map_t;
38 struct enum_map
39 {
40      int value;
41      char *str;
42 };
43
44 static const enum_map_t pkg_state_want_map[] = {
45      { SW_UNKNOWN, "unknown"},
46      { SW_INSTALL, "install"},
47      { SW_DEINSTALL, "deinstall"},
48      { SW_PURGE, "purge"}
49 };
50
51 static const enum_map_t pkg_state_flag_map[] = {
52      { SF_OK, "ok"},
53      { SF_REINSTREQ, "reinstreq"},
54      { SF_HOLD, "hold"},
55      { SF_REPLACE, "replace"},
56      { SF_NOPRUNE, "noprune"},
57      { SF_PREFER, "prefer"},
58      { SF_OBSOLETE, "obsolete"},
59      { SF_USER, "user"},
60 };
61
62 static const enum_map_t pkg_state_status_map[] = {
63      { SS_NOT_INSTALLED, "not-installed" },
64      { SS_UNPACKED, "unpacked" },
65      { SS_HALF_CONFIGURED, "half-configured" },
66      { SS_INSTALLED, "installed" },
67      { SS_HALF_INSTALLED, "half-installed" },
68      { SS_CONFIG_FILES, "config-files" },
69      { SS_POST_INST_FAILED, "post-inst-failed" },
70      { SS_REMOVAL_FAILED, "removal-failed" }
71 };
72
73 static int verrevcmp(const char *val, const char *ref);
74
75
76 pkg_t *pkg_new(void)
77 {
78      pkg_t *pkg;
79
80      pkg = calloc(1, sizeof(pkg_t));
81      if (pkg == NULL) {
82           fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
83           return NULL;
84      }
85
86      pkg_init(pkg);
87
88      return pkg;
89 }
90
91 int pkg_init(pkg_t *pkg)
92 {
93      pkg->name = NULL;
94      pkg->epoch = 0;
95      pkg->version = NULL;
96      pkg->revision = NULL;
97      pkg->dest = NULL;
98      pkg->src = NULL;
99      pkg->architecture = NULL;
100      pkg->maintainer = NULL;
101      pkg->section = NULL;
102      pkg->description = NULL;
103      pkg->state_want = SW_UNKNOWN;
104      pkg->state_flag = SF_OK;
105      pkg->state_status = SS_NOT_INSTALLED;
106      pkg->depends_str = NULL;
107      pkg->provides_str = NULL;
108      pkg->depends_count = 0;
109      pkg->depends = NULL;
110      pkg->suggests_str = NULL;
111      pkg->recommends_str = NULL;
112      pkg->suggests_count = 0;
113      pkg->recommends_count = 0;
114      
115      active_list_init(&pkg->list);
116      active_list_init(&pkg->searched_node);
117
118      /* Abhaya: added init for conflicts fields */
119      pkg->conflicts = NULL;
120      pkg->conflicts_count = 0;
121
122      /* added for replaces.  Jamey 7/23/2002 */
123      pkg->replaces = NULL;
124      pkg->replaces_count = 0;
125     
126      pkg->pre_depends_count = 0;
127      pkg->pre_depends_str = NULL;
128      pkg->provides_count = 0;
129      pkg->provides = NULL;
130      pkg->filename = NULL;
131      pkg->local_filename = NULL;
132      pkg->tmp_unpack_dir = NULL;
133      pkg->md5sum = NULL;
134      pkg->size = NULL;
135      pkg->installed_size = NULL;
136      pkg->priority = NULL;
137      pkg->source = NULL;
138      conffile_list_init(&pkg->conffiles);
139      pkg->installed_files = NULL;
140      pkg->installed_files_ref_cnt = 0;
141      pkg->essential = 0;
142      pkg->provided_by_hand = 0;
143
144      return 0;
145 }
146
147 void compound_depend_deinit (compound_depend_t *depends)
148 {
149     int i;
150     for (i = 0; i < depends->possibility_count; i++)
151     {
152         depend_t *d;
153         d = depends->possibilities[i];
154         free (d->version);
155         free (d);
156     }
157     free (depends->possibilities);
158 }
159
160 void pkg_deinit(pkg_t *pkg)
161 {
162      int i;
163
164      free(pkg->name);
165      pkg->name = NULL;
166      pkg->epoch = 0;
167      free(pkg->version);
168      pkg->version = NULL;
169      /* revision shares storage with version, so
170         don't free */
171      pkg->revision = NULL;
172      /* owned by opkg_conf_t */
173      pkg->dest = NULL;
174      /* owned by opkg_conf_t */
175      pkg->src = NULL;
176      free(pkg->architecture);
177      pkg->architecture = NULL;
178      free(pkg->maintainer);
179      pkg->maintainer = NULL;
180      free(pkg->section);
181      pkg->section = NULL;
182      free(pkg->description);
183      pkg->description = NULL;
184      pkg->state_want = SW_UNKNOWN;
185      pkg->state_flag = SF_OK;
186      pkg->state_status = SS_NOT_INSTALLED;
187
188      active_list_clear(&pkg->list);
189
190      free (pkg->replaces);
191      pkg->replaces = NULL;
192
193      for (i = 0; i < pkg->depends_count; i++)
194        free (pkg->depends_str[i]);
195      free(pkg->depends_str);
196      pkg->depends_str = NULL;
197
198      for (i = 0; i < pkg->provides_count; i++)
199        free (pkg->provides_str[i]);
200      free(pkg->provides_str);
201      pkg->provides_str = NULL;
202
203      for (i = 0; i < pkg->conflicts_count; i++)
204        free (pkg->conflicts_str[i]);
205      free(pkg->conflicts_str);
206      pkg->conflicts_str = NULL;
207
208      for (i = 0; i < pkg->replaces_count; i++)
209        free (pkg->replaces_str[i]);
210      free(pkg->replaces_str);
211      pkg->replaces_str = NULL;
212
213      for (i = 0; i < pkg->recommends_count; i++)
214        free (pkg->recommends_str[i]);
215      free(pkg->recommends_str);
216      pkg->recommends_str = NULL;
217
218      for (i = 0; i < pkg->suggests_count; i++)
219        free (pkg->suggests_str[i]);
220      free(pkg->suggests_str);
221      pkg->suggests_str = NULL;
222
223      if (pkg->depends)
224      {
225        int count = pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count;
226        int x;
227
228        for (x = 0; x < count; x++)
229          compound_depend_deinit (&pkg->depends[x]);
230        free (pkg->depends);
231      }
232
233      if (pkg->conflicts)
234      {
235        int x;
236        for (x = 0; x < pkg->conflicts_count; x++)
237          compound_depend_deinit (&pkg->conflicts[x]);
238        free (pkg->conflicts);
239      }
240
241      free (pkg->provides);
242
243      pkg->pre_depends_count = 0;
244      free(pkg->pre_depends_str);
245      pkg->pre_depends_str = NULL;
246      pkg->provides_count = 0;
247      free(pkg->filename);
248      pkg->filename = NULL;
249      free(pkg->local_filename);
250      pkg->local_filename = NULL;
251      /* CLEANUP: It'd be nice to pullin the cleanup function from
252         opkg_install.c here. See comment in
253         opkg_install.c:cleanup_temporary_files */
254      free(pkg->tmp_unpack_dir);
255      pkg->tmp_unpack_dir = NULL;
256      free(pkg->md5sum);
257      pkg->md5sum = NULL;
258      free(pkg->size);
259      pkg->size = NULL;
260      free(pkg->installed_size);
261      pkg->installed_size = NULL;
262      free(pkg->priority);
263      pkg->priority = NULL;
264      free(pkg->source);
265      pkg->source = NULL;
266      conffile_list_deinit(&pkg->conffiles);
267      /* XXX: QUESTION: Is forcing this to 1 correct? I suppose so,
268         since if they are calling deinit, they should know. Maybe do an
269         assertion here instead? */
270      pkg->installed_files_ref_cnt = 1;
271      pkg_free_installed_files(pkg);
272      pkg->essential = 0;
273      free (pkg->tags);
274      pkg->tags = NULL;
275 }
276
277 int pkg_init_from_file(pkg_t *pkg, const char *filename)
278 {
279      int err;
280      char **raw;
281      FILE *control_file;
282
283      err = pkg_init(pkg);
284      if (err) { return err; }
285
286      pkg->local_filename = strdup(filename);
287     
288      control_file = tmpfile();
289      err = pkg_extract_control_file_to_stream(pkg, control_file);
290      if (err) { return err; }
291
292      rewind(control_file);
293      raw = read_raw_pkgs_from_stream(control_file);
294      pkg_parse_raw(pkg, &raw, NULL, NULL);
295
296      fclose(control_file);
297
298      return 0;
299 }
300
301 /* Merge any new information in newpkg into oldpkg */
302 /* XXX: CLEANUP: This function shouldn't actually modify anything in
303    newpkg, but should leave it usable. This rework is so that
304    pkg_hash_insert doesn't clobber the pkg that you pass into it. */
305 /* 
306  * uh, i thought that i had originally written this so that it took 
307  * two pkgs and returned a new one?  we can do that again... -sma
308  */
309 int pkg_merge(pkg_t *oldpkg, pkg_t *newpkg, int set_status)
310 {
311      if (oldpkg == newpkg) {
312           return 0;
313      }
314
315      if (!oldpkg->src)
316           oldpkg->src = newpkg->src;
317      if (!oldpkg->dest)
318           oldpkg->dest = newpkg->dest;
319      if (!oldpkg->architecture)
320           oldpkg->architecture = str_dup_safe(newpkg->architecture);
321      if (!oldpkg->arch_priority)
322           oldpkg->arch_priority = newpkg->arch_priority;
323      if (!oldpkg->section)
324           oldpkg->section = str_dup_safe(newpkg->section);
325      if(!oldpkg->maintainer)
326           oldpkg->maintainer = str_dup_safe(newpkg->maintainer);
327      if(!oldpkg->description)
328           oldpkg->description = str_dup_safe(newpkg->description);
329      if (set_status) {
330           /* merge the state_flags from the new package */
331           oldpkg->state_want = newpkg->state_want;
332           oldpkg->state_status = newpkg->state_status;
333           oldpkg->state_flag = newpkg->state_flag;
334      } else {
335           if (oldpkg->state_want == SW_UNKNOWN)
336                oldpkg->state_want = newpkg->state_want;
337           if (oldpkg->state_status == SS_NOT_INSTALLED)
338                oldpkg->state_status = newpkg->state_status;
339           oldpkg->state_flag |= newpkg->state_flag;
340      }
341
342      if (!oldpkg->depends_str && !oldpkg->pre_depends_str && !oldpkg->recommends_str && !oldpkg->suggests_str) {
343           oldpkg->depends_str = newpkg->depends_str;
344           newpkg->depends_str = NULL;
345           oldpkg->depends_count = newpkg->depends_count;
346           newpkg->depends_count = 0;
347
348           oldpkg->depends = newpkg->depends;
349           newpkg->depends = NULL;
350
351           oldpkg->pre_depends_str = newpkg->pre_depends_str;
352           newpkg->pre_depends_str = NULL;
353           oldpkg->pre_depends_count = newpkg->pre_depends_count;
354           newpkg->pre_depends_count = 0;
355
356           oldpkg->recommends_str = newpkg->recommends_str;
357           newpkg->recommends_str = NULL;
358           oldpkg->recommends_count = newpkg->recommends_count;
359           newpkg->recommends_count = 0;
360
361           oldpkg->suggests_str = newpkg->suggests_str;
362           newpkg->suggests_str = NULL;
363           oldpkg->suggests_count = newpkg->suggests_count;
364           newpkg->suggests_count = 0;
365      }
366
367      if (!oldpkg->provides_str) {
368           oldpkg->provides_str = newpkg->provides_str;
369           newpkg->provides_str = NULL;
370           oldpkg->provides_count = newpkg->provides_count;
371           newpkg->provides_count = 0;
372
373           oldpkg->provides = newpkg->provides;
374           newpkg->provides = NULL;
375      }
376
377      if (!oldpkg->conflicts_str) {
378           oldpkg->conflicts_str = newpkg->conflicts_str;
379           newpkg->conflicts_str = NULL;
380           oldpkg->conflicts_count = newpkg->conflicts_count;
381           newpkg->conflicts_count = 0;
382
383           oldpkg->conflicts = newpkg->conflicts;
384           newpkg->conflicts = NULL;
385      }
386
387      if (!oldpkg->replaces_str) {
388           oldpkg->replaces_str = newpkg->replaces_str;
389           newpkg->replaces_str = NULL;
390           oldpkg->replaces_count = newpkg->replaces_count;
391           newpkg->replaces_count = 0;
392
393           oldpkg->replaces = newpkg->replaces;
394           newpkg->replaces = NULL;
395      }
396
397      if (!oldpkg->filename)
398           oldpkg->filename = str_dup_safe(newpkg->filename);
399      if (0)
400      fprintf(stdout, "pkg=%s old local_filename=%s new local_filename=%s\n", 
401              oldpkg->name, oldpkg->local_filename, newpkg->local_filename);
402      if (!oldpkg->local_filename)
403           oldpkg->local_filename = str_dup_safe(newpkg->local_filename);
404      if (!oldpkg->tmp_unpack_dir)
405           oldpkg->tmp_unpack_dir = str_dup_safe(newpkg->tmp_unpack_dir);
406      if (!oldpkg->md5sum)
407           oldpkg->md5sum = str_dup_safe(newpkg->md5sum);
408      if (!oldpkg->size)
409           oldpkg->size = str_dup_safe(newpkg->size);
410      if (!oldpkg->installed_size)
411           oldpkg->installed_size = str_dup_safe(newpkg->installed_size);
412      if (!oldpkg->priority)
413           oldpkg->priority = str_dup_safe(newpkg->priority);
414      if (!oldpkg->source)
415           oldpkg->source = str_dup_safe(newpkg->source);
416      if (oldpkg->conffiles.head == NULL){
417           oldpkg->conffiles = newpkg->conffiles;
418           conffile_list_init(&newpkg->conffiles);
419      }
420      if (!oldpkg->installed_files){
421           oldpkg->installed_files = newpkg->installed_files;
422           oldpkg->installed_files_ref_cnt = newpkg->installed_files_ref_cnt;
423           newpkg->installed_files = NULL;
424      }
425      if (!oldpkg->essential)
426           oldpkg->essential = newpkg->essential;
427
428      return 0;
429 }
430
431 abstract_pkg_t *abstract_pkg_new(void)
432 {
433      abstract_pkg_t * ab_pkg;
434
435      ab_pkg = calloc(1, sizeof(abstract_pkg_t));
436
437      if (ab_pkg == NULL) {
438           fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
439           return NULL;
440      }
441
442      if ( abstract_pkg_init(ab_pkg) < 0 ) 
443         return NULL;
444
445      return ab_pkg;
446 }
447
448 int abstract_pkg_init(abstract_pkg_t *ab_pkg)
449 {
450      ab_pkg->provided_by = abstract_pkg_vec_alloc();
451      if (ab_pkg->provided_by==NULL){
452         return -1;
453      }
454      ab_pkg->dependencies_checked = 0;
455      ab_pkg->state_status = SS_NOT_INSTALLED;
456      active_list_init(&ab_pkg->searched_node);
457
458      return 0;
459 }
460
461 void set_flags_from_control(opkg_conf_t *conf, pkg_t *pkg){
462      char * temp_str;
463      char **raw =NULL;
464      char **raw_start=NULL; 
465
466      temp_str = (char *) calloc (1, strlen(pkg->dest->info_dir)+strlen(pkg->name)+12);
467      if (temp_str == NULL ){
468         opkg_message(conf, OPKG_INFO, "Out of memory in  %s\n", __FUNCTION__);
469         return;
470      }
471      sprintf( temp_str,"%s/%s.control",pkg->dest->info_dir,pkg->name);
472    
473      raw = raw_start = read_raw_pkgs_from_file(temp_str);
474      if (raw == NULL ){
475         opkg_message(conf, OPKG_ERROR, "Unable to open the control file in  %s\n", __FUNCTION__);
476         return;
477      }
478
479      while(*raw){
480         if (!pkg_valorize_other_field(pkg, &raw ) == 0) {
481             opkg_message(conf, OPKG_DEBUG, "unable to read control file for %s. May be empty\n", pkg->name);
482         }
483      }
484      raw = raw_start;
485      while (*raw) {
486         if (raw!=NULL)
487           free(*raw++);
488      }
489
490      free(raw_start); 
491      free(temp_str);
492
493      return ;
494
495 }
496
497 char * pkg_formatted_info(pkg_t *pkg )
498 {
499      char *line;
500      char * buff;
501
502      buff = calloc(1, 8192);
503      if (buff == NULL) {
504           fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
505           return NULL;
506      }
507
508      buff[0] = '\0';
509
510      line = pkg_formatted_field(pkg, "Package");
511      strncat(buff ,line, strlen(line));
512      free(line);
513
514      line = pkg_formatted_field(pkg, "Version");
515      strncat(buff ,line, strlen(line));
516      free(line);
517
518      line = pkg_formatted_field(pkg, "Depends");
519      strncat(buff ,line, strlen(line));
520      free(line);
521      
522      line = pkg_formatted_field(pkg, "Recommends");
523      strncat(buff ,line, strlen(line));
524      free(line);
525
526      line = pkg_formatted_field(pkg, "Suggests");
527      strncat(buff ,line, strlen(line));
528      free(line);
529
530      line = pkg_formatted_field(pkg, "Provides");
531      strncat(buff ,line, strlen(line));
532      free(line);
533
534      line = pkg_formatted_field(pkg, "Replaces");
535      strncat(buff ,line, strlen(line));
536      free(line);
537
538      line = pkg_formatted_field(pkg, "Conflicts");
539      strncat(buff ,line, strlen(line));
540      free(line);
541
542      line = pkg_formatted_field(pkg, "Status");
543      strncat(buff ,line, strlen(line));
544      free(line);
545
546      line = pkg_formatted_field(pkg, "Section");
547      strncat(buff ,line, strlen(line));
548      free(line);
549
550      line = pkg_formatted_field(pkg, "Essential"); /* @@@@ should be removed in future release. *//* I do not agree with this Pigi*/
551      strncat(buff ,line, strlen(line));
552      free(line);
553
554      line = pkg_formatted_field(pkg, "Architecture");
555      strncat(buff ,line, strlen(line));
556      free(line);
557
558      line = pkg_formatted_field(pkg, "Maintainer");
559      strncat(buff ,line, strlen(line));
560      free(line);
561
562      line = pkg_formatted_field(pkg, "MD5sum");
563      strncat(buff ,line, strlen(line));
564      free(line);
565
566      line = pkg_formatted_field(pkg, "Size");
567      strncat(buff ,line, strlen(line));
568      free(line);
569
570      line = pkg_formatted_field(pkg, "Filename");
571      strncat(buff ,line, strlen(line));
572      free(line);
573
574      line = pkg_formatted_field(pkg, "Conffiles");
575      strncat(buff ,line, strlen(line));
576      free(line);
577
578      line = pkg_formatted_field(pkg, "Source");
579      strncat(buff ,line, strlen(line));
580      free(line);
581
582      line = pkg_formatted_field(pkg, "Description");
583      strncat(buff ,line, strlen(line));
584      free(line);
585
586      line = pkg_formatted_field(pkg, "Installed-Time");
587      strncat(buff ,line, strlen(line));
588      free(line);
589
590      line = pkg_formatted_field(pkg, "Tags");
591      strncat(buff ,line, strlen(line));
592      free(line);
593
594      return buff;
595 }
596
597 char * pkg_formatted_field(pkg_t *pkg, const char *field )
598 {
599      static size_t LINE_LEN = 128;
600      char * temp = (char *)malloc(1);
601      int len = 0;
602      int flag_provide_false = 0;
603
604 /*
605   Pigi: After some discussion with Florian we decided to modify the full procedure in 
606         dynamic memory allocation. This should avoid any other segv in this area ( except for bugs )
607 */
608
609      if (strlen(field) < PKG_MINIMUM_FIELD_NAME_LEN) {
610           goto UNKNOWN_FMT_FIELD;
611      }
612
613      temp[0]='\0'; 
614
615      switch (field[0])
616      {
617      case 'a':
618      case 'A':
619           if (strcasecmp(field, "Architecture") == 0) {
620                /* Architecture */
621                if (pkg->architecture) {
622                    temp = (char *)realloc(temp,strlen(pkg->architecture)+17);
623                    if ( temp == NULL ){
624                       fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
625                       return NULL;
626                    }
627                    temp[0]='\0';
628                    snprintf(temp, (strlen(pkg->architecture)+17), "Architecture: %s\n", pkg->architecture);
629                }
630           } else if (strcasecmp(field, "Auto-Installed") == 0) {
631                 /* Auto-Installed flag */
632                 if (pkg->auto_installed) {
633                     char * s = "Auto-Installed: yes\n";
634                     temp = (char *)realloc(temp, strlen(s) + 1);
635                     strcpy (temp, s);
636                 }
637           } else {
638                goto UNKNOWN_FMT_FIELD;
639           }
640           break;
641      case 'c':
642      case 'C':
643           if (strcasecmp(field, "Conffiles") == 0) {
644                /* Conffiles */
645                conffile_list_elt_t *iter;
646                char confstr[LINE_LEN];
647
648                if (pkg->conffiles.head == NULL) {
649                     return temp;
650                }
651
652                len = 14 ;
653                for (iter = pkg->conffiles.head; iter; iter = iter->next) {
654                     if (iter->data->name && iter->data->value) {
655                        len = len + (strlen(iter->data->name)+strlen(iter->data->value)+5);
656                     }
657                }
658                temp = (char *)realloc(temp,len);
659                if ( temp == NULL ){
660                   fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
661                   return NULL;
662                }
663                temp[0]='\0';
664                strncpy(temp, "Conffiles:\n", 12);
665                for (iter = pkg->conffiles.head; iter; iter = iter->next) {
666                     if (iter->data->name && iter->data->value) {
667                          snprintf(confstr, LINE_LEN, "%s %s\n", iter->data->name, iter->data->value);
668                          strncat(temp, confstr, strlen(confstr));           
669                     }
670                }
671           } else if (strcasecmp(field, "Conflicts") == 0) {
672                int i;
673
674                if (pkg->conflicts_count) {
675                     char conflictstr[LINE_LEN];
676                     len = 14 ;
677                     for(i = 0; i < pkg->conflicts_count; i++) {
678                         len = len + (strlen(pkg->conflicts_str[i])+5);
679                     }
680                     temp = (char *)realloc(temp,len);
681                     if ( temp == NULL ){
682                        fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
683                        return NULL;
684                     }
685                     temp[0]='\0';
686                     strncpy(temp, "Conflicts:", 11);
687                     for(i = 0; i < pkg->conflicts_count; i++) {
688                         snprintf(conflictstr, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->conflicts_str[i]);
689                         strncat(temp, conflictstr, strlen(conflictstr));           
690                     }
691                     strncat(temp, "\n", strlen("\n")); 
692                }
693           } else {
694                goto UNKNOWN_FMT_FIELD;
695           }
696           break;
697      case 'd':
698      case 'D':
699           if (strcasecmp(field, "Depends") == 0) {
700                /* Depends */
701                int i;
702
703                if (pkg->depends_count) {
704                     char depstr[LINE_LEN];
705                     len = 14 ;
706                     for(i = 0; i < pkg->depends_count; i++) {
707                         len = len + (strlen(pkg->depends_str[i])+4);
708                     }
709                     temp = (char *)realloc(temp,len);
710                     if ( temp == NULL ){
711                        fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
712                        return NULL;
713                     }
714                     temp[0]='\0';
715                     strncpy(temp, "Depends:", 10);
716                     for(i = 0; i < pkg->depends_count; i++) {
717                         snprintf(depstr, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->depends_str[i]);
718                         strncat(temp, depstr, strlen(depstr));           
719                     }
720                     strncat(temp, "\n", strlen("\n")); 
721                }
722           } else if (strcasecmp(field, "Description") == 0) {
723                /* Description */
724                if (pkg->description) {
725                    temp = (char *)realloc(temp,strlen(pkg->description)+16);
726                    if ( temp == NULL ){
727                       fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
728                       return NULL;
729                    }
730                    temp[0]='\0';
731                    snprintf(temp, (strlen(pkg->description)+16), "Description: %s\n", pkg->description);
732                }
733           } else {
734                goto UNKNOWN_FMT_FIELD;
735           }
736       break;
737      case 'e':
738      case 'E': {
739           /* Essential */
740           if (pkg->essential) {
741               temp = (char *)realloc(temp,16);
742               if ( temp == NULL ){
743                  fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
744                  return NULL;
745               }
746               temp[0]='\0';
747               snprintf(temp, (16), "Essential: yes\n");
748           }
749      }
750           break;
751      case 'f':
752      case 'F': {
753           /* Filename */
754           if (pkg->filename) {
755               temp = (char *)realloc(temp,strlen(pkg->filename)+12);
756               if ( temp == NULL ){
757                   fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
758                   return NULL;
759               }
760               temp[0]='\0';
761               snprintf(temp, (strlen(pkg->filename)+12), "Filename: %s\n", pkg->filename);
762           }
763      }
764           break;
765      case 'i':
766      case 'I': {
767           if (strcasecmp(field, "Installed-Size") == 0) {
768                /* Installed-Size */
769                temp = (char *)realloc(temp,strlen(pkg->installed_size)+17);
770                if ( temp == NULL ){
771                    fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
772                    return NULL;
773                }
774                temp[0]='\0';
775                snprintf(temp, (strlen(pkg->installed_size)+17), "Installed-Size: %s\n", pkg->installed_size);
776           } else if (strcasecmp(field, "Installed-Time") == 0 && pkg->installed_time) {
777                temp = (char *)realloc(temp,29);
778                if ( temp == NULL ){
779                   fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
780                   return NULL;
781                }
782                temp[0]='\0';
783                snprintf(temp, 29, "Installed-Time: %lu\n", pkg->installed_time);
784           }
785      }
786           break;
787      case 'm':
788      case 'M': {
789           /* Maintainer | MD5sum */
790           if (strcasecmp(field, "Maintainer") == 0) {
791                /* Maintainer */
792                if (pkg->maintainer) {
793                    temp = (char *)realloc(temp,strlen(pkg->maintainer)+14);
794                    if ( temp == NULL ){
795                       fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
796                       return NULL;
797                    }
798                    temp[0]='\0';
799                    snprintf(temp, (strlen(pkg->maintainer)+14), "maintainer: %s\n", pkg->maintainer);
800                }
801           } else if (strcasecmp(field, "MD5sum") == 0) {
802                /* MD5sum */
803                if (pkg->md5sum) {
804                    temp = (char *)realloc(temp,strlen(pkg->md5sum)+11);
805                    if ( temp == NULL ){
806                       fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
807                       return NULL;
808                    }
809                    temp[0]='\0';
810                    snprintf(temp, (strlen(pkg->md5sum)+11), "MD5Sum: %s\n", pkg->md5sum);
811                }
812           } else {
813                goto UNKNOWN_FMT_FIELD;
814           }
815      }
816           break;
817      case 'p':
818      case 'P': {
819           if (strcasecmp(field, "Package") == 0) {
820                /* Package */
821                temp = (char *)realloc(temp,strlen(pkg->name)+11);
822                if ( temp == NULL ){
823                   fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
824                   return NULL;
825                }
826                temp[0]='\0';
827                snprintf(temp, (strlen(pkg->name)+11), "Package: %s\n", pkg->name);
828           } else if (strcasecmp(field, "Priority") == 0) {
829                /* Priority */
830                temp = (char *)realloc(temp,strlen(pkg->priority)+12);
831                if ( temp == NULL ){
832                   fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
833                   return NULL;
834                }
835                temp[0]='\0';
836                snprintf(temp, (strlen(pkg->priority)+12), "Priority: %s\n", pkg->priority);
837           } else if (strcasecmp(field, "Provides") == 0) {
838                /* Provides */
839                int i;
840
841                if (pkg->provides_count) {
842                /* Here we check if the opkg_internal_use_only is used, and we discard it.*/
843                   for ( i=0; i < pkg->provides_count; i++ ){
844                       if (strstr(pkg->provides_str[i],"opkg_internal_use_only")!=NULL) {
845                          memset (pkg->provides_str[i],'\x0',strlen(pkg->provides_str[i])); /* Pigi clear my trick flag, just in case */
846                          flag_provide_false = 1;
847                       }
848                   }
849                   if ( !flag_provide_false ||                                             /* Pigi there is not my trick flag */
850                      ((flag_provide_false) &&  (pkg->provides_count > 1))){             /* Pigi There is, but we also have others Provides */
851                      char provstr[LINE_LEN];
852                      len = 15;
853                      for(i = 0; i < pkg->provides_count; i++) {
854                          len = len + (strlen(pkg->provides_str[i])+5);
855                      }
856                      temp = (char *)realloc(temp,len);
857                      if ( temp == NULL ){
858                         fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
859                         return NULL;
860                      }
861                      temp[0]='\0';
862                      strncpy(temp, "Provides:", 12);
863                      for(i = 0; i < pkg->provides_count; i++) {
864                          if (strlen(pkg->provides_str[i])>0){;
865                             snprintf(provstr, LINE_LEN, "%s %s", i == 1 ? "" : ",", pkg->provides_str[i]);
866                             strncat(temp, provstr, strlen(provstr));           
867                          }
868                      }
869                      strncat(temp, "\n", strlen("\n")); 
870                   }
871                }
872           } else {
873                goto UNKNOWN_FMT_FIELD;
874           }
875      }
876           break;
877      case 'r':
878      case 'R': {
879           int i;
880           /* Replaces | Recommends*/
881           if (strcasecmp (field, "Replaces") == 0) {
882                if (pkg->replaces_count) {
883                     char replstr[LINE_LEN];
884                     len = 14;
885                     for (i = 0; i < pkg->replaces_count; i++) {
886                         len = len + (strlen(pkg->replaces_str[i])+5);
887                     }
888                     temp = (char *)realloc(temp,len);
889                     if ( temp == NULL ){
890                        fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
891                        return NULL;
892                     }
893                     temp[0]='\0';
894                     strncpy(temp, "Replaces:", 12);
895                     for (i = 0; i < pkg->replaces_count; i++) {
896                         snprintf(replstr, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->replaces_str[i]);
897                         strncat(temp, replstr, strlen(replstr));           
898                     }
899                     strncat(temp, "\n", strlen("\n")); 
900                }
901           } else if (strcasecmp (field, "Recommends") == 0) {
902                if (pkg->recommends_count) {
903                     char recstr[LINE_LEN];
904                     len = 15;
905                     for(i = 0; i < pkg->recommends_count; i++) {
906                          len = len + (strlen( pkg->recommends_str[i])+5);
907                     }
908                     temp = (char *)realloc(temp,len);
909                    if ( temp == NULL ){
910                       fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
911                       return NULL;
912                    }
913                     temp[0]='\0';
914                     strncpy(temp, "Recommends:", 13);
915                     for(i = 0; i < pkg->recommends_count; i++) {
916                         snprintf(recstr, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->recommends_str[i]);
917                         strncat(temp, recstr, strlen(recstr));           
918                     }
919                     strncat(temp, "\n", strlen("\n")); 
920                }
921           } else {
922                goto UNKNOWN_FMT_FIELD;
923           }
924      }
925           break;
926      case 's':
927      case 'S': {
928           /* Section | Size | Source | Status | Suggests */
929           if (strcasecmp(field, "Section") == 0) {
930                /* Section */
931                if (pkg->section) {
932                    temp = (char *)realloc(temp,strlen(pkg->section)+11);
933                    if ( temp == NULL ){
934                       fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
935                       return NULL;
936                    }
937                    temp[0]='\0';
938                    snprintf(temp, (strlen(pkg->section)+11), "Section: %s\n", pkg->section);
939                }
940           } else if (strcasecmp(field, "Size") == 0) {
941                /* Size */
942                if (pkg->size) {
943                    temp = (char *)realloc(temp,strlen(pkg->size)+8);
944                    if ( temp == NULL ){
945                       fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
946                       return NULL;
947                    }
948                    temp[0]='\0';
949                    snprintf(temp, (strlen(pkg->size)+8), "Size: %s\n", pkg->size);
950                }
951           } else if (strcasecmp(field, "Source") == 0) {
952                /* Source */
953                if (pkg->source) {
954                    temp = (char *)realloc(temp,strlen(pkg->source)+10);
955                    if ( temp == NULL ){
956                       fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
957                       return NULL;
958                    }
959                    temp[0]='\0';
960                    snprintf(temp, (strlen(pkg->source)+10), "Source: %s\n", pkg->source);
961                }
962           } else if (strcasecmp(field, "Status") == 0) {
963                /* Status */
964                /* Benjamin Pineau note: we should avoid direct usage of 
965                 * strlen(arg) without keeping "arg" for later free()
966                 */
967                char *pflag=pkg_state_flag_to_str(pkg->state_flag);
968                char *pstat=pkg_state_status_to_str(pkg->state_status);
969                char *pwant=pkg_state_want_to_str(pkg->state_want);
970
971                size_t sum_of_sizes = (size_t) ( strlen(pwant)+ strlen(pflag)+ strlen(pstat) + 12 );
972                temp = (char *)realloc(temp,sum_of_sizes);
973                if ( temp == NULL ){
974                    fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
975                    return NULL;
976                 }
977                 temp[0]='\0';
978                 snprintf(temp, sum_of_sizes , "Status: %s %s %s\n", pwant, pflag, pstat);
979                 free(pflag);
980                 free(pwant);
981                if(pstat) /* pfstat can be NULL if ENOMEM */
982                    free(pstat);
983           } else if (strcasecmp(field, "Suggests") == 0) {
984                if (pkg->suggests_count) {
985                     int i;
986                     char sugstr[LINE_LEN];
987                     len = 13;
988                     for(i = 0; i < pkg->suggests_count; i++) {
989                         len = len + (strlen(pkg->suggests_str[i])+5);
990                     }
991                     temp = (char *)realloc(temp,len);
992                     if ( temp == NULL ){
993                        fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
994                        return NULL;
995                     }
996                     temp[0]='\0';
997                     strncpy(temp, "Suggests:", 10);
998                     for(i = 0; i < pkg->suggests_count; i++) {
999                         snprintf(sugstr, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->suggests_str[i]);
1000                         strncat(temp, sugstr, strlen(sugstr));           
1001                     }
1002                     strncat(temp, "\n", strlen("\n")); 
1003                }
1004           } else {
1005                goto UNKNOWN_FMT_FIELD;
1006           }
1007      }
1008           break;
1009      case 't':
1010      case 'T':
1011           if (strcasecmp(field, "Tags") == 0) {
1012                /* Tags */
1013                if (pkg->tags) {
1014                    temp = (char *)realloc(temp,strlen(pkg->tags)+8);
1015                    if ( temp == NULL ){
1016                       fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
1017                       return NULL;
1018                    }
1019                    temp[0]='\0';
1020                    snprintf(temp, (strlen(pkg->tags)+8), "Tags: %s\n", pkg->tags);
1021                }
1022           }
1023           break;
1024      case 'v':
1025      case 'V': {
1026           /* Version */
1027           char *version = pkg_version_str_alloc(pkg);
1028           temp = (char *)realloc(temp,strlen(version)+14);
1029           if ( temp == NULL ){
1030               fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
1031               return NULL;
1032           }
1033           temp[0]='\0';
1034           snprintf(temp, (strlen(version)+12), "Version: %s\n", version);
1035           free(version);
1036      }
1037           break;
1038      default:
1039           goto UNKNOWN_FMT_FIELD;
1040      }
1041
1042      if ( strlen(temp)<2 ) {
1043           temp[0]='\0';
1044      }
1045      return temp;
1046
1047  UNKNOWN_FMT_FIELD:
1048      fprintf(stderr, "%s: ERROR: Unknown field name: %s\n", __FUNCTION__, field);
1049      if ( strlen(temp)<2 ) {
1050           temp[0]='\0';
1051      }
1052
1053      return temp;
1054 }
1055
1056 void pkg_print_info(pkg_t *pkg, FILE *file)
1057 {
1058   int t=0;
1059      char * buff;
1060      if (pkg == NULL) {
1061         return;
1062      }
1063
1064      buff = pkg_formatted_info(pkg);
1065      if ( buff == NULL ) 
1066          return;
1067      if (strlen(buff)>2){
1068        t = fwrite(buff, 1, strlen(buff), file); //#~rzr:TODO
1069      } 
1070      free(buff);
1071 }
1072
1073 void pkg_print_status(pkg_t * pkg, FILE * file)
1074 {
1075      if (pkg == NULL) {
1076           return;
1077      }
1078
1079      /* XXX: QUESTION: Do we actually want more fields here? The
1080         original idea was to save space by installing only what was
1081         needed for actual computation, (package, version, status,
1082         essential, conffiles). The assumption is that all other fields
1083         can be found in th available file.
1084
1085         But, someone proposed the idea to make it possible to
1086         reconstruct a .opk from an installed package, (ie. for beaming
1087         from one handheld to another). So, maybe we actually want a few
1088         more fields here, (depends, suggests, etc.), so that that would
1089         be guaranteed to work even in the absence of more information
1090         from the available file.
1091
1092         28-MAR-03: kergoth and I discussed this yesterday.  We think
1093         the essential info needs to be here for all installed packages
1094         because they may not appear in the Packages files on various
1095         feeds.  Furthermore, one should be able to install from URL or
1096         local storage without requiring a Packages file from any feed.
1097         -Jamey
1098      */
1099      pkg_print_field(pkg, file, "Package");
1100      pkg_print_field(pkg, file, "Version");
1101      pkg_print_field(pkg, file, "Depends");
1102      pkg_print_field(pkg, file, "Recommends");
1103      pkg_print_field(pkg, file, "Suggests");
1104      pkg_print_field(pkg, file, "Provides");
1105      pkg_print_field(pkg, file, "Replaces");
1106      pkg_print_field(pkg, file, "Conflicts");
1107      pkg_print_field(pkg, file, "Status");
1108      pkg_print_field(pkg, file, "Essential"); /* @@@@ should be removed in future release. */
1109      pkg_print_field(pkg, file, "Architecture");
1110      pkg_print_field(pkg, file, "Conffiles");
1111      pkg_print_field(pkg, file, "Installed-Time");
1112      pkg_print_field(pkg, file, "Auto-Installed");
1113      fputs("\n", file);
1114 }
1115
1116 void pkg_print_field(pkg_t *pkg, FILE *file, const char *field)
1117 {
1118      char *buff;
1119      if (strlen(field) < PKG_MINIMUM_FIELD_NAME_LEN) {
1120        fprintf(stderr, "%s: ERROR: Unknown field name: %s\n",
1121              __FUNCTION__, field);
1122      }
1123      buff = pkg_formatted_field(pkg, field);
1124      if (strlen(buff)>2) {
1125        fprintf(file, "%s", buff);
1126        fflush(file);
1127      }
1128      free(buff);
1129      return;
1130 }
1131
1132 /*
1133  * libdpkg - Debian packaging suite library routines
1134  * vercmp.c - comparison of version numbers
1135  *
1136  * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
1137  */
1138 int pkg_compare_versions(const pkg_t *pkg, const pkg_t *ref_pkg)
1139 {
1140      int r;
1141
1142      if (pkg->epoch > ref_pkg->epoch) {
1143           return 1;
1144      }
1145
1146      if (pkg->epoch < ref_pkg->epoch) {
1147           return -1;
1148      }
1149
1150      r = verrevcmp(pkg->version, ref_pkg->version);
1151      if (r) {
1152           return r;
1153      }
1154
1155      r = verrevcmp(pkg->revision, ref_pkg->revision);
1156      if (r) {
1157           return r;
1158      }
1159
1160      return r;
1161 }
1162
1163 /* assume ascii; warning: evaluates x multiple times! */
1164 #define order(x) ((x) == '~' ? -1 \
1165                 : isdigit((x)) ? 0 \
1166                 : !(x) ? 0 \
1167                 : isalpha((x)) ? (x) \
1168                 : (x) + 256)
1169
1170 static int verrevcmp(const char *val, const char *ref) {
1171   if (!val) val= "";
1172   if (!ref) ref= "";
1173
1174   while (*val || *ref) {
1175     int first_diff= 0;
1176
1177     while ( (*val && !isdigit(*val)) || (*ref && !isdigit(*ref)) ) {
1178       int vc= order(*val), rc= order(*ref);
1179       if (vc != rc) return vc - rc;
1180       val++; ref++;
1181     }
1182
1183     while ( *val == '0' ) val++;
1184     while ( *ref == '0' ) ref++;
1185     while (isdigit(*val) && isdigit(*ref)) {
1186       if (!first_diff) first_diff= *val - *ref;
1187       val++; ref++;
1188     }
1189     if (isdigit(*val)) return 1;
1190     if (isdigit(*ref)) return -1;
1191     if (first_diff) return first_diff;
1192   }
1193   return 0;
1194 }
1195
1196 int pkg_version_satisfied(pkg_t *it, pkg_t *ref, const char *op)
1197 {
1198      int r;
1199
1200      r = pkg_compare_versions(it, ref);
1201
1202      if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0) {
1203           return r <= 0;
1204      }
1205
1206      if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0) {
1207           return r >= 0;
1208      }
1209
1210      if (strcmp(op, "<<") == 0) {
1211           return r < 0;
1212      }
1213
1214      if (strcmp(op, ">>") == 0) {
1215           return r > 0;
1216      }
1217
1218      if (strcmp(op, "=") == 0) {
1219           return r == 0;
1220      }
1221
1222      fprintf(stderr, "unknown operator: %s", op);
1223      return 0;
1224 }
1225
1226 int pkg_name_version_and_architecture_compare(const void *p1, const void *p2)
1227 {
1228      const pkg_t *a = *(const pkg_t**) p1;
1229      const pkg_t *b = *(const pkg_t**) p2;
1230      int namecmp;
1231      int vercmp;
1232      if (!a->name || !b->name) {
1233        fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->name=%p b=%p b->name=%p\n",
1234                a, a->name, b, b->name);
1235        return 0;
1236      }
1237        
1238      namecmp = strcmp(a->name, b->name);
1239      if (namecmp)
1240           return namecmp;
1241      vercmp = pkg_compare_versions(a, b);
1242      if (vercmp)
1243           return vercmp;
1244      if (!a->arch_priority || !b->arch_priority) {
1245        fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->arch_priority=%i b=%p b->arch_priority=%i\n",
1246                a, a->arch_priority, b, b->arch_priority);
1247        return 0;
1248      }
1249      if (a->arch_priority > b->arch_priority)
1250           return 1;
1251      if (a->arch_priority < b->arch_priority)
1252           return -1;
1253      return 0;
1254 }
1255
1256 int abstract_pkg_name_compare(const void *p1, const void *p2)
1257 {
1258      const abstract_pkg_t *a = *(const abstract_pkg_t **)p1;
1259      const abstract_pkg_t *b = *(const abstract_pkg_t **)p2;
1260      if (!a->name || !b->name) {
1261        fprintf(stderr, "abstract_pkg_name_compare: a=%p a->name=%p b=%p b->name=%p\n",
1262                a, a->name, b, b->name);
1263        return 0;
1264      }
1265      return strcmp(a->name, b->name);
1266 }
1267
1268
1269 char *pkg_version_str_alloc(pkg_t *pkg)
1270 {
1271      char *complete_version;
1272      char *epoch_str;
1273      char *revision_str;
1274
1275      if (pkg->epoch) {
1276           sprintf_alloc(&epoch_str, "%d:", pkg->epoch);
1277      } else {
1278           epoch_str = strdup("");
1279      }
1280
1281      if (pkg->revision && strlen(pkg->revision)) {
1282           sprintf_alloc(&revision_str, "-%s", pkg->revision);
1283      } else {
1284           revision_str = strdup("");
1285      }
1286
1287
1288      sprintf_alloc(&complete_version, "%s%s%s",
1289                    epoch_str, pkg->version, revision_str);
1290
1291      free(epoch_str);
1292      free(revision_str);
1293
1294      return complete_version;
1295 }
1296
1297 str_list_t *pkg_get_installed_files(pkg_t *pkg)
1298 {
1299      int err;
1300      char *list_file_name = NULL;
1301      FILE *list_file = NULL;
1302      char *line;
1303      char *installed_file_name;
1304      int rootdirlen;
1305
1306      pkg->installed_files_ref_cnt++;
1307
1308      if (pkg->installed_files) {
1309           return pkg->installed_files;
1310      }
1311
1312      pkg->installed_files = str_list_alloc();
1313      if (pkg->installed_files == NULL) {
1314           fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
1315           return NULL;
1316      }
1317
1318      /* For uninstalled packages, get the file list directly from the package.
1319         For installed packages, look at the package.list file in the database.
1320      */
1321      if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1322           if (pkg->local_filename == NULL) {
1323                return pkg->installed_files;
1324           }
1325           /* XXX: CLEANUP: Maybe rewrite this to avoid using a temporary
1326              file. In other words, change deb_extract so that it can
1327              simply return the file list as a char *[] rather than
1328              insisting on writing in to a FILE * as it does now. */
1329           list_file = tmpfile();
1330           err = pkg_extract_data_file_names_to_stream(pkg, list_file);
1331           if (err) {
1332                fclose(list_file);
1333                fprintf(stderr, "%s: Error extracting file list from %s: %s\n",
1334                        __FUNCTION__, pkg->local_filename, strerror(err));
1335                return pkg->installed_files;
1336           }
1337           rewind(list_file);
1338      } else {
1339           sprintf_alloc(&list_file_name, "%s/%s.list",
1340                         pkg->dest->info_dir, pkg->name);
1341           if (! file_exists(list_file_name)) {
1342                free(list_file_name);
1343                return pkg->installed_files;
1344           }
1345
1346           list_file = fopen(list_file_name, "r");
1347           if (list_file == NULL) {
1348                fprintf(stderr, "WARNING: Cannot open %s: %s\n",
1349                        list_file_name, strerror(errno));
1350                free(list_file_name);
1351                return pkg->installed_files;
1352           }
1353           free(list_file_name);
1354      }
1355
1356      rootdirlen = strlen( pkg->dest->root_dir );
1357      while (1) {
1358           char *file_name;
1359         
1360           line = file_read_line_alloc(list_file);
1361           if (line == NULL) {
1362                break;
1363           }
1364           str_chomp(line);
1365           file_name = line;
1366
1367           /* Take pains to avoid uglies like "/./" in the middle of file_name. */
1368           if( strncmp( pkg->dest->root_dir, 
1369                        file_name, 
1370                        rootdirlen ) ) {
1371                if (*file_name == '.') {
1372                     file_name++;
1373                }
1374                if (*file_name == '/') {
1375                     file_name++;
1376                }
1377
1378                /* Freed in pkg_free_installed_files */
1379                sprintf_alloc(&installed_file_name, "%s%s", pkg->dest->root_dir, file_name);
1380           } else {
1381                // already contains root_dir as header -> ABSOLUTE
1382                sprintf_alloc(&installed_file_name, "%s", file_name);
1383           }
1384           str_list_append(pkg->installed_files, installed_file_name);
1385           free(line);
1386      }
1387
1388      fclose(list_file);
1389
1390      return pkg->installed_files;
1391 }
1392
1393 /* XXX: CLEANUP: This function and it's counterpart,
1394    (pkg_get_installed_files), do not match our init/deinit naming
1395    convention. Nor the alloc/free convention. But, then again, neither
1396    of these conventions currrently fit the way these two functions
1397    work. */
1398 int pkg_free_installed_files(pkg_t *pkg)
1399 {
1400      str_list_elt_t *iter;
1401
1402      pkg->installed_files_ref_cnt--;
1403
1404      if (pkg->installed_files_ref_cnt > 0)
1405           return 0;
1406
1407      if (pkg->installed_files) {
1408
1409           for (iter = pkg->installed_files->head; iter; iter = iter->next) {
1410                /* malloced in pkg_get_installed_files */
1411                free (iter->data);
1412                iter->data = NULL;
1413           }
1414
1415           str_list_deinit(pkg->installed_files);
1416           free (pkg->installed_files);
1417      }
1418
1419      pkg->installed_files = NULL;
1420
1421      return 0;
1422 }
1423
1424 int pkg_remove_installed_files_list(opkg_conf_t *conf, pkg_t *pkg)
1425 {
1426      int err;
1427      char *list_file_name;
1428
1429      //I don't think pkg_free_installed_files should be called here. Jamey
1430      //pkg_free_installed_files(pkg);
1431
1432      sprintf_alloc(&list_file_name, "%s/%s.list",
1433                    pkg->dest->info_dir, pkg->name);
1434      if (!conf->noaction) {
1435           err = unlink(list_file_name);
1436           free(list_file_name);
1437
1438           if (err) {
1439                return errno;
1440           }
1441      }
1442      return 0;
1443 }
1444
1445 conffile_t *pkg_get_conffile(pkg_t *pkg, const char *file_name)
1446 {
1447      conffile_list_elt_t *iter;
1448      conffile_t *conffile;
1449
1450      if (pkg == NULL) {
1451           return NULL;
1452      }
1453
1454      for (iter = pkg->conffiles.head; iter; iter = iter->next) {
1455           conffile = iter->data;
1456
1457           if (strcmp(conffile->name, file_name) == 0) {
1458                return conffile;
1459           }
1460      }
1461
1462      return NULL;
1463 }
1464
1465 int pkg_run_script(opkg_conf_t *conf, pkg_t *pkg,
1466                    const char *script, const char *args)
1467 {
1468      int err;
1469      char *path;
1470      char *cmd;
1471
1472      /* XXX: FEATURE: When conf->offline_root is set, we should run the
1473         maintainer script within a chroot environment. */
1474
1475      /* Installed packages have scripts in pkg->dest->info_dir, uninstalled packages
1476         have scripts in pkg->tmp_unpack_dir. */
1477      if (pkg->state_status == SS_INSTALLED || pkg->state_status == SS_UNPACKED) {
1478           if (pkg->dest == NULL) {
1479                fprintf(stderr, "%s: ERROR: installed package %s has a NULL dest\n",
1480                        __FUNCTION__, pkg->name);
1481                return EINVAL;
1482           }
1483           sprintf_alloc(&path, "%s/%s.%s", pkg->dest->info_dir, pkg->name, script);
1484      } else {
1485           if (pkg->tmp_unpack_dir == NULL) {
1486                fprintf(stderr, "%s: ERROR: uninstalled package %s has a NULL tmp_unpack_dir\n",
1487                        __FUNCTION__, pkg->name);
1488                return EINVAL;
1489           }
1490           sprintf_alloc(&path, "%s/%s", pkg->tmp_unpack_dir, script);
1491      }
1492
1493      opkg_message(conf, OPKG_INFO, "Running script %s\n", path);
1494      if (conf->noaction) return 0;
1495
1496      /* XXX: CLEANUP: There must be a better way to handle maintainer
1497         scripts when running with offline_root mode and/or a dest other
1498         than '/'. I've been playing around with some clever chroot
1499         tricks and I might come up with something workable. */
1500      /*
1501       * Attempt to provide a restricted environment for offline operation
1502       * Need the following set as a minimum:
1503       * OPKG_OFFLINE_ROOT = absolute path to root dir
1504       * D                 = absolute path to root dir (for OE generated postinst)
1505       * PATH              = something safe (a restricted set of utilities)
1506       */
1507
1508      bool AllowOfflineMode = false;
1509      if (conf->offline_root) {
1510           setenv("OPKG_OFFLINE_ROOT", conf->offline_root, 1);
1511           setenv("D", conf->offline_root, 1);
1512           if (NULL == conf->offline_root_path || '\0' == conf->offline_root_path[0]) {
1513             setenv("PATH", "/dev/null", 1);
1514           } else {
1515             setenv("PATH", conf->offline_root_path, 1);
1516             AllowOfflineMode = true;
1517           }
1518      }
1519
1520      setenv("PKG_ROOT",
1521             pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir, 1);
1522
1523      if (! file_exists(path)) {
1524           free(path);
1525           return 0;
1526      }
1527
1528      if (conf->offline_root && !AllowOfflineMode) {
1529           fprintf(stderr, "(offline root mode: not running %s.%s)\n", pkg->name, script);
1530           free(path);
1531           return 0;
1532      }
1533
1534      sprintf_alloc(&cmd, "%s %s", path, args);
1535      free(path);
1536
1537      err = xsystem(cmd);
1538      free(cmd);
1539
1540      if (err) {
1541           fprintf(stderr, "%s script returned status %d\n", script, err);
1542           return err;
1543      }
1544
1545      return 0;
1546 }
1547
1548 char *pkg_state_want_to_str(pkg_state_want_t sw)
1549 {
1550      int i;
1551
1552      for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1553           if (pkg_state_want_map[i].value == sw) {
1554                return strdup(pkg_state_want_map[i].str);
1555           }
1556      }
1557
1558      fprintf(stderr, "%s: ERROR: Illegal value for state_want: %d\n",
1559              __FUNCTION__, sw);
1560      return strdup("<STATE_WANT_UNKNOWN>");
1561 }
1562
1563 pkg_state_want_t pkg_state_want_from_str(char *str)
1564 {
1565      int i;
1566
1567      for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1568           if (strcmp(str, pkg_state_want_map[i].str) == 0) {
1569                return pkg_state_want_map[i].value;
1570           }
1571      }
1572
1573      fprintf(stderr, "%s: ERROR: Illegal value for state_want string: %s\n",
1574              __FUNCTION__, str);
1575      return SW_UNKNOWN;
1576 }
1577
1578 char *pkg_state_flag_to_str(pkg_state_flag_t sf)
1579 {
1580      int i;
1581      int len = 3; /* ok\000 is minimum */
1582      char *str = NULL;
1583
1584      /* clear the temporary flags before converting to string */
1585      sf &= SF_NONVOLATILE_FLAGS;
1586
1587      if (sf == 0) {
1588           return strdup("ok");
1589      } else {
1590
1591           for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1592                if (sf & pkg_state_flag_map[i].value) {
1593                     len += strlen(pkg_state_flag_map[i].str) + 1;
1594                }
1595           }
1596           str = malloc(len);
1597           if ( str == NULL ) {
1598               fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
1599               return NULL;
1600           }
1601           str[0] = 0;
1602           for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1603                if (sf & pkg_state_flag_map[i].value) {
1604                     strcat(str, pkg_state_flag_map[i].str);
1605                     strcat(str, ",");
1606                }
1607           }
1608           len = strlen(str);
1609           str[len-1] = 0; /* squash last comma */
1610           return str;
1611      }
1612 }
1613
1614 pkg_state_flag_t pkg_state_flag_from_str(const char *str)
1615 {
1616      int i;
1617      int sf = SF_OK;
1618
1619      if (strcmp(str, "ok") == 0) {
1620           return SF_OK;
1621      }
1622      for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1623           const char *sfname = pkg_state_flag_map[i].str;
1624           int sfname_len = strlen(sfname);
1625           if (strncmp(str, sfname, sfname_len) == 0) {
1626                sf |= pkg_state_flag_map[i].value;
1627                str += sfname_len;
1628                if (str[0] == ',') {
1629                     str++;
1630                } else {
1631                     break;
1632                }
1633           }
1634      }
1635
1636      return sf;
1637 }
1638
1639 char *pkg_state_status_to_str(pkg_state_status_t ss)
1640 {
1641      int i;
1642
1643      for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1644           if (pkg_state_status_map[i].value == ss) {
1645                return strdup(pkg_state_status_map[i].str);
1646           }
1647      }
1648
1649      fprintf(stderr, "%s: ERROR: Illegal value for state_status: %d\n",
1650              __FUNCTION__, ss);
1651      return strdup("<STATE_STATUS_UNKNOWN>");
1652 }
1653
1654 pkg_state_status_t pkg_state_status_from_str(const char *str)
1655 {
1656      int i;
1657
1658      for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1659           if (strcmp(str, pkg_state_status_map[i].str) == 0) {
1660                return pkg_state_status_map[i].value;
1661           }
1662      }
1663
1664      fprintf(stderr, "%s: ERROR: Illegal value for state_status string: %s\n",
1665              __FUNCTION__, str);
1666      return SS_NOT_INSTALLED;
1667 }
1668
1669 int pkg_arch_supported(opkg_conf_t *conf, pkg_t *pkg)
1670 {
1671      nv_pair_list_elt_t *l;
1672
1673      if (!pkg->architecture)
1674           return 1;
1675
1676      l = conf->arch_list.head;
1677
1678      while (l) {
1679           nv_pair_t *nv = l->data;
1680           if (strcmp(nv->name, pkg->architecture) == 0) {
1681                opkg_message(conf, OPKG_DEBUG, "arch %s (priority %s) supported for pkg %s\n", nv->name, nv->value, pkg->name);
1682                return 1;
1683           }
1684           l = l->next;
1685      }
1686
1687      opkg_message(conf, OPKG_DEBUG, "arch %s unsupported for pkg %s\n", pkg->architecture, pkg->name);
1688      return 0;
1689 }
1690
1691 int pkg_get_arch_priority(opkg_conf_t *conf, const char *archname)
1692 {
1693      nv_pair_list_elt_t *l;
1694
1695      l = conf->arch_list.head;
1696
1697      while (l) {
1698           nv_pair_t *nv = l->data;
1699           if (strcmp(nv->name, archname) == 0) {
1700                int priority = strtol(nv->value, NULL, 0);
1701                return priority;
1702           }
1703           l = l->next;
1704      }
1705      return 0;
1706 }
1707
1708 int pkg_info_preinstall_check(opkg_conf_t *conf)
1709 {
1710      int i;
1711      hash_table_t *pkg_hash = &conf->pkg_hash;
1712      pkg_vec_t *available_pkgs = pkg_vec_alloc();
1713      pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1714
1715      opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: updating arch priority for each package\n");
1716      pkg_hash_fetch_available(pkg_hash, available_pkgs);
1717      /* update arch_priority for each package */
1718      for (i = 0; i < available_pkgs->len; i++) {
1719           pkg_t *pkg = available_pkgs->pkgs[i];
1720           int arch_priority = 1;
1721           if (!pkg)
1722                continue;
1723           // opkg_message(conf, OPKG_DEBUG2, " package %s version=%s arch=%p:", pkg->name, pkg->version, pkg->architecture);
1724           if (pkg->architecture) 
1725                arch_priority = pkg_get_arch_priority(conf, pkg->architecture);
1726           else 
1727                opkg_message(conf, OPKG_ERROR, "pkg_info_preinstall_check: no architecture for package %s\n", pkg->name);
1728           // opkg_message(conf, OPKG_DEBUG2, "%s arch_priority=%d\n", pkg->architecture, arch_priority);
1729           pkg->arch_priority = arch_priority;
1730      }
1731
1732      for (i = 0; i < available_pkgs->len; i++) {
1733           pkg_t *pkg = available_pkgs->pkgs[i];
1734           if (!pkg->arch_priority && (pkg->state_flag || (pkg->state_want != SW_UNKNOWN))) {
1735                /* clear flags and want for any uninstallable package */
1736                opkg_message(conf, OPKG_DEBUG, "Clearing state_want and state_flag for pkg=%s (arch_priority=%d flag=%d want=%d)\n", 
1737                             pkg->name, pkg->arch_priority, pkg->state_flag, pkg->state_want);
1738                pkg->state_want = SW_UNKNOWN;
1739                pkg->state_flag = 0;
1740           }
1741      }
1742      pkg_vec_free(available_pkgs);
1743
1744      /* update the file owner data structure */
1745      opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: update file owner list\n");
1746      pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1747      for (i = 0; i < installed_pkgs->len; i++) {
1748           pkg_t *pkg = installed_pkgs->pkgs[i];
1749           str_list_t *installed_files = pkg_get_installed_files(pkg); /* this causes installed_files to be cached */
1750           str_list_elt_t *iter;
1751           if (installed_files == NULL) {
1752                opkg_message(conf, OPKG_ERROR, "No installed files for pkg %s\n", pkg->name);
1753                break;
1754           }
1755           for (iter = installed_files->head; iter; iter = iter->next) {
1756                char *installed_file = iter->data;
1757                // opkg_message(conf, OPKG_DEBUG2, "pkg %s: file=%s\n", pkg->name, installed_file);
1758                file_hash_set_file_owner(conf, installed_file, pkg);
1759           }
1760           pkg_free_installed_files(pkg);
1761      }
1762      pkg_vec_free(installed_pkgs);
1763
1764      return 0;
1765 }
1766
1767 struct pkg_write_filelist_data {
1768      opkg_conf_t *conf;
1769      pkg_t *pkg;
1770      FILE *stream;
1771 };
1772
1773 void pkg_write_filelist_helper(const char *key, void *entry_, void *data_)
1774 {
1775      struct pkg_write_filelist_data *data = data_;
1776      pkg_t *entry = entry_;
1777      if (entry == data->pkg) {
1778           fprintf(data->stream, "%s\n", key);
1779      }
1780 }
1781
1782 int pkg_write_filelist(opkg_conf_t *conf, pkg_t *pkg)
1783 {
1784      struct pkg_write_filelist_data data;
1785      char *list_file_name = NULL;
1786      int err = 0;
1787
1788      if (!pkg) {
1789           opkg_message(conf, OPKG_ERROR, "Null pkg\n");
1790           return -EINVAL;
1791      }
1792      opkg_message(conf, OPKG_INFO,
1793                   "    creating %s.list file\n", pkg->name);
1794      sprintf_alloc(&list_file_name, "%s/%s.list", pkg->dest->info_dir, pkg->name);
1795      if (!list_file_name) {
1796           opkg_message(conf, OPKG_ERROR, "Failed to alloc list_file_name\n");
1797           return -ENOMEM;
1798      }
1799      opkg_message(conf, OPKG_INFO,
1800                   "    creating %s file for pkg %s\n", list_file_name, pkg->name);
1801      data.stream = fopen(list_file_name, "w");
1802      if (!data.stream) {
1803           opkg_message(conf, OPKG_ERROR, "Could not open %s for writing: %s\n",
1804                        list_file_name, strerror(errno));
1805                        return errno;
1806      }
1807      data.pkg = pkg;
1808      data.conf = conf;
1809      hash_table_foreach(&conf->file_hash, pkg_write_filelist_helper, &data);
1810      fclose(data.stream);
1811      free(list_file_name);
1812
1813      pkg->state_flag &= ~SF_FILELIST_CHANGED;
1814
1815      return err;
1816 }
1817
1818 int pkg_write_changed_filelists(opkg_conf_t *conf)
1819 {
1820      pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1821      hash_table_t *pkg_hash = &conf->pkg_hash;
1822      int i;
1823      int err;
1824      if (conf->noaction)
1825           return 0;
1826
1827      opkg_message(conf, OPKG_INFO, "%s: saving changed filelists\n", __FUNCTION__);
1828      pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1829      for (i = 0; i < installed_pkgs->len; i++) {
1830           pkg_t *pkg = installed_pkgs->pkgs[i];
1831           if (pkg->state_flag & SF_FILELIST_CHANGED) {
1832                opkg_message(conf, OPKG_DEBUG, "Calling pkg_write_filelist for pkg=%s from %s\n", pkg->name, __FUNCTION__);
1833                err = pkg_write_filelist(conf, pkg);
1834                if (err)
1835                     opkg_message(conf, OPKG_NOTICE, "pkg_write_filelist pkg=%s returned %d\n", pkg->name, err);
1836           }
1837      }
1838      pkg_vec_free (installed_pkgs);
1839      return 0;
1840 }