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