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