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