1 /* pkg_depends.c - the opkg package management system
5 Copyright (C) 2002 Compaq Computer Corporation
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.
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.
22 #include "opkg_utils.h"
24 #include "opkg_message.h"
25 #include "pkg_parse.h"
26 #include "hash_table.h"
27 #include "libbb/libbb.h"
29 static int parseDepends(compound_depend_t
* compound_depend
, char *depend_str
);
30 static depend_t
*depend_init(void);
31 static char **add_unresolved_dep(pkg_t
* pkg
, char **the_lost
, int ref_ndx
);
32 static char **merge_unresolved(char **oldstuff
, char **newstuff
);
33 static int is_pkg_in_pkg_vec(pkg_vec_t
* vec
, pkg_t
* pkg
);
35 static int pkg_installed_and_constraint_satisfied(pkg_t
* pkg
, void *cdata
)
37 depend_t
*depend
= (depend_t
*) cdata
;
38 if ((pkg
->state_status
== SS_INSTALLED
39 || pkg
->state_status
== SS_UNPACKED
)
40 && version_constraints_satisfied(depend
, pkg
))
46 static int pkg_constraint_satisfied(pkg_t
* pkg
, void *cdata
)
48 depend_t
*depend
= (depend_t
*) cdata
;
49 if (version_constraints_satisfied(depend
, pkg
))
55 /* returns ndependencies or negative error value */
57 pkg_hash_fetch_unsatisfied_dependencies(pkg_t
* pkg
, pkg_vec_t
* unsatisfied
,
60 pkg_t
*satisfier_entry_pkg
;
64 abstract_pkg_t
*ab_pkg
;
67 * this is a setup to check for redundant/cyclic dependency checks,
68 * which are marked at the abstract_pkg level
70 if (!(ab_pkg
= pkg
->parent
)) {
71 opkg_msg(ERROR
, "Internal error, with pkg %s.\n", pkg
->name
);
75 if (ab_pkg
->dependencies_checked
) { /* avoid duplicate or cyclic checks */
79 ab_pkg
->dependencies_checked
= 1; /* mark it for subsequent visits */
83 pkg
->pre_depends_count
+ pkg
->depends_count
+
84 pkg
->recommends_count
+ pkg
->suggests_count
;
92 /* foreach dependency */
93 for (i
= 0; i
< count
; i
++) {
94 compound_depend_t
*compound_depend
= &pkg
->depends
[i
];
95 depend_t
**possible_satisfiers
=
96 compound_depend
->possibilities
;;
98 satisfier_entry_pkg
= NULL
;
100 if (compound_depend
->type
== GREEDY_DEPEND
) {
101 /* foreach possible satisfier */
102 for (j
= 0; j
< compound_depend
->possibility_count
; j
++) {
103 /* foreach provided_by, which includes the abstract_pkg itself */
104 abstract_pkg_t
*abpkg
=
105 possible_satisfiers
[j
]->pkg
;
106 abstract_pkg_vec_t
*ab_provider_vec
=
108 int nposs
= ab_provider_vec
->len
;
109 abstract_pkg_t
**ab_providers
=
110 ab_provider_vec
->pkgs
;
112 for (l
= 0; l
< nposs
; l
++) {
113 pkg_vec_t
*test_vec
=
114 ab_providers
[l
]->pkgs
;
115 /* if no depends on this one, try the first package that Provides this one */
116 if (!test_vec
) { /* no pkg_vec hooked up to the abstract_pkg! (need another feed?) */
120 /* cruise this possiblity's pkg_vec looking for an installed version */
121 for (k
= 0; k
< test_vec
->len
; k
++) {
124 /* not installed, and not already known about? */
125 if ((pkg_scout
->state_want
!=
127 && !pkg_scout
->parent
->
131 (unsatisfied
, pkg_scout
)) {
132 char **newstuff
= NULL
;
136 /* check for not-already-installed dependencies */
137 rc
= pkg_hash_fetch_unsatisfied_dependencies(pkg_scout
, tmp_vec
, &newstuff
);
138 if (newstuff
== NULL
) {
156 "Not installing %s due"
157 " to requirement for %s.\n",
168 /* mark this one for installation */
171 "Adding satisfier for greedy"
181 "Not installing %s due to "
195 /* foreach possible satisfier, look for installed package */
196 for (j
= 0; j
< compound_depend
->possibility_count
; j
++) {
197 /* foreach provided_by, which includes the abstract_pkg itself */
198 depend_t
*dependence_to_satisfy
=
199 possible_satisfiers
[j
];
200 abstract_pkg_t
*satisfying_apkg
=
201 possible_satisfiers
[j
]->pkg
;
202 pkg_t
*satisfying_pkg
=
203 pkg_hash_fetch_best_installation_candidate
205 pkg_installed_and_constraint_satisfied
,
206 dependence_to_satisfy
, 1);
207 /* Being that I can't test constraing in pkg_hash, I will test it here */
208 if (satisfying_pkg
!= NULL
) {
209 if (!pkg_installed_and_constraint_satisfied
210 (satisfying_pkg
, dependence_to_satisfy
)) {
211 satisfying_pkg
= NULL
;
214 opkg_msg(DEBUG
, "satisfying_pkg=%p\n", satisfying_pkg
);
215 if (satisfying_pkg
!= NULL
) {
221 /* if nothing installed matches, then look for uninstalled satisfier */
223 /* foreach possible satisfier, look for installed package */
224 for (j
= 0; j
< compound_depend
->possibility_count
; j
++) {
225 /* foreach provided_by, which includes the abstract_pkg itself */
226 depend_t
*dependence_to_satisfy
=
227 possible_satisfiers
[j
];
228 abstract_pkg_t
*satisfying_apkg
=
229 possible_satisfiers
[j
]->pkg
;
230 pkg_t
*satisfying_pkg
=
231 pkg_hash_fetch_best_installation_candidate
233 pkg_constraint_satisfied
,
234 dependence_to_satisfy
, 1);
235 /* Being that I can't test constraing in pkg_hash, I will test it here too */
236 if (satisfying_pkg
!= NULL
) {
237 if (!pkg_constraint_satisfied
239 dependence_to_satisfy
)) {
240 satisfying_pkg
= NULL
;
244 /* user request overrides package recommendation */
245 if (satisfying_pkg
!= NULL
246 && (compound_depend
->type
== RECOMMEND
247 || compound_depend
->type
== SUGGEST
)
248 && (satisfying_pkg
->state_want
==
250 || satisfying_pkg
->state_want
==
253 "%s: ignoring recommendation for "
254 "%s at user request\n",
256 satisfying_pkg
->name
);
260 opkg_msg(DEBUG
, "satisfying_pkg=%p\n",
262 if (satisfying_pkg
!= NULL
) {
263 satisfier_entry_pkg
= satisfying_pkg
;
269 /* we didn't find one, add something to the unsatisfied vector */
271 if (!satisfier_entry_pkg
) {
272 /* failure to meet recommendations is not an error */
273 if (compound_depend
->type
!= RECOMMEND
274 && compound_depend
->type
!= SUGGEST
)
276 add_unresolved_dep(pkg
, the_lost
,
280 "%s: unsatisfied recommendation for %s\n",
283 possibilities
[0]->pkg
->name
);
285 if (compound_depend
->type
== SUGGEST
) {
286 /* just mention it politely */
288 "package %s suggests installing %s\n",
290 satisfier_entry_pkg
->name
);
292 char **newstuff
= NULL
;
294 if (satisfier_entry_pkg
!= pkg
&&
295 !is_pkg_in_pkg_vec(unsatisfied
,
296 satisfier_entry_pkg
))
298 pkg_vec_insert(unsatisfied
,
299 satisfier_entry_pkg
);
300 pkg_hash_fetch_unsatisfied_dependencies
301 (satisfier_entry_pkg
,
302 unsatisfied
, &newstuff
);
304 merge_unresolved(the_lost
,
313 *unresolved
= the_lost
;
315 return unsatisfied
->len
;
318 /*checking for conflicts !in replaces
319 If a packages conflicts with another but is also replacing it, I should not consider it a
321 returns 0 if conflicts <> replaces or 1 if conflicts == replaces
323 static int is_pkg_a_replaces(pkg_t
* pkg_scout
, pkg_t
* pkg
)
326 int replaces_count
= pkg
->replaces_count
;
327 abstract_pkg_t
**replaces
;
329 if (pkg
->replaces_count
== 0) // No replaces, it's surely a conflict
332 replaces
= pkg
->replaces
;
334 for (i
= 0; i
< replaces_count
; i
++) {
335 if (strcmp(pkg_scout
->name
, pkg
->replaces
[i
]->name
) == 0) { // Found
336 opkg_msg(DEBUG2
, "Seems I've found a replace %s %s\n",
337 pkg_scout
->name
, pkg
->replaces
[i
]->name
);
345 pkg_vec_t
*pkg_hash_fetch_conflicts(pkg_t
* pkg
)
347 pkg_vec_t
*installed_conflicts
, *test_vec
;
348 compound_depend_t
*conflicts
;
349 depend_t
**possible_satisfiers
;
350 depend_t
*possible_satisfier
;
353 abstract_pkg_t
*ab_pkg
;
358 * this is a setup to check for redundant/cyclic dependency checks,
359 * which are marked at the abstract_pkg level
361 if (!(ab_pkg
= pkg
->parent
)) {
362 opkg_msg(ERROR
, "Internal error: %s not in hash table\n",
364 return (pkg_vec_t
*) NULL
;
367 conflicts
= pkg
->conflicts
;
369 return (pkg_vec_t
*) NULL
;
371 installed_conflicts
= pkg_vec_alloc();
373 count
= pkg
->conflicts_count
;
375 /* foreach conflict */
376 for (i
= 0; i
< pkg
->conflicts_count
; i
++) {
378 possible_satisfiers
= conflicts
->possibilities
;
380 /* foreach possible satisfier */
381 for (j
= 0; j
< conflicts
->possibility_count
; j
++) {
382 possible_satisfier
= possible_satisfiers
[j
];
383 if (!possible_satisfier
)
385 "Internal error: possible_satisfier=NULL\n");
386 if (!possible_satisfier
->pkg
)
388 "Internal error: possible_satisfier->pkg=NULL\n");
389 test_vec
= possible_satisfier
->pkg
->pkgs
;
391 /* pkg_vec found, it is an actual package conflict
392 * cruise this possiblity's pkg_vec looking for an installed version */
393 pkg_scouts
= test_vec
->pkgs
;
394 for (k
= 0; k
< test_vec
->len
; k
++) {
395 pkg_scout
= pkg_scouts
[k
];
398 "Internal error: pkg_scout=NULL\n");
401 if ((pkg_scout
->state_status
==
403 || pkg_scout
->state_want
==
406 version_constraints_satisfied
407 (possible_satisfier
, pkg_scout
)
408 && !is_pkg_a_replaces(pkg_scout
,
410 if (!is_pkg_in_pkg_vec
411 (installed_conflicts
,
414 (installed_conflicts
,
424 if (installed_conflicts
->len
)
425 return installed_conflicts
;
426 pkg_vec_free(installed_conflicts
);
427 return (pkg_vec_t
*) NULL
;
430 int version_constraints_satisfied(depend_t
* depends
, pkg_t
* pkg
)
435 if (depends
->constraint
== NONE
)
440 parse_version(temp
, depends
->version
);
442 comparison
= pkg_compare_versions(pkg
, temp
);
447 if ((depends
->constraint
== EARLIER
) && (comparison
< 0))
449 else if ((depends
->constraint
== LATER
) && (comparison
> 0))
451 else if (comparison
== 0)
453 else if ((depends
->constraint
== LATER_EQUAL
) && (comparison
>= 0))
455 else if ((depends
->constraint
== EARLIER_EQUAL
) && (comparison
<= 0))
461 int pkg_dependence_satisfiable(depend_t
* depend
)
463 abstract_pkg_t
*apkg
= depend
->pkg
;
464 abstract_pkg_vec_t
*provider_apkgs
= apkg
->provided_by
;
465 int n_providers
= provider_apkgs
->len
;
466 abstract_pkg_t
**apkgs
= provider_apkgs
->pkgs
;
472 for (i
= 0; i
< n_providers
; i
++) {
473 abstract_pkg_t
*papkg
= apkgs
[i
];
474 pkg_vec
= papkg
->pkgs
;
476 n_pkgs
= pkg_vec
->len
;
477 for (j
= 0; j
< n_pkgs
; j
++) {
478 pkg_t
*pkg
= pkg_vec
->pkgs
[j
];
479 if (version_constraints_satisfied(depend
, pkg
)) {
488 int pkg_dependence_satisfied(depend_t
* depend
)
490 abstract_pkg_t
*apkg
= depend
->pkg
;
491 abstract_pkg_vec_t
*provider_apkgs
= apkg
->provided_by
;
492 int n_providers
= provider_apkgs
->len
;
493 abstract_pkg_t
**apkgs
= provider_apkgs
->pkgs
;
498 for (i
= 0; i
< n_providers
; i
++) {
499 abstract_pkg_t
*papkg
= apkgs
[i
];
500 pkg_vec_t
*pkg_vec
= papkg
->pkgs
;
502 n_pkgs
= pkg_vec
->len
;
503 for (j
= 0; j
< n_pkgs
; j
++) {
504 pkg_t
*pkg
= pkg_vec
->pkgs
[j
];
505 if (version_constraints_satisfied(depend
, pkg
)) {
506 if (pkg
->state_status
== SS_INSTALLED
507 || pkg
->state_status
== SS_UNPACKED
)
516 static int is_pkg_in_pkg_vec(pkg_vec_t
* vec
, pkg_t
* pkg
)
520 pkg_t
**pkgs
= vec
->pkgs
;
521 arch1
= pkg_get_string(pkg
, PKG_ARCHITECTURE
);
523 for (i
= 0; i
< vec
->len
; i
++) {
524 arch2
= pkg_get_string(*(pkgs
+ i
), PKG_ARCHITECTURE
);
526 if ((strcmp(pkg
->name
, (*(pkgs
+ i
))->name
) == 0)
527 && (pkg_compare_versions(pkg
, *(pkgs
+ i
)) == 0)
528 && (strcmp(arch1
, arch2
) == 0))
535 * pkg_replaces returns 1 if pkg->replaces contains one of replacee's provides and 0
538 int pkg_replaces(pkg_t
* pkg
, pkg_t
* replacee
)
540 abstract_pkg_t
**replaces
= pkg
->replaces
;
541 int replaces_count
= pkg
->replaces_count
;
542 int replacee_provides_count
= replacee
->provides_count
;
544 for (i
= 0; i
< replaces_count
; i
++) {
545 abstract_pkg_t
*abstract_replacee
= replaces
[i
];
546 for (j
= 0; j
< replacee_provides_count
; j
++) {
547 if (replacee
->provides
[j
] == abstract_replacee
)
555 * pkg_conflicts_abstract returns 1 if pkg->conflicts contains conflictee and 0
558 int pkg_conflicts_abstract(pkg_t
* pkg
, abstract_pkg_t
* conflictee
)
560 compound_depend_t
*conflicts
= pkg
->conflicts
;
561 int conflicts_count
= pkg
->conflicts_count
;
563 for (i
= 0; i
< conflicts_count
; i
++) {
564 int possibility_count
= conflicts
[i
].possibility_count
;
565 struct depend
**possibilities
= conflicts
[i
].possibilities
;
566 for (j
= 0; j
< possibility_count
; j
++) {
567 if (possibilities
[j
]->pkg
== conflictee
) {
576 * pkg_conflicts returns 1 if pkg->conflicts contains one of
577 * conflictee's provides and 0 otherwise.
579 int pkg_conflicts(pkg_t
* pkg
, pkg_t
* conflictee
)
581 compound_depend_t
*conflicts
= pkg
->conflicts
;
582 int conflicts_count
= pkg
->conflicts_count
;
583 abstract_pkg_t
**conflictee_provides
= conflictee
->provides
;
584 int conflictee_provides_count
= conflictee
->provides_count
;
586 int possibility_count
;
587 struct depend
**possibilities
;
588 abstract_pkg_t
*possibility
;
590 for (i
= 0; i
< conflicts_count
; i
++) {
591 possibility_count
= conflicts
[i
].possibility_count
;
592 possibilities
= conflicts
[i
].possibilities
;
593 for (j
= 0; j
< possibility_count
; j
++) {
594 possibility
= possibilities
[j
]->pkg
;
595 for (k
= 0; k
< conflictee_provides_count
; k
++) {
596 if (possibility
== conflictee_provides
[k
]) {
605 static char **merge_unresolved(char **oldstuff
, char **newstuff
)
607 int oldlen
= 0, newlen
= 0;
614 while (oldstuff
&& oldstuff
[oldlen
])
616 while (newstuff
&& newstuff
[newlen
])
619 result
= xrealloc(oldstuff
, sizeof(char *) * (oldlen
+ newlen
+ 1));
621 for (i
= oldlen
, j
= 0; i
< (oldlen
+ newlen
); i
++, j
++)
622 *(result
+ i
) = *(newstuff
+ j
);
624 *(result
+ i
) = NULL
;
630 * a kinda kludgy way to back out depends str from two different arrays (reg'l'r 'n pre)
631 * this is null terminated, no count is carried around
633 char **add_unresolved_dep(pkg_t
* pkg
, char **the_lost
, int ref_ndx
)
639 while (the_lost
&& the_lost
[count
])
642 count
++; /* need one to hold the null */
643 resized
= xrealloc(the_lost
, sizeof(char *) * (count
+ 1));
644 resized
[count
- 1] = pkg_depend_str(pkg
, ref_ndx
);
645 resized
[count
] = NULL
;
650 void buildProvides(abstract_pkg_t
* ab_pkg
, pkg_t
* pkg
)
654 /* every pkg provides itself */
655 pkg
->provides_count
++;
656 abstract_pkg_vec_insert(ab_pkg
->provided_by
, ab_pkg
);
657 pkg
->provides
= xcalloc(pkg
->provides_count
, sizeof(abstract_pkg_t
*));
658 pkg
->provides
[0] = ab_pkg
;
660 for (i
= 1; i
< pkg
->provides_count
; i
++) {
661 abstract_pkg_t
*provided_abpkg
=
662 ensure_abstract_pkg_by_name(pkg
->provides_str
[i
- 1]);
663 free(pkg
->provides_str
[i
- 1]);
665 pkg
->provides
[i
] = provided_abpkg
;
667 abstract_pkg_vec_insert(provided_abpkg
->provided_by
, ab_pkg
);
669 if (pkg
->provides_str
)
670 free(pkg
->provides_str
);
673 void buildConflicts(pkg_t
* pkg
)
676 compound_depend_t
*conflicts
;
678 if (!pkg
->conflicts_count
)
681 conflicts
= pkg
->conflicts
=
682 xcalloc(pkg
->conflicts_count
, sizeof(compound_depend_t
));
683 for (i
= 0; i
< pkg
->conflicts_count
; i
++) {
684 conflicts
->type
= CONFLICTS
;
685 parseDepends(conflicts
, pkg
->conflicts_str
[i
]);
686 free(pkg
->conflicts_str
[i
]);
689 if (pkg
->conflicts_str
)
690 free(pkg
->conflicts_str
);
693 void buildReplaces(abstract_pkg_t
* ab_pkg
, pkg_t
* pkg
)
697 if (!pkg
->replaces_count
)
700 pkg
->replaces
= xcalloc(pkg
->replaces_count
, sizeof(abstract_pkg_t
*));
702 for (i
= 0; i
< pkg
->replaces_count
; i
++) {
703 abstract_pkg_t
*old_abpkg
=
704 ensure_abstract_pkg_by_name(pkg
->replaces_str
[i
]);
706 pkg
->replaces
[i
] = old_abpkg
;
707 free(pkg
->replaces_str
[i
]);
709 if (!old_abpkg
->replaced_by
)
710 old_abpkg
->replaced_by
= abstract_pkg_vec_alloc();
711 /* if a package pkg both replaces and conflicts old_abpkg,
712 * then add it to the replaced_by vector so that old_abpkg
713 * will be upgraded to ab_pkg automatically */
714 if (pkg_conflicts_abstract(pkg
, old_abpkg
))
715 abstract_pkg_vec_insert(old_abpkg
->replaced_by
, ab_pkg
);
718 if (pkg
->replaces_str
)
719 free(pkg
->replaces_str
);
722 void buildDepends(pkg_t
* pkg
)
726 compound_depend_t
*depends
;
730 pkg
->pre_depends_count
+ pkg
->depends_count
+
731 pkg
->recommends_count
+ pkg
->suggests_count
))
734 depends
= pkg
->depends
= xcalloc(count
, sizeof(compound_depend_t
));
736 for (i
= 0; i
< pkg
->pre_depends_count
; i
++) {
737 parseDepends(depends
, pkg
->pre_depends_str
[i
]);
738 free(pkg
->pre_depends_str
[i
]);
739 depends
->type
= PREDEPEND
;
742 if (pkg
->pre_depends_str
)
743 free(pkg
->pre_depends_str
);
745 for (i
= 0; i
< pkg
->depends_count
; i
++) {
746 parseDepends(depends
, pkg
->depends_str
[i
]);
747 free(pkg
->depends_str
[i
]);
750 if (pkg
->depends_str
)
751 free(pkg
->depends_str
);
753 for (i
= 0; i
< pkg
->recommends_count
; i
++) {
754 parseDepends(depends
, pkg
->recommends_str
[i
]);
755 free(pkg
->recommends_str
[i
]);
756 depends
->type
= RECOMMEND
;
759 if (pkg
->recommends_str
)
760 free(pkg
->recommends_str
);
762 for (i
= 0; i
< pkg
->suggests_count
; i
++) {
763 parseDepends(depends
, pkg
->suggests_str
[i
]);
764 free(pkg
->suggests_str
[i
]);
765 depends
->type
= SUGGEST
;
768 if (pkg
->suggests_str
)
769 free(pkg
->suggests_str
);
772 const char *constraint_to_str(enum version_constraint c
)
793 * Returns a printable string for pkg's dependency at the specified idx. The
794 * resultant string must be passed to free() by the caller.
796 char *pkg_depend_str(pkg_t
* pkg
, int idx
)
801 compound_depend_t
*cdep
;
805 cdep
= &pkg
->depends
[idx
];
807 /* calculate string length */
808 for (i
= 0; i
< cdep
->possibility_count
; i
++) {
809 dep
= cdep
->possibilities
[i
];
812 len
+= 3; /* space, pipe, space */
814 len
+= strlen(dep
->pkg
->name
);
817 len
+= 2; /* space, left parenthesis */
818 len
+= 3; /* constraint string (<=, >=, etc), space */
819 len
+= strlen(dep
->version
);
820 len
+= 1; /* right parenthesis */
824 str
= xmalloc(len
+ 1); /* +1 for the NULL terminator */
827 for (i
= 0; i
< cdep
->possibility_count
; i
++) {
828 dep
= cdep
->possibilities
[i
];
831 strncat(str
, " | ", len
);
833 strncat(str
, dep
->pkg
->name
, len
);
836 strncat(str
, " (", len
);
837 strncat(str
, constraint_to_str(dep
->constraint
), len
);
838 strncat(str
, dep
->version
, len
);
839 strncat(str
, ")", len
);
846 void buildDependedUponBy(pkg_t
* pkg
, abstract_pkg_t
* ab_pkg
)
848 compound_depend_t
*depends
;
849 int count
, othercount
;
851 abstract_pkg_t
*ab_depend
;
852 abstract_pkg_t
**temp
;
854 count
= pkg
->pre_depends_count
+
855 pkg
->depends_count
+ pkg
->recommends_count
+ pkg
->suggests_count
;
857 for (i
= 0; i
< count
; i
++) {
858 depends
= &pkg
->depends
[i
];
859 if (depends
->type
!= PREDEPEND
860 && depends
->type
!= DEPEND
&& depends
->type
!= RECOMMEND
)
862 for (j
= 0; j
< depends
->possibility_count
; j
++) {
863 ab_depend
= depends
->possibilities
[j
]->pkg
;
864 if (!ab_depend
->depended_upon_by
) {
865 ab_depend
->depended_upon_by
=
866 xcalloc(1, sizeof(abstract_pkg_t
*));
869 temp
= ab_depend
->depended_upon_by
;
877 ab_depend
->depended_upon_by
=
878 xrealloc(ab_depend
->depended_upon_by
,
880 1) * sizeof(abstract_pkg_t
*));
882 /* the array may have been moved by realloc */
883 temp
= ab_depend
->depended_upon_by
+ othercount
;
889 static depend_t
*depend_init(void)
891 depend_t
*d
= xcalloc(1, sizeof(depend_t
));
892 d
->constraint
= NONE
;
899 static int parseDepends(compound_depend_t
* compound_depend
, char *depend_str
)
901 char *pkg_name
, buffer
[2048];
902 unsigned int num_of_ors
= 0;
905 depend_t
**possibilities
;
907 /* first count the number of ored possibilities for satisfying dependency */
913 compound_depend
->type
= DEPEND
;
915 compound_depend
->possibility_count
= num_of_ors
+ 1;
916 possibilities
= xcalloc((num_of_ors
+ 1), sizeof(depend_t
*));
917 compound_depend
->possibilities
= possibilities
;
920 for (i
= 0; i
< num_of_ors
+ 1; i
++) {
921 possibilities
[i
] = depend_init();
922 /* gobble up just the name first */
926 (*src
!= '(') && (*src
!= '*') && (*src
!= '|'))
929 pkg_name
= trim_xstrdup(buffer
);
931 /* now look at possible version info */
933 /* skip to next chars */
935 while (*src
&& isspace(*src
))
938 /* extract constraint and version */
941 if (!strncmp(src
, "<<", 2)) {
942 possibilities
[i
]->constraint
= EARLIER
;
944 } else if (!strncmp(src
, "<=", 2)) {
945 possibilities
[i
]->constraint
= EARLIER_EQUAL
;
947 } else if (!strncmp(src
, ">=", 2)) {
948 possibilities
[i
]->constraint
= LATER_EQUAL
;
950 } else if (!strncmp(src
, ">>", 2)) {
951 possibilities
[i
]->constraint
= LATER
;
953 } else if (!strncmp(src
, "=", 1)) {
954 possibilities
[i
]->constraint
= EQUAL
;
957 /* should these be here to support deprecated designations; dpkg does */
958 else if (!strncmp(src
, "<", 1)) {
959 possibilities
[i
]->constraint
= EARLIER_EQUAL
;
961 } else if (!strncmp(src
, ">", 1)) {
962 possibilities
[i
]->constraint
= LATER_EQUAL
;
966 /* now we have any constraint, pass space to version string */
967 while (isspace(*src
))
970 /* this would be the version string */
972 while (*src
&& *src
!= ')')
976 possibilities
[i
]->version
= trim_xstrdup(buffer
);
978 /* hook up the dependency to its abstract pkg */
979 possibilities
[i
]->pkg
= ensure_abstract_pkg_by_name(pkg_name
);
983 /* now get past the ) and any possible | chars */
985 (isspace(*src
) || (*src
== ')') || (*src
== '|')))
988 compound_depend
->type
= GREEDY_DEPEND
;