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