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