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