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