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