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