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