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