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