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