Remove the old installability tester

Signed-off-by: Niels Thykier <niels@thykier.net>
master
Niels Thykier 11 years ago
parent 7051d5b0e9
commit ea4e4493a2

@ -5,13 +5,5 @@ Requirements:
-------------
* Python 2.7 aptitude install python2.7
* Python APT/DPKG bindings aptitude install python2.7-apt libapt-pkg-dev dpkg-dev
* Python dev headers aptitude install python2.7-dev
Compiling:
----------
Run "make all" in the lib directory and add a symlink called
britneymodule.so pointing to the freshly generated britneymodule.so in
the lib directory.
* Python APT/DPKG bindings aptitude install python2.7-apt

@ -212,7 +212,6 @@ from installability.builder import InstallabilityTesterBuilder
from excuse import Excuse
from migrationitem import MigrationItem
from hints import HintCollection
from britney import buildSystem
from britney_util import (old_libraries_format, same_source, undo_changes,
register_reverses, compute_reverse_tree,
read_nuninst, write_nuninst, write_heidi,

@ -1,33 +0,0 @@
CC = gcc
CXX = g++
CFLAGS = -Wall -W -O2 -DNDEBUG -DMDEBUG0 -g -p -fPIC
CXXFLAGS += -fPIC
all : britneymodule.so # checklib aptvercmp freelist libajdpkg.a
clean :
rm -f *.so *.o *~ Makefile.dep gmon.out
rm -f freelist aptvercmp checklib libajdpkg.a
checklib : checklib.o dpkg.o dpkg-lib.o memory3.o freelist.o assert.o
$(CC) $(CFLAGS) -o checklib -lapt-pkg $^ # -lccmalloc -ldl
aptvercmp : dpkg-lib.cpp
$(CXX) $(CFLAGS) -DTESTBIN -o aptvercmp dpkg-lib.cpp -lapt-pkg
freelist : freelist.c assert.o
$(CC) $(CFLAGS) -DTESTBIN -o $@ $^
#libajdpkg.a : dpkg.o dpkg-lib.o memory3.o freelist.o assert.o
# ar rv $@ $^
# ranlib $@
britneymodule.so : britney-py.o dpkg.o dpkg-lib.o memory3.o freelist.o assert.o
$(CC) -shared -o britneymodule.so $^ -lapt-pkg
Makefile.dep :
@gcc -MM *.c *.cpp > Makefile.dep
@echo Makefile.dep : Makefile *.c *.h >> Makefile.dep
-include Makefile.dep

@ -1,32 +0,0 @@
BUILDING
========
Install libapt-pkg-dev
testing/ $ make
testing/ $ mkdir old cur out
testing/ $ cd testing
testing/testing/ $ perl Makefile.PL
testing/testing/ $ make
Add old and new packages files into old and cur, respectively.
testing/ $ ./checklib i386 alpha
Will generate some test stuff in out/
TODO
====
Need some way of actually updating archives.
Need some way of judging differences between Packages files.
(so I can see what hasn't been updated and work out why;
so I can check that Packages.gz matches dpkg-scanpackages output)
Need some way of automatically explaining why packages aren't upgraded.
(shouldn't be hard?)
BUGS
====
out/ directory must exist for checklib, or segfault

@ -1,11 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
int _myassertbug(int line, char *file, char *err) {
fprintf(stderr, "Assertion failed: %s:%d: %s\n", file, line, err);
fprintf(stderr, "I HATE YOU!!!");
((void(*)())0)();
abort();
return 0;
}

@ -1,299 +0,0 @@
#include <python2.7/Python.h>
#include "dpkg.h"
#define MAKE_PY_LIST(L,S,E,I,V) \
do { \
L = PyList_New(0); \
if (!L) break; \
for (S; E; I) { \
PyObject *EL; \
EL = Py_BuildValue V; \
if (!EL) { \
Py_DECREF(L); \
L = NULL; \
break; \
} \
PyList_Append(L, EL); \
Py_DECREF(EL); \
} \
if (L) PyList_Sort(L); \
} while(0)
/**************************************************************************
* britney.Packages -- dpkg_packages wrapper
*******************************************/
typedef enum { DONTFREE, FREE } dpkgpackages_freeme;
typedef struct {
PyObject_HEAD
dpkg_packages *pkgs;
PyObject *ref; /* object packages are "in" */
dpkgpackages_freeme freeme; /* free pkgs when deallocing? */
} dpkgpackages;
staticforward PyTypeObject Packages_Type;
static void dpkgpackages_dealloc(dpkgpackages *self) {
if (self->freeme == FREE) free_packages(self->pkgs);
Py_XDECREF(self->ref);
self->pkgs = NULL;
self->ref = NULL;
PyObject_DEL(self);
}
static PyObject *dpkgpackages_isinstallable(dpkgpackages *self, PyObject *args)
{
char *pkgname;
int r;
if (!PyArg_ParseTuple(args, "s", &pkgname)) return NULL;
if ((r=checkinstallable2(self->pkgs, pkgname))) {
return Py_BuildValue("i", r);
} else {
return Py_BuildValue("");
}
}
static PyObject *dpkgpackages_remove_binary(dpkgpackages *self, PyObject *args) {
char *pkg_name;
(void)self; /* unused */
if (!PyArg_ParseTuple(args, "s", &pkg_name))
return NULL;
dpkg_collected_package *cpkg = lookup_packagetbl(self->pkgs->packages, pkg_name);
if (cpkg == NULL) return Py_BuildValue("i", 0);
remove_package(self->pkgs, cpkg);
return Py_BuildValue("i", 1);
}
static PyObject *dpkgpackages_add_binary(dpkgpackages *self, PyObject *args) {
char *pkg_name;
PyObject *value, *pyString;
(void)self; /* unused */
if (!PyArg_ParseTuple(args, "sO", &pkg_name, &value) ||
!PyList_Check(value)) return NULL;
/* initialize the new package */
dpkg_package *pkg;
pkg = block_malloc(sizeof(dpkg_package));
pkg->package = strdup(pkg_name);
pkg->priority = 0;
pkg->details = NULL;
pkg->depends[1] = NULL;
pkg->depends[2] = NULL;
pkg->depends[3] = NULL;
pyString = PyList_GetItem(value, 0);
if (pyString == NULL) return NULL;
pkg->version = PyString_AsString(pyString);
pyString = PyList_GetItem(value, 2);
if (pyString == NULL) return NULL;
pkg->source = PyString_AsString(pyString);
pyString = PyList_GetItem(value, 3);
if (pyString == NULL) return NULL;
pkg->source_ver = PyString_AsString(pyString);
pyString = PyList_GetItem(value, 4);
if (pyString == NULL) return NULL;
pkg->arch_all = (pyString == Py_None || strcmp(PyString_AsString(pyString), "all") ? 0 : 1);
pyString = PyList_GetItem(value, 5);
if (pyString == NULL) return NULL;
if (pyString != Py_None) {
pkg->multiarch = PyString_AsString(pyString);
} else pkg->multiarch = NULL;
pyString = PyList_GetItem(value, 6);
if (pyString == NULL) return NULL;
if (pyString != Py_None) {
pkg->depends[0] = read_dep_andor(PyString_AsString(pyString));
} else pkg->depends[0] = NULL;
pyString = PyList_GetItem(value, 7);
if (pyString == NULL) return NULL;
if (pyString != Py_None) {
pkg->conflicts = read_dep_and(PyString_AsString(pyString));
} else pkg->conflicts = NULL;
pyString = PyList_GetItem(value, 8);
if (pyString == NULL) return NULL;
if (pyString != Py_None) {
pkg->provides = read_packagenames(PyString_AsString(pyString));
} else pkg->provides = NULL;
add_package(self->pkgs, pkg);
return Py_BuildValue("i", 1);
}
static PyObject *dpkgpackages_getattr(dpkgpackages *self, char *name) {
static struct PyMethodDef dpkgsources_methods[] = {
{ "is_installable", (binaryfunc) dpkgpackages_isinstallable,
METH_VARARGS, NULL },
{ "remove_binary", (binaryfunc) dpkgpackages_remove_binary,
METH_VARARGS, NULL },
{ "add_binary", (binaryfunc) dpkgpackages_add_binary,
METH_VARARGS, NULL },
{ NULL, NULL, 0, NULL }
};
if (strcmp(name, "packages") == 0) {
PyObject *packages;
packagetbl_iter it;
MAKE_PY_LIST(packages,
it = first_packagetbl(self->pkgs->packages),
!done_packagetbl(it), it = next_packagetbl(it),
("s", it.k)
);
return packages;
}
return Py_FindMethod(dpkgsources_methods, (PyObject *)self, name);
}
static PyTypeObject Packages_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0, /* ob_size (0) */
"Packages", /* type name */
sizeof(dpkgpackages), /* basicsize */
0, /* itemsize (0) */
(destructor) dpkgpackages_dealloc,
(printfunc) 0,
(getattrfunc) dpkgpackages_getattr,
(setattrfunc) 0,
(cmpfunc) 0,
(reprfunc) 0,
0, /* number methods */
0, /* sequence methods */
0, /* mapping methods */
(hashfunc) 0, /* dict[x] ?? */
(ternaryfunc) 0, /* x() */
(reprfunc) 0 /* str(x) */
};
/**************************************************************************
* britney.buildSystem() -- build a fake package system, with the only purpose of
* calling the is_installable method on the packages.
******************************************************/
static PyObject *build_system(PyObject *self, PyObject *args) {
Py_ssize_t pos = 0;
char *arch;
PyObject *pkgs, *key, *value, *pyString;
(void)self; /* unused */
if (!PyArg_ParseTuple(args, "sO", &arch, &pkgs) ||
!PyDict_Check(pkgs)) return NULL;
/* Fields and positions for the binary package:
# VERSION = 0
# SECTION = 1
# SOURCE = 2
# SOURCEVER = 3
# ARCHITECTURE = 4
# MULTIARCH = 5
# DEPENDS = 6
# CONFLICTS = 7
# PROVIDES = 8
# RDEPENDS = 9
# RCONFLICTS = 10
*/
dpkg_packages *dpkg_pkgs = new_packages(arch);
/* loop on the dictionary keys to build the packages */
while (PyDict_Next(pkgs, &pos, &key, &value)) {
/* initialize the new package */
dpkg_package *pkg;
pkg = block_malloc(sizeof(dpkg_package));
pkg->package = strdup(PyString_AsString(key));
pkg->priority = 0;
pkg->details = NULL;
pkg->depends[1] = NULL;
pkg->depends[2] = NULL;
pkg->depends[3] = NULL;
pyString = PyList_GetItem(value, 0);
if (pyString == NULL) continue;
pkg->version = PyString_AsString(pyString);
pyString = PyList_GetItem(value, 2);
if (pyString == NULL) continue;
pkg->source = PyString_AsString(pyString);
pyString = PyList_GetItem(value, 3);
if (pyString == NULL) continue;
pkg->source_ver = PyString_AsString(pyString);
pyString = PyList_GetItem(value, 4);
if (pyString == NULL) continue;
pkg->arch_all = (pyString == Py_None || strcmp(PyString_AsString(pyString), "all") ? 0 : 1);
pyString = PyList_GetItem(value, 5);
if (pyString == NULL) continue;
if (pyString != Py_None) {
pkg->multiarch = PyString_AsString(pyString);
} else pkg->multiarch = NULL;
pyString = PyList_GetItem(value, 6);
if (pyString == NULL) continue;
if (pyString != Py_None) {
pkg->depends[0] = read_dep_andor(PyString_AsString(pyString));
} else pkg->depends[0] = NULL;
pyString = PyList_GetItem(value, 7);
if (pyString == NULL) continue;
if (pyString != Py_None) {
pkg->conflicts = read_dep_and(PyString_AsString(pyString));
} else pkg->conflicts = NULL;
pyString = PyList_GetItem(value, 8);
if (pyString == NULL) continue;
if (pyString != Py_None) {
pkg->provides = read_packagenames(PyString_AsString(pyString));
} else pkg->provides = NULL;
add_package(dpkg_pkgs, pkg);
}
dpkgpackages *res;
res = PyObject_NEW(dpkgpackages, &Packages_Type);
if (res == NULL) return NULL;
res->pkgs = dpkg_pkgs;
res->freeme = FREE;
res->ref = NULL;
return (PyObject *)res;
}
/**************************************************************************
* module initialisation
***********************/
static PyMethodDef britneymethods[] = {
{ "buildSystem", build_system, METH_VARARGS, NULL },
{ NULL, NULL, 0, NULL }
};
void initbritney(void) {
Py_InitModule("britney", britneymethods);
}

@ -1,185 +0,0 @@
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include "dpkg.h"
#if 0
static void checknewsrc(sourcetbl *srcstbl, dpkg_source *cur, void *data) {
dpkg_sources *oldsrc = data;
dpkg_source *old;
old = lookup_sourcetbl(oldsrc->sources, cur->package);
if (old == NULL) {
printf("New: %s (%s)\n", cur->package, cur->version );
} else if (strcmp(old->version, cur->version) != 0) {
printf("Updated: %s (%s, was %s)\n",
cur->package, cur->version, old->version );
} else {
dpkg_source *src2;
src2 = remove_sourcetbl(srcstbl, cur->package);
assert(cur == src2);
free_source(cur);
}
}
static void checkoldsrc(sourcetbl *oldsrctbl, dpkg_source *old, void *data) {
dpkg_sources *src = data;
dpkg_source *cur;
(void)oldsrctbl;
cur = lookup_sourcetbl(src->sources, old->package);
if (cur == NULL) {
printf("Removed: %s (was %s)\n", old->package, old->version );
}
}
static void checkuptodate(sourcetbl *srctbl, dpkg_source *src, void *data) {
int i;
int remove;
ownedpackagelist **p;
dpkg_sources *srcs = data;
(void)srctbl;
remove = 0;
for (i = 0; i < srcs->n_arches; i++) {
p = &src->packages[i];
while(*p != NULL) {
if (strcmp((*p)->value->source_ver, src->version) != 0) {
if (cmpversions((*p)->value->source_ver, GT, src->version)) {
printf("ALERT: old source: ");
} else {
printf("WARN: out of date: ");
}
printf("%s %s: %s binary: %s %s from %s\n",
src->package, src->version, srcs->archname[i],
(*p)->value->package, (*p)->value->version,
(*p)->value->source_ver);
delete_ownedpackagelist(p);
} else {
p = &(*p)->next;
}
}
if (src->packages[i] == NULL) {
printf("%s missing uptodate binaries for %s\n",
src->package, srcs->archname[i]);
remove = 1;
}
}
if (remove) {
dpkg_source *src2;
src2 = remove_sourcetbl(srcs->sources, src->package);
assert(src == src2);
free_source(src);
}
}
#endif
static void upgrade(sourcetbl *srctbl, dpkg_source *src, void *data) {
static int i = 0;
dpkg_sources_note *srcsn = data;
(void)srctbl;
i++; i %= 1000;
if (can_undo(srcsn)) {
if (i % 29 == 1 || i % 31 == 1 || i % 7 == 5)
undo_change(srcsn);
if (i % 33 == 0) commit_changes(srcsn);
}
upgrade_source(data, src);
}
static void checkpkgs(packagetbl *pkgtbl, dpkg_collected_package *cpkg,
void *data)
{
dpkg_packages *pkgs = data;
assert(pkgs->packages == pkgtbl);
printf("Trying %s (%s, %s)\n", cpkg->pkg->package, cpkg->pkg->version, pkgs->arch);
if (!checkinstallable2(pkgs, cpkg->pkg->package)) {
printf("Package: %s (%s, %s) is uninstallable\n",
cpkg->pkg->package, cpkg->pkg->version, pkgs->arch);
}
}
void print_memblock_summary(void);
int main(int argc, char **argv) {
dpkg_sources *src = NULL, *oldsrc = NULL;
dpkg_sources_note *srcsn;
dpkg_source *srcpkg;
dpkg_packages *pkgs[10];
int n_pkgs;
int i,j;
int reps;
if (argc < 3) {
printf("Usage: %s <reps> <arch>...\n", argv[0]);
exit(EXIT_FAILURE);
}
reps = atoi(argv[1]);
if (reps < 1) {
printf("reps must be >= 1\n");
exit(EXIT_FAILURE);
}
src = read_directory("cur", argc - 2, argv + 2);
oldsrc = read_directory("old", argc - 2, argv + 2);
srcsn = new_sources_note(argc - 2, argv + 2);
printf("FINISHED LOADING\n"); fflush(stdout); /* sleep(5); */
#if 0
iterate_sourcetbl(oldsrc->sources, checkoldsrc, src);
printf("FIRST\n");
iterate_sourcetbl(src->sources, checkuptodate, src);
printf("SECOND\n");
iterate_sourcetbl(src->sources, checkuptodate, src);
printf("END\n");
iterate_sourcetbl(src->sources, checknewsrc, oldsrc);
#endif
n_pkgs = 0;
for (i = argc - 1; i > 1; i--) {
pkgs[n_pkgs++] = get_architecture(oldsrc, argv[i]);
}
for (j = 0; j < reps; j++) {
printf("Round %d/%d starting...\n", j + 1, reps);
for (i = 0; i < n_pkgs; i++) {
iterate_packagetbl(pkgs[i]->packages, checkpkgs, pkgs[i]);
}
printf("Round %d ended.\n", j+1);
}
iterate_sourcetbl(src->sources, upgrade, srcsn);
iterate_sourcetbl(oldsrc->sources, upgrade, srcsn);
for (i = 0; i < n_pkgs; i++) {
free_packages(pkgs[i]);
}
srcpkg = lookup_sourcetbl(oldsrc->sources, "omirr");
if (srcpkg != NULL) {
printf("Adding old\n");
upgrade_source(srcsn, srcpkg);
}
srcpkg = lookup_sourcetbl(src->sources, "omirr");
if (srcpkg != NULL) {
printf("Adding cur\n");
upgrade_source(srcsn, srcpkg);
}
printf("FINISHED PROCESSING\n"); fflush(stdout); /* sleep(5); */
write_directory("out", oldsrc);
printf("FINISHED WRITING\n"); fflush(stdout); /* sleep(5); */
free_sources_note(srcsn);
free_sources(src);
free_sources(oldsrc);
DEBUG_ONLY( print_memblock_summary(); )
return 0;
}

@ -1,30 +0,0 @@
#include <apt-pkg/debversion.h>
extern "C" {
#include "dpkg.h"
int cmpversions(char *left, int op, char *right) {
int i = debVS.CmpVersion(left, right);
switch(op) {
case dr_LT: return i < 0;
case dr_LTEQ: return i <= 0;
case dr_EQ: return i == 0;
case dr_GTEQ: return i >= 0;
case dr_GT: return i > 0;
}
return 0;
}
}
#ifdef TESTBIN
int main(int argc, char **argv) {
if (argc != 3) { printf("Usage: %s <ver> <ver>\n", argv[0]); exit(1); }
printf("%d\n", versioncmp(argv[1], argv[2]));
return 0;
}
#endif

@ -1,966 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "dpkg.h"
#include "memory.h"
// enlarge this if britney has issues parsing packages
// (e.g. very slow installability checks)
#define SIZEOFHASHMAP 16
/* #define DIAGNOSE 1 */
#define insert_packagenamelist(x,y) insert_l_packagenamelist(x,y,__LINE__)
static void free_dependency(dependency *dep);
static void free_collected_package(dpkg_collected_package *pkg);
static collpackagelist **get_matching_low(collpackagelist **addto,
dpkg_packages *pkgs, dependency *dep, int line);
static collpackagelist *get_matching(dpkg_packages *pkgs, deplist *depopts, int line);
static deplist *read_deplist(char **buf, char sep, char end);
static dependency *read_dependency(char **buf, char *end);
static void add_virtualpackage(virtualpkgtbl *vpkgs, char *package,
char *version, char *multiarch,
dpkg_collected_package *cpkg);
static void remove_virtualpackage(virtualpkgtbl *vpkgs, char *pkgname,
dpkg_collected_package *cpkg);
static char *read_packagename(char **buf, char *end);
static char *read_until_char(char **buf, char *end);
static int checkinstallable(dpkg_packages *pkgs, collpackagelist *instoneof);
// implemented in dpkg-lib.c
int cmpversions(char *left, int op, char *right);
#define block_malloc(s) block_malloc2(s, __LINE__)
static int dependency_counts[] = { 1, 1, 0, 0 };
#define SMB_SIZE (1<<22)
struct stringmemblock {
struct stringmemblock *next;
size_t last;
char mem[SMB_SIZE];
};
static struct stringmemblock *stringmemory = NULL;
static int stringmemorycount = 0;
static const unsigned long stringmemblocksizekib = (unsigned long) sizeof(struct stringmemblock) / 1024;
static char *my_strdup(char *foo) {
struct stringmemblock *which;
size_t len;
if (!foo) return NULL;
len = strlen(foo) + 1;
if (len > SMB_SIZE) return strdup(foo);
for (which = stringmemory; which; which = which->next) {
if (SMB_SIZE - which->last > len + 1) {
break;
}
}
if (!which) {
which = malloc(sizeof(struct stringmemblock));
if (!which) return NULL;
MDEBUG1_ONLY(fprintf(stderr,
"ALLOC: string memblock %d (%lu KiB, %lu KiB total)\n",
stringmemorycount, stringmemblocksizekib,
(stringmemorycount+1) * stringmemblocksizekib));
memset(which->mem, 0, SMB_SIZE);
which->last = 0;
which->next = stringmemory;
stringmemory = which;
stringmemorycount++;
}
strcpy(&which->mem[which->last], foo);
foo = &which->mem[which->last];
which->last += len;
return foo;
}
/* DIE **/
static void die(char *orig_msg) {
char *msg = my_strdup(orig_msg);
if (*msg && msg[strlen(msg)-1] == ':') {
msg[strlen(msg)-1] = '\0';
perror(msg);
} else {
printf("%s\n", msg);
}
abort();
}
/*************************************************************************
* Basic Package Operations
*/
static dpkg_collected_package *new_collected_package(dpkg_package *pkg) {
dpkg_collected_package *result;
result = block_malloc(sizeof(dpkg_collected_package));
if (result == NULL) die("new_collected_package alloc:");
result->pkg = pkg;
result->installed = 0;
result->conflicted = 0;
result->installable = UNKNOWN;
result->mayaffect = NULL;
return result;
}
static void free_collected_package(dpkg_collected_package *cpkg) {
if (cpkg == NULL) return;
cpkg->pkg = NULL;
free_packagenamelist(cpkg->mayaffect);
cpkg->mayaffect = NULL;
block_free(cpkg, sizeof(dpkg_collected_package));
}
LIST_IMPL(deplist, dependency*, free_dependency, block_malloc, block_free);
LIST_IMPL(deplistlist, deplist*, free_deplist, block_malloc, block_free);
LIST_IMPLX(packagenamelist, char*, KEEP(char*));
LIST_IMPL(ownedpackagenamelist, char*, KEEP(char*), block_malloc, block_free);
/* ownedpackagenamelist stores the packagename in the string store */
static int packagecmp(dpkg_package *l, dpkg_package *r) {
if (l->priority < r->priority) return -1;
if (l->priority > r->priority) return +1;
return strcmp(l->package, r->package);
}
/* container for existing pkgs */
LIST_IMPL(packagelist, dpkg_package *, KEEP(dpkg_package *), block_malloc, block_free);
LIST_IMPLX(collpackagelist, dpkg_collected_package *,
KEEP(dpkg_collected_package *))
#define insert_collpackagelist(x,y) insert_l_collpackagelist(x,y,__LINE__)
/*************************************************************************
* Operations on distributions (collections of packages)
*/
dpkg_packages *new_packages(char *arch) {
dpkg_packages *result;
result = block_malloc(sizeof(dpkg_packages));
if (result == NULL) die("new_packages alloc:");
result->arch = my_strdup(arch);
result->packages = new_packagetbl();
result->virtualpkgs = new_virtualpkgtbl();
return result;
}
void add_package(dpkg_packages *pkgs, dpkg_package *pkg)
{
ownedpackagenamelist *v;
dpkg_collected_package *cpkg;
if (lookup_packagetbl(pkgs->packages, pkg->package) != NULL)
return;
cpkg = new_collected_package(pkg);
add_packagetbl(pkgs->packages, cpkg->pkg->package, cpkg);
add_virtualpackage(pkgs->virtualpkgs, cpkg->pkg->package,
cpkg->pkg->version, cpkg->pkg->multiarch, cpkg);
for (v = cpkg->pkg->provides; v != NULL; v = v->next) {
add_virtualpackage(pkgs->virtualpkgs, v->value, NULL, NULL, cpkg);
}
}
void remove_package(dpkg_packages *pkgs, dpkg_collected_package *cpkg) {
ownedpackagenamelist *v;
packagenamelist *aff;
dpkg_collected_package *p;
for (aff = cpkg->mayaffect; aff != NULL; aff = aff->next) {
p = lookup_packagetbl(pkgs->packages, aff->value);
if (p == NULL) continue;
p->installable = UNKNOWN;
}
p = remove_packagetbl(pkgs->packages, cpkg->pkg->package);
if (p != cpkg) return;
remove_virtualpackage(pkgs->virtualpkgs, cpkg->pkg->package, cpkg);
for (v = cpkg->pkg->provides; v != NULL; v = v->next) {
remove_virtualpackage(pkgs->virtualpkgs, v->value, cpkg);
}
free_collected_package(cpkg);
}
void free_packages(dpkg_packages *pkgs) {
if (pkgs == NULL) return;
/* block_free(pkgs->arch); */
free_packagetbl(pkgs->packages);
free_virtualpkgtbl(pkgs->virtualpkgs);
block_free(pkgs, sizeof(dpkg_packages));
}
HASH_IMPL(packagetbl, char *, dpkg_collected_package *, SIZEOFHASHMAP, strhash, strcmp,
KEEP(char*),free_collected_package);
HASH_IMPL(virtualpkgtbl, char *, virtualpkg *, SIZEOFHASHMAP, strhash, strcmp,
KEEP(char*), free_virtualpkg);
/* dpkg_provision refers to memory allocated elsewhere */
LIST_IMPL(virtualpkg, dpkg_provision, KEEP(dpkg_provision), block_malloc, block_free);
static void remove_virtualpackage(virtualpkgtbl *vpkgs, char *pkgname,
dpkg_collected_package *cpkg)
{
virtualpkg *list;
virtualpkg **where;
list = lookup_virtualpkgtbl(vpkgs, pkgname);
assert(list != NULL);
where = &list;
while((*where)->value.pkg != cpkg) {
where = &(*where)->next;
assert(*where != NULL);
}
delete_virtualpkg(where);
if (list == NULL) {
remove_virtualpkgtbl(vpkgs, pkgname);
} else {
replace_virtualpkgtbl(vpkgs, pkgname, list);
}
}
static void add_virtualpackage(virtualpkgtbl *vpkgs, char *package,
char *version, char *multiarch,
dpkg_collected_package *cpkg)
{
dpkg_provision value;
virtualpkg *list, **addto;
int shouldreplace;
value.pkg = cpkg;
value.version = version;
value.multiarch = multiarch;
list = lookup_virtualpkgtbl(vpkgs, package);
shouldreplace = (list != NULL);
addto = &list;
while (*addto != NULL
&& packagecmp(cpkg->pkg, (*addto)->value.pkg->pkg) >= 0)
{
addto = &(*addto)->next;
}
insert_virtualpkg(addto, value);
if (shouldreplace) {
replace_virtualpkgtbl(vpkgs, package, list);
/* old list is included in new list, so we don't need to free */
} else {
add_virtualpkgtbl(vpkgs, package, list);
}
}
/*************************************************************************
* Parsing Helper Functions
*/
ownedpackagenamelist *read_packagenames(char *buf) {
ownedpackagenamelist *result = NULL;
ownedpackagenamelist **addto = &result;
DEBUG_ONLY( char *strend = buf + strlen(buf); )
char *sub;
while ((sub = my_strdup(read_packagename(&buf, ",")))) {
insert_ownedpackagenamelist(addto, sub);
addto = &(*addto)->next;
while(isspace(*buf)) buf++;
if (*buf == ',') {
buf++;
continue;
}
if (*buf == '\0') {
break;
}
die("read_packagenames no/bad seperator");
}
DEBUG_ONLY( assert(buf <= strend); )
return result;
}
static char *read_until_char(char **buf, char *end) {
static char *result = NULL;
char *start;
DEBUG_ONLY( char *strend = *buf + strlen(*buf); )
int n;
while(isspace(**buf)) (*buf)++;
start = *buf;
while (**buf && !isspace(**buf) && strchr(end, **buf) == NULL) {
(*buf)++;
}
n = *buf - start;
if (n == 0) return NULL;
result = realloc(result, n + 1);
if (result == NULL) die("read_until_char alloc:");
strncpy(result, start, n);
result[n] = '\0';
while(isspace(**buf)) (*buf)++;
DEBUG_ONLY( assert(*buf <= strend); )
return result;
}
static char *read_packagename(char **buf, char *end) {
return read_until_char(buf, end);
}
deplist *read_dep_and(char *buf) {
return read_deplist(&buf, ',', '\0');
}
static deplist *read_deplist(char **buf, char sep, char end) {
deplist *result = NULL;
deplist **addto = &result;
char separs[3] = { sep, end, '\0' };
DEBUG_ONLY( char *strend = *buf + strlen(*buf); )
dependency *sub;
while ((sub = read_dependency(buf, separs))) {
insert_deplist(addto, sub);
addto = &(*addto)->next;
while(isspace(**buf)) (*buf)++;
if (**buf == sep) {
(*buf)++;
continue;
}
if (**buf == '\0' || **buf == end) {
break;
}
die("read_deplist no/bad seperator");
}
DEBUG_ONLY( assert(*buf <= strend); )
return result;
}
deplistlist *read_dep_andor(char *buf) {
deplistlist *result = NULL;
deplistlist **addto = &result;
deplist *sub;
DEBUG_ONLY( char *strend = buf + strlen(buf); )
while ((sub = read_deplist(&buf, '|', ','))) {
insert_deplistlist(addto, sub);
addto = &(*addto)->next;
if (*buf == ',') buf++;
}
DEBUG_ONLY( assert(buf <= strend); )
return result;
}
static dependency *read_dependency(char **buf, char *end) {
dependency *dep;
char *name;
char newend[11];
DEBUG_ONLY( char *strend = *buf + strlen(*buf); )
assert(strlen(end) <= 8);
newend[0] = '('; newend[1] = ':'; strcpy(newend + 2, end);
name = my_strdup(read_until_char(buf, newend));
if (name == NULL) return NULL;
dep = block_malloc(sizeof(dependency));
if (dep == NULL) die("read_dependency alloc 1:");
dep->package = name;
if (**buf == ':') {
(*buf)++;
dep->archqual = my_strdup(read_until_char(buf, newend));
if (dep->archqual == NULL) return NULL;
} else
dep->archqual = NULL;
while(isspace(**buf)) (*buf)++;
if (**buf != '(') {
dep->op = dr_NOOP;
dep->version = NULL;
} else {
(*buf)++;
while(isspace(**buf)) (*buf)++;
/* << , <= , = , >= , >> */
if (**buf == '<') {
(*buf)++;
if (**buf == '<') {
dep->op = dr_LT;
(*buf)++;
} else if (**buf == '=') {
dep->op = dr_LTEQ;
(*buf)++;
} else {
/* The forms `<' and `>' were used to mean earlier/later or
* equal, rather than strictly earlier/later, so they should
* not appear in new packages (though `dpkg' still supports
* them).
*/
dep->op = dr_LTEQ;
}
} else if (**buf == '>') {
(*buf)++;
if (**buf == '>') {
dep->op = dr_GT;
(*buf)++;
} else if (**buf == '=') {
dep->op = dr_GTEQ;
(*buf)++;
} else {
dep->op = dr_GTEQ;
}
} else if (**buf == '=') {
dep->op = dr_EQ;
(*buf)++;
if (**buf == '>') {
dep->op = dr_GTEQ;
(*buf)++;
} else if (**buf == '<') {
dep->op = dr_LTEQ;
(*buf)++;
}
} else {
/* treat it as an implicit = :( */
dep->op = dr_EQ;
/* would prefer to: die("read_dependency unknown version op"); */
}
while (isspace(**buf)) (*buf)++;
newend[0] = ')'; strcpy(newend + 1, end);
dep->version = my_strdup(read_until_char(buf, newend));
while (isspace(**buf)) (*buf)++;
if (dep->version == NULL) die("read_dependency: no version");
if (**buf != ')') die("read_dependency: unterminated version");
(*buf)++;
}
DEBUG_ONLY( assert(*buf <= strend); )
return dep;
}
static void free_dependency(dependency *dep) {
if (dep == NULL) return;
/* block_free(dep->package); */
/* if (dep->version) block_free(dep->version); */
block_free(dep, sizeof(dependency));
}
/*************************************************************************
* Installability Checking
*/
static collpackagelist **get_matching_low(collpackagelist **addto,
dpkg_packages *pkgs, dependency *dep, int line)
{
virtualpkg *vpkg;
for (vpkg = lookup_virtualpkgtbl(pkgs->virtualpkgs, dep->package);
vpkg != NULL;
vpkg = vpkg->next)
{
int add;
add = 0;
if (dep->op == dr_NOOP) {
add = 1;
} else if (vpkg->value.version != NULL) {
if (cmpversions(vpkg->value.version, dep->op, dep->version)) {
add = 1;
}
}
if (dep->archqual != NULL) {
if (strcmp(dep->archqual, "any") == 0) {
if (vpkg->value.multiarch == NULL || strcmp(vpkg->value.multiarch, "allowed") != 0)
add = 0;
} else
add = 0;
}
if (add) {
insert_l_collpackagelist(addto, vpkg->value.pkg, line);
addto = &(*addto)->next;
}
}
return addto;
}
static collpackagelist *get_matching(dpkg_packages *pkgs, deplist *depopts, int line) {
collpackagelist *list = NULL;
collpackagelist **addto = &list;
for(; depopts != NULL; depopts = depopts->next) {
addto = get_matching_low(addto, pkgs, depopts->value, line);
}
return list;
}
typedef struct instonelist instonelist;
struct instonelist {
collpackagelist *curX;
collpackagelist *instoneX;
int expandedX;
struct instonelist *nextX, *prevX, *cutoffX;
};
#define I1CUR(i1) ((i1)->curX)
#define I1INSTONE(i1) ((i1)->instoneX)
#define I1CUTOFF(i1) ((i1)->cutoffX)
#define I1NEXT(i1) ((i1)->nextX) /* can be modified ! */
#define I1PREV(i1) ((i1)->prevX)
#define I1EXPANDED(i1) ((i1)->expandedX)
static instonelist *insert_instonelist(instonelist *where, collpackagelist *instone);
static void trim_instonelist_after(instonelist *first);
static void free_instonelist(instonelist *l);
static instonelist *insert_instonelist(instonelist *old, collpackagelist *instone)
{
instonelist *n = block_malloc(sizeof(instonelist));
if (n == NULL)
die("insert_instonelist alloc:");
n->curX = NULL;
n->instoneX = instone;
n->cutoffX = NULL;
n->nextX = (old ? old->nextX : NULL);
n->prevX = old;
n->expandedX = 0;
if (old) old->nextX = n;
if (n->nextX) n->nextX->prevX = n;
return n;
}
static void trim_instonelist_after(instonelist *first) {
if (!first->nextX) return;
first->nextX->prevX = NULL;
free_instonelist(first->nextX);
first->nextX = NULL;
}
static void free_instonelist(instonelist *l) {
instonelist *p, *k;
if (!l) return;
for (p = l; p->nextX; p = p->nextX);
do {
k = p;
p = k->prevX;
free_collpackagelist(k->instoneX);
block_free(k, sizeof(instonelist));
} while (k != l);
}
static int caninstall(dpkg_packages *pkgs, dpkg_collected_package *cpkg) {
collpackagelist *conflicts;
collpackagelist *conf;
int okay;
if (cpkg->installed > 0) return 1;
if (cpkg->conflicted > 0) return 0;
conflicts = get_matching(pkgs, cpkg->pkg->conflicts, __LINE__);
okay = 1;
for (conf = conflicts; conf != NULL; conf = conf->next) {
if (conf->value->installed > 0) {
okay = 0;
break;
}
}
free_collpackagelist(conflicts);
return okay;
}
static void install(dpkg_packages *pkgs, dpkg_collected_package *cpkg) {
if (cpkg->installed == 0) {
collpackagelist *conflicts = get_matching(pkgs, cpkg->pkg->conflicts, __LINE__);
collpackagelist *conf;
for (conf = conflicts; conf != NULL; conf = conf->next) {
if (conf->value == cpkg) continue;
assert(conf->value->installed == 0);
conf->value->conflicted++;
}
free_collpackagelist(conflicts);
}
assert(cpkg->conflicted == 0);
cpkg->installed++;
}
static void uninstall(dpkg_packages *pkgs, dpkg_collected_package *cpkg) {
assert(cpkg->installed > 0);
assert(cpkg->conflicted == 0);
cpkg->installed--;
if (cpkg->installed == 0) {
collpackagelist *conflicts = get_matching(pkgs, cpkg->pkg->conflicts, __LINE__);
collpackagelist *conf;
for (conf = conflicts; conf != NULL; conf = conf->next) {
if (conf->value == cpkg) continue;
assert(conf->value->installed == 0);
assert(conf->value->conflicted > 0);
conf->value->conflicted--;
}
free_collpackagelist(conflicts);
}
}
int checkinstallable2(dpkg_packages *pkgs, char *pkgname) {
dpkg_collected_package *cpkg = lookup_packagetbl(pkgs->packages, pkgname);
collpackagelist *cpl = NULL;
if (cpkg == NULL) return 0;
insert_collpackagelist(&cpl, cpkg);
/* cpl gets freed in checkinstallable :-/ */
return checkinstallable(pkgs, cpl);
}
static void debug_checkinstallable(FILE *out, instonelist *list,
instonelist *last, instonelist *pointer)
{
instonelist *l;
fprintf(out, "Status:");
/* codes: | = multiple options here
* @ = no options can satisfy this dep
* + = dependencies that can be expanded have been
* * = nothing selected yet
* > = where pointer points
* ^ = the cut point for where we are
*/
for (l = list; ; l = I1NEXT(l)) {
fprintf(out, " ");
if (l == pointer) fprintf(out, ">");
if (l == I1CUTOFF(pointer)) fprintf(out, "^");
if (I1INSTONE(l) == NULL) {
fprintf(out, "@");
} else {
if (I1INSTONE(l)->next != NULL) {
fprintf(out, "|");
}
if (I1EXPANDED(l)) {
fprintf(out, "+");
}
if (I1CUR(l) == NULL) {
fprintf(out, "*%s", I1INSTONE(l)->value->pkg->package);
} else {
fprintf(out, "%s", I1CUR(l)->value->pkg->package);
}
}
if (l == last) break;
}
fprintf(out, " ###\n");
fflush(out);
}
static int checkinstallable(dpkg_packages *pkgs, collpackagelist *instoneof) {
/* We use pkg->installed, pkg->conflicted to note how many
* times we've used this pkg to satisfy a dependency or installed
* a package that conflicts with it.
* Thus: pkg->installed == 0, or pkg->conflicted == 0
*
* We assume these are okay initially, aren't being played with
* concurrently elsewhere, and make sure they're still okay when
* we return.
*/
instonelist *list;
instonelist *last;
instonelist *pointer;
unsigned long counter = 10000000;
{
collpackagelist *cpkg;
for (cpkg = instoneof; cpkg; cpkg = cpkg->next) {
if (cpkg->value->installable == YES) {
free_collpackagelist(instoneof);
return 1;
}
}
}
list = insert_instonelist(NULL, instoneof);
last = list;
pointer = list;
while(--counter > 0 && pointer) {
deplistlist *dep;
dpkg_collected_package *instpkg; /* convenient alias */
int i;
#ifndef NDEBUG
{
instonelist *p;
for (p = list; p != pointer; p = I1NEXT(p)) {
assert(p != NULL);
assert(I1CUR(p) != NULL);
assert(I1CUR(p)->value != NULL);
assert(I1CUR(p)->value->installed > 0);
assert(I1CUR(p)->value->conflicted == 0);
}
if (I1NEXT(pointer) == NULL) {
assert(pointer == last);
} else {
for (p = I1NEXT(pointer); p; p = I1NEXT(p)) {
if (I1NEXT(p) == NULL) {
assert(p == last);
}
assert(I1CUR(p) == NULL);
}
}
}
#endif
#ifdef DIAGNOSE
debug_checkinstallable(stdout, list, last, pointer);
#endif
if (I1CUR(pointer) == NULL) {
I1CUR(pointer) = I1INSTONE(pointer);
/* try to choose an already installed package if there is one */
while (I1CUR(pointer) != NULL) {
if (I1CUR(pointer)->value->installed != 0) {
break;
}
I1CUR(pointer) = I1CUR(pointer)->next;
}
if (I1CUR(pointer) == NULL) {
I1CUR(pointer) = I1INSTONE(pointer);
}
assert(I1CUR(pointer) || !I1INSTONE(pointer));
I1CUTOFF(pointer) = last;
} else {
uninstall(pkgs, I1CUR(pointer)->value);
trim_instonelist_after(I1CUTOFF(pointer));
last = I1CUTOFF(pointer);
if (I1CUR(pointer)->value->installed > 0) {
/* this dependency isn't the issue -- even doing
* nothing to satisfy it (ie, using an already
* installed package) doesn't do any good. So give up.
*/
I1CUR(pointer) = NULL;
} else {
I1CUR(pointer) = I1CUR(pointer)->next;
}
}
while(I1CUR(pointer) && !caninstall(pkgs, I1CUR(pointer)->value)) {
I1CUR(pointer) = I1CUR(pointer)->next;
}
if (I1CUR(pointer) == NULL) {
if (I1PREV(pointer) == NULL) break;
pointer = I1PREV(pointer);
continue;
}
instpkg = I1CUR(pointer)->value;
install(pkgs, instpkg);
assert(instpkg->installed > 0);
if (instpkg->installed == 1) {
/* if it's been installed exactly once, then this must've been
* the first time it was touched, so we need to look at the
* dependencies. If it's the second or later, then we don't care
* about them.
*/
/* if any of the deps can't be satisfied, don't move on */
int bother = 1;
int expanded = I1EXPANDED(pointer);
for (i = 0; i < 4; i++) {
if (!dependency_counts[i]) continue;
for (dep = instpkg->pkg->depends[i];
dep != NULL; dep = dep->next)
{
collpackagelist *thisdep = get_matching(pkgs, dep->value, __LINE__);
if (thisdep == NULL) {
bother = 0;
} else if (thisdep != NULL && thisdep->next == NULL) {
collpackagelist *x;
/* if there's only one way of fulfilling this dep,
* do it "ASAP"
*/
/* optimisation: if thisdep == foo, but the parent
* was foo|bar, then we already know "foo" is not going
* to work in this combination, and we can skip it.
*
* This deals with cases like X deps: Y|bar, bar deps: Y
* where bar is a virtual package; cf xlibs
*/
for (x = I1INSTONE(pointer); x != I1CUR(pointer); x = x->next) {
if (x->value == thisdep->value) {
bother = 0;
break;
}
}
if (I1INSTONE(pointer)->next == NULL) {
/* the parent of this entry essentially depends
* on this too, so we'll get it out of the way
* ASAP, to reduce the degree of exponentiation
* in bad cases.
*
* _However_ we only want to do this _once_ for
* any particular node.
*/
if (expanded) {
/* thisdep isn't used! */
free_collpackagelist(thisdep);
} else {
insert_instonelist(pointer, thisdep);
I1EXPANDED(pointer) = 1;
}
} else {
insert_instonelist(I1CUTOFF(pointer), thisdep);
}
if (I1NEXT(last)) last = I1NEXT(last);
assert(!I1NEXT(last));
} else {
/* otherwise it's a multi possibility dep, so do it
* at the end
*/
last = insert_instonelist(last, thisdep);
}
}
}
if (!bother) {
/* stay where we are, and try the next possibility */
continue;
}
}
pointer = I1NEXT(pointer);
}
if (counter == 0) {
unsigned int package_count = 0;
fprintf(stderr, "AIEEE: counter overflow:");
assert(pointer != NULL);
if (I1CUR(pointer) == NULL || I1CUR(pointer)->value == NULL) {
/* we're not guaranteed that pointer will make sense here */
pointer = I1PREV(pointer);
}
for (; pointer != NULL; pointer = I1PREV(pointer)) {
if (I1CUR(pointer) == NULL) {
/* should only happen at pointer, so not here */
fprintf(stderr, " >> eep, no packages at pointer <<");
continue;
}
if (I1CUR(pointer)->value == NULL) {
/* should never happen */
fprintf(stderr, " >> eep, no package selected <<");
continue;
}
/* the full list is no as interesting as the "guilty" package,
* display the number of involved packages instead */
#if 0
fprintf(stderr, " %s%s",
(I1INSTONE(pointer)->next == NULL ? "" : "|"),
I1CUR(pointer)->value->pkg->package);
#endif
package_count++;
uninstall(pkgs, I1CUR(pointer)->value);
}
fprintf(stderr, " %u involved packages.\n", package_count);
free_instonelist(list);
/* let the caller know we hit a bad failure */
return -1;
}
if (pointer == NULL) {
dpkg_collected_package *cpkg = I1CUR(list)->value;
assert(cpkg->installable != YES);
cpkg->installable = YES;
for (pointer = last; pointer != NULL; pointer = I1PREV(pointer)) {
if (I1CUR(pointer)->value->installed == 1) {
packagenamelist **p = &I1CUR(pointer)->value->mayaffect;
#if 0
while ( *p && (*p)->value < cpkg->pkg->package ) {
p = &(*p)->next;
}
if (*p == NULL || (*p)->value > cpkg->pkg->package)
#endif
{
insert_packagenamelist(p, cpkg->pkg->package);
}
}
uninstall(pkgs, I1CUR(pointer)->value);
}
free_instonelist(list);
return 1;
} else {
assert(I1CUR(list) == NULL);
free_instonelist(list);
return 0;
}
}

@ -1,139 +0,0 @@
#ifndef DPKG_H
#define DPKG_H
#include "templates.h"
#include "memory.h"
#include <stdio.h>
/**************************************************************************
* Coping with an rfc822-esque field
*/
typedef struct dpkg_entry dpkg_entry;
struct dpkg_entry {
char *name;
char *value;
};
typedef struct dpkg_paragraph dpkg_paragraph;
struct dpkg_paragraph {
int n_entries;
int n_allocated;
dpkg_entry *entry;
};
/**************************************************************************
* Coping with a package (or many pkgs) as an abstract entity
*/
typedef enum {dr_NOOP,dr_LT,dr_LTEQ,dr_EQ,dr_GTEQ,dr_GT} dependency_relation;
extern char *dependency_relation_sym[];
typedef struct dependency dependency;
struct dependency {
char *package;
char *archqual;
dependency_relation op;
char *version;
};
LIST(deplist, dependency*);
LIST(deplistlist, deplist*);
LIST(packagenamelist, char*);
LIST(ownedpackagenamelist, char*);
typedef struct dpkg_package dpkg_package;
struct dpkg_package {
char *package;
char *version;
char *multiarch;
char *source;
char *source_ver;
int priority;
int arch_all;
deplistlist *depends[4];
deplist *conflicts;
ownedpackagenamelist *provides;
dpkg_paragraph *details;
};
LIST(packagelist, dpkg_package *);
LIST(ownedpackagelist, dpkg_package *);
/**************************************************************************
* Coping with a source package (and collections thereof) as an abstract
* entity, owning a bunch of binary packages
*/
/**************************************************************************
*/
typedef struct dpkg_collected_package dpkg_collected_package;
struct dpkg_collected_package {
dpkg_package *pkg;
int installed, conflicted;
enum { UNKNOWN, YES } installable;
packagenamelist *mayaffect;
/* on update, the installability_checked of each /mayaffect/ed package
* is cleared, and the mayaffect list is cleared.
*
* note that installable = NO couldn't be maintained over adding a package
* to testing. installable = YES can be, thanks to the mayaffect list
* (once a package is removed, everything it mayaffect must be set back
* to unknown, but everything else is okay)
*/
};
LIST(collpackagelist, dpkg_collected_package *);
/**************************************************************************
*/
typedef struct dpkg_provision dpkg_provision;
struct dpkg_provision {
char *version;
char *multiarch;
dpkg_collected_package *pkg;
};
LIST(virtualpkg, dpkg_provision);
HASH(virtualpkgtbl,char *,virtualpkg *);
HASH(packagetbl,char *,dpkg_collected_package *);
typedef struct dpkg_packages dpkg_packages;
struct dpkg_packages {
char *arch;
packagetbl *packages;
virtualpkgtbl *virtualpkgs;
};
// Used by britney-py.c
void add_package(dpkg_packages *pkgs, dpkg_package *pkg);
void remove_package(dpkg_packages *pkgs, dpkg_collected_package *pkg);
dpkg_packages *new_packages(char *arch);
void free_packages(dpkg_packages *pkgs);
deplistlist *read_dep_andor(char *buf);
deplist *read_dep_and(char *buf);
ownedpackagenamelist *read_packagenames(char *buf);
int checkinstallable2(dpkg_packages *pkgs, char *pkgname);
#endif

@ -1,27 +0,0 @@
#!/usr/bin/env python
import sys
import britney
# VERSION = 0
# SECTION = 1
# SOURCE = 2
# SOURCEVER = 3
# ARCHITECTURE = 4
# PREDEPENDS = 5
# DEPENDS = 6
# CONFLICTS = 7
# PROVIDES = 8
# RDEPENDS = 9
# RCONFLICTS = 10
packages = {'phpldapadmin': ['1.0', 'web', 'phpldapadmin', '1.0', 'all', '', 'apache2 (>= 2.0)', '', '', [], []],
'apache2': ['2.0', 'web', 'apache2', '2.0', 'i386', '', '', 'phpldapadmin (<= 1.0~)', '', [], []],
}
system = britney.buildSystem('i386', packages)
print system.is_installable('phpldapadmin'), system.packages
system.remove_binary('apache2')
print system.is_installable('phpldapadmin'), system.packages
system.add_binary('apache2', ['2.0', 'web', 'apache2', '2.0', 'i386', '', '', 'phpldapadmin (<= 1.0~)', '', [], []])
print system.is_installable('phpldapadmin'), system.packages

@ -1,188 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include "templates.h"
typedef unsigned long ul;
#define SIZE (sizeof(ul) * 8)
#define ROUND_DOWN(x) ((x) & ~(SIZE-1))
#define ROUND_UP(x) ROUND_DOWN((x) + (SIZE-1))
#define NEXT_UP(x) ROUND_DOWN((x) + SIZE)
#define NEXT_DOWN(x) ROUND_DOWN((x) - 1)
#define SETBIT(s,p) \
assert( (bits[(s)/SIZE] & (p)) == (setp ? 0 : (p)) ); \
if (setp) bits[(s)/SIZE] |= (p); \
else bits[(s)/SIZE] &= ~(p)
#define GETBIT(s) (bits[ROUND_DOWN(s)/SIZE] & (1ul << (NEXT_UP(s) - s - 1)))
size_t count_free_bits_back(ul *bits, size_t s) {
size_t cnt = 0;
ul w = ROUND_DOWN(s) / SIZE;
size_t add = s % SIZE;
ul off = (~0ul) << (SIZE - add);
ul H, d;
while ((bits[w] & off) == 0) {
cnt += add;
add = SIZE;
off = ~0ul;
if (w == 0)
return cnt;
w--;
}
H = add;
add = 0;
while ((d = (H - add) / 2) > 0) {
ul offM = (off >> d) & off;
if (bits[w] & offM) {
off = offM;
H = H - d;
} else {
add = H - d;
}
}
cnt += add;
return cnt;
}
size_t count_free_bits_after(ul *bits, size_t s, size_t end) {
size_t cnt = 0;
ul w = ROUND_DOWN(s) / SIZE;
size_t add = SIZE - s % SIZE;
ul off = (~0ul) >> (SIZE - add);
ul H, d;
end /= SIZE;
while ((bits[w] & off) == 0) {
cnt += add;
add = SIZE;
off = ~0ul;
w++;
if (w == end)
return cnt;
}
H = add;
add = 0;
while ((d = (H - add) / 2) > 0) {
ul offM = off << d;
if (bits[w] & offM) {
off = offM;
H = H - d;
} else {
add = H - d;
}
}
cnt += add;
return cnt;
}
void find_long_freebits(ul *bits, size_t s, ul *start, size_t *size) {
ul clen = 0;
ul bstart = 0, blen = 0;
ul i, k;
for (i = 0; i < s; i++) {
if (bits[i] == 0) {
clen++;
} else {
if (clen > blen) {
bstart = i - clen;
blen = clen;
}
clen = 0;
}
}
if (blen == 0) return;
bstart *= SIZE; blen *= SIZE;
k = count_free_bits_back(bits, bstart);
bstart -= k; blen += k;
blen += count_free_bits_after(bits, bstart + blen, s*SIZE);
*start = bstart; *size = blen;
}
void mark_bits(ul *bits, ul s, size_t size, int setp) {
ul e = s+size;
ul rds = ROUND_DOWN(s);
ul nus = rds + SIZE;
ul rue = ROUND_UP(e);
ul patl = (~0UL) >> (s % SIZE);
ul patr = (~0UL) << (rue - e);
assert(size > 0);
/* bits[s1..e1] get touched, but bits[s1], bits[e1] only partially
*
* if s1 == e1, then bits[s1] get touched from [s%SIZE, e%SIZE)
* else
* bits[s1] gets touched from [s%SIZE, SIZE)
* bits[s2..e1) get reset completely
* bits[e1] gets touched from [0, e%SIZE)
*/
if (nus >= e) {
/* ROUND_DOWN(s) <= s < e <= NEXT_UP(s) */
SETBIT(rds, patl & patr);
} else {
/* ROUND_DOWN(s) <= s < NEXT_UP(s) <= NEXT_DOWN(e) < e */
ul rde = ROUND_DOWN(e);
SETBIT(rds, patl);
SETBIT(rde, patr);
while (nus < rde) {
SETBIT(nus, ~0UL);
nus += SIZE;
}
}
}
void print_bits(ul *bits, ul s) {
ul i;
putchar(' ');
for (i = 0; i < s * SIZE; i++) {
putchar( GETBIT(i) ? '1' : '0' );
}
}
#ifdef TESTBIN
#define X 2
int main(void) {
ul memory[X];
ul l, r;
ul k = 5;
memset(memory, 0, sizeof(memory));
for (l = 0; l < X*SIZE; l += k) {
for (r = 1; l+(r*r) < X*SIZE; r++) {
printf("%lu %lu (%lu %lu", l, r*r,
(unsigned long) count_free_bits_back(memory, X*SIZE), (unsigned long) X*SIZE);
mark_bits(memory, l, r*r, 1);
printf("; %lu %lu %lu; %lu %lu %lu;): ",
(unsigned long) count_free_bits_back(memory, X*SIZE) + l + r*r,
(unsigned long) count_free_bits_after(memory, l + r*r, X*SIZE) + l + r*r,
(unsigned long) X*SIZE,
(unsigned long) count_free_bits_back(memory, l),
(unsigned long) count_free_bits_after(memory, 0, X*SIZE),
l);
print_bits(memory, X);
printf("\n");
mark_bits(memory, l, r*r, 0);
}
}
return 0;
}
#endif

@ -1,14 +0,0 @@
#ifndef FREELIST_H
#define FREELIST_H
#include <stdlib.h>
typedef unsigned long flb_t;
void mark_bits(flb_t *bits, flb_t s, size_t size, int setp);
size_t count_free_bits_back(flb_t *bits, size_t s);
size_t count_free_bits_after(flb_t *bits, size_t s, size_t end);
void find_long_freebits(flb_t *bits, flb_t s, flb_t *start, size_t *size);
#endif

@ -1,18 +0,0 @@
<a href="README">README</a><br>
<a href="Makefile">Makefile</a><br>
<a href="assert.c">assert.c</a><br>
<a href="britney-py.c">britney-py.c</a><br>
<a href="checklib.c">checklib.c</a><br>
<a href="dpkg.c">dpkg.c</a><br>
<a href="freelist.c">freelist.c</a><br>
<a href="memory.c">memory.c</a><br>
<a href="memory2.c">memory2.c</a><br>
<a href="memory3.c">memory3.c</a><br>
<a href="dpkg-lib.cpp">dpkg-lib.cpp</a><br>
<a href="dpkg.h">dpkg.h</a><br>
<a href="freelist.h">freelist.h</a><br>
<a href="memory.h">memory.h</a><br>
<a href="templates.h">templates.h</a><br>
<a href="check_out.py">check_out.py</a><br>
<a href="check_uptodate.py">check_uptodate.py</a><br>
<a href="update_out.py">update_out.py</a><br>

@ -1,47 +0,0 @@
#ifndef MEMORY_H
#define MEMORY_H
#if 1
void *block_malloc(size_t size);
void *block_malloc2(size_t size, int pool);
void block_free(void *vmem, size_t size);
#if defined(MDEBUG)
#define MDEBUG1
#endif
#define MDEBUG1_ONLY(x)
#define MDEBUG2_ONLY(x)
#define MDEBUG3_ONLY(x)
#ifdef MDEBUG3
#define MDEBUG1
#define MDEBUG2
#undef MDEBUG3_ONLY
#define MDEBUG3_ONLY(x) x
#endif
#ifdef MDEBUG2
#define MDEBUG1
#undef MDEBUG2_ONLY
#define MDEBUG2_ONLY(x) x
#endif
#ifdef MDEBUG1
#undef MDEBUG1_ONLY
#define MDEBUG1_ONLY(x) x
#endif
MDEBUG1_ONLY( void print_memblock_summary(void); )
#else
#define block_malloc(x) malloc(x)
#define block_free(x, s) free(x)
static void print_memblock_summary(void) {}
#endif
#endif /* MEMORY_H */

@ -1,209 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include "memory.h"
#include "templates.h"
#include "freelist.h"
typedef struct chunk chunk;
struct chunk {
chunk *next; /* only used when in free_lists */
};
#define GRAN (sizeof (struct chunk))
#define ALLOC_SIZE (1 << 20)
#define MAX_CHUNK_SIZE 256
#define NUM_BLOCK_TYPES (MAX_CHUNK_SIZE / GRAN)
#ifdef MDEBUG1
#define MAX_POOLS 100
#else
#define MAX_POOLS 1
#endif
#ifdef MDEBUG1
static void freesize(void *p, size_t s) { (void)s; free(p); }
static void die(char *blah) { perror(blah); abort(); }
LIST(alloclist, chunk *);
LIST_IMPL(alloclist, chunk *, KEEP(chunk *), malloc, freesize);
void print_memblock_summary2(int size);
#endif
struct chunkpool {
chunk *ch;
MDEBUG1_ONLY( int pool_id; )
MDEBUG1_ONLY( alloclist *all; )
};
static struct chunkpool free_lists[NUM_BLOCK_TYPES][MAX_POOLS];
#ifdef MDEBUG1
static int total[NUM_BLOCK_TYPES][MAX_POOLS];
static int used[NUM_BLOCK_TYPES][MAX_POOLS];
static int allocs[NUM_BLOCK_TYPES][MAX_POOLS];
static int total_mallocs = 0;
static int total_alloc = 0;
#endif
void *block_malloc(size_t size) {
return block_malloc2(size, -1);
}
void *block_malloc2(size_t size, int pool_id) {
chunk **fl = NULL;
void *result;
int granmult;
int pool = 0;
if (size > MAX_CHUNK_SIZE || size % GRAN != 0) {
MDEBUG1_ONLY( total_mallocs++; )
return malloc(size);
}
granmult = size / GRAN;
#ifdef MDEBUG1
for (pool = 0; pool + 1 < MAX_POOLS; pool++) {
if (free_lists[granmult - 1][pool].pool_id == 0) {
free_lists[granmult - 1][pool].pool_id = pool_id;
}
if (free_lists[granmult - 1][pool].pool_id == pool_id) {
break;
}
}
#endif
fl = &free_lists[granmult - 1][pool].ch;
if (*fl == NULL)
{
chunk *new_block = malloc(ALLOC_SIZE);
chunk *p;
MDEBUG1_ONLY( int old_size = total[granmult-1][pool]; )
if (!new_block) return NULL;
MDEBUG1_ONLY( insert_alloclist(&free_lists[granmult - 1][pool].all, new_block); )
for (p = new_block; (char*)(p + granmult) <= ((char*)new_block) + ALLOC_SIZE; p += granmult) {
/* each iteration adds a new chunk to the list */
MDEBUG1_ONLY( total[granmult-1][pool]++; )
*fl = p;
fl = &p->next;
}
*fl = NULL;
fl = &free_lists[granmult - 1][pool].ch;
MDEBUG1_ONLY( assert((total[granmult-1][pool]-old_size)*size <= ALLOC_SIZE); )
MDEBUG1_ONLY( assert(total[granmult-1][pool]*(int)size - old_size > ALLOC_SIZE - (int) size); )
#ifdef MDEBUG1
// print some info
MDEBUG2_ONLY(
fprintf(stderr, "ALLOC: for size %2ld (%d:line %d), %4ld B of %4ld B used, total alloced is %8ld KiB\n", (long int) size, pool, pool_id, (long int) used[granmult-1][pool] * size, (long int) total[granmult-1][pool] * size, (long int) total_alloc / 1024);
)
assert( used[granmult-1][pool] <= (signed long) total[granmult-1][pool] );
total_alloc += ALLOC_SIZE;
#endif
}
#ifdef MDEBUG1
{
static unsigned long cnt = 0, cnt2 = 0;
if (++cnt % (1L << 20) == 0) {
if (++cnt2 % 10 == 0) {
print_memblock_summary2(0);
} else {
print_memblock_summary();
}
}
}
#endif
MDEBUG1_ONLY( used[granmult-1][pool]++; )
MDEBUG1_ONLY( allocs[granmult-1][pool]++; )
result = *fl;
*fl = (*fl)->next;
*(int *)result = ~0;
return result;
}
#ifdef MDEBUG1
static int find_closest(void *vmem, size_t size, chunk **ch, int *p) {
int pool;
*ch = NULL;
for (pool = 0; pool < MAX_POOLS; pool++) {
alloclist *a;
if (!free_lists[size/GRAN - 1][pool].all) break;
for (a = free_lists[size/GRAN - 1][pool].all; a; a = a->next) {
if (*ch < a->value && a->value <= (chunk*)vmem) {
*ch = a->value;
*p = pool;
}
}
}
assert((char*)*ch <= (char*)vmem);
if ((char*)vmem - (char*)*ch < ALLOC_SIZE) {
return 1;
} else {
return 0;
}
}
#endif
void block_free(void *vmem, size_t size) {
int pool = 0;
if (size > MAX_CHUNK_SIZE || size % GRAN != 0) {
free(vmem);
return;
}
#if MDEBUG1
{ chunk *closest;
if (!find_closest(vmem, size, &closest, &pool)) {
fprintf(stderr, "AIEE: %p + %lx < %p\n", closest, (unsigned long) ALLOC_SIZE, vmem);
assert(0);
}
}
#endif
MDEBUG1_ONLY( used[size/GRAN-1][pool]--; )
{
chunk **fl, *x;
fl = &free_lists[size/GRAN - 1][pool].ch;
x = (chunk *) vmem;
x->next = *fl;
*fl = x;
}
}
#ifdef MDEBUG1
void print_memblock_summary(void) {
print_memblock_summary2(5*1024*1024);
}
void print_memblock_summary2(int size) {
unsigned int i, j;
fprintf(stderr, "MEMORY SUMMARY:\n");
for (i = 0; i < NUM_BLOCK_TYPES; i++) {
for (j = 0; j < MAX_POOLS; j++) {
if (total[i][j] * GRAN * (i+1) < size) continue;
if (free_lists[i][j].all != NULL) {
fprintf(stderr, " pool %dB/%d:%d; %d used %d allocated (%0.1f%% of %d MiB, %0.2f%% current)\n",
(i+1) * GRAN, j, free_lists[i][j].pool_id,
used[i][j], total[i][j],
(100.0 * used[i][j]) / total[i][j],
total[i][j] * GRAN * (i+1) / 1024 / 1024,
(100.0 * used[i][j]) / allocs[i][j]);
}
}
}
}
#endif

@ -1,277 +0,0 @@
#ifndef TEMPLATE_H
#define TEMPLATE_H
#include <stdio.h>
#include <string.h>
#include "memory.h"
#undef assert
/* gcc-3.0 sucks */
#if defined(DEBUG) && defined(NDEBUG)
#error "Can't debug and notdebug both"
#endif
#if !defined(DEBUG) && !defined(NDEBUG)
#define NDEBUG
#endif
#ifdef NDEBUG
# define DEBUG_ONLY( stmt )
# define assert(x) (void)0
#else
# define DEBUG_ONLY( stmt ) stmt
# define assert(x) ((x) ? 1 : _myassertbug(__LINE__, __FILE__, #x))
extern int _myassertbug(int line, char *file, char *err);
#endif
#ifdef __STRICT_ANSI__
#define inline __inline__
#endif
static inline unsigned long strhash(const char *x, unsigned char pow) {
unsigned long i = 0;
while (*x) {
i = (i * 39 + *x) % (1UL << pow);
x++;
}
return i;
}
#define KEEP(TYPE) ((void(*)(TYPE))NULL)
#define LIST(NAME,TYPE) \
typedef struct NAME NAME; \
struct NAME { TYPE value; struct NAME *next; }; \
void insert_##NAME(NAME **where, TYPE v); \
void insert_l_##NAME(NAME **where, TYPE v, int line); \
TYPE remove_##NAME(NAME **where); \
void delete_##NAME(NAME **where); \
void free_##NAME(NAME *l)
#define LIST_IMPL_2(NAME,TYPE,FREE,LFREE) \
TYPE remove_##NAME(NAME **where) { \
NAME *next; \
TYPE res; \
assert(*where != NULL); \
next = (*where)->next; \
res = (*where)->value; \
LFREE(*where, sizeof(NAME)); \
*where = next; \
return res; \
} \
void delete_##NAME(NAME **where) { \
NAME *next; \
assert(*where != NULL); \
next = (*where)->next; \
if (FREE != NULL) (FREE)((*where)->value); \
LFREE(*where, sizeof(NAME)); \
*where = next; \
} \
void free_##NAME(NAME *l) { \
NAME *n; \
while (l != NULL) { \
n = l->next; \
if (FREE != NULL) (FREE)(l->value); \
LFREE(l, sizeof(NAME)); \
l = n; \
} \
}
#define LIST_IMPL(NAME,TYPE,FREE,LMALLOC,LFREE) \
void insert_##NAME(NAME **where, TYPE v) { \
NAME *n = *where; \
*where = LMALLOC(sizeof(NAME)); \
if (*where == NULL) \
die("insert_" #NAME " malloc:"); \
(*where)->value = v; \
(*where)->next = n; \
} \
LIST_IMPL_2(NAME,TYPE,FREE,LFREE)
#define LIST_IMPLX(NAME,TYPE,FREE) \
void insert_l_##NAME(NAME **where, TYPE v, int line) { \
NAME *n = *where; \
*where = block_malloc2(sizeof(NAME), line); \
if (*where == NULL) \
die("insert_" #NAME " malloc:"); \
(*where)->value = v; \
(*where)->next = n; \
} \
LIST_IMPL_2(NAME,TYPE,FREE,block_free)
#define HASH(TYPE, KEY, VALUE) \
typedef struct TYPE TYPE; \
typedef struct TYPE##_iter TYPE##_iter; \
struct TYPE##_iter { \
unsigned long i; TYPE *h; KEY k; VALUE v; \
}; \
TYPE *new_##TYPE(void); \
void free_##TYPE(TYPE *h); \
TYPE##_iter first_##TYPE(TYPE *h); \
TYPE##_iter next_##TYPE(TYPE##_iter i); \
int done_##TYPE(TYPE##_iter i); \
\
void iterate_##TYPE(TYPE *h, void (*itf)(TYPE*,VALUE,void*), \
void *data); \
VALUE lookup_##TYPE(TYPE *h, KEY k); \
void add_##TYPE(TYPE *h, KEY k, VALUE v); \
VALUE replace_##TYPE(TYPE *h, KEY k, VALUE v); \
VALUE remove_##TYPE(TYPE *h, KEY k)
#define HASH_MAGIC (0x22DEAD22)
#define HASH_IMPL(TYPE, KEY, VALUE, POW2, HASH, CMP, FREEK, FREEV) \
struct TYPE { \
unsigned long magic; \
unsigned long size; \
unsigned long n_used; \
unsigned long n_collisions; \
struct { KEY key; VALUE value; } *hash; \
}; \
TYPE *new_##TYPE(void) { \
size_t i; \
TYPE *h = malloc(sizeof(TYPE)); \
if (h == NULL) die("new_" #TYPE " malloc:"); \
\
h->magic = HASH_MAGIC; \
h->size = (1 << POW2); \
h->n_used = 0; \
h->n_collisions = 0; \
h->hash = malloc(sizeof(*h->hash) * h->size ); \
if (h == NULL) die("new_" #TYPE " hash malloc:"); \
\
for (i = 0; i < h->size; i++) { \
h->hash[i].key = NULL; \
h->hash[i].value = NULL; \
} \
\
return h; \
} \
\
void free_##TYPE(TYPE *h) { \
size_t i; \
if (h == NULL) return; \
assert(h->magic == HASH_MAGIC); \
/* printf("Freeing: size: %lu used: %lu coll: %lu\n", */ \
/* h->size, h->n_used, h->n_collisions); */ \
h->magic = ~HASH_MAGIC; \
for (i = 0; i < h->size; i++) { \
if (FREEK && h->hash[i].key) \
(FREEK)(h->hash[i].key); \
if (FREEV && h->hash[i].value) \
(FREEV)(h->hash[i].value); \
} \
free(h->hash); \
free(h); \
} \
\
void iterate_##TYPE(TYPE *h, void (*itf)(TYPE*,VALUE,void*), \
void *data) \
{ \
TYPE##_iter x; \
for (x = first_##TYPE(h); \
!done_##TYPE(x); \
x = next_##TYPE(x)) \
{ \
itf(h, x.v, data); \
} \
} \
\
TYPE##_iter first_##TYPE(TYPE *h) { \
TYPE##_iter i; \
i.i = 0; \
i.h = h; \
return next_##TYPE(i); \
} \
\
TYPE##_iter next_##TYPE(TYPE##_iter i) { \
assert(i.h->magic == HASH_MAGIC); \
while(i.i < i.h->size) { \
if (i.h->hash[i.i].value != NULL) { \
i.k = i.h->hash[i.i].key; \
i.v = i.h->hash[i.i].value; \
i.i++; \
return i; \
} \
i.i++; \
} \
i.h = NULL; \
return i; \
} \
\
int done_##TYPE(TYPE##_iter i) { \
assert(i.h == NULL || i.h->magic == HASH_MAGIC); \
assert(i.h == NULL || (i.k != NULL && i.v != NULL)); \
assert(i.h == NULL || (0 < i.i && i.i <= i.h->size)); \
return i.h == NULL; \
} \
\
VALUE lookup_##TYPE(TYPE *h, KEY k) { \
int i = HASH(k, POW2); \
assert(h->magic == HASH_MAGIC); \
assert(h->n_used < h->size); /* ensure termination */ \
while(h->hash[i].key) { \
if ((CMP)(h->hash[i].key, k) == 0) { \
if (h->hash[i].value != NULL) { \
return h->hash[i].value; \
} \
} \
i = (i + 1) % (1 << POW2); \
} \
return NULL; \
} \
\
void add_##TYPE(TYPE *h, KEY k, VALUE v) { \
int i = HASH(k, POW2); \
assert(h->magic == HASH_MAGIC); \
assert(h->n_used < h->size); /* ensure termination */ \
assert(v != NULL); \
while(h->hash[i].value) { \
assert((CMP)(h->hash[i].key, k) != 0); \
i = (i + 1) % (1 << POW2); \
h->n_collisions++; \
} \
if (FREEK != NULL && h->hash[i].key) \
FREEK(h->hash[i].key); \
h->n_used++; \
h->hash[i].key = k; \
h->hash[i].value = v; \
} \
\
VALUE replace_##TYPE(TYPE *h, KEY k, VALUE v) { \
VALUE tmp; \
int i = HASH(k,POW2); \
assert(h->magic == HASH_MAGIC); \
assert(v != NULL); \
while(h->hash[i].key) { \
if ((CMP)(h->hash[i].key, k) == 0) break; \
i = (i + 1) % (1 << POW2); \
} \
assert(h->hash[i].value != NULL); \
tmp = h->hash[i].value; \
h->hash[i].key = k; \
h->hash[i].value = v; \
return tmp; \
} \
\
VALUE remove_##TYPE(TYPE *h, KEY k) { \
VALUE tmp; \
int i = HASH(k, POW2); \
assert(h->magic == HASH_MAGIC); \
while(h->hash[i].key) { \
if ((CMP)(h->hash[i].key, k) == 0) break; \
i = (i + 1) % (1 << POW2); \
} \
tmp = h->hash[i].value; \
h->hash[i].value = NULL; \
if (tmp != NULL) h->n_used--; \
return tmp; \
}
#endif

@ -1,13 +0,0 @@
remove_source(name) source exists
remove_sourcetbl
remove the binaries?? but how?
upgrade_source(dpkg_source) source may exist
remove_source(src->name)
add the new source to the table thing
foreach arch, binary: add binary to arch pkgs
upgrade_architecture(dpkg_source, arch) source exists, binary may
find source
foreach binary in <arch>: remove it
foreach binary in new <arch>: add it
(remove_architecture, upgrade_source_only; could also be used, theoretically)
Loading…
Cancel
Save