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