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