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