opkg: re-arrange source code into sub-directories
[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 int verrevcmp(const char *val, const char *ref)
1083 {
1084 int vc, rc;
1085 long vl, rl;
1086 const char *vp, *rp;
1087 const char *vsep, *rsep;
1088
1089 if (!val) val= "";
1090 if (!ref) ref= "";
1091 for (;;) {
1092 vp= val; while (*vp && !isdigit(*vp)) vp++;
1093 rp= ref; while (*rp && !isdigit(*rp)) rp++;
1094 for (;;) {
1095 vc= (val == vp) ? 0 : *val++;
1096 rc= (ref == rp) ? 0 : *ref++;
1097 if (!rc && !vc) break;
1098 if (vc && !isalpha(vc)) vc += 256; /* assumes ASCII character set */
1099 if (rc && !isalpha(rc)) rc += 256;
1100 if (vc != rc) return vc - rc;
1101 }
1102 val= vp;
1103 ref= rp;
1104 vl=0; if (isdigit(*vp)) vl= strtol(val,(char**)&val,10);
1105 rl=0; if (isdigit(*rp)) rl= strtol(ref,(char**)&ref,10);
1106 if (vl != rl) return vl - rl;
1107
1108 vc = *val;
1109 rc = *ref;
1110 vsep = strchr(".-", vc);
1111 rsep = strchr(".-", rc);
1112 if (vsep && !rsep) return -1;
1113 if (!vsep && rsep) return +1;
1114
1115 if (!*val && !*ref) return 0;
1116 if (!*val) return -1;
1117 if (!*ref) return +1;
1118 }
1119 }
1120
1121 int pkg_version_satisfied(pkg_t *it, pkg_t *ref, const char *op)
1122 {
1123 int r;
1124
1125 r = pkg_compare_versions(it, ref);
1126
1127 if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0) {
1128 return r <= 0;
1129 }
1130
1131 if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0) {
1132 return r >= 0;
1133 }
1134
1135 if (strcmp(op, "<<") == 0) {
1136 return r < 0;
1137 }
1138
1139 if (strcmp(op, ">>") == 0) {
1140 return r > 0;
1141 }
1142
1143 if (strcmp(op, "=") == 0) {
1144 return r == 0;
1145 }
1146
1147 fprintf(stderr, "unknown operator: %s", op);
1148 return 0;
1149 }
1150
1151 int pkg_name_version_and_architecture_compare(void *p1, void *p2)
1152 {
1153 const pkg_t *a = *(const pkg_t **)p1;
1154 const pkg_t *b = *(const pkg_t **)p2;
1155 int namecmp;
1156 int vercmp;
1157 if (!a->name || !b->name) {
1158 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->name=%p b=%p b->name=%p\n",
1159 a, a->name, b, b->name);
1160 return 0;
1161 }
1162
1163 namecmp = strcmp(a->name, b->name);
1164 if (namecmp)
1165 return namecmp;
1166 vercmp = pkg_compare_versions(a, b);
1167 if (vercmp)
1168 return vercmp;
1169 if (!a->arch_priority || !b->arch_priority) {
1170 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->arch_priority=%i b=%p b->arch_priority=%i\n",
1171 a, a->arch_priority, b, b->arch_priority);
1172 return 0;
1173 }
1174 if (a->arch_priority > b->arch_priority)
1175 return 1;
1176 if (a->arch_priority < b->arch_priority)
1177 return -1;
1178 return 0;
1179 }
1180
1181 int abstract_pkg_name_compare(void *p1, void *p2)
1182 {
1183 const abstract_pkg_t *a = *(const abstract_pkg_t **)p1;
1184 const abstract_pkg_t *b = *(const abstract_pkg_t **)p2;
1185 if (!a->name || !b->name) {
1186 fprintf(stderr, "abstract_pkg_name_compare: a=%p a->name=%p b=%p b->name=%p\n",
1187 a, a->name, b, b->name);
1188 return 0;
1189 }
1190 return strcmp(a->name, b->name);
1191 }
1192
1193
1194 char *pkg_version_str_alloc(pkg_t *pkg)
1195 {
1196 char *complete_version;
1197 char *epoch_str;
1198 #ifdef USE_DEBVERSION
1199 char *revision_str;
1200 char *familiar_revision_str;
1201 #endif
1202
1203 if (pkg->epoch) {
1204 sprintf_alloc(&epoch_str, "%d:", pkg->epoch);
1205 } else {
1206 epoch_str = strdup("");
1207 }
1208
1209 #ifdef USE_DEBVERSION
1210 if (pkg->revision && strlen(pkg->revision)) {
1211 sprintf_alloc(&revision_str, "-%s", pkg->revision);
1212 } else {
1213 revision_str = strdup("");
1214 }
1215
1216 if (pkg->familiar_revision && strlen(pkg->familiar_revision)) {
1217 sprintf_alloc(&familiar_revision_str, "-fam%s", pkg->familiar_revision);
1218 } else {
1219 familiar_revision_str = strdup("");
1220 }
1221 #endif
1222
1223 #ifdef USE_DEBVERSION
1224 sprintf_alloc(&complete_version, "%s%s%s%s",
1225 epoch_str, pkg->version, revision_str, familiar_revision_str);
1226 #else
1227 sprintf_alloc(&complete_version, "%s%s",
1228 epoch_str, pkg->version);
1229 #endif
1230
1231 free(epoch_str);
1232 #ifdef USE_DEBVERSION
1233 free(revision_str);
1234 free(familiar_revision_str);
1235 #endif
1236
1237 return complete_version;
1238 }
1239
1240 str_list_t *pkg_get_installed_files(pkg_t *pkg)
1241 {
1242 int err;
1243 char *list_file_name = NULL;
1244 FILE *list_file = NULL;
1245 char *line;
1246 char *installed_file_name;
1247 int rootdirlen;
1248
1249 pkg->installed_files_ref_cnt++;
1250
1251 if (pkg->installed_files) {
1252 return pkg->installed_files;
1253 }
1254
1255 pkg->installed_files = str_list_alloc();
1256 if (pkg->installed_files == NULL) {
1257 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
1258 return NULL;
1259 }
1260
1261 /* For uninstalled packages, get the file list firectly from the package.
1262 For installed packages, look at the package.list file in the database.
1263 */
1264 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1265 if (pkg->local_filename == NULL) {
1266 return pkg->installed_files;
1267 }
1268 /* XXX: CLEANUP: Maybe rewrite this to avoid using a temporary
1269 file. In other words, change deb_extract so that it can
1270 simply return the file list as a char *[] rather than
1271 insisting on writing in to a FILE * as it does now. */
1272 list_file = tmpfile();
1273 err = pkg_extract_data_file_names_to_stream(pkg, list_file);
1274 if (err) {
1275 fclose(list_file);
1276 fprintf(stderr, "%s: Error extracting file list from %s: %s\n",
1277 __FUNCTION__, pkg->local_filename, strerror(err));
1278 return pkg->installed_files;
1279 }
1280 rewind(list_file);
1281 } else {
1282 sprintf_alloc(&list_file_name, "%s/%s.list",
1283 pkg->dest->info_dir, pkg->name);
1284 if (! file_exists(list_file_name)) {
1285 free(list_file_name);
1286 return pkg->installed_files;
1287 }
1288
1289 list_file = fopen(list_file_name, "r");
1290 if (list_file == NULL) {
1291 fprintf(stderr, "WARNING: Cannot open %s: %s\n",
1292 list_file_name, strerror(errno));
1293 free(list_file_name);
1294 return pkg->installed_files;
1295 }
1296 free(list_file_name);
1297 }
1298
1299 rootdirlen = strlen( pkg->dest->root_dir );
1300 while (1) {
1301 char *file_name;
1302
1303 line = file_read_line_alloc(list_file);
1304 if (line == NULL) {
1305 break;
1306 }
1307 str_chomp(line);
1308 file_name = line;
1309
1310 /* Take pains to avoid uglies like "/./" in the middle of file_name. */
1311 if( strncmp( pkg->dest->root_dir,
1312 file_name,
1313 rootdirlen ) ) {
1314 if (*file_name == '.') {
1315 file_name++;
1316 }
1317 if (*file_name == '/') {
1318 file_name++;
1319 }
1320
1321 /* Freed in pkg_free_installed_files */
1322 sprintf_alloc(&installed_file_name, "%s%s", pkg->dest->root_dir, file_name);
1323 } else {
1324 // already contains root_dir as header -> ABSOLUTE
1325 sprintf_alloc(&installed_file_name, "%s", file_name);
1326 }
1327 str_list_append(pkg->installed_files, installed_file_name);
1328 free(line);
1329 }
1330
1331 fclose(list_file);
1332
1333 return pkg->installed_files;
1334 }
1335
1336 /* XXX: CLEANUP: This function and it's counterpart,
1337 (pkg_get_installed_files), do not match our init/deinit naming
1338 convention. Nor the alloc/free convention. But, then again, neither
1339 of these conventions currrently fit the way these two functions
1340 work. */
1341 int pkg_free_installed_files(pkg_t *pkg)
1342 {
1343 str_list_elt_t *iter;
1344
1345 pkg->installed_files_ref_cnt--;
1346 if (pkg->installed_files_ref_cnt > 0) {
1347 return 0;
1348 }
1349
1350 if (pkg->installed_files) {
1351
1352 for (iter = pkg->installed_files->head; iter; iter = iter->next) {
1353 /* malloced in pkg_get_installed_files */
1354 free (iter->data);
1355 iter->data = NULL;
1356 }
1357
1358 str_list_deinit(pkg->installed_files);
1359 }
1360
1361 pkg->installed_files = NULL;
1362
1363 return 0;
1364 }
1365
1366 int pkg_remove_installed_files_list(opkg_conf_t *conf, pkg_t *pkg)
1367 {
1368 int err;
1369 char *list_file_name;
1370
1371 //I don't think pkg_free_installed_files should be called here. Jamey
1372 //pkg_free_installed_files(pkg);
1373
1374 sprintf_alloc(&list_file_name, "%s/%s.list",
1375 pkg->dest->info_dir, pkg->name);
1376 if (!conf->noaction) {
1377 err = unlink(list_file_name);
1378 free(list_file_name);
1379
1380 if (err) {
1381 return errno;
1382 }
1383 }
1384 return 0;
1385 }
1386
1387 conffile_t *pkg_get_conffile(pkg_t *pkg, const char *file_name)
1388 {
1389 conffile_list_elt_t *iter;
1390 conffile_t *conffile;
1391
1392 if (pkg == NULL) {
1393 return NULL;
1394 }
1395
1396 for (iter = pkg->conffiles.head; iter; iter = iter->next) {
1397 conffile = iter->data;
1398
1399 if (strcmp(conffile->name, file_name) == 0) {
1400 return conffile;
1401 }
1402 }
1403
1404 return NULL;
1405 }
1406
1407 int pkg_run_script(opkg_conf_t *conf, pkg_t *pkg,
1408 const char *script, const char *args)
1409 {
1410 int err;
1411 char *path;
1412 char *cmd;
1413
1414 /* XXX: FEATURE: When conf->offline_root is set, we should run the
1415 maintainer script within a chroot environment. */
1416
1417 /* Installed packages have scripts in pkg->dest->info_dir, uninstalled packages
1418 have scripts in pkg->tmp_unpack_dir. */
1419 if (pkg->state_status == SS_INSTALLED || pkg->state_status == SS_UNPACKED) {
1420 if (pkg->dest == NULL) {
1421 fprintf(stderr, "%s: ERROR: installed package %s has a NULL dest\n",
1422 __FUNCTION__, pkg->name);
1423 return EINVAL;
1424 }
1425 sprintf_alloc(&path, "%s/%s.%s", pkg->dest->info_dir, pkg->name, script);
1426 } else {
1427 if (pkg->tmp_unpack_dir == NULL) {
1428 fprintf(stderr, "%s: ERROR: uninstalled package %s has a NULL tmp_unpack_dir\n",
1429 __FUNCTION__, pkg->name);
1430 return EINVAL;
1431 }
1432 sprintf_alloc(&path, "%s/%s", pkg->tmp_unpack_dir, script);
1433 }
1434
1435 opkg_message(conf, OPKG_INFO, "Running script %s\n", path);
1436 if (conf->noaction) return 0;
1437
1438 /* XXX: CLEANUP: There must be a better way to handle maintainer
1439 scripts when running with offline_root mode and/or a dest other
1440 than '/'. I've been playing around with some clever chroot
1441 tricks and I might come up with something workable. */
1442 if (conf->offline_root) {
1443 setenv("OPKG_OFFLINE_ROOT", conf->offline_root, 1);
1444 }
1445
1446 setenv("PKG_ROOT",
1447 pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir, 1);
1448
1449 if (! file_exists(path)) {
1450 free(path);
1451 return 0;
1452 }
1453
1454 if (conf->offline_root) {
1455 fprintf(stderr, "(offline root mode: not running %s.%s)\n", pkg->name, script);
1456 free(path);
1457 return 0;
1458 }
1459
1460 sprintf_alloc(&cmd, "%s %s", path, args);
1461 free(path);
1462
1463 err = xsystem(cmd);
1464 free(cmd);
1465
1466 if (err) {
1467 fprintf(stderr, "%s script returned status %d\n", script, err);
1468 return err;
1469 }
1470
1471 return 0;
1472 }
1473
1474 char *pkg_state_want_to_str(pkg_state_want_t sw)
1475 {
1476 int i;
1477
1478 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1479 if (pkg_state_want_map[i].value == sw) {
1480 return strdup(pkg_state_want_map[i].str);
1481 }
1482 }
1483
1484 fprintf(stderr, "%s: ERROR: Illegal value for state_want: %d\n",
1485 __FUNCTION__, sw);
1486 return strdup("<STATE_WANT_UNKNOWN>");
1487 }
1488
1489 pkg_state_want_t pkg_state_want_from_str(char *str)
1490 {
1491 int i;
1492
1493 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1494 if (strcmp(str, pkg_state_want_map[i].str) == 0) {
1495 return pkg_state_want_map[i].value;
1496 }
1497 }
1498
1499 fprintf(stderr, "%s: ERROR: Illegal value for state_want string: %s\n",
1500 __FUNCTION__, str);
1501 return SW_UNKNOWN;
1502 }
1503
1504 char *pkg_state_flag_to_str(pkg_state_flag_t sf)
1505 {
1506 int i;
1507 int len = 3; /* ok\000 is minimum */
1508 char *str = NULL;
1509
1510 /* clear the temporary flags before converting to string */
1511 sf &= SF_NONVOLATILE_FLAGS;
1512
1513 if (sf == 0) {
1514 return strdup("ok");
1515 } else {
1516
1517 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1518 if (sf & pkg_state_flag_map[i].value) {
1519 len += strlen(pkg_state_flag_map[i].str) + 1;
1520 }
1521 }
1522 str = malloc(len);
1523 if ( str == NULL ) {
1524 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
1525 return NULL;
1526 }
1527 str[0] = 0;
1528 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1529 if (sf & pkg_state_flag_map[i].value) {
1530 strcat(str, pkg_state_flag_map[i].str);
1531 strcat(str, ",");
1532 }
1533 }
1534 len = strlen(str);
1535 str[len-1] = 0; /* squash last comma */
1536 return str;
1537 }
1538 }
1539
1540 pkg_state_flag_t pkg_state_flag_from_str(const char *str)
1541 {
1542 int i;
1543 int sf = SF_OK;
1544
1545 if (strcmp(str, "ok") == 0) {
1546 return SF_OK;
1547 }
1548 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1549 const char *sfname = pkg_state_flag_map[i].str;
1550 int sfname_len = strlen(sfname);
1551 if (strncmp(str, sfname, sfname_len) == 0) {
1552 sf |= pkg_state_flag_map[i].value;
1553 str += sfname_len;
1554 if (str[0] == ',') {
1555 str++;
1556 } else {
1557 break;
1558 }
1559 }
1560 }
1561
1562 return sf;
1563 }
1564
1565 char *pkg_state_status_to_str(pkg_state_status_t ss)
1566 {
1567 int i;
1568
1569 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1570 if (pkg_state_status_map[i].value == ss) {
1571 return strdup(pkg_state_status_map[i].str);
1572 }
1573 }
1574
1575 fprintf(stderr, "%s: ERROR: Illegal value for state_status: %d\n",
1576 __FUNCTION__, ss);
1577 return strdup("<STATE_STATUS_UNKNOWN>");
1578 }
1579
1580 pkg_state_status_t pkg_state_status_from_str(const char *str)
1581 {
1582 int i;
1583
1584 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1585 if (strcmp(str, pkg_state_status_map[i].str) == 0) {
1586 return pkg_state_status_map[i].value;
1587 }
1588 }
1589
1590 fprintf(stderr, "%s: ERROR: Illegal value for state_status string: %s\n",
1591 __FUNCTION__, str);
1592 return SS_NOT_INSTALLED;
1593 }
1594
1595 int pkg_arch_supported(opkg_conf_t *conf, pkg_t *pkg)
1596 {
1597 nv_pair_list_elt_t *l;
1598
1599 if (!pkg->architecture)
1600 return 1;
1601
1602 l = conf->arch_list.head;
1603
1604 while (l) {
1605 nv_pair_t *nv = l->data;
1606 if (strcmp(nv->name, pkg->architecture) == 0) {
1607 opkg_message(conf, OPKG_DEBUG, "arch %s (priority %s) supported for pkg %s\n", nv->name, nv->value, pkg->name);
1608 return 1;
1609 }
1610 l = l->next;
1611 }
1612
1613 opkg_message(conf, OPKG_DEBUG, "arch %s unsupported for pkg %s\n", pkg->architecture, pkg->name);
1614 return 0;
1615 }
1616
1617 int pkg_get_arch_priority(opkg_conf_t *conf, const char *archname)
1618 {
1619 nv_pair_list_elt_t *l;
1620
1621 l = conf->arch_list.head;
1622
1623 while (l) {
1624 nv_pair_t *nv = l->data;
1625 if (strcmp(nv->name, archname) == 0) {
1626 int priority = strtol(nv->value, NULL, 0);
1627 return priority;
1628 }
1629 l = l->next;
1630 }
1631 return 0;
1632 }
1633
1634 int pkg_info_preinstall_check(opkg_conf_t *conf)
1635 {
1636 int i;
1637 hash_table_t *pkg_hash = &conf->pkg_hash;
1638 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1639 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1640
1641 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: updating arch priority for each package\n");
1642 pkg_hash_fetch_available(pkg_hash, available_pkgs);
1643 /* update arch_priority for each package */
1644 for (i = 0; i < available_pkgs->len; i++) {
1645 pkg_t *pkg = available_pkgs->pkgs[i];
1646 int arch_priority = 1;
1647 if (!pkg)
1648 continue;
1649 // opkg_message(conf, OPKG_DEBUG2, " package %s version=%s arch=%p:", pkg->name, pkg->version, pkg->architecture);
1650 if (pkg->architecture)
1651 arch_priority = pkg_get_arch_priority(conf, pkg->architecture);
1652 else
1653 opkg_message(conf, OPKG_ERROR, "pkg_info_preinstall_check: no architecture for package %s\n", pkg->name);
1654 // opkg_message(conf, OPKG_DEBUG2, "%s arch_priority=%d\n", pkg->architecture, arch_priority);
1655 pkg->arch_priority = arch_priority;
1656 }
1657
1658 for (i = 0; i < available_pkgs->len; i++) {
1659 pkg_t *pkg = available_pkgs->pkgs[i];
1660 if (!pkg->arch_priority && (pkg->state_flag || (pkg->state_want != SW_UNKNOWN))) {
1661 /* clear flags and want for any uninstallable package */
1662 opkg_message(conf, OPKG_NOTICE, "Clearing state_want and state_flag for pkg=%s (arch_priority=%d flag=%d want=%d)\n",
1663 pkg->name, pkg->arch_priority, pkg->state_flag, pkg->state_want);
1664 pkg->state_want = SW_UNKNOWN;
1665 pkg->state_flag = 0;
1666 }
1667 }
1668 pkg_vec_free(available_pkgs);
1669
1670 /* update the file owner data structure */
1671 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: update file owner list\n");
1672 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1673 for (i = 0; i < installed_pkgs->len; i++) {
1674 pkg_t *pkg = installed_pkgs->pkgs[i];
1675 str_list_t *installed_files = pkg_get_installed_files(pkg); /* this causes installed_files to be cached */
1676 str_list_elt_t *iter;
1677 if (installed_files == NULL) {
1678 opkg_message(conf, OPKG_ERROR, "No installed files for pkg %s\n", pkg->name);
1679 break;
1680 }
1681 for (iter = installed_files->head; iter; iter = iter->next) {
1682 char *installed_file = iter->data;
1683 // opkg_message(conf, OPKG_DEBUG2, "pkg %s: file=%s\n", pkg->name, installed_file);
1684 file_hash_set_file_owner(conf, installed_file, pkg);
1685 }
1686 }
1687 pkg_vec_free(installed_pkgs);
1688
1689 return 0;
1690 }
1691
1692 struct pkg_write_filelist_data {
1693 opkg_conf_t *conf;
1694 pkg_t *pkg;
1695 FILE *stream;
1696 };
1697
1698 void pkg_write_filelist_helper(const char *key, void *entry_, void *data_)
1699 {
1700 struct pkg_write_filelist_data *data = data_;
1701 pkg_t *entry = entry_;
1702 if (entry == data->pkg) {
1703 fprintf(data->stream, "%s\n", key);
1704 }
1705 }
1706
1707 int pkg_write_filelist(opkg_conf_t *conf, pkg_t *pkg)
1708 {
1709 struct pkg_write_filelist_data data;
1710 char *list_file_name = NULL;
1711 int err = 0;
1712
1713 if (!pkg) {
1714 opkg_message(conf, OPKG_ERROR, "Null pkg\n");
1715 return -EINVAL;
1716 }
1717 opkg_message(conf, OPKG_INFO,
1718 " creating %s.list file\n", pkg->name);
1719 sprintf_alloc(&list_file_name, "%s/%s.list", pkg->dest->info_dir, pkg->name);
1720 if (!list_file_name) {
1721 opkg_message(conf, OPKG_ERROR, "Failed to alloc list_file_name\n");
1722 return -ENOMEM;
1723 }
1724 opkg_message(conf, OPKG_INFO,
1725 " creating %s file for pkg %s\n", list_file_name, pkg->name);
1726 data.stream = fopen(list_file_name, "w");
1727 if (!data.stream) {
1728 opkg_message(conf, OPKG_ERROR, "Could not open %s for writing: %s\n",
1729 list_file_name, strerror(errno));
1730 return errno;
1731 }
1732 data.pkg = pkg;
1733 data.conf = conf;
1734 hash_table_foreach(&conf->file_hash, pkg_write_filelist_helper, &data);
1735 fclose(data.stream);
1736 free(list_file_name);
1737
1738 return err;
1739 }
1740
1741 int pkg_write_changed_filelists(opkg_conf_t *conf)
1742 {
1743 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1744 hash_table_t *pkg_hash = &conf->pkg_hash;
1745 int i;
1746 int err;
1747 if (conf->noaction)
1748 return 0;
1749
1750 opkg_message(conf, OPKG_INFO, "%s: saving changed filelists\n", __FUNCTION__);
1751 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1752 for (i = 0; i < installed_pkgs->len; i++) {
1753 pkg_t *pkg = installed_pkgs->pkgs[i];
1754 if (pkg->state_flag & SF_FILELIST_CHANGED) {
1755 opkg_message(conf, OPKG_DEBUG, "Calling pkg_write_filelist for pkg=%s from %s\n", pkg->name, __FUNCTION__);
1756 err = pkg_write_filelist(conf, pkg);
1757 if (err)
1758 opkg_message(conf, OPKG_NOTICE, "pkg_write_filelist pkg=%s returned %d\n", pkg->name, err);
1759 }
1760 }
1761 return 0;
1762 }