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