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