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