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