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