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