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