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