Commit 7be853e6 authored by Timo Teräs's avatar Timo Teräs

all: rework how arrays work

Instead of having a null pointer, use a dummy array which just
says the array is empty. This helps in multiple places of the code
which would otherwise need explicitly need to check first if the
array exists. This has been cause of multiple seg.faults in the
past as the array check is easily omitted.

This also removes (or fixes) all existing checks accordingly.
parent 069c8989
......@@ -5,7 +5,7 @@ $(error Build dependencies are not met)
endif
progs-y += apk
apk-objs := state.o database.o package.o archive.o \
apk-objs := common.o state.o database.o package.o archive.o \
version.o io.o url.o gunzip.o blob.o hash.o apk.o \
add.o del.o fix.o update.o info.o search.o upgrade.o \
cache.o ver.o index.o fetch.o audit.o verify.o
......
/* apk_defines.c - Alpine Package Keeper (APK)
*
* Copyright (C) 2005-2008 Natanael Copa <n@tanael.org>
* Copyright (C) 2008 Timo Teräs <timo.teras@iki.fi>
* Copyright (C) 2008-2010 Timo Teräs <timo.teras@iki.fi>
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
......@@ -12,7 +12,6 @@
#ifndef APK_DEFINES_H
#define APK_DEFINES_H
#include <malloc.h>
#include <string.h>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
......@@ -92,32 +91,33 @@ typedef void (*apk_progress_cb)(void *cb_ctx, size_t);
#define APK_PROGRESS_SCALE 0x100
void *apk_array_resize(void *array, size_t new_size, size_t elem_size);
#define APK_ARRAY(array_type_name, elem_type_name) \
struct array_type_name { \
int num; \
elem_type_name item[]; \
}; \
static inline struct array_type_name * \
array_type_name##_resize(struct array_type_name *a, int size) \
static inline void \
array_type_name##_init(struct array_type_name **a) \
{ \
*a = apk_array_resize(NULL, 0, 0); \
} \
static inline void \
array_type_name##_free(struct array_type_name **a) \
{ \
*a = apk_array_resize(*a, 0, 0); \
} \
static inline void \
array_type_name##_resize(struct array_type_name **a, size_t size)\
{ \
struct array_type_name *tmp; \
int oldnum = a ? a->num : 0; \
int diff = size - oldnum; \
tmp = (struct array_type_name *) \
realloc(a, sizeof(struct array_type_name) + \
size * sizeof(elem_type_name)); \
if (diff > 0) \
memset(&tmp->item[oldnum], 0, \
diff * sizeof(a->item[0])); \
tmp->num = size; \
return tmp; \
*a = apk_array_resize(*a, size, sizeof(elem_type_name));\
} \
static inline elem_type_name * \
array_type_name##_add(struct array_type_name **a) \
{ \
int size = 1; \
if (*a != NULL) size += (*a)->num; \
*a = array_type_name##_resize(*a, size); \
int size = 1 + (*a)->num; \
*a = apk_array_resize(*a, size, sizeof(elem_type_name));\
return &(*a)->item[size-1]; \
}
......
......@@ -32,9 +32,6 @@ static int cache_download(struct apk_database *db)
char item[PATH_MAX], cacheitem[PATH_MAX];
int i, r = 0;
if (db->world == NULL)
return 0;
state = apk_state_new(db);
if (state == NULL)
goto err;
......@@ -111,7 +108,7 @@ static int cache_clean(struct apk_database *db)
} else {
/* Package - search for it */
name = apk_db_get_name(db, bname);
if (name == NULL || name->pkgs == NULL)
if (name == NULL)
break;
for (i = 0; i < name->pkgs->num; i++) {
struct apk_package *pkg = name->pkgs->item[i];
......
/* common.c - Alpine Package Keeper (APK)
*
* Copyright (C) 2010 Timo Teräs <timo.teras@iki.fi>
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation. See http://www.gnu.org/ for details.
*/
#include <malloc.h>
#include <string.h>
#include "apk_defines.h"
static int *dummy_array = 0;
void *apk_array_resize(void *array, size_t new_size, size_t elem_size)
{
int old_size, diff;
void *tmp;
if (new_size == 0) {
if (array != &dummy_array)
free(array);
return &dummy_array;
}
old_size = array ? *((int*) array) : 0;
diff = new_size - old_size;
if (array == &dummy_array)
array = NULL;
tmp = realloc(array, sizeof(int) + new_size * elem_size);
if (diff > 0)
memset(tmp + sizeof(int) + old_size * elem_size, 0,
diff * elem_size);
*((int*) tmp) = new_size;
return tmp;
}
......@@ -64,10 +64,8 @@ static apk_blob_t pkg_name_get_key(apk_hash_item item)
static void pkg_name_free(struct apk_name *name)
{
free(name->name);
if (name->pkgs)
free(name->pkgs);
if (name->rdepends)
free(name->rdepends);
apk_package_array_free(&name->pkgs);
apk_name_array_free(&name->rdepends);
free(name);
}
......@@ -178,6 +176,8 @@ struct apk_name *apk_db_get_name(struct apk_database *db, apk_blob_t name)
pn->name = apk_blob_cstr(name);
pn->id = db->name_id++;
apk_package_array_init(&pn->pkgs);
apk_name_array_init(&pn->rdepends);
apk_hash_insert_hashed(&db->available.names, pn, hash);
return pn;
......@@ -382,17 +382,13 @@ static void apk_db_pkg_rdepends(struct apk_database *db, struct apk_package *pkg
{
int i, j;
if (pkg->depends == NULL)
return;
for (i = 0; i < pkg->depends->num; i++) {
struct apk_name *rname = pkg->depends->item[i].name;
if (rname->rdepends) {
for (j = 0; j < rname->rdepends->num; j++)
if (rname->rdepends->item[j] == pkg->name)
return;
}
for (j = 0; j < rname->rdepends->num; j++)
if (rname->rdepends->item[j] == pkg->name)
return;
*apk_name_array_add(&rname->rdepends) = pkg->name;
}
}
......@@ -859,7 +855,8 @@ static void apk_db_triggers_read(struct apk_database *db, struct apk_bstream *bs
ipkg = pkg->ipkg;
apk_blob_for_each_segment(l, " ", parse_triggers, ipkg);
if (ipkg->triggers && !list_hashed(&ipkg->trigger_pkgs_list))
if (ipkg->triggers->num != 0 &&
!list_hashed(&ipkg->trigger_pkgs_list))
list_add_tail(&ipkg->trigger_pkgs_list,
&db->installed.triggers);
}
......@@ -887,7 +884,7 @@ static int apk_db_read_state(struct apk_database *db, int flags)
apk_deps_parse(db, &db->world, blob);
free(blob.ptr);
for (i = 0; db->world != NULL && i < db->world->num; i++)
for (i = 0; i < db->world->num; i++)
db->world->item[i].name->flags |= APK_NAME_TOPLEVEL;
}
......@@ -1046,6 +1043,8 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts)
apk_hash_init(&db->installed.files, &file_hash_ops, 10000);
list_init(&db->installed.packages);
list_init(&db->installed.triggers);
apk_dependency_array_init(&db->world);
apk_string_array_init(&db->protected_paths);
db->cache_dir = apk_static_cache_dir;
db->permanent = 1;
......@@ -1262,13 +1261,10 @@ void apk_db_close(struct apk_database *db)
for (i = 0; i < db->num_repos; i++) {
free(db->repos[i].url);
}
if (db->protected_paths) {
for (i = 0; i < db->protected_paths->num; i++)
free(db->protected_paths->item[i]);
free(db->protected_paths);
}
if (db->world)
free(db->world);
for (i = 0; i < db->protected_paths->num; i++)
free(db->protected_paths->item[i]);
apk_dependency_array_free(&db->world);
apk_string_array_free(&db->protected_paths);
apk_hash_free(&db->available.packages);
apk_hash_free(&db->available.names);
......@@ -1309,10 +1305,10 @@ static int fire_triggers(apk_hash_item item, void *ctx)
FNM_PATHNAME) != 0)
continue;
if (ipkg->pending_triggers == NULL)
/* And place holder for script name */
if (ipkg->pending_triggers->num == 0)
*apk_string_array_add(&ipkg->pending_triggers) =
NULL;
*apk_string_array_add(&ipkg->pending_triggers) =
dbd->rooted_name;
break;
......@@ -1329,14 +1325,13 @@ int apk_db_run_triggers(struct apk_database *db)
apk_hash_foreach(&db->installed.dirs, fire_triggers, db);
list_for_each_entry(ipkg, &db->installed.triggers, trigger_pkgs_list) {
if (ipkg->pending_triggers == NULL)
if (ipkg->pending_triggers->num == 0)
continue;
*apk_string_array_add(&ipkg->pending_triggers) = NULL;
apk_ipkg_run_script(ipkg, db->root_fd, APK_SCRIPT_TRIGGER,
ipkg->pending_triggers->item);
free(ipkg->pending_triggers);
ipkg->pending_triggers = NULL;
apk_string_array_free(&ipkg->pending_triggers);
}
return 0;
......@@ -1651,13 +1646,11 @@ static int read_info_line(void *_ctx, apk_blob_t line)
if (apk_blob_compare(APK_BLOB_STR("replaces"), l) == 0) {
apk_blob_for_each_segment(r, " ", parse_replaces, ctx);
} else if (apk_blob_compare(APK_BLOB_STR("triggers"), l) == 0) {
if (ipkg->triggers) {
free(ipkg->triggers);
ipkg->triggers = NULL;
}
apk_string_array_resize(&ipkg->triggers, 0);
apk_blob_for_each_segment(r, " ", parse_triggers, ctx->ipkg);
if (ctx->ipkg->triggers && !list_hashed(&ipkg->trigger_pkgs_list))
if (ctx->ipkg->triggers->num != 0 &&
!list_hashed(&ipkg->trigger_pkgs_list))
list_add_tail(&ipkg->trigger_pkgs_list,
&db->installed.triggers);
} else {
......@@ -2118,10 +2111,9 @@ int apk_db_install_pkg(struct apk_database *db,
}
ipkg->flags |= APK_IPKGF_RUN_ALL_TRIGGERS;
if (ipkg->triggers) {
if (ipkg->triggers->num != 0) {
list_del(&ipkg->trigger_pkgs_list);
free(ipkg->triggers);
ipkg->triggers = NULL;
apk_string_array_free(&ipkg->triggers);
}
if (oldpkg != NULL && oldpkg != newpkg && oldpkg->ipkg != NULL) {
......
......@@ -33,9 +33,6 @@ static int del_main(void *ctx, struct apk_database *db, int argc, char **argv)
struct apk_name *name;
int i, r = 0;
if (db->world == NULL)
return 0;
for (i = 0; i < argc; i++) {
name = apk_db_get_name(db, APK_BLOB_STR(argv[i]));
name->flags &= ~APK_NAME_TOPLEVEL;
......
......@@ -205,7 +205,7 @@ static int fetch_main(void *ctx, struct apk_database *db, int argc, char **argv)
}
apk_state_unref(state);
} else if (dep.name->pkgs != NULL) {
} else {
struct apk_package *pkg = NULL;
for (j = 0; j < dep.name->pkgs->num; j++)
......@@ -215,13 +215,15 @@ static int fetch_main(void *ctx, struct apk_database *db, int argc, char **argv)
== APK_VERSION_GREATER)
pkg = dep.name->pkgs->item[j];
if (pkg == NULL) {
apk_message("Unable to get '%s'", dep.name->name);
r = -1;
break;
}
r = fetch_package(fctx, db, pkg);
if (r != 0)
goto err;
} else {
apk_message("Unable to get '%s'", dep.name->name);
r = -1;
break;
}
}
......
......@@ -69,7 +69,7 @@ static int fix_main(void *pctx, struct apk_database *db, int argc, char **argv)
apk_dep_from_blob(&deps[i], db, APK_BLOB_STR(argv[i]));
name = deps[i].name;
for (j = 0; name->pkgs && j < name->pkgs->num; j++) {
for (j = 0; j < name->pkgs->num; j++) {
if (name->pkgs->item[j]->ipkg != NULL) {
pkg = name->pkgs->item[j];
break;
......
......@@ -16,14 +16,15 @@ void apk_hash_init(struct apk_hash *h, const struct apk_hash_ops *ops,
int num_buckets)
{
h->ops = ops;
h->buckets = apk_hash_array_resize(NULL, num_buckets);
apk_hash_array_init(&h->buckets);
apk_hash_array_resize(&h->buckets, num_buckets);
h->num_items = 0;
}
void apk_hash_free(struct apk_hash *h)
{
apk_hash_foreach(h, (apk_hash_enumerator_f) h->ops->delete_item, NULL);
free(h->buckets);
apk_hash_array_free(&h->buckets);
}
int apk_hash_foreach(struct apk_hash *h, apk_hash_enumerator_f e, void *ctx)
......
......@@ -72,7 +72,7 @@ static int warn_if_no_providers(apk_hash_item item, void *ctx)
struct counts *counts = (struct counts *) ctx;
struct apk_name *name = (struct apk_name *) item;
if (name->pkgs == NULL) {
if (name->pkgs->num == 0) {
if (++counts->unsatisfied < 10) {
apk_warning("No provider for dependency '%s'",
name->name);
......@@ -139,7 +139,7 @@ static int index_main(void *ctx, struct apk_database *db, int argc, char **argv)
/* If we have it in the old index already? */
name = apk_db_query_name(db, bname);
if (name == NULL || name->pkgs == NULL)
if (name == NULL)
break;
for (j = 0; j < name->pkgs->num; j++) {
......
......@@ -75,9 +75,6 @@ static int info_exists(struct info_ctx *ctx, struct apk_database *db,
continue;
name = dep.name;
if (name->pkgs == NULL)
continue;
for (j = 0; j < name->pkgs->num; j++) {
pkg = name->pkgs->item[j];
if (pkg->ipkg != NULL)
......@@ -168,13 +165,10 @@ static void info_print_depends(struct apk_package *pkg)
char *separator = apk_verbosity > 1 ? " " : "\n";
if (apk_verbosity == 1)
printf("%s-%s depends on:\n", pkg->name->name, pkg->version);
if (pkg->depends == NULL)
return;
if (apk_verbosity > 1)
printf("%s: ", pkg->name->name);
for (i = 0; i < pkg->depends->num; i++) {
for (i = 0; i < pkg->depends->num; i++)
printf("%s%s", pkg->depends->item[i].name->name, separator);
}
}
static void info_print_required_by(struct apk_package *pkg)
......@@ -184,8 +178,6 @@ static void info_print_required_by(struct apk_package *pkg)
if (apk_verbosity == 1)
printf("%s-%s is required by:\n", pkg->name->name, pkg->version);
if (pkg->name->rdepends == NULL)
return;
if (apk_verbosity > 1)
printf("%s: ", pkg->name->name);
for (i = 0; i < pkg->name->rdepends->num; i++) {
......@@ -193,12 +185,10 @@ static void info_print_required_by(struct apk_package *pkg)
/* Check only the package that is installed, and that
* it actually has this package as dependency. */
if (name0->pkgs == NULL)
continue;
for (j = 0; j < name0->pkgs->num; j++) {
struct apk_package *pkg0 = name0->pkgs->item[j];
if (pkg0->ipkg == NULL || pkg0->depends == NULL)
if (pkg0->ipkg == NULL)
continue;
for (k = 0; k < pkg0->depends->num; k++) {
if (pkg0->depends->item[k].name != pkg->name)
......@@ -240,7 +230,7 @@ static void info_print_triggers(struct apk_package *pkg)
if (apk_verbosity == 1)
printf("%s-%s triggers:\n", pkg->name->name, pkg->version);
for (i = 0; ipkg->triggers && i < ipkg->triggers->num; i++) {
for (i = 0; i < ipkg->triggers->num; i++) {
if (apk_verbosity > 1)
printf("%s: trigger ", pkg->name->name);
printf("%s\n", ipkg->triggers->item[i]);
......@@ -283,7 +273,7 @@ static int info_package(struct info_ctx *ctx, struct apk_database *db,
for (i = 0; i < argc; i++) {
name = apk_db_query_name(db, APK_BLOB_STR(argv[i]));
if (name == NULL || name->pkgs == NULL) {
if (name == NULL || name->pkgs->num == 0) {
apk_error("Not found: %s", argv[i]);
return 1;
}
......
......@@ -53,7 +53,13 @@ void apk_pkg_format_cache(struct apk_package *pkg, apk_blob_t to)
struct apk_package *apk_pkg_new(void)
{
return calloc(1, sizeof(struct apk_package));
struct apk_package *pkg;
pkg = calloc(1, sizeof(struct apk_package));
if (pkg != NULL)
apk_dependency_array_init(&pkg->depends);
return pkg;
}
struct apk_installed_package *apk_pkg_install(struct apk_database *db,
......@@ -66,6 +72,8 @@ struct apk_installed_package *apk_pkg_install(struct apk_database *db,
pkg->ipkg = ipkg = calloc(1, sizeof(struct apk_installed_package));
ipkg->pkg = pkg;
apk_string_array_init(&ipkg->triggers);
apk_string_array_init(&ipkg->pending_triggers);
/* Overlay override information resides in a nameless package */
if (pkg->name != NULL) {
......@@ -90,13 +98,14 @@ void apk_pkg_uninstall(struct apk_database *db, struct apk_package *pkg)
list_del(&ipkg->installed_pkgs_list);
if (ipkg->triggers) {
if (ipkg->triggers->num) {
list_del(&ipkg->trigger_pkgs_list);
list_init(&ipkg->trigger_pkgs_list);
for (i = 0; i < ipkg->triggers->num; i++)
free(ipkg->triggers->item[i]);
free(ipkg->triggers);
}
apk_string_array_free(&ipkg->triggers);
apk_string_array_free(&ipkg->pending_triggers);
for (i = 0; i < APK_SCRIPT_MAX; i++)
if (ipkg->script[i].ptr != NULL)
......@@ -180,7 +189,7 @@ void apk_deps_del(struct apk_dependency_array **pdeps,
continue;
deps->item[i] = deps->item[deps->num-1];
*pdeps = apk_dependency_array_resize(deps, deps->num-1);
apk_dependency_array_resize(pdeps, deps->num-1);
break;
}
}
......@@ -809,8 +818,7 @@ void apk_pkg_free(struct apk_package *pkg)
return;
apk_pkg_uninstall(NULL, pkg);
if (pkg->depends)
free(pkg->depends);
apk_dependency_array_free(&pkg->depends);
if (pkg->version)
free(pkg->version);
if (pkg->url)
......@@ -970,7 +978,7 @@ int apk_pkg_write_index_entry(struct apk_package *info,
if (os->write(os, bbuf.ptr, bbuf.len) != bbuf.len)
return -1;
if (info->depends != NULL) {
if (info->depends->num > 0) {
if (os->write(os, "D:", 2) != 2)
return -1;
r = apk_deps_write(info->depends, os);
......
......@@ -45,18 +45,12 @@ static int print_rdepends(struct apk_package *pkg)
int i, j, k;
name = pkg->name;
if (name->rdepends == NULL)
return 0;
printf("%s-%s:", pkg->name->name, pkg->version);
for (i = 0; i < name->rdepends->num; i++) {
name0 = name->rdepends->item[i];
if (name0->pkgs == NULL)
continue;
for (j = 0; j < name0->pkgs->num; j++) {
pkg0 = name0->pkgs->item[j];
if (pkg0->depends == NULL)
continue;
for (k = 0; k < pkg0->depends->num; k++) {
dep = &pkg0->depends->item[k];
if (name == dep->name &&
......@@ -146,7 +140,7 @@ static int search_main(void *ctx, struct apk_database *db, int argc, char **argv
} else {
for (i = 0; i < argc; i++) {
name = apk_db_query_name(db, APK_BLOB_STR(argv[i]));
if (name == NULL || name->pkgs == NULL)
if (name == NULL)
continue;
for (j = 0; j < name->pkgs->num; j++)
ictx->print(name->pkgs->item[j]);
......
......@@ -105,7 +105,7 @@ static struct apk_name_choices *name_choices_new(struct apk_database *db,
struct apk_name_choices *nc;
int i, j;
if (name->pkgs == NULL)
if (name->pkgs->num == 0)
return NULL;
nc = malloc(sizeof(struct apk_name_choices) +
......@@ -122,7 +122,7 @@ static struct apk_name_choices *name_choices_new(struct apk_database *db,
return nc;
/* Check for global dependencies */
for (i = 0; db->world != NULL && i < db->world->num; i++) {
for (i = 0; i < db->world->num; i++) {
struct apk_dependency *dep = &db->world->item[i];
if (dep->name != name)
......@@ -198,6 +198,9 @@ struct apk_state *apk_state_new(struct apk_database *db)
state->db = db;
list_init(&state->change_list_head);
apk_name_array_init(&state->missing);
apk_package_array_init(&state->conflicts);
return state;
}
......@@ -211,6 +214,9 @@ void apk_state_unref(struct apk_state *state)
{
if (--state->refs > 0)
return;
apk_package_array_free(&state->conflicts);
apk_name_array_free(&state->missing);
free(state);
}
......@@ -397,7 +403,7 @@ static int apk_state_fix_package(struct apk_state *state,
{
int i, r, ret = 0;
if (pkg == NULL || pkg->depends == NULL)
if (pkg == NULL)
return 0;
for (i = 0; i < pkg->depends->num; i++) {
......@@ -422,9 +428,6 @@ static int call_if_dependency_broke(struct apk_state *state,
struct apk_package *dep_pkg;
int k;
if (pkg->depends == NULL)
return 0;
dep_pkg = ns_to_pkg(state->name[dep_name->id]);
for (k = 0; k < pkg->depends->num; k++) {
struct apk_dependency *dep = &pkg->depends->item[k];
......@@ -454,9 +457,6 @@ static int for_each_broken_reverse_depency(struct apk_state *state,
struct apk_package *pkg0;
int i, j, r;
if (name->rdepends == NULL)
return 0;
for (i = 0; i < name->rdepends->num; i++) {
struct apk_name *name0 = name->rdepends->item[i];
......@@ -536,14 +536,11 @@ int apk_state_lock_name(struct apk_state *state,
ns_free(state->name[name->id]);
state->name[name->id] = ns_from_pkg_non_pending(newpkg);
if (name->pkgs != NULL) {
for (i = 0; i < name->pkgs->num; i++) {
struct apk_package *pkg = name->pkgs->item[i];
if (name->pkgs->item[i]->name == name &&
pkg->ipkg != NULL)
oldpkg = pkg;
}
for (i = 0; i < name->pkgs->num; i++) {
struct apk_package *pkg = name->pkgs->item[i];
if (name->pkgs->item[i]->name == name &&
pkg->ipkg != NULL)
oldpkg = pkg;
}
/* First we need to make sure the dependants of the old package
......@@ -766,9 +763,6 @@ static int apk_state_autoclean(struct apk_state *state,
apk_name_state_t oldns;
int i, r;
if (pkg->depends == NULL)
return 0;
for (i = 0; i < pkg->depends->num; i++) {
struct apk_name *n = pkg->depends->item[i].name;
......@@ -831,14 +825,14 @@ void apk_state_print_errors(struct apk_state *state)
struct error_state es;
int i, j, r;
for (i = 0; state->conflicts != NULL && i < state->conflicts->num; i++) {
for (i = 0; i < state->conflicts->num; i++) {
if (i == 0)
apk_error("Unable to satisfy all dependencies:");
es.prevpkg = pkg = state->conflicts->item[i];
es.indent.x = es.indent.indent =
printf(" %s-%s:", pkg->name->name, pkg->version);
for (j = 0; pkg->depends != NULL && j < pkg->depends->num; j++) {
for (j = 0; j < pkg->depends->num; j++) {
r = apk_state_lock_dependency(state,
&pkg->depends->item[j]);
if (r != 0)
......@@ -851,7 +845,7 @@ void apk_state_print_errors(struct apk_state *state)
printf("\n");
}
for (i = 0; state->missing != NULL && i < state->missing->num; i++) {
for (i = 0; i < state->missing->num; i++) {
struct apk_name *name = state->missing->item[i];
if (i == 0) {
apk_error("Missing packages:");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment