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