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