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