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