* Add ipkg for future development
[project/opkg-lede.git] / 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 "ipkg.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 "ipkg_message.h"
28 #include "ipkg_utils.h"
29
30 #include "sprintf_alloc.h"
31 #include "file_util.h"
32 #include "str_util.h"
33 #include "xsystem.h"
34 #include "ipkg_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 ipkg_conf_t */
157 pkg->dest = NULL;
158 /* owned by ipkg_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 ipkg_install.c here. See comment in
189 ipkg_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(ipkg_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 ipkg_message(conf, IPKG_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 ipkg_message(conf, IPKG_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 ipkg_message(conf, IPKG_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 {
562 goto UNKNOWN_FMT_FIELD;
563 }
564 break;
565 case 'c':
566 case 'C':
567 if (strcasecmp(field, "Conffiles") == 0) {
568 /* Conffiles */
569 conffile_list_elt_t *iter;
570 char confstr[LINE_LEN];
571
572 if (pkg->conffiles.head == NULL) {
573 return temp;
574 }
575
576 len = 14 ;
577 for (iter = pkg->conffiles.head; iter; iter = iter->next) {
578 if (iter->data->name && iter->data->value) {
579 len = len + (strlen(iter->data->name)+strlen(iter->data->value)+5);
580 }
581 }
582 temp = (char *)realloc(temp,len);
583 if ( temp == NULL ){
584 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
585 return NULL;
586 }
587 temp[0]='\0';
588 strncpy(temp, "Conffiles:\n", 12);
589 for (iter = pkg->conffiles.head; iter; iter = iter->next) {
590 if (iter->data->name && iter->data->value) {
591 snprintf(confstr, LINE_LEN, "%s %s\n", iter->data->name, iter->data->value);
592 strncat(temp, confstr, strlen(confstr));
593 }
594 }
595 } else if (strcasecmp(field, "Conflicts") == 0) {
596 int i;
597
598 if (pkg->conflicts_count) {
599 char conflictstr[LINE_LEN];
600 len = 14 ;
601 for(i = 0; i < pkg->conflicts_count; i++) {
602 len = len + (strlen(pkg->conflicts_str[i])+5);
603 }
604 temp = (char *)realloc(temp,len);
605 if ( temp == NULL ){
606 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
607 return NULL;
608 }
609 temp[0]='\0';
610 strncpy(temp, "Conflicts:", 11);
611 for(i = 0; i < pkg->conflicts_count; i++) {
612 snprintf(conflictstr, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->conflicts_str[i]);
613 strncat(temp, conflictstr, strlen(conflictstr));
614 }
615 strncat(temp, "\n", strlen("\n"));
616 }
617 } else {
618 goto UNKNOWN_FMT_FIELD;
619 }
620 break;
621 case 'd':
622 case 'D':
623 if (strcasecmp(field, "Depends") == 0) {
624 /* Depends */
625 int i;
626
627 if (pkg->depends_count) {
628 char depstr[LINE_LEN];
629 len = 14 ;
630 for(i = 0; i < pkg->depends_count; i++) {
631 len = len + (strlen(pkg->depends_str[i])+4);
632 }
633 temp = (char *)realloc(temp,len);
634 if ( temp == NULL ){
635 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
636 return NULL;
637 }
638 temp[0]='\0';
639 strncpy(temp, "Depends:", 10);
640 for(i = 0; i < pkg->depends_count; i++) {
641 snprintf(depstr, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->depends_str[i]);
642 strncat(temp, depstr, strlen(depstr));
643 }
644 strncat(temp, "\n", strlen("\n"));
645 }
646 } else if (strcasecmp(field, "Description") == 0) {
647 /* Description */
648 if (pkg->description) {
649 temp = (char *)realloc(temp,strlen(pkg->description)+16);
650 if ( temp == NULL ){
651 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
652 return NULL;
653 }
654 temp[0]='\0';
655 snprintf(temp, (strlen(pkg->description)+16), "Description: %s\n", pkg->description);
656 }
657 } else {
658 goto UNKNOWN_FMT_FIELD;
659 }
660 break;
661 case 'e':
662 case 'E': {
663 /* Essential */
664 if (pkg->essential) {
665 temp = (char *)realloc(temp,16);
666 if ( temp == NULL ){
667 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
668 return NULL;
669 }
670 temp[0]='\0';
671 snprintf(temp, (16), "Essential: yes\n");
672 }
673 }
674 break;
675 case 'f':
676 case 'F': {
677 /* Filename */
678 if (pkg->filename) {
679 temp = (char *)realloc(temp,strlen(pkg->filename)+12);
680 if ( temp == NULL ){
681 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
682 return NULL;
683 }
684 temp[0]='\0';
685 snprintf(temp, (strlen(pkg->filename)+12), "Filename: %s\n", pkg->filename);
686 }
687 }
688 break;
689 case 'i':
690 case 'I': {
691 if (strcasecmp(field, "Installed-Size") == 0) {
692 /* Installed-Size */
693 temp = (char *)realloc(temp,strlen(pkg->installed_size)+17);
694 if ( temp == NULL ){
695 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
696 return NULL;
697 }
698 temp[0]='\0';
699 snprintf(temp, (strlen(pkg->installed_size)+17), "Installed-Size: %s\n", pkg->installed_size);
700 } else if (strcasecmp(field, "Installed-Time") == 0 && pkg->installed_time) {
701 temp = (char *)realloc(temp,29);
702 if ( temp == NULL ){
703 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
704 return NULL;
705 }
706 temp[0]='\0';
707 snprintf(temp, 29, "Installed-Time: %lu\n", pkg->installed_time);
708 }
709 }
710 break;
711 case 'm':
712 case 'M': {
713 /* Maintainer | MD5sum */
714 if (strcasecmp(field, "Maintainer") == 0) {
715 /* Maintainer */
716 if (pkg->maintainer) {
717 temp = (char *)realloc(temp,strlen(pkg->maintainer)+14);
718 if ( temp == NULL ){
719 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
720 return NULL;
721 }
722 temp[0]='\0';
723 snprintf(temp, (strlen(pkg->maintainer)+14), "maintainer: %s\n", pkg->maintainer);
724 }
725 } else if (strcasecmp(field, "MD5sum") == 0) {
726 /* MD5sum */
727 if (pkg->md5sum) {
728 temp = (char *)realloc(temp,strlen(pkg->md5sum)+11);
729 if ( temp == NULL ){
730 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
731 return NULL;
732 }
733 temp[0]='\0';
734 snprintf(temp, (strlen(pkg->md5sum)+11), "MD5Sum: %s\n", pkg->md5sum);
735 }
736 } else {
737 goto UNKNOWN_FMT_FIELD;
738 }
739 }
740 break;
741 case 'p':
742 case 'P': {
743 if (strcasecmp(field, "Package") == 0) {
744 /* Package */
745 temp = (char *)realloc(temp,strlen(pkg->name)+11);
746 if ( temp == NULL ){
747 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
748 return NULL;
749 }
750 temp[0]='\0';
751 snprintf(temp, (strlen(pkg->name)+11), "Package: %s\n", pkg->name);
752 } else if (strcasecmp(field, "Priority") == 0) {
753 /* Priority */
754 temp = (char *)realloc(temp,strlen(pkg->priority)+12);
755 if ( temp == NULL ){
756 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
757 return NULL;
758 }
759 temp[0]='\0';
760 snprintf(temp, (strlen(pkg->priority)+12), "Priority: %s\n", pkg->priority);
761 } else if (strcasecmp(field, "Provides") == 0) {
762 /* Provides */
763 int i;
764
765 if (pkg->provides_count) {
766 /* Here we check if the ipkg_internal_use_only is used, and we discard it.*/
767 for ( i=0; i < pkg->provides_count; i++ ){
768 if (strstr(pkg->provides_str[i],"ipkg_internal_use_only")!=NULL) {
769 memset (pkg->provides_str[i],'\x0',strlen(pkg->provides_str[i])); /* Pigi clear my trick flag, just in case */
770 flag_provide_false = 1;
771 }
772 }
773 if ( !flag_provide_false || /* Pigi there is not my trick flag */
774 ((flag_provide_false) && (pkg->provides_count > 1))){ /* Pigi There is, but we also have others Provides */
775 char provstr[LINE_LEN];
776 len = 15;
777 for(i = 0; i < pkg->provides_count; i++) {
778 len = len + (strlen(pkg->provides_str[i])+5);
779 }
780 temp = (char *)realloc(temp,len);
781 if ( temp == NULL ){
782 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
783 return NULL;
784 }
785 temp[0]='\0';
786 strncpy(temp, "Provides:", 12);
787 for(i = 0; i < pkg->provides_count; i++) {
788 if (strlen(pkg->provides_str[i])>0){;
789 snprintf(provstr, LINE_LEN, "%s %s", i == 1 ? "" : ",", pkg->provides_str[i]);
790 strncat(temp, provstr, strlen(provstr));
791 }
792 }
793 strncat(temp, "\n", strlen("\n"));
794 }
795 }
796 } else {
797 goto UNKNOWN_FMT_FIELD;
798 }
799 }
800 break;
801 case 'r':
802 case 'R': {
803 int i;
804 /* Replaces | Recommends*/
805 if (strcasecmp (field, "Replaces") == 0) {
806 if (pkg->replaces_count) {
807 char replstr[LINE_LEN];
808 len = 14;
809 for (i = 0; i < pkg->replaces_count; i++) {
810 len = len + (strlen(pkg->replaces_str[i])+5);
811 }
812 temp = (char *)realloc(temp,len);
813 if ( temp == NULL ){
814 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
815 return NULL;
816 }
817 temp[0]='\0';
818 strncpy(temp, "Replaces:", 12);
819 for (i = 0; i < pkg->replaces_count; i++) {
820 snprintf(replstr, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->replaces_str[i]);
821 strncat(temp, replstr, strlen(replstr));
822 }
823 strncat(temp, "\n", strlen("\n"));
824 }
825 } else if (strcasecmp (field, "Recommends") == 0) {
826 if (pkg->recommends_count) {
827 char recstr[LINE_LEN];
828 len = 15;
829 for(i = 0; i < pkg->recommends_count; i++) {
830 len = len + (strlen( pkg->recommends_str[i])+5);
831 }
832 temp = (char *)realloc(temp,len);
833 if ( temp == NULL ){
834 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
835 return NULL;
836 }
837 temp[0]='\0';
838 strncpy(temp, "Recommends:", 13);
839 for(i = 0; i < pkg->recommends_count; i++) {
840 snprintf(recstr, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->recommends_str[i]);
841 strncat(temp, recstr, strlen(recstr));
842 }
843 strncat(temp, "\n", strlen("\n"));
844 }
845 } else {
846 goto UNKNOWN_FMT_FIELD;
847 }
848 }
849 break;
850 case 's':
851 case 'S': {
852 /* Section | Size | Source | Status | Suggests */
853 if (strcasecmp(field, "Section") == 0) {
854 /* Section */
855 if (pkg->section) {
856 temp = (char *)realloc(temp,strlen(pkg->section)+11);
857 if ( temp == NULL ){
858 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
859 return NULL;
860 }
861 temp[0]='\0';
862 snprintf(temp, (strlen(pkg->section)+11), "Section: %s\n", pkg->section);
863 }
864 } else if (strcasecmp(field, "Size") == 0) {
865 /* Size */
866 if (pkg->size) {
867 temp = (char *)realloc(temp,strlen(pkg->size)+8);
868 if ( temp == NULL ){
869 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
870 return NULL;
871 }
872 temp[0]='\0';
873 snprintf(temp, (strlen(pkg->size)+8), "Size: %s\n", pkg->size);
874 }
875 } else if (strcasecmp(field, "Source") == 0) {
876 /* Source */
877 if (pkg->source) {
878 temp = (char *)realloc(temp,strlen(pkg->source)+10);
879 if ( temp == NULL ){
880 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
881 return NULL;
882 }
883 temp[0]='\0';
884 snprintf(temp, (strlen(pkg->source)+10), "Source: %s\n", pkg->source);
885 }
886 } else if (strcasecmp(field, "Status") == 0) {
887 /* Status */
888 /* Benjamin Pineau note: we should avoid direct usage of
889 * strlen(arg) without keeping "arg" for later free()
890 */
891 char *pflag=pkg_state_flag_to_str(pkg->state_flag);
892 char *pstat=pkg_state_status_to_str(pkg->state_status);
893 char *pwant=pkg_state_want_to_str(pkg->state_want);
894
895 size_t sum_of_sizes = (size_t) ( strlen(pwant)+ strlen(pflag)+ strlen(pstat) + 12 );
896 temp = (char *)realloc(temp,sum_of_sizes);
897 if ( temp == NULL ){
898 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
899 return NULL;
900 }
901 temp[0]='\0';
902 snprintf(temp, sum_of_sizes , "Status: %s %s %s\n", pwant, pflag, pstat);
903 free(pflag);
904 free(pwant);
905 if(pstat) /* pfstat can be NULL if ENOMEM */
906 free(pstat);
907 } else if (strcasecmp(field, "Suggests") == 0) {
908 if (pkg->suggests_count) {
909 int i;
910 char sugstr[LINE_LEN];
911 len = 13;
912 for(i = 0; i < pkg->suggests_count; i++) {
913 len = len + (strlen(pkg->suggests_str[i])+5);
914 }
915 temp = (char *)realloc(temp,len);
916 if ( temp == NULL ){
917 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
918 return NULL;
919 }
920 temp[0]='\0';
921 strncpy(temp, "Suggests:", 10);
922 for(i = 0; i < pkg->suggests_count; i++) {
923 snprintf(sugstr, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->suggests_str[i]);
924 strncat(temp, sugstr, strlen(sugstr));
925 }
926 strncat(temp, "\n", strlen("\n"));
927 }
928 } else {
929 goto UNKNOWN_FMT_FIELD;
930 }
931 }
932 break;
933 case 'v':
934 case 'V': {
935 /* Version */
936 char *version = pkg_version_str_alloc(pkg);
937 temp = (char *)realloc(temp,strlen(version)+14);
938 if ( temp == NULL ){
939 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
940 return NULL;
941 }
942 temp[0]='\0';
943 snprintf(temp, (strlen(version)+12), "Version: %s\n", version);
944 free(version);
945 }
946 break;
947 default:
948 goto UNKNOWN_FMT_FIELD;
949 }
950
951 if ( strlen(temp)<2 ) {
952 temp[0]='\0';
953 }
954 return temp;
955
956 UNKNOWN_FMT_FIELD:
957 fprintf(stderr, "%s: ERROR: Unknown field name: %s\n", __FUNCTION__, field);
958 if ( strlen(temp)<2 ) {
959 temp[0]='\0';
960 }
961
962 return temp;
963 }
964
965 void pkg_print_info(pkg_t *pkg, FILE *file)
966 {
967 char * buff;
968 if (pkg == NULL) {
969 return;
970 }
971
972 buff = pkg_formatted_info(pkg);
973 if ( buff == NULL )
974 return;
975 if (strlen(buff)>2){
976 fwrite(buff, 1, strlen(buff), file);
977 }
978 free(buff);
979 }
980
981 void pkg_print_status(pkg_t * pkg, FILE * file)
982 {
983 if (pkg == NULL) {
984 return;
985 }
986
987 /* XXX: QUESTION: Do we actually want more fields here? The
988 original idea was to save space by installing only what was
989 needed for actual computation, (package, version, status,
990 essential, conffiles). The assumption is that all other fields
991 can be found in th available file.
992
993 But, someone proposed the idea to make it possible to
994 reconstruct a .ipk from an installed package, (ie. for beaming
995 from one handheld to another). So, maybe we actually want a few
996 more fields here, (depends, suggests, etc.), so that that would
997 be guaranteed to work even in the absence of more information
998 from the available file.
999
1000 28-MAR-03: kergoth and I discussed this yesterday. We think
1001 the essential info needs to be here for all installed packages
1002 because they may not appear in the Packages files on various
1003 feeds. Furthermore, one should be able to install from URL or
1004 local storage without requiring a Packages file from any feed.
1005 -Jamey
1006 */
1007 pkg_print_field(pkg, file, "Package");
1008 pkg_print_field(pkg, file, "Version");
1009 pkg_print_field(pkg, file, "Depends");
1010 pkg_print_field(pkg, file, "Recommends");
1011 pkg_print_field(pkg, file, "Suggests");
1012 pkg_print_field(pkg, file, "Provides");
1013 pkg_print_field(pkg, file, "Replaces");
1014 pkg_print_field(pkg, file, "Conflicts");
1015 pkg_print_field(pkg, file, "Status");
1016 pkg_print_field(pkg, file, "Essential"); /* @@@@ should be removed in future release. */
1017 pkg_print_field(pkg, file, "Architecture");
1018 pkg_print_field(pkg, file, "Conffiles");
1019 pkg_print_field(pkg, file, "Installed-Time");
1020 fputs("\n", file);
1021 }
1022
1023 void pkg_print_field(pkg_t *pkg, FILE *file, const char *field)
1024 {
1025 char *buff;
1026 if (strlen(field) < PKG_MINIMUM_FIELD_NAME_LEN) {
1027 fprintf(stderr, "%s: ERROR: Unknown field name: %s\n",
1028 __FUNCTION__, field);
1029 }
1030 buff = pkg_formatted_field(pkg, field);
1031 if (strlen(buff)>2) {
1032 fprintf(file, "%s", buff);
1033 fflush(file);
1034 }
1035 free(buff);
1036 return;
1037 }
1038
1039 /*
1040 * libdpkg - Debian packaging suite library routines
1041 * vercmp.c - comparison of version numbers
1042 *
1043 * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
1044 */
1045 int pkg_compare_versions(const pkg_t *pkg, const pkg_t *ref_pkg)
1046 {
1047 int r;
1048
1049 if (pkg->epoch > ref_pkg->epoch) {
1050 return 1;
1051 }
1052
1053 if (pkg->epoch < ref_pkg->epoch) {
1054 return -1;
1055 }
1056
1057 r = verrevcmp(pkg->version, ref_pkg->version);
1058 if (r) {
1059 return r;
1060 }
1061
1062 #ifdef USE_DEBVERSION
1063 r = verrevcmp(pkg->revision, ref_pkg->revision);
1064 if (r) {
1065 return r;
1066 }
1067
1068 r = verrevcmp(pkg->familiar_revision, ref_pkg->familiar_revision);
1069 #endif
1070
1071 return r;
1072 }
1073
1074 int verrevcmp(const char *val, const char *ref)
1075 {
1076 int vc, rc;
1077 long vl, rl;
1078 const char *vp, *rp;
1079 const char *vsep, *rsep;
1080
1081 if (!val) val= "";
1082 if (!ref) ref= "";
1083 for (;;) {
1084 vp= val; while (*vp && !isdigit(*vp)) vp++;
1085 rp= ref; while (*rp && !isdigit(*rp)) rp++;
1086 for (;;) {
1087 vc= (val == vp) ? 0 : *val++;
1088 rc= (ref == rp) ? 0 : *ref++;
1089 if (!rc && !vc) break;
1090 if (vc && !isalpha(vc)) vc += 256; /* assumes ASCII character set */
1091 if (rc && !isalpha(rc)) rc += 256;
1092 if (vc != rc) return vc - rc;
1093 }
1094 val= vp;
1095 ref= rp;
1096 vl=0; if (isdigit(*vp)) vl= strtol(val,(char**)&val,10);
1097 rl=0; if (isdigit(*rp)) rl= strtol(ref,(char**)&ref,10);
1098 if (vl != rl) return vl - rl;
1099
1100 vc = *val;
1101 rc = *ref;
1102 vsep = strchr(".-", vc);
1103 rsep = strchr(".-", rc);
1104 if (vsep && !rsep) return -1;
1105 if (!vsep && rsep) return +1;
1106
1107 if (!*val && !*ref) return 0;
1108 if (!*val) return -1;
1109 if (!*ref) return +1;
1110 }
1111 }
1112
1113 int pkg_version_satisfied(pkg_t *it, pkg_t *ref, const char *op)
1114 {
1115 int r;
1116
1117 r = pkg_compare_versions(it, ref);
1118
1119 if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0) {
1120 return r <= 0;
1121 }
1122
1123 if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0) {
1124 return r >= 0;
1125 }
1126
1127 if (strcmp(op, "<<") == 0) {
1128 return r < 0;
1129 }
1130
1131 if (strcmp(op, ">>") == 0) {
1132 return r > 0;
1133 }
1134
1135 if (strcmp(op, "=") == 0) {
1136 return r == 0;
1137 }
1138
1139 fprintf(stderr, "unknown operator: %s", op);
1140 return 0;
1141 }
1142
1143 int pkg_name_version_and_architecture_compare(void *p1, void *p2)
1144 {
1145 const pkg_t *a = *(const pkg_t **)p1;
1146 const pkg_t *b = *(const pkg_t **)p2;
1147 int namecmp;
1148 int vercmp;
1149 if (!a->name || !b->name) {
1150 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->name=%p b=%p b->name=%p\n",
1151 a, a->name, b, b->name);
1152 return 0;
1153 }
1154
1155 namecmp = strcmp(a->name, b->name);
1156 if (namecmp)
1157 return namecmp;
1158 vercmp = pkg_compare_versions(a, b);
1159 if (vercmp)
1160 return vercmp;
1161 if (!a->arch_priority || !b->arch_priority) {
1162 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->arch_priority=%i b=%p b->arch_priority=%i\n",
1163 a, a->arch_priority, b, b->arch_priority);
1164 return 0;
1165 }
1166 if (a->arch_priority > b->arch_priority)
1167 return 1;
1168 if (a->arch_priority < b->arch_priority)
1169 return -1;
1170 return 0;
1171 }
1172
1173 int abstract_pkg_name_compare(void *p1, void *p2)
1174 {
1175 const abstract_pkg_t *a = *(const abstract_pkg_t **)p1;
1176 const abstract_pkg_t *b = *(const abstract_pkg_t **)p2;
1177 if (!a->name || !b->name) {
1178 fprintf(stderr, "abstract_pkg_name_compare: a=%p a->name=%p b=%p b->name=%p\n",
1179 a, a->name, b, b->name);
1180 return 0;
1181 }
1182 return strcmp(a->name, b->name);
1183 }
1184
1185
1186 char *pkg_version_str_alloc(pkg_t *pkg)
1187 {
1188 char *complete_version;
1189 char *epoch_str;
1190 #ifdef USE_DEBVERSION
1191 char *revision_str;
1192 char *familiar_revision_str;
1193 #endif
1194
1195 if (pkg->epoch) {
1196 sprintf_alloc(&epoch_str, "%d:", pkg->epoch);
1197 } else {
1198 epoch_str = strdup("");
1199 }
1200
1201 #ifdef USE_DEBVERSION
1202 if (pkg->revision && strlen(pkg->revision)) {
1203 sprintf_alloc(&revision_str, "-%s", pkg->revision);
1204 } else {
1205 revision_str = strdup("");
1206 }
1207
1208 if (pkg->familiar_revision && strlen(pkg->familiar_revision)) {
1209 sprintf_alloc(&familiar_revision_str, "-fam%s", pkg->familiar_revision);
1210 } else {
1211 familiar_revision_str = strdup("");
1212 }
1213 #endif
1214
1215 #ifdef USE_DEBVERSION
1216 sprintf_alloc(&complete_version, "%s%s%s%s",
1217 epoch_str, pkg->version, revision_str, familiar_revision_str);
1218 #else
1219 sprintf_alloc(&complete_version, "%s%s",
1220 epoch_str, pkg->version);
1221 #endif
1222
1223 free(epoch_str);
1224 #ifdef USE_DEBVERSION
1225 free(revision_str);
1226 free(familiar_revision_str);
1227 #endif
1228
1229 return complete_version;
1230 }
1231
1232 str_list_t *pkg_get_installed_files(pkg_t *pkg)
1233 {
1234 int err;
1235 char *list_file_name = NULL;
1236 FILE *list_file = NULL;
1237 char *line;
1238 char *installed_file_name;
1239 int rootdirlen;
1240
1241 pkg->installed_files_ref_cnt++;
1242
1243 if (pkg->installed_files) {
1244 return pkg->installed_files;
1245 }
1246
1247 pkg->installed_files = str_list_alloc();
1248 if (pkg->installed_files == NULL) {
1249 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
1250 return NULL;
1251 }
1252
1253 /* For uninstalled packages, get the file list firectly from the package.
1254 For installed packages, look at the package.list file in the database.
1255 */
1256 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1257 if (pkg->local_filename == NULL) {
1258 return pkg->installed_files;
1259 }
1260 /* XXX: CLEANUP: Maybe rewrite this to avoid using a temporary
1261 file. In other words, change deb_extract so that it can
1262 simply return the file list as a char *[] rather than
1263 insisting on writing in to a FILE * as it does now. */
1264 list_file = tmpfile();
1265 err = pkg_extract_data_file_names_to_stream(pkg, list_file);
1266 if (err) {
1267 fclose(list_file);
1268 fprintf(stderr, "%s: Error extracting file list from %s: %s\n",
1269 __FUNCTION__, pkg->local_filename, strerror(err));
1270 return pkg->installed_files;
1271 }
1272 rewind(list_file);
1273 } else {
1274 sprintf_alloc(&list_file_name, "%s/%s.list",
1275 pkg->dest->info_dir, pkg->name);
1276 if (! file_exists(list_file_name)) {
1277 free(list_file_name);
1278 return pkg->installed_files;
1279 }
1280
1281 list_file = fopen(list_file_name, "r");
1282 if (list_file == NULL) {
1283 fprintf(stderr, "WARNING: Cannot open %s: %s\n",
1284 list_file_name, strerror(errno));
1285 free(list_file_name);
1286 return pkg->installed_files;
1287 }
1288 free(list_file_name);
1289 }
1290
1291 rootdirlen = strlen( pkg->dest->root_dir );
1292 while (1) {
1293 char *file_name;
1294
1295 line = file_read_line_alloc(list_file);
1296 if (line == NULL) {
1297 break;
1298 }
1299 str_chomp(line);
1300 file_name = line;
1301
1302 /* Take pains to avoid uglies like "/./" in the middle of file_name. */
1303 if( strncmp( pkg->dest->root_dir,
1304 file_name,
1305 rootdirlen ) ) {
1306 if (*file_name == '.') {
1307 file_name++;
1308 }
1309 if (*file_name == '/') {
1310 file_name++;
1311 }
1312
1313 /* Freed in pkg_free_installed_files */
1314 sprintf_alloc(&installed_file_name, "%s%s", pkg->dest->root_dir, file_name);
1315 } else {
1316 // already contains root_dir as header -> ABSOLUTE
1317 sprintf_alloc(&installed_file_name, "%s", file_name);
1318 }
1319 str_list_append(pkg->installed_files, installed_file_name);
1320 free(line);
1321 }
1322
1323 fclose(list_file);
1324
1325 return pkg->installed_files;
1326 }
1327
1328 /* XXX: CLEANUP: This function and it's counterpart,
1329 (pkg_get_installed_files), do not match our init/deinit naming
1330 convention. Nor the alloc/free convention. But, then again, neither
1331 of these conventions currrently fit the way these two functions
1332 work. */
1333 int pkg_free_installed_files(pkg_t *pkg)
1334 {
1335 str_list_elt_t *iter;
1336
1337 pkg->installed_files_ref_cnt--;
1338 if (pkg->installed_files_ref_cnt > 0) {
1339 return 0;
1340 }
1341
1342 if (pkg->installed_files) {
1343
1344 for (iter = pkg->installed_files->head; iter; iter = iter->next) {
1345 /* malloced in pkg_get_installed_files */
1346 free (iter->data);
1347 iter->data = NULL;
1348 }
1349
1350 str_list_deinit(pkg->installed_files);
1351 }
1352
1353 pkg->installed_files = NULL;
1354
1355 return 0;
1356 }
1357
1358 int pkg_remove_installed_files_list(ipkg_conf_t *conf, pkg_t *pkg)
1359 {
1360 int err;
1361 char *list_file_name;
1362
1363 //I don't think pkg_free_installed_files should be called here. Jamey
1364 //pkg_free_installed_files(pkg);
1365
1366 sprintf_alloc(&list_file_name, "%s/%s.list",
1367 pkg->dest->info_dir, pkg->name);
1368 if (!conf->noaction) {
1369 err = unlink(list_file_name);
1370 free(list_file_name);
1371
1372 if (err) {
1373 return errno;
1374 }
1375 }
1376 return 0;
1377 }
1378
1379 conffile_t *pkg_get_conffile(pkg_t *pkg, const char *file_name)
1380 {
1381 conffile_list_elt_t *iter;
1382 conffile_t *conffile;
1383
1384 if (pkg == NULL) {
1385 return NULL;
1386 }
1387
1388 for (iter = pkg->conffiles.head; iter; iter = iter->next) {
1389 conffile = iter->data;
1390
1391 if (strcmp(conffile->name, file_name) == 0) {
1392 return conffile;
1393 }
1394 }
1395
1396 return NULL;
1397 }
1398
1399 int pkg_run_script(ipkg_conf_t *conf, pkg_t *pkg,
1400 const char *script, const char *args)
1401 {
1402 int err;
1403 char *path;
1404 char *cmd;
1405
1406 /* XXX: FEATURE: When conf->offline_root is set, we should run the
1407 maintainer script within a chroot environment. */
1408
1409 /* Installed packages have scripts in pkg->dest->info_dir, uninstalled packages
1410 have scripts in pkg->tmp_unpack_dir. */
1411 if (pkg->state_status == SS_INSTALLED || pkg->state_status == SS_UNPACKED) {
1412 if (pkg->dest == NULL) {
1413 fprintf(stderr, "%s: ERROR: installed package %s has a NULL dest\n",
1414 __FUNCTION__, pkg->name);
1415 return EINVAL;
1416 }
1417 sprintf_alloc(&path, "%s/%s.%s", pkg->dest->info_dir, pkg->name, script);
1418 } else {
1419 if (pkg->tmp_unpack_dir == NULL) {
1420 fprintf(stderr, "%s: ERROR: uninstalled package %s has a NULL tmp_unpack_dir\n",
1421 __FUNCTION__, pkg->name);
1422 return EINVAL;
1423 }
1424 sprintf_alloc(&path, "%s/%s", pkg->tmp_unpack_dir, script);
1425 }
1426
1427 ipkg_message(conf, IPKG_INFO, "Running script %s\n", path);
1428 if (conf->noaction) return 0;
1429
1430 /* XXX: CLEANUP: There must be a better way to handle maintainer
1431 scripts when running with offline_root mode and/or a dest other
1432 than '/'. I've been playing around with some clever chroot
1433 tricks and I might come up with something workable. */
1434 if (conf->offline_root) {
1435 setenv("IPKG_OFFLINE_ROOT", conf->offline_root, 1);
1436 }
1437
1438 setenv("PKG_ROOT",
1439 pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir, 1);
1440
1441 if (! file_exists(path)) {
1442 free(path);
1443 return 0;
1444 }
1445
1446 if (conf->offline_root) {
1447 fprintf(stderr, "(offline root mode: not running %s.%s)\n", pkg->name, script);
1448 free(path);
1449 return 0;
1450 }
1451
1452 sprintf_alloc(&cmd, "%s %s", path, args);
1453 free(path);
1454
1455 err = xsystem(cmd);
1456 free(cmd);
1457
1458 if (err) {
1459 fprintf(stderr, "%s script returned status %d\n", script, err);
1460 return err;
1461 }
1462
1463 return 0;
1464 }
1465
1466 char *pkg_state_want_to_str(pkg_state_want_t sw)
1467 {
1468 int i;
1469
1470 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1471 if (pkg_state_want_map[i].value == sw) {
1472 return strdup(pkg_state_want_map[i].str);
1473 }
1474 }
1475
1476 fprintf(stderr, "%s: ERROR: Illegal value for state_want: %d\n",
1477 __FUNCTION__, sw);
1478 return strdup("<STATE_WANT_UNKNOWN>");
1479 }
1480
1481 pkg_state_want_t pkg_state_want_from_str(char *str)
1482 {
1483 int i;
1484
1485 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1486 if (strcmp(str, pkg_state_want_map[i].str) == 0) {
1487 return pkg_state_want_map[i].value;
1488 }
1489 }
1490
1491 fprintf(stderr, "%s: ERROR: Illegal value for state_want string: %s\n",
1492 __FUNCTION__, str);
1493 return SW_UNKNOWN;
1494 }
1495
1496 char *pkg_state_flag_to_str(pkg_state_flag_t sf)
1497 {
1498 int i;
1499 int len = 3; /* ok\000 is minimum */
1500 char *str = NULL;
1501
1502 /* clear the temporary flags before converting to string */
1503 sf &= SF_NONVOLATILE_FLAGS;
1504
1505 if (sf == 0) {
1506 return strdup("ok");
1507 } else {
1508
1509 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1510 if (sf & pkg_state_flag_map[i].value) {
1511 len += strlen(pkg_state_flag_map[i].str) + 1;
1512 }
1513 }
1514 str = malloc(len);
1515 if ( str == NULL ) {
1516 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
1517 return NULL;
1518 }
1519 str[0] = 0;
1520 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1521 if (sf & pkg_state_flag_map[i].value) {
1522 strcat(str, pkg_state_flag_map[i].str);
1523 strcat(str, ",");
1524 }
1525 }
1526 len = strlen(str);
1527 str[len-1] = 0; /* squash last comma */
1528 return str;
1529 }
1530 }
1531
1532 pkg_state_flag_t pkg_state_flag_from_str(char *str)
1533 {
1534 int i;
1535 int sf = SF_OK;
1536
1537 if (strcmp(str, "ok") == 0) {
1538 return SF_OK;
1539 }
1540 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1541 const char *sfname = pkg_state_flag_map[i].str;
1542 int sfname_len = strlen(sfname);
1543 if (strncmp(str, sfname, sfname_len) == 0) {
1544 sf |= pkg_state_flag_map[i].value;
1545 str += sfname_len;
1546 if (str[0] == ',') {
1547 str++;
1548 } else {
1549 break;
1550 }
1551 }
1552 }
1553
1554 return sf;
1555 }
1556
1557 char *pkg_state_status_to_str(pkg_state_status_t ss)
1558 {
1559 int i;
1560
1561 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1562 if (pkg_state_status_map[i].value == ss) {
1563 return strdup(pkg_state_status_map[i].str);
1564 }
1565 }
1566
1567 fprintf(stderr, "%s: ERROR: Illegal value for state_status: %d\n",
1568 __FUNCTION__, ss);
1569 return strdup("<STATE_STATUS_UNKNOWN>");
1570 }
1571
1572 pkg_state_status_t pkg_state_status_from_str(char *str)
1573 {
1574 int i;
1575
1576 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1577 if (strcmp(str, pkg_state_status_map[i].str) == 0) {
1578 return pkg_state_status_map[i].value;
1579 }
1580 }
1581
1582 fprintf(stderr, "%s: ERROR: Illegal value for state_status string: %s\n",
1583 __FUNCTION__, str);
1584 return SS_NOT_INSTALLED;
1585 }
1586
1587 int pkg_arch_supported(ipkg_conf_t *conf, pkg_t *pkg)
1588 {
1589 nv_pair_list_elt_t *l;
1590
1591 if (!pkg->architecture)
1592 return 1;
1593
1594 l = conf->arch_list.head;
1595
1596 while (l) {
1597 nv_pair_t *nv = l->data;
1598 if (strcmp(nv->name, pkg->architecture) == 0) {
1599 ipkg_message(conf, IPKG_DEBUG, "arch %s (priority %s) supported for pkg %s\n", nv->name, nv->value, pkg->name);
1600 return 1;
1601 }
1602 l = l->next;
1603 }
1604
1605 ipkg_message(conf, IPKG_DEBUG, "arch %s unsupported for pkg %s\n", pkg->architecture, pkg->name);
1606 return 0;
1607 }
1608
1609 int pkg_get_arch_priority(ipkg_conf_t *conf, const char *archname)
1610 {
1611 nv_pair_list_elt_t *l;
1612
1613 l = conf->arch_list.head;
1614
1615 while (l) {
1616 nv_pair_t *nv = l->data;
1617 if (strcmp(nv->name, archname) == 0) {
1618 int priority = strtol(nv->value, NULL, 0);
1619 return priority;
1620 }
1621 l = l->next;
1622 }
1623 return 0;
1624 }
1625
1626 int pkg_info_preinstall_check(ipkg_conf_t *conf)
1627 {
1628 int i;
1629 hash_table_t *pkg_hash = &conf->pkg_hash;
1630 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1631 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1632
1633 ipkg_message(conf, IPKG_INFO, "pkg_info_preinstall_check: updating arch priority for each package\n");
1634 pkg_hash_fetch_available(pkg_hash, available_pkgs);
1635 /* update arch_priority for each package */
1636 for (i = 0; i < available_pkgs->len; i++) {
1637 pkg_t *pkg = available_pkgs->pkgs[i];
1638 int arch_priority = 1;
1639 if (!pkg)
1640 continue;
1641 // ipkg_message(conf, IPKG_DEBUG2, " package %s version=%s arch=%p:", pkg->name, pkg->version, pkg->architecture);
1642 if (pkg->architecture)
1643 arch_priority = pkg_get_arch_priority(conf, pkg->architecture);
1644 else
1645 ipkg_message(conf, IPKG_ERROR, "pkg_info_preinstall_check: no architecture for package %s\n", pkg->name);
1646 // ipkg_message(conf, IPKG_DEBUG2, "%s arch_priority=%d\n", pkg->architecture, arch_priority);
1647 pkg->arch_priority = arch_priority;
1648 }
1649
1650 for (i = 0; i < available_pkgs->len; i++) {
1651 pkg_t *pkg = available_pkgs->pkgs[i];
1652 if (!pkg->arch_priority && (pkg->state_flag || (pkg->state_want != SW_UNKNOWN))) {
1653 /* clear flags and want for any uninstallable package */
1654 ipkg_message(conf, IPKG_NOTICE, "Clearing state_want and state_flag for pkg=%s (arch_priority=%d flag=%d want=%d)\n",
1655 pkg->name, pkg->arch_priority, pkg->state_flag, pkg->state_want);
1656 pkg->state_want = SW_UNKNOWN;
1657 pkg->state_flag = 0;
1658 }
1659 }
1660 pkg_vec_free(available_pkgs);
1661
1662 /* update the file owner data structure */
1663 ipkg_message(conf, IPKG_INFO, "pkg_info_preinstall_check: update file owner list\n");
1664 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1665 for (i = 0; i < installed_pkgs->len; i++) {
1666 pkg_t *pkg = installed_pkgs->pkgs[i];
1667 str_list_t *installed_files = pkg_get_installed_files(pkg); /* this causes installed_files to be cached */
1668 str_list_elt_t *iter;
1669 if (installed_files == NULL) {
1670 ipkg_message(conf, IPKG_ERROR, "No installed files for pkg %s\n", pkg->name);
1671 break;
1672 }
1673 for (iter = installed_files->head; iter; iter = iter->next) {
1674 char *installed_file = iter->data;
1675 // ipkg_message(conf, IPKG_DEBUG2, "pkg %s: file=%s\n", pkg->name, installed_file);
1676 file_hash_set_file_owner(conf, installed_file, pkg);
1677 }
1678 }
1679 pkg_vec_free(installed_pkgs);
1680
1681 return 0;
1682 }
1683
1684 struct pkg_write_filelist_data {
1685 ipkg_conf_t *conf;
1686 pkg_t *pkg;
1687 FILE *stream;
1688 };
1689
1690 void pkg_write_filelist_helper(const char *key, void *entry_, void *data_)
1691 {
1692 struct pkg_write_filelist_data *data = data_;
1693 pkg_t *entry = entry_;
1694 if (entry == data->pkg) {
1695 fprintf(data->stream, "%s\n", key);
1696 }
1697 }
1698
1699 int pkg_write_filelist(ipkg_conf_t *conf, pkg_t *pkg)
1700 {
1701 struct pkg_write_filelist_data data;
1702 char *list_file_name = NULL;
1703 int err = 0;
1704
1705 if (!pkg) {
1706 ipkg_message(conf, IPKG_ERROR, "Null pkg\n");
1707 return -EINVAL;
1708 }
1709 ipkg_message(conf, IPKG_INFO,
1710 " creating %s.list file\n", pkg->name);
1711 sprintf_alloc(&list_file_name, "%s/%s.list", pkg->dest->info_dir, pkg->name);
1712 if (!list_file_name) {
1713 ipkg_message(conf, IPKG_ERROR, "Failed to alloc list_file_name\n");
1714 return -ENOMEM;
1715 }
1716 ipkg_message(conf, IPKG_INFO,
1717 " creating %s file for pkg %s\n", list_file_name, pkg->name);
1718 data.stream = fopen(list_file_name, "w");
1719 if (!data.stream) {
1720 ipkg_message(conf, IPKG_ERROR, "Could not open %s for writing: %s\n",
1721 list_file_name, strerror(errno));
1722 return errno;
1723 }
1724 data.pkg = pkg;
1725 data.conf = conf;
1726 hash_table_foreach(&conf->file_hash, pkg_write_filelist_helper, &data);
1727 fclose(data.stream);
1728 free(list_file_name);
1729
1730 return err;
1731 }
1732
1733 int pkg_write_changed_filelists(ipkg_conf_t *conf)
1734 {
1735 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1736 hash_table_t *pkg_hash = &conf->pkg_hash;
1737 int i;
1738 int err;
1739 if (conf->noaction)
1740 return 0;
1741
1742 ipkg_message(conf, IPKG_INFO, "%s: saving changed filelists\n", __FUNCTION__);
1743 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1744 for (i = 0; i < installed_pkgs->len; i++) {
1745 pkg_t *pkg = installed_pkgs->pkgs[i];
1746 if (pkg->state_flag & SF_FILELIST_CHANGED) {
1747 ipkg_message(conf, IPKG_DEBUG, "Calling pkg_write_filelist for pkg=%s from %s\n", pkg->name, __FUNCTION__);
1748 err = pkg_write_filelist(conf, pkg);
1749 if (err)
1750 ipkg_message(conf, IPKG_NOTICE, "pkg_write_filelist pkg=%s returned %d\n", pkg->name, err);
1751 }
1752 }
1753 return 0;
1754 }