bd7e9f8866fba6e01b25b9a6233b3de3bd2745df
[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 "config.h"
19
20 #include <stdio.h>
21 #include <string.h>
22 #include <ctype.h>
23 #include <unistd.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 "libbb/libbb.h"
33 #include "sprintf_alloc.h"
34 #include "file_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      unsigned int value;
42      const 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 void
75 pkg_init(pkg_t *pkg)
76 {
77      pkg->name = NULL;
78      pkg->epoch = 0;
79      pkg->version = NULL;
80      pkg->revision = NULL;
81      pkg->dest = NULL;
82      pkg->src = NULL;
83      pkg->architecture = NULL;
84      pkg->maintainer = NULL;
85      pkg->section = NULL;
86      pkg->description = NULL;
87      pkg->state_want = SW_UNKNOWN;
88      pkg->state_flag = SF_OK;
89      pkg->state_status = SS_NOT_INSTALLED;
90      pkg->depends_str = NULL;
91      pkg->provides_str = NULL;
92      pkg->depends_count = 0;
93      pkg->depends = NULL;
94      pkg->suggests_str = NULL;
95      pkg->recommends_str = NULL;
96      pkg->suggests_count = 0;
97      pkg->recommends_count = 0;
98      
99      active_list_init(&pkg->list);
100
101      pkg->conflicts = NULL;
102      pkg->conflicts_count = 0;
103
104      pkg->replaces = NULL;
105      pkg->replaces_count = 0;
106     
107      pkg->pre_depends_count = 0;
108      pkg->pre_depends_str = NULL;
109      pkg->provides_count = 0;
110      pkg->provides = NULL;
111      pkg->filename = NULL;
112      pkg->local_filename = NULL;
113      pkg->tmp_unpack_dir = NULL;
114      pkg->md5sum = NULL;
115 #if defined HAVE_SHA256
116      pkg->sha256sum = NULL;
117 #endif
118      pkg->size = 0;
119      pkg->installed_size = 0;
120      pkg->priority = NULL;
121      pkg->source = NULL;
122      conffile_list_init(&pkg->conffiles);
123      pkg->installed_files = NULL;
124      pkg->installed_files_ref_cnt = 0;
125      pkg->essential = 0;
126      pkg->provided_by_hand = 0;
127 }
128
129 pkg_t *
130 pkg_new(void)
131 {
132      pkg_t *pkg;
133
134      pkg = xcalloc(1, sizeof(pkg_t));
135      pkg_init(pkg);
136
137      return pkg;
138 }
139
140 static void
141 compound_depend_deinit(compound_depend_t *depends)
142 {
143     int i;
144     for (i = 0; i < depends->possibility_count; i++)
145     {
146         depend_t *d;
147         d = depends->possibilities[i];
148         free (d->version);
149         free (d);
150     }
151     free (depends->possibilities);
152 }
153
154 void
155 pkg_deinit(pkg_t *pkg)
156 {
157         int i;
158
159         if (pkg->name)
160                 free(pkg->name);
161         pkg->name = NULL;
162
163         pkg->epoch = 0;
164
165         if (pkg->version)
166                 free(pkg->version);
167         pkg->version = NULL;
168         /* revision shares storage with version, so don't free */
169         pkg->revision = NULL;
170
171         /* owned by opkg_conf_t */
172         pkg->dest = NULL;
173         /* owned by opkg_conf_t */
174         pkg->src = NULL;
175
176         if (pkg->architecture)
177                 free(pkg->architecture);
178         pkg->architecture = NULL;
179
180         if (pkg->maintainer)
181                 free(pkg->maintainer);
182         pkg->maintainer = NULL;
183
184         if (pkg->section)
185                 free(pkg->section);
186         pkg->section = NULL;
187
188         if (pkg->description)
189                 free(pkg->description);
190         pkg->description = NULL;
191         
192         pkg->state_want = SW_UNKNOWN;
193         pkg->state_flag = SF_OK;
194         pkg->state_status = SS_NOT_INSTALLED;
195
196         active_list_clear(&pkg->list);
197
198         if (pkg->replaces)
199                 free (pkg->replaces);
200         pkg->replaces = NULL;
201
202         if (pkg->depends) {
203                 int count = pkg->pre_depends_count
204                                 + pkg->depends_count
205                                 + pkg->recommends_count
206                                 + pkg->suggests_count;
207
208                 for (i=0; i<count; i++)
209                         compound_depend_deinit (&pkg->depends[i]);
210                 free (pkg->depends);
211         }
212
213         if (pkg->conflicts) {
214                 for (i=0; i<pkg->conflicts_count; i++)
215                         compound_depend_deinit (&pkg->conflicts[i]);
216                 free (pkg->conflicts);
217         }
218
219         if (pkg->provides)
220                 free (pkg->provides);
221
222         pkg->pre_depends_count = 0;
223         pkg->provides_count = 0;
224         
225         if (pkg->filename)
226                 free(pkg->filename);
227         pkg->filename = NULL;
228         
229         if (pkg->local_filename)
230                 free(pkg->local_filename);
231         pkg->local_filename = NULL;
232
233      /* CLEANUP: It'd be nice to pullin the cleanup function from
234         opkg_install.c here. See comment in
235         opkg_install.c:cleanup_temporary_files */
236         if (pkg->tmp_unpack_dir)
237                 free(pkg->tmp_unpack_dir);
238         pkg->tmp_unpack_dir = NULL;
239
240         if (pkg->md5sum)
241                 free(pkg->md5sum);
242         pkg->md5sum = NULL;
243
244 #if defined HAVE_SHA256
245         if (pkg->sha256sum)
246                 free(pkg->sha256sum);
247         pkg->sha256sum = NULL;
248 #endif
249
250         if (pkg->priority)
251                 free(pkg->priority);
252         pkg->priority = NULL;
253
254         if (pkg->source)
255                 free(pkg->source);
256         pkg->source = NULL;
257
258         conffile_list_deinit(&pkg->conffiles);
259
260         /* XXX: QUESTION: Is forcing this to 1 correct? I suppose so,
261         since if they are calling deinit, they should know. Maybe do an
262         assertion here instead? */
263         pkg->installed_files_ref_cnt = 1;
264         pkg_free_installed_files(pkg);
265         pkg->essential = 0;
266
267         if (pkg->tags)
268                 free (pkg->tags);
269         pkg->tags = NULL;
270 }
271
272 int
273 pkg_init_from_file(pkg_t *pkg, const char *filename)
274 {
275         int fd, err = 0;
276         FILE *control_file;
277         char *control_path, *tmp;
278
279         pkg_init(pkg);
280
281         pkg->local_filename = xstrdup(filename);
282
283         tmp = xstrdup(filename);
284         sprintf_alloc(&control_path, "%s/%s.control.XXXXXX", 
285                         conf->tmp_dir,
286                         basename(tmp));
287         free(tmp);
288         fd = mkstemp(control_path);
289         if (fd == -1) {
290                 opkg_perror(ERROR, "Failed to make temp file %s", control_path);
291                 err = -1;
292                 goto err0;
293         }
294
295         control_file = fdopen(fd, "r+");
296         if (control_file == NULL) {
297                 opkg_perror(ERROR, "Failed to fdopen %s", control_path);
298                 close(fd);
299                 err = -1;
300                 goto err1;
301         }
302
303         err = pkg_extract_control_file_to_stream(pkg, control_file);
304         if (err) {
305                 opkg_msg(ERROR, "Failed to extract control file from %s.\n",
306                                 filename);
307                 goto err2;
308         }
309
310         rewind(control_file);
311
312         if (pkg_parse_from_stream(pkg, control_file, 0))
313                 err = -1;
314
315 err2:
316         fclose(control_file);
317 err1:
318         unlink(control_path);
319 err0:
320         free(control_path);
321
322         return err;
323 }
324
325 /* Merge any new information in newpkg into oldpkg */
326 int
327 pkg_merge(pkg_t *oldpkg, pkg_t *newpkg)
328 {
329      if (oldpkg == newpkg) {
330           return 0;
331      }
332
333      if (!oldpkg->auto_installed)
334           oldpkg->auto_installed = newpkg->auto_installed;
335
336      if (!oldpkg->src)
337           oldpkg->src = newpkg->src;
338      if (!oldpkg->dest)
339           oldpkg->dest = newpkg->dest;
340      if (!oldpkg->architecture)
341           oldpkg->architecture = xstrdup(newpkg->architecture);
342      if (!oldpkg->arch_priority)
343           oldpkg->arch_priority = newpkg->arch_priority;
344      if (!oldpkg->section)
345           oldpkg->section = xstrdup(newpkg->section);
346      if(!oldpkg->maintainer)
347           oldpkg->maintainer = xstrdup(newpkg->maintainer);
348      if(!oldpkg->description)
349           oldpkg->description = xstrdup(newpkg->description);
350
351      if (!oldpkg->depends_count && !oldpkg->pre_depends_count && !oldpkg->recommends_count && !oldpkg->suggests_count) {
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_count = newpkg->pre_depends_count;
359           newpkg->pre_depends_count = 0;
360
361           oldpkg->recommends_count = newpkg->recommends_count;
362           newpkg->recommends_count = 0;
363
364           oldpkg->suggests_count = newpkg->suggests_count;
365           newpkg->suggests_count = 0;
366      }
367
368      if (oldpkg->provides_count <= 1) {
369           oldpkg->provides_count = newpkg->provides_count;
370           newpkg->provides_count = 0;
371
372           if (!oldpkg->provides) {
373                 oldpkg->provides = newpkg->provides;
374                 newpkg->provides = NULL;
375           }
376      }
377
378      if (!oldpkg->conflicts_count) {
379           oldpkg->conflicts_count = newpkg->conflicts_count;
380           newpkg->conflicts_count = 0;
381
382           oldpkg->conflicts = newpkg->conflicts;
383           newpkg->conflicts = NULL;
384      }
385
386      if (!oldpkg->replaces_count) {
387           oldpkg->replaces_count = newpkg->replaces_count;
388           newpkg->replaces_count = 0;
389
390           oldpkg->replaces = newpkg->replaces;
391           newpkg->replaces = NULL;
392      }
393
394      if (!oldpkg->filename)
395           oldpkg->filename = xstrdup(newpkg->filename);
396      if (!oldpkg->local_filename)
397           oldpkg->local_filename = xstrdup(newpkg->local_filename);
398      if (!oldpkg->tmp_unpack_dir)
399           oldpkg->tmp_unpack_dir = xstrdup(newpkg->tmp_unpack_dir);
400      if (!oldpkg->md5sum)
401           oldpkg->md5sum = xstrdup(newpkg->md5sum);
402 #if defined HAVE_SHA256
403      if (!oldpkg->sha256sum)
404           oldpkg->sha256sum = xstrdup(newpkg->sha256sum);
405 #endif
406      if (!oldpkg->size)
407           oldpkg->size = newpkg->size;
408      if (!oldpkg->installed_size)
409           oldpkg->installed_size = newpkg->installed_size;
410      if (!oldpkg->priority)
411           oldpkg->priority = xstrdup(newpkg->priority);
412      if (!oldpkg->source)
413           oldpkg->source = xstrdup(newpkg->source);
414
415      if (nv_pair_list_empty(&oldpkg->conffiles)){
416           list_splice_init(&newpkg->conffiles.head, &oldpkg->conffiles.head);
417      }
418
419      if (!oldpkg->installed_files){
420           oldpkg->installed_files = newpkg->installed_files;
421           oldpkg->installed_files_ref_cnt = newpkg->installed_files_ref_cnt;
422           newpkg->installed_files = NULL;
423      }
424
425      if (!oldpkg->essential)
426           oldpkg->essential = newpkg->essential;
427
428      return 0;
429 }
430
431 static void
432 abstract_pkg_init(abstract_pkg_t *ab_pkg)
433 {
434      ab_pkg->provided_by = abstract_pkg_vec_alloc();
435      ab_pkg->dependencies_checked = 0;
436      ab_pkg->state_status = SS_NOT_INSTALLED;
437 }
438
439 abstract_pkg_t *
440 abstract_pkg_new(void)
441 {
442      abstract_pkg_t * ab_pkg;
443
444      ab_pkg = xcalloc(1, sizeof(abstract_pkg_t));
445      abstract_pkg_init(ab_pkg);
446
447      return ab_pkg;
448 }
449
450 void
451 set_flags_from_control(pkg_t *pkg){
452      char *file_name;
453      FILE *fp;
454
455      sprintf_alloc(&file_name,"%s/%s.control", pkg->dest->info_dir, pkg->name);
456
457      fp = fopen(file_name, "r");
458      if (fp == NULL) {
459              opkg_perror(ERROR, "Failed to open %s");
460              free(file_name);
461              return;
462      }
463
464      free(file_name);
465
466      if (pkg_parse_from_stream(pkg, fp, PFM_ALL ^ PFM_ESSENTIAL)) {
467         opkg_msg(DEBUG, "Unable to read control file for %s. May be empty.\n",
468                         pkg->name);
469      }
470
471      fclose(fp);
472
473      return;
474 }
475
476 static const char *
477 pkg_state_want_to_str(pkg_state_want_t sw)
478 {
479      int i;
480
481      for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
482           if (pkg_state_want_map[i].value == sw) {
483                return pkg_state_want_map[i].str;
484           }
485      }
486
487      opkg_msg(ERROR, "Internal error: state_want=%d\n", sw);
488      return "<STATE_WANT_UNKNOWN>";
489 }
490
491 pkg_state_want_t
492 pkg_state_want_from_str(char *str)
493 {
494      int i;
495
496      for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
497           if (strcmp(str, pkg_state_want_map[i].str) == 0) {
498                return pkg_state_want_map[i].value;
499           }
500      }
501
502      opkg_msg(ERROR, "Internal error: state_want=%s\n", str);
503      return SW_UNKNOWN;
504 }
505
506 static char *
507 pkg_state_flag_to_str(pkg_state_flag_t sf)
508 {
509         int i;
510         unsigned int len;
511         char *str;
512
513         /* clear the temporary flags before converting to string */
514         sf &= SF_NONVOLATILE_FLAGS;
515
516         if (sf == 0)
517                 return xstrdup("ok");
518
519         len = 0;
520         for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
521                 if (sf & pkg_state_flag_map[i].value)
522                         len += strlen(pkg_state_flag_map[i].str) + 1;
523         }
524
525         str = xmalloc(len+1);
526         str[0] = '\0';
527
528         for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
529                 if (sf & pkg_state_flag_map[i].value) {
530                         strncat(str, pkg_state_flag_map[i].str, len);
531                         strncat(str, ",", len);
532                 }
533         }
534
535         len = strlen(str);
536         str[len-1] = '\0'; /* squash last comma */
537
538         return str;
539 }
540
541 pkg_state_flag_t
542 pkg_state_flag_from_str(const char *str)
543 {
544      int i;
545      int sf = SF_OK;
546      const char *sfname;
547      unsigned int sfname_len;
548
549      if (strcmp(str, "ok") == 0) {
550           return SF_OK;
551      }
552      for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
553           sfname = pkg_state_flag_map[i].str;
554           sfname_len = strlen(sfname);
555           if (strncmp(str, sfname, sfname_len) == 0) {
556                sf |= pkg_state_flag_map[i].value;
557                str += sfname_len;
558                if (str[0] == ',') {
559                     str++;
560                } else {
561                     break;
562                }
563           }
564      }
565
566      return sf;
567 }
568
569 static const char *
570 pkg_state_status_to_str(pkg_state_status_t ss)
571 {
572      int i;
573
574      for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
575           if (pkg_state_status_map[i].value == ss) {
576                return pkg_state_status_map[i].str;
577           }
578      }
579
580      opkg_msg(ERROR, "Internal error: state_status=%d\n", ss);
581      return "<STATE_STATUS_UNKNOWN>";
582 }
583
584 pkg_state_status_t
585 pkg_state_status_from_str(const char *str)
586 {
587      int i;
588
589      for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
590           if (strcmp(str, pkg_state_status_map[i].str) == 0) {
591                return pkg_state_status_map[i].value;
592           }
593      }
594
595      opkg_msg(ERROR, "Internal error: state_status=%s\n", str);
596      return SS_NOT_INSTALLED;
597 }
598
599 void
600 pkg_formatted_field(FILE *fp, pkg_t *pkg, const char *field)
601 {
602      int i, j;
603      char *str;
604      int depends_count = pkg->pre_depends_count +
605                          pkg->depends_count +
606                          pkg->recommends_count +
607                          pkg->suggests_count;
608
609      if (strlen(field) < PKG_MINIMUM_FIELD_NAME_LEN) {
610           goto UNKNOWN_FMT_FIELD;
611      }
612
613      switch (field[0])
614      {
615      case 'a':
616      case 'A':
617           if (strcasecmp(field, "Architecture") == 0) {
618                if (pkg->architecture) {
619                    fprintf(fp, "Architecture: %s\n", pkg->architecture);
620                }
621           } else if (strcasecmp(field, "Auto-Installed") == 0) {
622                 if (pkg->auto_installed)
623                     fprintf(fp, "Auto-Installed: yes\n");
624           } else {
625                goto UNKNOWN_FMT_FIELD;
626           }
627           break;
628      case 'c':
629      case 'C':
630           if (strcasecmp(field, "Conffiles") == 0) {
631                conffile_list_elt_t *iter;
632
633                if (nv_pair_list_empty(&pkg->conffiles))
634                     return;
635
636                fprintf(fp, "Conffiles:\n");
637                for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
638                     if (((conffile_t *)iter->data)->name && ((conffile_t *)iter->data)->value) {
639                          fprintf(fp, " %s %s\n", 
640                                  ((conffile_t *)iter->data)->name, 
641                                  ((conffile_t *)iter->data)->value);
642                     }
643                }
644           } else if (strcasecmp(field, "Conflicts") == 0) {
645                struct depend *cdep;
646                if (pkg->conflicts_count) {
647                     fprintf(fp, "Conflicts:");
648                     for(i = 0; i < pkg->conflicts_count; i++) {
649                         cdep = pkg->conflicts[i].possibilities[0];
650                         fprintf(fp, "%s %s", i == 0 ? "" : ",",
651                                 cdep->pkg->name);
652                         if (cdep->version) {
653                                 fprintf(fp, " (%s%s)",
654                                         constraint_to_str(cdep->constraint),
655                                         cdep->version);
656                         }
657                     }
658                     fprintf(fp, "\n");
659                }
660           } else {
661                goto UNKNOWN_FMT_FIELD;
662           }
663           break;
664      case 'd':
665      case 'D':
666           if (strcasecmp(field, "Depends") == 0) {
667                if (pkg->depends_count) {
668                     fprintf(fp, "Depends:");
669                     for (j=0, i=0; i<depends_count; i++) {
670                         if (pkg->depends[i].type != DEPEND)
671                                 continue;
672                         str = pkg_depend_str(pkg, i);
673                         fprintf(fp, "%s %s", j == 0 ? "" : ",", str);
674                         free(str);
675                         j++;
676                     }
677                     fprintf(fp, "\n");
678                }
679           } else if (strcasecmp(field, "Description") == 0) {
680                if (pkg->description) {
681                    fprintf(fp, "Description: %s\n", pkg->description);
682                }
683           } else {
684                goto UNKNOWN_FMT_FIELD;
685           }
686           break;
687      case 'e':
688      case 'E':
689           if (pkg->essential) {
690               fprintf(fp, "Essential: yes\n");
691           }
692           break;
693      case 'f':
694      case 'F':
695           if (pkg->filename) {
696               fprintf(fp, "Filename: %s\n", pkg->filename);
697           }
698           break;
699      case 'i':
700      case 'I':
701           if (strcasecmp(field, "Installed-Size") == 0) {
702                fprintf(fp, "Installed-Size: %ld\n", pkg->installed_size);
703           } else if (strcasecmp(field, "Installed-Time") == 0 && pkg->installed_time) {
704                fprintf(fp, "Installed-Time: %lu\n", pkg->installed_time);
705           }
706           break;
707      case 'm':
708      case 'M':
709           if (strcasecmp(field, "Maintainer") == 0) {
710                if (pkg->maintainer) {
711                    fprintf(fp, "maintainer: %s\n", pkg->maintainer);
712                }
713           } else if (strcasecmp(field, "MD5sum") == 0) {
714                if (pkg->md5sum) {
715                    fprintf(fp, "MD5Sum: %s\n", pkg->md5sum);
716                }
717           } else {
718                goto UNKNOWN_FMT_FIELD;
719           }
720           break;
721      case 'p':
722      case 'P':
723           if (strcasecmp(field, "Package") == 0) {
724                fprintf(fp, "Package: %s\n", pkg->name);
725           } else if (strcasecmp(field, "Priority") == 0) {
726                fprintf(fp, "Priority: %s\n", pkg->priority);
727           } else if (strcasecmp(field, "Provides") == 0) {
728                if (pkg->provides_count) {
729                   fprintf(fp, "Provides:");
730                   for(i = 1; i < pkg->provides_count; i++) {
731                       fprintf(fp, "%s %s", i == 1 ? "" : ",",
732                                       pkg->provides[i]->name);
733                   }
734                   fprintf(fp, "\n");
735                }
736           } else {
737                goto UNKNOWN_FMT_FIELD;
738           }
739           break;
740      case 'r':
741      case 'R':
742           if (strcasecmp (field, "Replaces") == 0) {
743                if (pkg->replaces_count) {
744                     fprintf(fp, "Replaces:");
745                     for (i = 0; i < pkg->replaces_count; i++) {
746                         fprintf(fp, "%s %s", i == 0 ? "" : ",",
747                                         pkg->replaces[i]->name);
748                     }
749                     fprintf(fp, "\n");
750                }
751           } else if (strcasecmp (field, "Recommends") == 0) {
752                if (pkg->recommends_count) {
753                     fprintf(fp, "Recommends:");
754                     for (j=0, i=0; i<depends_count; i++) {
755                         if (pkg->depends[i].type != RECOMMEND)
756                                 continue;
757                         str = pkg_depend_str(pkg, i);
758                         fprintf(fp, "%s %s", j == 0 ? "" : ",", str);
759                         free(str);
760                         j++;
761                     }
762                     fprintf(fp, "\n");
763                }
764           } else {
765                goto UNKNOWN_FMT_FIELD;
766           }
767           break;
768      case 's':
769      case 'S':
770           if (strcasecmp(field, "Section") == 0) {
771                if (pkg->section) {
772                    fprintf(fp, "Section: %s\n", pkg->section);
773                }
774 #if defined HAVE_SHA256
775           } else if (strcasecmp(field, "SHA256sum") == 0) {
776                if (pkg->sha256sum) {
777                    fprintf(fp, "SHA256sum: %s\n", pkg->sha256sum);
778                }
779 #endif
780           } else if (strcasecmp(field, "Size") == 0) {
781                if (pkg->size) {
782                    fprintf(fp, "Size: %ld\n", pkg->size);
783                }
784           } else if (strcasecmp(field, "Source") == 0) {
785                if (pkg->source) {
786                    fprintf(fp, "Source: %s\n", pkg->source);
787                }
788           } else if (strcasecmp(field, "Status") == 0) {
789                char *pflag = pkg_state_flag_to_str(pkg->state_flag);
790                fprintf(fp, "Status: %s %s %s\n",
791                                pkg_state_want_to_str(pkg->state_want),
792                                pflag,
793                                pkg_state_status_to_str(pkg->state_status));
794                free(pflag);
795           } else if (strcasecmp(field, "Suggests") == 0) {
796                if (pkg->suggests_count) {
797                     fprintf(fp, "Suggests:");
798                     for (j=0, i=0; i<depends_count; i++) {
799                         if (pkg->depends[i].type != SUGGEST)
800                                 continue;
801                         str = pkg_depend_str(pkg, i);
802                         fprintf(fp, "%s %s", j == 0 ? "" : ",", str);
803                         free(str);
804                         j++;
805                     }
806                     fprintf(fp, "\n");
807                }
808           } else {
809                goto UNKNOWN_FMT_FIELD;
810           }
811           break;
812      case 't':
813      case 'T':
814           if (strcasecmp(field, "Tags") == 0) {
815                if (pkg->tags) {
816                    fprintf(fp, "Tags: %s\n", pkg->tags);
817                }
818           }
819           break;
820      case 'v':
821      case 'V':
822           {
823                char *version = pkg_version_str_alloc(pkg);
824                if (version == NULL)
825                     return;
826                fprintf(fp, "Version: %s\n", version);
827                free(version);
828           }
829           break;
830      default:
831           goto UNKNOWN_FMT_FIELD;
832      }
833
834      return;
835
836 UNKNOWN_FMT_FIELD:
837      opkg_msg(ERROR, "Internal error: field=%s\n", field);
838 }
839
840 void
841 pkg_formatted_info(FILE *fp, pkg_t *pkg)
842 {
843         pkg_formatted_field(fp, pkg, "Package");
844         pkg_formatted_field(fp, pkg, "Version");
845         pkg_formatted_field(fp, pkg, "Depends");
846         pkg_formatted_field(fp, pkg, "Recommends");
847         pkg_formatted_field(fp, pkg, "Suggests");
848         pkg_formatted_field(fp, pkg, "Provides");
849         pkg_formatted_field(fp, pkg, "Replaces");
850         pkg_formatted_field(fp, pkg, "Conflicts");
851         pkg_formatted_field(fp, pkg, "Status");
852         pkg_formatted_field(fp, pkg, "Section");
853         pkg_formatted_field(fp, pkg, "Essential");
854         pkg_formatted_field(fp, pkg, "Architecture");
855         pkg_formatted_field(fp, pkg, "Maintainer");
856         pkg_formatted_field(fp, pkg, "MD5sum");
857         pkg_formatted_field(fp, pkg, "Size");
858         pkg_formatted_field(fp, pkg, "Filename");
859         pkg_formatted_field(fp, pkg, "Conffiles");
860         pkg_formatted_field(fp, pkg, "Source");
861         pkg_formatted_field(fp, pkg, "Description");
862         pkg_formatted_field(fp, pkg, "Installed-Time");
863         pkg_formatted_field(fp, pkg, "Tags");
864         fputs("\n", fp);
865 }
866
867 void
868 pkg_print_status(pkg_t * pkg, FILE * file)
869 {
870      if (pkg == NULL) {
871           return;
872      }
873
874      pkg_formatted_field(file, pkg, "Package");
875      pkg_formatted_field(file, pkg, "Version");
876      pkg_formatted_field(file, pkg, "Depends");
877      pkg_formatted_field(file, pkg, "Recommends");
878      pkg_formatted_field(file, pkg, "Suggests");
879      pkg_formatted_field(file, pkg, "Provides");
880      pkg_formatted_field(file, pkg, "Replaces");
881      pkg_formatted_field(file, pkg, "Conflicts");
882      pkg_formatted_field(file, pkg, "Status");
883      pkg_formatted_field(file, pkg, "Essential");
884      pkg_formatted_field(file, pkg, "Architecture");
885      pkg_formatted_field(file, pkg, "Conffiles");
886      pkg_formatted_field(file, pkg, "Installed-Time");
887      pkg_formatted_field(file, pkg, "Auto-Installed");
888      fputs("\n", file);
889 }
890
891 /*
892  * libdpkg - Debian packaging suite library routines
893  * vercmp.c - comparison of version numbers
894  *
895  * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
896  */
897
898 /* assume ascii; warning: evaluates x multiple times! */
899 #define order(x) ((x) == '~' ? -1 \
900                 : isdigit((x)) ? 0 \
901                 : !(x) ? 0 \
902                 : isalpha((x)) ? (x) \
903                 : (x) + 256)
904
905 static int
906 verrevcmp(const char *val, const char *ref) {
907   if (!val) val= "";
908   if (!ref) ref= "";
909
910   while (*val || *ref) {
911     int first_diff= 0;
912
913     while ( (*val && !isdigit(*val)) || (*ref && !isdigit(*ref)) ) {
914       int vc= order(*val), rc= order(*ref);
915       if (vc != rc) return vc - rc;
916       val++; ref++;
917     }
918
919     while ( *val == '0' ) val++;
920     while ( *ref == '0' ) ref++;
921     while (isdigit(*val) && isdigit(*ref)) {
922       if (!first_diff) first_diff= *val - *ref;
923       val++; ref++;
924     }
925     if (isdigit(*val)) return 1;
926     if (isdigit(*ref)) return -1;
927     if (first_diff) return first_diff;
928   }
929   return 0;
930 }
931
932 int
933 pkg_compare_versions(const pkg_t *pkg, const pkg_t *ref_pkg)
934 {
935      int r;
936
937      if (pkg->epoch > ref_pkg->epoch) {
938           return 1;
939      }
940
941      if (pkg->epoch < ref_pkg->epoch) {
942           return -1;
943      }
944
945      r = verrevcmp(pkg->version, ref_pkg->version);
946      if (r) {
947           return r;
948      }
949
950      r = verrevcmp(pkg->revision, ref_pkg->revision);
951      if (r) {
952           return r;
953      }
954
955      return r;
956 }
957
958
959 int
960 pkg_version_satisfied(pkg_t *it, pkg_t *ref, const char *op)
961 {
962      int r;
963
964      r = pkg_compare_versions(it, ref);
965
966      if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0) {
967           return r <= 0;
968      }
969
970      if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0) {
971           return r >= 0;
972      }
973
974      if (strcmp(op, "<<") == 0) {
975           return r < 0;
976      }
977
978      if (strcmp(op, ">>") == 0) {
979           return r > 0;
980      }
981
982      if (strcmp(op, "=") == 0) {
983           return r == 0;
984      }
985
986      opkg_msg(ERROR, "Unknown operator: %s.\n", op);
987      return 0;
988 }
989
990 int
991 pkg_name_version_and_architecture_compare(const void *p1, const void *p2)
992 {
993      const pkg_t *a = *(const pkg_t**) p1;
994      const pkg_t *b = *(const pkg_t**) p2;
995      int namecmp;
996      int vercmp;
997      if (!a->name || !b->name) {
998        opkg_msg(ERROR, "Internal error: a->name=%p, b->name=%p.\n",
999                a->name, b->name);
1000        return 0;
1001      }
1002        
1003      namecmp = strcmp(a->name, b->name);
1004      if (namecmp)
1005           return namecmp;
1006      vercmp = pkg_compare_versions(a, b);
1007      if (vercmp)
1008           return vercmp;
1009      if (!a->arch_priority || !b->arch_priority) {
1010        opkg_msg(ERROR, "Internal error: a->arch_priority=%i b->arch_priority=%i.\n",
1011                a->arch_priority, b->arch_priority);
1012        return 0;
1013      }
1014      if (a->arch_priority > b->arch_priority)
1015           return 1;
1016      if (a->arch_priority < b->arch_priority)
1017           return -1;
1018      return 0;
1019 }
1020
1021 int
1022 abstract_pkg_name_compare(const void *p1, const void *p2)
1023 {
1024      const abstract_pkg_t *a = *(const abstract_pkg_t **)p1;
1025      const abstract_pkg_t *b = *(const abstract_pkg_t **)p2;
1026      if (!a->name || !b->name) {
1027        opkg_msg(ERROR, "Internal error: a->name=%p b->name=%p.\n",
1028                a->name, b->name);
1029        return 0;
1030      }
1031      return strcmp(a->name, b->name);
1032 }
1033
1034
1035 char *
1036 pkg_version_str_alloc(pkg_t *pkg)
1037 {
1038         char *version;
1039
1040         if (pkg->epoch) {
1041                 if (pkg->revision)
1042                         sprintf_alloc(&version, "%d:%s-%s",
1043                                 pkg->epoch, pkg->version, pkg->revision);
1044                 else
1045                         sprintf_alloc(&version, "%d:%s",
1046                                 pkg->epoch, pkg->version);
1047         } else {
1048                 if (pkg->revision)
1049                         sprintf_alloc(&version, "%s-%s",
1050                                 pkg->version, pkg->revision);
1051                 else
1052                         version = xstrdup(pkg->version);
1053         }
1054
1055         return version;
1056 }
1057
1058 /*
1059  * XXX: this should be broken into two functions
1060  */
1061 str_list_t *
1062 pkg_get_installed_files(pkg_t *pkg)
1063 {
1064      int err, fd;
1065      char *list_file_name = NULL;
1066      FILE *list_file = NULL;
1067      char *line;
1068      char *installed_file_name;
1069      unsigned int rootdirlen = 0;
1070
1071      pkg->installed_files_ref_cnt++;
1072
1073      if (pkg->installed_files) {
1074           return pkg->installed_files;
1075      }
1076
1077      pkg->installed_files = str_list_alloc();
1078
1079      /* For uninstalled packages, get the file list directly from the package.
1080         For installed packages, look at the package.list file in the database.
1081      */
1082      if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1083           if (pkg->local_filename == NULL) {
1084                return pkg->installed_files;
1085           }
1086           /* XXX: CLEANUP: Maybe rewrite this to avoid using a temporary
1087              file. In other words, change deb_extract so that it can
1088              simply return the file list as a char *[] rather than
1089              insisting on writing in to a FILE * as it does now. */
1090           sprintf_alloc(&list_file_name, "%s/%s.list.XXXXXX",
1091                                           conf->tmp_dir, pkg->name);
1092           fd = mkstemp(list_file_name);
1093           if (fd == -1) {
1094                opkg_perror(ERROR, "Failed to make temp file %s.",
1095                                list_file_name);
1096                free(list_file_name);
1097                return pkg->installed_files;
1098           }
1099           list_file = fdopen(fd, "r+");
1100           if (list_file == NULL) {
1101                opkg_perror(ERROR, "Failed to fdopen temp file %s.",
1102                                list_file_name);
1103                close(fd);
1104                unlink(list_file_name);
1105                free(list_file_name);
1106                return pkg->installed_files;
1107           }
1108           err = pkg_extract_data_file_names_to_stream(pkg, list_file);
1109           if (err) {
1110                opkg_msg(ERROR, "Error extracting file list from %s.\n",
1111                                pkg->local_filename);
1112                fclose(list_file);
1113                unlink(list_file_name);
1114                free(list_file_name);
1115                str_list_deinit(pkg->installed_files);
1116                pkg->installed_files = NULL;
1117                return NULL;
1118           }
1119           rewind(list_file);
1120      } else {
1121           sprintf_alloc(&list_file_name, "%s/%s.list",
1122                         pkg->dest->info_dir, pkg->name);
1123           list_file = fopen(list_file_name, "r");
1124           if (list_file == NULL) {
1125                opkg_perror(ERROR, "Failed to open %s",
1126                        list_file_name);
1127                free(list_file_name);
1128                return pkg->installed_files;
1129           }
1130           free(list_file_name);
1131      }
1132
1133      if (conf->offline_root)
1134           rootdirlen = strlen(conf->offline_root);
1135
1136      while (1) {
1137           char *file_name;
1138         
1139           line = file_read_line_alloc(list_file);
1140           if (line == NULL) {
1141                break;
1142           }
1143           file_name = line;
1144
1145           if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1146                if (*file_name == '.') {
1147                     file_name++;
1148                }
1149                if (*file_name == '/') {
1150                     file_name++;
1151                }
1152                sprintf_alloc(&installed_file_name, "%s%s",
1153                                pkg->dest->root_dir, file_name);
1154           } else {
1155                if (conf->offline_root &&
1156                        strncmp(conf->offline_root, file_name, rootdirlen)) {
1157                     sprintf_alloc(&installed_file_name, "%s%s",
1158                                     conf->offline_root, file_name);
1159                } else {
1160                     // already contains root_dir as header -> ABSOLUTE
1161                     sprintf_alloc(&installed_file_name, "%s", file_name);
1162                }
1163           }
1164           str_list_append(pkg->installed_files, installed_file_name);
1165           free(installed_file_name);
1166           free(line);
1167      }
1168
1169      fclose(list_file);
1170
1171      if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1172           unlink(list_file_name);
1173           free(list_file_name);
1174      }
1175
1176      return pkg->installed_files;
1177 }
1178
1179 /* XXX: CLEANUP: This function and it's counterpart,
1180    (pkg_get_installed_files), do not match our init/deinit naming
1181    convention. Nor the alloc/free convention. But, then again, neither
1182    of these conventions currrently fit the way these two functions
1183    work. */
1184 void
1185 pkg_free_installed_files(pkg_t *pkg)
1186 {
1187      pkg->installed_files_ref_cnt--;
1188
1189      if (pkg->installed_files_ref_cnt > 0)
1190           return;
1191
1192      if (pkg->installed_files) {
1193          str_list_purge(pkg->installed_files);
1194      }
1195
1196      pkg->installed_files = NULL;
1197 }
1198
1199 void
1200 pkg_remove_installed_files_list(pkg_t *pkg)
1201 {
1202         char *list_file_name;
1203
1204         sprintf_alloc(&list_file_name, "%s/%s.list",
1205                 pkg->dest->info_dir, pkg->name);
1206
1207         if (!conf->noaction)
1208                 (void)unlink(list_file_name);
1209
1210         free(list_file_name);
1211 }
1212
1213 conffile_t *
1214 pkg_get_conffile(pkg_t *pkg, const char *file_name)
1215 {
1216      conffile_list_elt_t *iter;
1217      conffile_t *conffile;
1218
1219      if (pkg == NULL) {
1220           return NULL;
1221      }
1222
1223      for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
1224           conffile = (conffile_t *)iter->data;
1225
1226           if (strcmp(conffile->name, file_name) == 0) {
1227                return conffile;
1228           }
1229      }
1230
1231      return NULL;
1232 }
1233
1234 int
1235 pkg_run_script(pkg_t *pkg, const char *script, const char *args)
1236 {
1237      int err;
1238      char *path;
1239      char *cmd;
1240
1241      if (conf->noaction)
1242              return 0;
1243
1244      /* XXX: FEATURE: When conf->offline_root is set, we should run the
1245         maintainer script within a chroot environment. */
1246      if (conf->offline_root) {
1247           opkg_msg(INFO, "Offline root mode: not running %s.%s.\n",
1248                           pkg->name, script);
1249           return 0;
1250      }
1251
1252      /* Installed packages have scripts in pkg->dest->info_dir, uninstalled packages
1253         have scripts in pkg->tmp_unpack_dir. */
1254      if (pkg->state_status == SS_INSTALLED || pkg->state_status == SS_UNPACKED) {
1255           if (pkg->dest == NULL) {
1256                opkg_msg(ERROR, "Internal error: %s has a NULL dest.\n",
1257                        pkg->name);
1258                return -1;
1259           }
1260           sprintf_alloc(&path, "%s/%s.%s", pkg->dest->info_dir, pkg->name, script);
1261      } else {
1262           if (pkg->tmp_unpack_dir == NULL) {
1263                opkg_msg(ERROR, "Internal error: %s has a NULL tmp_unpack_dir.\n",
1264                        pkg->name);
1265                return -1;
1266           }
1267           sprintf_alloc(&path, "%s/%s", pkg->tmp_unpack_dir, script);
1268      }
1269
1270      opkg_msg(INFO, "Running script %s.\n", path);
1271
1272      setenv("PKG_ROOT",
1273             pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir, 1);
1274
1275      if (! file_exists(path)) {
1276           free(path);
1277           return 0;
1278      }
1279
1280      sprintf_alloc(&cmd, "%s %s", path, args);
1281      free(path);
1282      {
1283           const char *argv[] = {"sh", "-c", cmd, NULL};
1284           err = xsystem(argv);
1285      }
1286      free(cmd);
1287
1288      if (err) {
1289           opkg_msg(ERROR, "%s script returned status %d.\n", script, err);
1290           return err;
1291      }
1292
1293      return 0;
1294 }
1295
1296 int
1297 pkg_arch_supported(pkg_t *pkg)
1298 {
1299      nv_pair_list_elt_t *l;
1300
1301      if (!pkg->architecture)
1302           return 1;
1303
1304      list_for_each_entry(l , &conf->arch_list.head, node) {
1305           nv_pair_t *nv = (nv_pair_t *)l->data;
1306           if (strcmp(nv->name, pkg->architecture) == 0) {
1307                opkg_msg(DEBUG, "Arch %s (priority %s) supported for pkg %s.\n",
1308                                nv->name, nv->value, pkg->name);
1309                return 1;
1310           }
1311      }
1312
1313      opkg_msg(DEBUG, "Arch %s unsupported for pkg %s.\n",
1314                      pkg->architecture, pkg->name);
1315      return 0;
1316 }
1317
1318 static int
1319 pkg_get_arch_priority(const char *archname)
1320 {
1321      nv_pair_list_elt_t *l;
1322
1323      list_for_each_entry(l , &conf->arch_list.head, node) {
1324           nv_pair_t *nv = (nv_pair_t *)l->data;
1325           if (strcmp(nv->name, archname) == 0) {
1326                int priority = strtol(nv->value, NULL, 0);
1327                return priority;
1328           }
1329      }
1330      return 0;
1331 }
1332
1333 void
1334 pkg_info_preinstall_check(void)
1335 {
1336      int i;
1337      pkg_vec_t *available_pkgs = pkg_vec_alloc();
1338      pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1339
1340      opkg_msg(INFO, "Updating arch priority for each package.\n");
1341      pkg_hash_fetch_available(available_pkgs);
1342      /* update arch_priority for each package */
1343      for (i = 0; i < available_pkgs->len; i++) {
1344           pkg_t *pkg = available_pkgs->pkgs[i];
1345           int arch_priority = 1;
1346           if (!pkg)
1347                continue;
1348           arch_priority = pkg_get_arch_priority(pkg->architecture);
1349           pkg->arch_priority = arch_priority;
1350      }
1351
1352      for (i = 0; i < available_pkgs->len; i++) {
1353           pkg_t *pkg = available_pkgs->pkgs[i];
1354           if (!pkg->arch_priority && (pkg->state_flag || (pkg->state_want != SW_UNKNOWN))) {
1355                /* clear flags and want for any uninstallable package */
1356                opkg_msg(DEBUG, "Clearing state_want and state_flag for pkg=%s "
1357                                "(arch_priority=%d flag=%d want=%d)\n", 
1358                                pkg->name, pkg->arch_priority,
1359                                pkg->state_flag, pkg->state_want);
1360                pkg->state_want = SW_UNKNOWN;
1361                pkg->state_flag = 0;
1362           }
1363      }
1364      pkg_vec_free(available_pkgs);
1365
1366      /* update the file owner data structure */
1367      opkg_msg(INFO, "Updating file owner list.\n");
1368      pkg_hash_fetch_all_installed(installed_pkgs);
1369      for (i = 0; i < installed_pkgs->len; i++) {
1370           pkg_t *pkg = installed_pkgs->pkgs[i];
1371           str_list_t *installed_files = pkg_get_installed_files(pkg); /* this causes installed_files to be cached */
1372           str_list_elt_t *iter, *niter;
1373           if (installed_files == NULL) {
1374                opkg_msg(ERROR, "Failed to determine installed "
1375                                "files for pkg %s.\n", pkg->name);
1376                break;
1377           }
1378           for (iter = str_list_first(installed_files), niter = str_list_next(installed_files, iter); 
1379                   iter; 
1380                   iter = niter, niter = str_list_next(installed_files, iter)) {
1381                char *installed_file = (char *) iter->data;
1382                file_hash_set_file_owner(installed_file, pkg);
1383           }
1384           pkg_free_installed_files(pkg);
1385      }
1386      pkg_vec_free(installed_pkgs);
1387 }
1388
1389 struct pkg_write_filelist_data {
1390      pkg_t *pkg;
1391      FILE *stream;
1392 };
1393
1394 static void
1395 pkg_write_filelist_helper(const char *key, void *entry_, void *data_)
1396 {
1397      struct pkg_write_filelist_data *data = data_;
1398      pkg_t *entry = entry_;
1399      if (entry == data->pkg) {
1400           fprintf(data->stream, "%s\n", key);
1401      }
1402 }
1403
1404 int
1405 pkg_write_filelist(pkg_t *pkg)
1406 {
1407         struct pkg_write_filelist_data data;
1408         char *list_file_name;
1409
1410         sprintf_alloc(&list_file_name, "%s/%s.list",
1411                         pkg->dest->info_dir, pkg->name);
1412
1413         opkg_msg(INFO, "Creating %s file for pkg %s.\n",
1414                         list_file_name, pkg->name);
1415
1416         data.stream = fopen(list_file_name, "w");
1417         if (!data.stream) {
1418                 opkg_perror(ERROR, "Failed to open %s",
1419                         list_file_name);
1420                 free(list_file_name);
1421                 return -1;
1422         }
1423
1424         data.pkg = pkg;
1425         hash_table_foreach(&conf->file_hash, pkg_write_filelist_helper, &data);
1426         fclose(data.stream);
1427         free(list_file_name);
1428
1429         pkg->state_flag &= ~SF_FILELIST_CHANGED;
1430
1431         return 0;
1432 }
1433
1434 int
1435 pkg_write_changed_filelists(void)
1436 {
1437         pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1438         int i, err, ret = 0;
1439
1440         if (conf->noaction)
1441                 return 0;
1442
1443         opkg_msg(INFO, "Saving changed filelists.\n");
1444
1445         pkg_hash_fetch_all_installed(installed_pkgs);
1446         for (i = 0; i < installed_pkgs->len; i++) {
1447                 pkg_t *pkg = installed_pkgs->pkgs[i];
1448                 if (pkg->state_flag & SF_FILELIST_CHANGED) {
1449                         err = pkg_write_filelist(pkg);
1450                         if (err)
1451                                 ret = -1;
1452                 }
1453         }
1454
1455         pkg_vec_free (installed_pkgs);
1456
1457         return ret;
1458 }