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