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