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