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