|
|
|
@ -34,7 +34,6 @@ static char *read_packagename(char **buf, char *end);
|
|
|
|
|
static char *read_until_char(char **buf, char *end);
|
|
|
|
|
void add_package(dpkg_packages *pkgs, dpkg_package *pkg);
|
|
|
|
|
void remove_package(dpkg_packages *pkgs, dpkg_collected_package *pkg);
|
|
|
|
|
static dpkg_source_note *copy_source_note(dpkg_source_note *srcn);
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
static inline void *bm(size_t s, int n) { void *res = block_malloc(s); fprintf(stderr, "ALLOCED: %d %p %lu\n", n, res, s); return res; }
|
|
|
|
@ -123,16 +122,6 @@ static void die(char *orig_msg) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void write_paragraph(FILE *f, dpkg_paragraph *p) {
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < p->n_entries; i++) {
|
|
|
|
|
fprintf(f, "%s: %s", p->entry[i].name, p->entry[i].value);
|
|
|
|
|
}
|
|
|
|
|
fprintf(f, "\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void free_paragraph(dpkg_paragraph *p) {
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
@ -195,8 +184,6 @@ static void free_package(dpkg_package *pkg) {
|
|
|
|
|
block_free(pkg, sizeof(dpkg_package));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void freesize(void *p, size_t s) { (void)s; free(p); }
|
|
|
|
|
|
|
|
|
|
LIST_IMPL(deplist, dependency*, free_dependency, block_malloc, block_free);
|
|
|
|
|
LIST_IMPL(deplistlist, deplist*, free_deplist, block_malloc, block_free);
|
|
|
|
|
|
|
|
|
@ -280,35 +267,6 @@ void remove_package(dpkg_packages *pkgs, dpkg_collected_package *cpkg) {
|
|
|
|
|
free_collected_package(cpkg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dpkg_packages *get_architecture(dpkg_sources *srcs, char *arch) {
|
|
|
|
|
int i, arch_index;
|
|
|
|
|
dpkg_packages *result;
|
|
|
|
|
sourcetbl_iter srci;
|
|
|
|
|
ownedpackagelist *p;
|
|
|
|
|
|
|
|
|
|
arch_index = -1;
|
|
|
|
|
for (i = 0; i < srcs->n_arches; i++) {
|
|
|
|
|
if (strcmp(srcs->archname[i], arch) == 0) {
|
|
|
|
|
arch_index = i;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (arch_index == -1) die("get_architecture: unknown arch");
|
|
|
|
|
|
|
|
|
|
result = new_packages(arch);
|
|
|
|
|
|
|
|
|
|
for (srci = first_sourcetbl(srcs->sources);
|
|
|
|
|
!done_sourcetbl(srci);
|
|
|
|
|
srci = next_sourcetbl(srci))
|
|
|
|
|
{
|
|
|
|
|
for (p = srci.v->packages[arch_index]; p != NULL; p = p->next) {
|
|
|
|
|
add_package(result, p->value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void free_packages(dpkg_packages *pkgs) {
|
|
|
|
|
if (pkgs == NULL) return;
|
|
|
|
|
/* block_free(pkgs->arch); */
|
|
|
|
@ -1096,304 +1054,3 @@ int checkinstallable(dpkg_packages *pkgs, collpackagelist *instoneof) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************/
|
|
|
|
|
|
|
|
|
|
HASH_IMPL(sourcetbl, char *, dpkg_source *, SIZEOFHASHMAP, strhash, strcmp,
|
|
|
|
|
KEEP(char*), free_source);
|
|
|
|
|
|
|
|
|
|
void free_source(dpkg_source *s) {
|
|
|
|
|
int i;
|
|
|
|
|
if (s == NULL) return;
|
|
|
|
|
assert(s->owner != NULL); /* shouldn't have allocated it */
|
|
|
|
|
/* block_free(s->package); */
|
|
|
|
|
/* block_free(s->version); */
|
|
|
|
|
free_paragraph(s->details);
|
|
|
|
|
for (i = 0; i < s->owner->n_arches; i++) {
|
|
|
|
|
free_ownedpackagelist(s->packages[i]);
|
|
|
|
|
}
|
|
|
|
|
block_free(s->packages, s->owner->n_arches * sizeof(ownedpackagelist*));
|
|
|
|
|
block_free(s, sizeof(dpkg_source));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************/
|
|
|
|
|
|
|
|
|
|
HASH_IMPL(sourcenotetbl, char *, dpkg_source_note *, SIZEOFHASHMAP, strhash, strcmp,
|
|
|
|
|
KEEP(char*), free_source_note);
|
|
|
|
|
|
|
|
|
|
dpkg_source_note *new_source_note(dpkg_source *src, int n_arches) {
|
|
|
|
|
dpkg_source_note *result = block_malloc(sizeof(dpkg_source_note));
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (result == NULL) die("new_source_note alloc 1:");
|
|
|
|
|
result->source = src;
|
|
|
|
|
result->n_arches = n_arches;
|
|
|
|
|
result->binaries = block_malloc(n_arches * sizeof(packagelist*));
|
|
|
|
|
if (result->binaries == NULL) die("new_source_note alloc 2:");
|
|
|
|
|
for (i = 0; i < n_arches; i++) {
|
|
|
|
|
result->binaries[i] = NULL;
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void free_source_note(dpkg_source_note *srcn) {
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (srcn == NULL) return;
|
|
|
|
|
|
|
|
|
|
if (srcn->binaries != NULL) {
|
|
|
|
|
for (i = 0; i < srcn->n_arches; i++) {
|
|
|
|
|
free_packagelist(srcn->binaries[i]);
|
|
|
|
|
}
|
|
|
|
|
block_free(srcn->binaries, sizeof(packagelist*) * srcn->n_arches);
|
|
|
|
|
}
|
|
|
|
|
block_free(srcn, sizeof(dpkg_source_note));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
static int is_sources_note(dpkg_sources_note *srcsn) {
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
assert(srcsn != NULL);
|
|
|
|
|
assert(srcsn->magic == 0xa1eebabe);
|
|
|
|
|
assert(srcsn->pkgs != NULL);
|
|
|
|
|
for (i = 0; i < srcsn->n_arches; i++) {
|
|
|
|
|
assert(srcsn->pkgs[i] != NULL && srcsn->archname[i] != NULL);
|
|
|
|
|
assert(strcmp(srcsn->archname[i], srcsn->pkgs[i]->arch) == 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
dpkg_sources_note *new_sources_note(int n_arches, char **archname) {
|
|
|
|
|
dpkg_sources_note *result = block_malloc(sizeof(dpkg_sources_note));
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (result == NULL) die("new_sources_note alloc 1:");
|
|
|
|
|
result->magic = 0xA1EEBABE;
|
|
|
|
|
result->sources = new_sourcenotetbl();
|
|
|
|
|
result->pkgs = block_malloc(n_arches * sizeof(dpkg_packages*));
|
|
|
|
|
if (result->pkgs == NULL) die("new_sources_note alloc 2:");
|
|
|
|
|
result->archname = block_malloc(n_arches * sizeof(char*));
|
|
|
|
|
if (result->archname == NULL) die("new_sources_note alloc 3:");
|
|
|
|
|
|
|
|
|
|
result->n_arches = n_arches;
|
|
|
|
|
for (i = 0; i < n_arches; i++) {
|
|
|
|
|
result->archname[i] = my_strdup(archname[i]);
|
|
|
|
|
result->pkgs[i] = new_packages(result->archname[i]);
|
|
|
|
|
}
|
|
|
|
|
result->undo = NULL;
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void free_sources_note(dpkg_sources_note *srcsn) {
|
|
|
|
|
int i;
|
|
|
|
|
if (srcsn == NULL) return;
|
|
|
|
|
assert(is_sources_note(srcsn));
|
|
|
|
|
srcsn->magic = 0xBABEA1EE;
|
|
|
|
|
free_sourcenotetbl(srcsn->sources);
|
|
|
|
|
for (i = 0; i < srcsn->n_arches; i++) {
|
|
|
|
|
free_packages(srcsn->pkgs[i]);
|
|
|
|
|
/* block_free(srcsn->archname[i]); */
|
|
|
|
|
}
|
|
|
|
|
block_free(srcsn->pkgs, sizeof(dpkg_packages*) * srcsn->n_arches);
|
|
|
|
|
block_free(srcsn->archname, sizeof(char*) * srcsn->n_arches);
|
|
|
|
|
free_source_note_listlist(srcsn->undo);
|
|
|
|
|
block_free(srcsn, sizeof(dpkg_sources_note));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void new_op(dpkg_sources_note *srcsn) {
|
|
|
|
|
assert(is_sources_note(srcsn));
|
|
|
|
|
insert_source_note_listlist(&srcsn->undo, NULL);
|
|
|
|
|
}
|
|
|
|
|
static void save_source_note(dpkg_sources_note *srcsn, dpkg_source_note *srcn) {
|
|
|
|
|
source_note_list **where;
|
|
|
|
|
assert(is_sources_note(srcsn));
|
|
|
|
|
assert(srcsn->undo != NULL);
|
|
|
|
|
|
|
|
|
|
for (where = &srcsn->undo->value;
|
|
|
|
|
*where != NULL;
|
|
|
|
|
where = &(*where)->next)
|
|
|
|
|
{
|
|
|
|
|
if ((*where)->value->source == srcn->source)
|
|
|
|
|
return; /* already saved */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
insert_source_note_list(where, copy_source_note(srcn));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef enum { DO_ARCHALL = 0, SKIP_ARCHALL = 1 } do_this;
|
|
|
|
|
static void remove_binaries_by_arch(dpkg_sources_note *srcsn,
|
|
|
|
|
dpkg_source_note *srcn, int archnum,
|
|
|
|
|
do_this arch_all)
|
|
|
|
|
{
|
|
|
|
|
packagelist *p;
|
|
|
|
|
packagelist *leftovers = NULL, **addto = &leftovers;
|
|
|
|
|
assert(is_sources_note(srcsn));
|
|
|
|
|
|
|
|
|
|
assert(arch_all == SKIP_ARCHALL || NULL == lookup_sourcenotetbl(srcsn->sources,srcn->source->package));
|
|
|
|
|
/* if we're removing the entire binary, we should already have
|
|
|
|
|
* removed the source. if we're removing just the binaries on this
|
|
|
|
|
* arch (not arch:all) then we may be keeping the source
|
|
|
|
|
*
|
|
|
|
|
* really a logical XOR, I think. we don't rely on this assertion
|
|
|
|
|
* here
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
for (p = srcn->binaries[archnum]; p != NULL; p = p->next) {
|
|
|
|
|
dpkg_collected_package *cpkg;
|
|
|
|
|
if (arch_all == SKIP_ARCHALL && p->value->arch_all) {
|
|
|
|
|
insert_packagelist(addto, p->value);
|
|
|
|
|
addto = &(*addto)->next;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
cpkg = lookup_packagetbl(srcsn->pkgs[archnum]->packages,
|
|
|
|
|
p->value->package);
|
|
|
|
|
remove_package(srcsn->pkgs[archnum], cpkg);
|
|
|
|
|
}
|
|
|
|
|
free_packagelist(srcn->binaries[archnum]);
|
|
|
|
|
srcn->binaries[archnum] = leftovers;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef enum { NOTUNDOABLE = 0, UNDOABLE = 1 } undoable;
|
|
|
|
|
|
|
|
|
|
void remove_source(dpkg_sources_note *srcsn, char *name) {
|
|
|
|
|
dpkg_source_note *srcn;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
assert(is_sources_note(srcsn));
|
|
|
|
|
srcn = remove_sourcenotetbl(srcsn->sources, name);
|
|
|
|
|
assert(srcn != NULL);
|
|
|
|
|
|
|
|
|
|
new_op(srcsn);
|
|
|
|
|
save_source_note(srcsn, srcn);
|
|
|
|
|
for (i = 0; i < srcn->n_arches; i++) {
|
|
|
|
|
remove_binaries_by_arch(srcsn, srcn, i, DO_ARCHALL);
|
|
|
|
|
}
|
|
|
|
|
free_source_note(srcn);
|
|
|
|
|
assert(is_sources_note(srcsn));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int can_undo(dpkg_sources_note *srcsn) {
|
|
|
|
|
assert(is_sources_note(srcsn));
|
|
|
|
|
return srcsn->undo != NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void undo_change(dpkg_sources_note *srcsn) {
|
|
|
|
|
dpkg_source_note *srcnO, *srcnC; /* old, current */
|
|
|
|
|
source_note_list *srcnl;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
assert(is_sources_note(srcsn));
|
|
|
|
|
assert(can_undo(srcsn));
|
|
|
|
|
|
|
|
|
|
srcnl = remove_source_note_listlist(&srcsn->undo);
|
|
|
|
|
|
|
|
|
|
while(srcnl) {
|
|
|
|
|
srcnO = remove_source_note_list(&srcnl);
|
|
|
|
|
assert(srcnO != NULL); /* can_undo() implies this is true... */
|
|
|
|
|
|
|
|
|
|
srcnC = remove_sourcenotetbl(srcsn->sources, srcnO->source->package);
|
|
|
|
|
if (srcnC != NULL) {
|
|
|
|
|
for (i = 0; i < srcnC->n_arches; i++) {
|
|
|
|
|
remove_binaries_by_arch(srcsn, srcnC, i, DO_ARCHALL);
|
|
|
|
|
}
|
|
|
|
|
free_source_note(srcnC);
|
|
|
|
|
assert(!lookup_sourcenotetbl(srcsn->sources,
|
|
|
|
|
srcnO->source->package));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (srcnO->binaries == NULL) {
|
|
|
|
|
/* no original source */
|
|
|
|
|
assert(srcnC != NULL); /* some sort of no-op? freaky. */
|
|
|
|
|
free_source_note(srcnO);
|
|
|
|
|
} else {
|
|
|
|
|
packagelist *p;
|
|
|
|
|
/* original source */
|
|
|
|
|
add_sourcenotetbl(srcsn->sources, srcnO->source->package, srcnO);
|
|
|
|
|
for (i = 0; i < srcsn->n_arches; i++) {
|
|
|
|
|
for (p = srcnO->binaries[i]; p != NULL; p = p->next) {
|
|
|
|
|
add_package(srcsn->pkgs[i], p->value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LIST_IMPL(source_note_list, dpkg_source_note *, free_source_note,
|
|
|
|
|
block_malloc, block_free);
|
|
|
|
|
LIST_IMPL(source_note_listlist, source_note_list *, free_source_note_list,
|
|
|
|
|
block_malloc, block_free);
|
|
|
|
|
|
|
|
|
|
void commit_changes(dpkg_sources_note *srcsn) {
|
|
|
|
|
assert(is_sources_note(srcsn));
|
|
|
|
|
free_source_note_listlist(srcsn->undo);
|
|
|
|
|
srcsn->undo = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dpkg_source_note *copy_source_note(dpkg_source_note *srcn) {
|
|
|
|
|
dpkg_source_note *srcn2;
|
|
|
|
|
packagelist *src, **dest;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
assert(srcn->binaries != NULL);
|
|
|
|
|
|
|
|
|
|
srcn2 = block_malloc(sizeof(dpkg_source_note));
|
|
|
|
|
if (srcn2 == NULL) die("copy_source_note alloc:");
|
|
|
|
|
|
|
|
|
|
srcn2->source = srcn->source;
|
|
|
|
|
srcn2->n_arches = srcn->n_arches;
|
|
|
|
|
srcn2->binaries = block_malloc(sizeof(packagenamelist*) * srcn2->n_arches);
|
|
|
|
|
if (srcn2->binaries == NULL) die("copy_source_note alloc:");
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < srcn2->n_arches; i++) {
|
|
|
|
|
dest = &(srcn2->binaries[i]);
|
|
|
|
|
*dest = NULL;
|
|
|
|
|
for (src = srcn->binaries[i]; src; src = src->next) {
|
|
|
|
|
insert_packagelist(dest, src->value);
|
|
|
|
|
dest = &((*dest)->next);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return srcn2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void write_notes(char *dir, dpkg_sources_note *srcsn) {
|
|
|
|
|
FILE *src;
|
|
|
|
|
FILE *archfile[100];
|
|
|
|
|
char buf[1000];
|
|
|
|
|
int i;
|
|
|
|
|
sourcenotetbl_iter srciter;
|
|
|
|
|
|
|
|
|
|
assert(is_sources_note(srcsn));
|
|
|
|
|
snprintf(buf, 1000, "%s/Sources", dir);
|
|
|
|
|
src = fopen(buf, "w");
|
|
|
|
|
for (i = 0; i < srcsn->n_arches; i++) {
|
|
|
|
|
snprintf(buf, 1000, "%s/Packages_%s", dir, srcsn->archname[i]);
|
|
|
|
|
archfile[i] = fopen(buf, "w");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (srciter = first_sourcenotetbl(srcsn->sources);
|
|
|
|
|
!done_sourcenotetbl(srciter);
|
|
|
|
|
srciter = next_sourcenotetbl(srciter))
|
|
|
|
|
{
|
|
|
|
|
packagelist *p;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (!srciter.v->source->fake)
|
|
|
|
|
write_paragraph(src, srciter.v->source->details);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < srcsn->n_arches; i++) {
|
|
|
|
|
for (p = srciter.v->binaries[i]; p != NULL; p = p->next) {
|
|
|
|
|
write_paragraph(archfile[i], p->value->details);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fclose(src);
|
|
|
|
|
for (i = 0; i < srcsn->n_arches; i++) {
|
|
|
|
|
fclose(archfile[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|