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