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