1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
#include "udpkg.h"
#ifdef DODEPENDS
#include <stdio.h>
#include <stdlib.h>
#include <search.h>
#include <string.h>
#include <ctype.h>
static char **depends_split(const char *dependsstr)
{
static char *dependsvec[DEPENDSMAX];
char *p;
int i = 0;
dependsvec[0] = 0;
if (dependsstr != 0)
{
p = strdup(dependsstr);
while (*p != 0 && *p != '\n')
{
if (*p != ' ')
{
if (*p == ',')
{
*p = 0;
dependsvec[++i] = 0;
}
else if (dependsvec[i] == 0)
dependsvec[i] = p;
}
else
*p = 0; /* eat the space... */
p++;
}
*p = 0;
}
dependsvec[i+1] = 0;
return dependsvec;
}
static void depends_sort_visit(struct package_t **ordered,
struct package_t *pkgs, struct package_t *pkg)
{
/* Topological sort algorithm:
* ordered is the output list, pkgs is the dependency graph, pkg is
* the current node
*
* recursively add all the adjacent nodes to the ordered list, marking
* each one as visited along the way
*
* yes, this algorithm looks a bit odd when all the params have the
* same type :-)
*/
unsigned short i;
/* mark node as processing */
pkg->color = COLOR_GRAY;
/* visit each not-yet-visited node */
for (i = 0; i < pkg->requiredcount; i++)
if (pkg->requiredfor[i]->color == COLOR_WHITE)
depends_sort_visit(ordered, pkgs, pkg->requiredfor[i]);
#if 0
/* add it to the list */
newnode = (struct package_t *)di_malloc(sizeof(struct package_t));
/* make a shallow copy */
*newnode = *pkg;
newnode->next = *ordered;
*ordered = newnode;
#endif
pkg->next = *ordered;
*ordered = pkg;
/* mark node as done */
pkg->color = COLOR_BLACK;
}
static struct package_t *depends_sort(struct package_t *pkgs)
{
/* TODO: it needs to break cycles in the to-be-installed package
* graph... */
struct package_t *ordered = NULL;
struct package_t *pkg;
for (pkg = pkgs; pkg != 0; pkg = pkg->next)
pkg->color = COLOR_WHITE;
for (pkg = pkgs; pkg != 0; pkg = pkg->next)
if (pkg->color == COLOR_WHITE)
depends_sort_visit(&ordered, pkgs, pkg);
/* Leaks the old list... return the new one... */
return ordered;
}
/* resolve package dependencies --
* for each package in the list of packages to be installed, we parse its
* dependency info to determine if the dependent packages are either
* already installed, or are scheduled to be installed. If both tests fail
* than bail.
*
* The algorithm here is O(n^2*m) where n = number of packages to be
* installed and m is the # of dependencies per package. Not a terribly
* efficient algorithm, but given that at any one time you are unlikely
* to install a very large number of packages it doesn't really matter
*/
struct package_t *depends_resolve(struct package_t *pkgs, void *status)
{
struct package_t *pkg, *chk;
struct package_t dependpkg;
char **dependsvec;
int i;
void *found;
for (pkg = pkgs; pkg != 0; pkg = pkg->next)
{
dependsvec = depends_split(pkg->depends);
i = 0;
while (dependsvec[i] != 0)
{
/* Check for dependencies; first look for installed packages */
dependpkg.package = dependsvec[i];
if ((found = tfind(&dependpkg, &status, package_compare)) == 0 ||
((chk = *(struct package_t **)found) &&
(chk->status & (STATUS_FLAGOK | STATUS_STATUSINSTALLED)) !=
(STATUS_FLAGOK | STATUS_STATUSINSTALLED)))
{
/* if it fails, we look through the list of packages we are going to
* install */
for (chk = pkgs; chk != 0; chk = chk->next)
{
if (strcmp(chk->package, dependsvec[i]) == 0 ||
(chk->provides &&
strncmp(chk->provides, dependsvec[i], strlen(dependsvec[i])) == 0))
{
if (chk->requiredcount >= DEPENDSMAX)
{
fprintf(stderr, "Too many dependencies for %s\n",
chk->package);
return 0;
}
if (chk != pkg)
chk->requiredfor[chk->requiredcount++] = pkg;
break;
}
}
if (chk == 0)
{
fprintf(stderr, "%s depends on %s, but it is not going to be installed\n", pkg->package, dependsvec[i]);
return 0;
}
}
i++;
}
}
return depends_sort(pkgs);
}
#endif
|