reduce a big memory 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(installed_file_name);
1416           free(line);
1417      }
1418
1419      fclose(list_file);
1420
1421      return pkg->installed_files;
1422 }
1423
1424 /* XXX: CLEANUP: This function and it's counterpart,
1425    (pkg_get_installed_files), do not match our init/deinit naming
1426    convention. Nor the alloc/free convention. But, then again, neither
1427    of these conventions currrently fit the way these two functions
1428    work. */
1429 int pkg_free_installed_files(pkg_t *pkg)
1430 {
1431      pkg->installed_files_ref_cnt--;
1432
1433      if (pkg->installed_files_ref_cnt > 0)
1434           return 0;
1435
1436      if (pkg->installed_files) {
1437          str_list_purge(pkg->installed_files);
1438      }
1439
1440      pkg->installed_files = NULL;
1441
1442      return 0;
1443 }
1444
1445 int pkg_remove_installed_files_list(opkg_conf_t *conf, pkg_t *pkg)
1446 {
1447      int err;
1448      char *list_file_name;
1449
1450      //I don't think pkg_free_installed_files should be called here. Jamey
1451      //pkg_free_installed_files(pkg);
1452
1453      sprintf_alloc(&list_file_name, "%s/%s.list",
1454                    pkg->dest->info_dir, pkg->name);
1455      if (!conf->noaction) {
1456           err = unlink(list_file_name);
1457           free(list_file_name);
1458
1459           if (err) {
1460                return errno;
1461           }
1462      }
1463      return 0;
1464 }
1465
1466 conffile_t *pkg_get_conffile(pkg_t *pkg, const char *file_name)
1467 {
1468      conffile_list_elt_t *iter;
1469      conffile_t *conffile;
1470
1471      if (pkg == NULL) {
1472           return NULL;
1473      }
1474
1475      for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
1476           conffile = (conffile_t *)iter->data;
1477
1478           if (strcmp(conffile->name, file_name) == 0) {
1479                return conffile;
1480           }
1481      }
1482
1483      return NULL;
1484 }
1485
1486 int pkg_run_script(opkg_conf_t *conf, pkg_t *pkg,
1487                    const char *script, const char *args)
1488 {
1489      int err;
1490      char *path;
1491      char *cmd;
1492
1493      /* XXX: FEATURE: When conf->offline_root is set, we should run the
1494         maintainer script within a chroot environment. */
1495
1496      /* Installed packages have scripts in pkg->dest->info_dir, uninstalled packages
1497         have scripts in pkg->tmp_unpack_dir. */
1498      if (pkg->state_status == SS_INSTALLED || pkg->state_status == SS_UNPACKED) {
1499           if (pkg->dest == NULL) {
1500                fprintf(stderr, "%s: ERROR: installed package %s has a NULL dest\n",
1501                        __FUNCTION__, pkg->name);
1502                return EINVAL;
1503           }
1504           sprintf_alloc(&path, "%s/%s.%s", pkg->dest->info_dir, pkg->name, script);
1505      } else {
1506           if (pkg->tmp_unpack_dir == NULL) {
1507                fprintf(stderr, "%s: ERROR: uninstalled package %s has a NULL tmp_unpack_dir\n",
1508                        __FUNCTION__, pkg->name);
1509                return EINVAL;
1510           }
1511           sprintf_alloc(&path, "%s/%s", pkg->tmp_unpack_dir, script);
1512      }
1513
1514      opkg_message(conf, OPKG_INFO, "Running script %s\n", path);
1515      if (conf->noaction) return 0;
1516
1517      /* XXX: CLEANUP: There must be a better way to handle maintainer
1518         scripts when running with offline_root mode and/or a dest other
1519         than '/'. I've been playing around with some clever chroot
1520         tricks and I might come up with something workable. */
1521      /*
1522       * Attempt to provide a restricted environment for offline operation
1523       * Need the following set as a minimum:
1524       * OPKG_OFFLINE_ROOT = absolute path to root dir
1525       * D                 = absolute path to root dir (for OE generated postinst)
1526       * PATH              = something safe (a restricted set of utilities)
1527       */
1528
1529      bool AllowOfflineMode = false;
1530      if (conf->offline_root) {
1531           setenv("OPKG_OFFLINE_ROOT", conf->offline_root, 1);
1532           setenv("D", conf->offline_root, 1);
1533           if (NULL == conf->offline_root_path || '\0' == conf->offline_root_path[0]) {
1534             setenv("PATH", "/dev/null", 1);
1535           } else {
1536             setenv("PATH", conf->offline_root_path, 1);
1537             AllowOfflineMode = true;
1538           }
1539      }
1540
1541      setenv("PKG_ROOT",
1542             pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir, 1);
1543
1544      if (! file_exists(path)) {
1545           free(path);
1546           return 0;
1547      }
1548
1549      if (conf->offline_root && !AllowOfflineMode) {
1550           fprintf(stderr, "(offline root mode: not running %s.%s)\n", pkg->name, script);
1551           free(path);
1552           return 0;
1553      }
1554
1555      sprintf_alloc(&cmd, "%s %s", path, args);
1556      free(path);
1557
1558      err = xsystem(cmd);
1559      free(cmd);
1560
1561      if (err) {
1562           fprintf(stderr, "%s script returned status %d\n", script, err);
1563           return err;
1564      }
1565
1566      return 0;
1567 }
1568
1569 char *pkg_state_want_to_str(pkg_state_want_t sw)
1570 {
1571      int i;
1572
1573      for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1574           if (pkg_state_want_map[i].value == sw) {
1575                return strdup(pkg_state_want_map[i].str);
1576           }
1577      }
1578
1579      fprintf(stderr, "%s: ERROR: Illegal value for state_want: %d\n",
1580              __FUNCTION__, sw);
1581      return strdup("<STATE_WANT_UNKNOWN>");
1582 }
1583
1584 pkg_state_want_t pkg_state_want_from_str(char *str)
1585 {
1586      int i;
1587
1588      for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1589           if (strcmp(str, pkg_state_want_map[i].str) == 0) {
1590                return pkg_state_want_map[i].value;
1591           }
1592      }
1593
1594      fprintf(stderr, "%s: ERROR: Illegal value for state_want string: %s\n",
1595              __FUNCTION__, str);
1596      return SW_UNKNOWN;
1597 }
1598
1599 char *pkg_state_flag_to_str(pkg_state_flag_t sf)
1600 {
1601      int i;
1602      int len = 3; /* ok\000 is minimum */
1603      char *str = NULL;
1604
1605      /* clear the temporary flags before converting to string */
1606      sf &= SF_NONVOLATILE_FLAGS;
1607
1608      if (sf == 0) {
1609           return strdup("ok");
1610      } else {
1611
1612           for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1613                if (sf & pkg_state_flag_map[i].value) {
1614                     len += strlen(pkg_state_flag_map[i].str) + 1;
1615                }
1616           }
1617           str = malloc(len);
1618           if ( str == NULL ) {
1619               fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
1620               return NULL;
1621           }
1622           str[0] = 0;
1623           for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1624                if (sf & pkg_state_flag_map[i].value) {
1625                     strcat(str, pkg_state_flag_map[i].str);
1626                     strcat(str, ",");
1627                }
1628           }
1629           len = strlen(str);
1630           str[len-1] = 0; /* squash last comma */
1631           return str;
1632      }
1633 }
1634
1635 pkg_state_flag_t pkg_state_flag_from_str(const char *str)
1636 {
1637      int i;
1638      int sf = SF_OK;
1639
1640      if (strcmp(str, "ok") == 0) {
1641           return SF_OK;
1642      }
1643      for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1644           const char *sfname = pkg_state_flag_map[i].str;
1645           int sfname_len = strlen(sfname);
1646           if (strncmp(str, sfname, sfname_len) == 0) {
1647                sf |= pkg_state_flag_map[i].value;
1648                str += sfname_len;
1649                if (str[0] == ',') {
1650                     str++;
1651                } else {
1652                     break;
1653                }
1654           }
1655      }
1656
1657      return sf;
1658 }
1659
1660 char *pkg_state_status_to_str(pkg_state_status_t ss)
1661 {
1662      int i;
1663
1664      for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1665           if (pkg_state_status_map[i].value == ss) {
1666                return strdup(pkg_state_status_map[i].str);
1667           }
1668      }
1669
1670      fprintf(stderr, "%s: ERROR: Illegal value for state_status: %d\n",
1671              __FUNCTION__, ss);
1672      return strdup("<STATE_STATUS_UNKNOWN>");
1673 }
1674
1675 pkg_state_status_t pkg_state_status_from_str(const char *str)
1676 {
1677      int i;
1678
1679      for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1680           if (strcmp(str, pkg_state_status_map[i].str) == 0) {
1681                return pkg_state_status_map[i].value;
1682           }
1683      }
1684
1685      fprintf(stderr, "%s: ERROR: Illegal value for state_status string: %s\n",
1686              __FUNCTION__, str);
1687      return SS_NOT_INSTALLED;
1688 }
1689
1690 int pkg_arch_supported(opkg_conf_t *conf, pkg_t *pkg)
1691 {
1692      nv_pair_list_elt_t *l;
1693
1694      if (!pkg->architecture)
1695           return 1;
1696
1697      list_for_each_entry(l , &conf->arch_list.head, node) {
1698           nv_pair_t *nv = (nv_pair_t *)l->data;
1699           if (strcmp(nv->name, pkg->architecture) == 0) {
1700                opkg_message(conf, OPKG_DEBUG, "arch %s (priority %s) supported for pkg %s\n", nv->name, nv->value, pkg->name);
1701                return 1;
1702           }
1703      }
1704
1705      opkg_message(conf, OPKG_DEBUG, "arch %s unsupported for pkg %s\n", pkg->architecture, pkg->name);
1706      return 0;
1707 }
1708
1709 int pkg_get_arch_priority(opkg_conf_t *conf, const char *archname)
1710 {
1711      nv_pair_list_elt_t *l;
1712
1713      list_for_each_entry(l , &conf->arch_list.head, node) {
1714           nv_pair_t *nv = (nv_pair_t *)l->data;
1715           if (strcmp(nv->name, archname) == 0) {
1716                int priority = strtol(nv->value, NULL, 0);
1717                return priority;
1718           }
1719      }
1720      return 0;
1721 }
1722
1723 int pkg_info_preinstall_check(opkg_conf_t *conf)
1724 {
1725      int i;
1726      hash_table_t *pkg_hash = &conf->pkg_hash;
1727      pkg_vec_t *available_pkgs = pkg_vec_alloc();
1728      pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1729
1730      opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: updating arch priority for each package\n");
1731      pkg_hash_fetch_available(pkg_hash, available_pkgs);
1732      /* update arch_priority for each package */
1733      for (i = 0; i < available_pkgs->len; i++) {
1734           pkg_t *pkg = available_pkgs->pkgs[i];
1735           int arch_priority = 1;
1736           if (!pkg)
1737                continue;
1738           // opkg_message(conf, OPKG_DEBUG2, " package %s version=%s arch=%p:", pkg->name, pkg->version, pkg->architecture);
1739           if (pkg->architecture) 
1740                arch_priority = pkg_get_arch_priority(conf, pkg->architecture);
1741           else 
1742                opkg_message(conf, OPKG_ERROR, "pkg_info_preinstall_check: no architecture for package %s\n", pkg->name);
1743           // opkg_message(conf, OPKG_DEBUG2, "%s arch_priority=%d\n", pkg->architecture, arch_priority);
1744           pkg->arch_priority = arch_priority;
1745      }
1746
1747      for (i = 0; i < available_pkgs->len; i++) {
1748           pkg_t *pkg = available_pkgs->pkgs[i];
1749           if (!pkg->arch_priority && (pkg->state_flag || (pkg->state_want != SW_UNKNOWN))) {
1750                /* clear flags and want for any uninstallable package */
1751                opkg_message(conf, OPKG_DEBUG, "Clearing state_want and state_flag for pkg=%s (arch_priority=%d flag=%d want=%d)\n", 
1752                             pkg->name, pkg->arch_priority, pkg->state_flag, pkg->state_want);
1753                pkg->state_want = SW_UNKNOWN;
1754                pkg->state_flag = 0;
1755           }
1756      }
1757      pkg_vec_free(available_pkgs);
1758
1759      /* update the file owner data structure */
1760      opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: update file owner list\n");
1761      pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1762      for (i = 0; i < installed_pkgs->len; i++) {
1763           pkg_t *pkg = installed_pkgs->pkgs[i];
1764           str_list_t *installed_files = pkg_get_installed_files(pkg); /* this causes installed_files to be cached */
1765           str_list_elt_t *iter, *niter;
1766           if (installed_files == NULL) {
1767                opkg_message(conf, OPKG_ERROR, "No installed files for pkg %s\n", pkg->name);
1768                break;
1769           }
1770           for (iter = str_list_first(installed_files), niter = str_list_next(installed_files, iter); 
1771                   iter; 
1772                   iter = niter, niter = str_list_next(installed_files, iter)) {
1773                char *installed_file = (char *) iter->data;
1774                // opkg_message(conf, OPKG_DEBUG2, "pkg %s: file=%s\n", pkg->name, installed_file);
1775                file_hash_set_file_owner(conf, installed_file, pkg);
1776           }
1777           pkg_free_installed_files(pkg);
1778      }
1779      pkg_vec_free(installed_pkgs);
1780
1781      return 0;
1782 }
1783
1784 struct pkg_write_filelist_data {
1785      opkg_conf_t *conf;
1786      pkg_t *pkg;
1787      FILE *stream;
1788 };
1789
1790 void pkg_write_filelist_helper(const char *key, void *entry_, void *data_)
1791 {
1792      struct pkg_write_filelist_data *data = data_;
1793      pkg_t *entry = entry_;
1794      if (entry == data->pkg) {
1795           fprintf(data->stream, "%s\n", key);
1796      }
1797 }
1798
1799 int pkg_write_filelist(opkg_conf_t *conf, pkg_t *pkg)
1800 {
1801      struct pkg_write_filelist_data data;
1802      char *list_file_name = NULL;
1803      int err = 0;
1804
1805      if (!pkg) {
1806           opkg_message(conf, OPKG_ERROR, "Null pkg\n");
1807           return -EINVAL;
1808      }
1809      opkg_message(conf, OPKG_INFO,
1810                   "    creating %s.list file\n", pkg->name);
1811      sprintf_alloc(&list_file_name, "%s/%s.list", pkg->dest->info_dir, pkg->name);
1812      if (!list_file_name) {
1813           opkg_message(conf, OPKG_ERROR, "Failed to alloc list_file_name\n");
1814           return -ENOMEM;
1815      }
1816      opkg_message(conf, OPKG_INFO,
1817                   "    creating %s file for pkg %s\n", list_file_name, pkg->name);
1818      data.stream = fopen(list_file_name, "w");
1819      if (!data.stream) {
1820           opkg_message(conf, OPKG_ERROR, "Could not open %s for writing: %s\n",
1821                        list_file_name, strerror(errno));
1822                        return errno;
1823      }
1824      data.pkg = pkg;
1825      data.conf = conf;
1826      hash_table_foreach(&conf->file_hash, pkg_write_filelist_helper, &data);
1827      fclose(data.stream);
1828      free(list_file_name);
1829
1830      pkg->state_flag &= ~SF_FILELIST_CHANGED;
1831
1832      return err;
1833 }
1834
1835 int pkg_write_changed_filelists(opkg_conf_t *conf)
1836 {
1837      pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1838      hash_table_t *pkg_hash = &conf->pkg_hash;
1839      int i;
1840      int err;
1841      if (conf->noaction)
1842           return 0;
1843
1844      opkg_message(conf, OPKG_INFO, "%s: saving changed filelists\n", __FUNCTION__);
1845      pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1846      for (i = 0; i < installed_pkgs->len; i++) {
1847           pkg_t *pkg = installed_pkgs->pkgs[i];
1848           if (pkg->state_flag & SF_FILELIST_CHANGED) {
1849                opkg_message(conf, OPKG_DEBUG, "Calling pkg_write_filelist for pkg=%s from %s\n", pkg->name, __FUNCTION__);
1850                err = pkg_write_filelist(conf, pkg);
1851                if (err)
1852                     opkg_message(conf, OPKG_NOTICE, "pkg_write_filelist pkg=%s returned %d\n", pkg->name, err);
1853           }
1854      }
1855      pkg_vec_free (installed_pkgs);
1856      return 0;
1857 }