From f0609951b9fd2938c0f30853e0aa6b08b8698a88 Mon Sep 17 00:00:00 2001
From: Timo Teras <timo.teras@iki.fi>
Date: Thu, 27 Nov 2008 20:25:01 +0200
Subject: hash, db: use apk_blob_t and list_*

---
 src/add.c          |  2 +-
 src/apk_blob.h     |  4 ++-
 src/apk_database.h | 13 +++++---
 src/apk_defines.h  | 69 +++++++++++++++++++++++++++++++++++++++
 src/apk_hash.h     | 19 +++++------
 src/apk_package.h  |  2 +-
 src/blob.c         | 20 ++++++++++++
 src/database.c     | 96 +++++++++++++++++++++++++++++-------------------------
 src/hash.c         | 24 +++-----------
 src/package.c      | 40 +++++++++++------------
 src/state.c        |  5 ++-
 src/ver.c          |  3 +-
 12 files changed, 190 insertions(+), 107 deletions(-)

(limited to 'src')

diff --git a/src/add.c b/src/add.c
index be8012b..b20d16f 100644
--- a/src/add.c
+++ b/src/add.c
@@ -23,7 +23,7 @@ static int add_main(int argc, char **argv)
 
 	for (i = 0; i < argc; i++) {
 		struct apk_dependency dep = {
-			.name = apk_db_get_name(&db, argv[i]),
+			.name = apk_db_get_name(&db, APK_BLOB_STR(argv[i])),
 		};
 		apk_deps_add(&db.world, &dep);
 	}
diff --git a/src/apk_blob.h b/src/apk_blob.h
index 5f30fd6..fa7ad0f 100644
--- a/src/apk_blob.h
+++ b/src/apk_blob.h
@@ -23,7 +23,7 @@ typedef struct apk_blob apk_blob_t;
 #define APK_BLOB_IS_NULL(blob)		(blob.ptr == NULL)
 
 #define APK_BLOB_NULL			((apk_blob_t){0, NULL})
-#define APK_BLOB_STR(str)		((apk_blob_t){strlen(str), (str)})
+#define APK_BLOB_STR(str)		((apk_blob_t){strlen(str), (void *)(str)})
 #define APK_BLOB_BUF(buf)		((apk_blob_t){sizeof(buf), (char *)(buf)})
 #define APK_BLOB_PTR_LEN(beg,len)	((apk_blob_t){(len), (beg)})
 #define APK_BLOB_PTR_PTR(beg,end)	APK_BLOB_PTR_LEN((beg),(end)-(beg)+1)
@@ -32,6 +32,8 @@ char *apk_blob_cstr(apk_blob_t str);
 int apk_blob_splitstr(apk_blob_t blob, const char *split, apk_blob_t *l, apk_blob_t *r);
 int apk_blob_rsplit(apk_blob_t blob, char split, apk_blob_t *l, apk_blob_t *r);
 unsigned apk_blob_uint(apk_blob_t blob, int base);
+unsigned long apk_blob_hash(apk_blob_t str);
+int apk_blob_compare(apk_blob_t a, apk_blob_t b);
 
 int apk_blob_for_each_segment(apk_blob_t blob, const char *split,
 			      int (*cb)(void *ctx, apk_blob_t blob), void *ctx);
diff --git a/src/apk_database.h b/src/apk_database.h
index 5cf2928..b0b84d6 100644
--- a/src/apk_database.h
+++ b/src/apk_database.h
@@ -71,7 +71,7 @@ struct apk_database {
 	} available;
 
 	struct {
-		struct hlist_head packages;
+		struct list_head packages;
 		struct apk_hash dirs;
 		struct {
 			unsigned files;
@@ -81,7 +81,12 @@ struct apk_database {
 	} installed;
 };
 
-struct apk_name *apk_db_get_name(struct apk_database *db, const char *name);
+typedef union apk_database_or_void {
+	struct apk_database *db;
+	void *ptr;
+} apk_database_t __attribute__ ((__transparent_union__));
+
+struct apk_name *apk_db_get_name(struct apk_database *db, apk_blob_t name);
 void apk_name_free(struct apk_name *pkgname);
 
 int apk_db_create(const char *root);
@@ -91,10 +96,10 @@ void apk_db_close(struct apk_database *db);
 int apk_db_pkg_add_file(struct apk_database *db, const char *file);
 struct apk_package *apk_db_get_pkg(struct apk_database *db, csum_t sum);
 
-int apk_db_index_read(struct apk_database *db, int fd, int repo);
+int apk_db_index_read(struct apk_database *db, struct apk_istream *is, int repo);
 void apk_db_index_write(struct apk_database *db, int fd);
 
-int apk_db_add_repository(struct apk_database *db, const char *repo);
+int apk_db_add_repository(apk_database_t db, apk_blob_t repository);
 int apk_db_recalculate_and_commit(struct apk_database *db);
 
 int apk_db_install_pkg(struct apk_database *db,
diff --git a/src/apk_defines.h b/src/apk_defines.h
index 64abe72..4b741d4 100644
--- a/src/apk_defines.h
+++ b/src/apk_defines.h
@@ -169,4 +169,73 @@ static inline struct hlist_node **hlist_tail_ptr(struct hlist_head *h)
 		({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
 	     pos = n)
 
+
+struct list_head {
+	struct list_head *next, *prev;
+};
+
+static inline void list_init(struct list_head *list)
+{
+	list->next = list;
+	list->prev = list;
+}
+
+static inline void __list_add(struct list_head *new,
+			      struct list_head *prev,
+			      struct list_head *next)
+{
+	next->prev = new;
+	new->next = next;
+	new->prev = prev;
+	prev->next = new;
+}
+
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+	__list_add(new, head, head->next);
+}
+
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+	__list_add(new, head->prev, head);
+}
+
+static inline void __list_del(struct list_head * prev, struct list_head * next)
+{
+	next->prev = prev;
+	prev->next = next;
+}
+
+static inline void list_del(struct list_head *entry)
+{
+	__list_del(entry->prev, entry->next);
+	entry->next = LIST_POISON1;
+	entry->prev = LIST_POISON2;
+}
+
+static inline int list_hashed(const struct list_head *n)
+{
+	return n->next != n->prev;
+}
+
+#define list_entry(ptr, type, member) container_of(ptr,type,member)
+
+#define list_for_each(pos, head) \
+	for (pos = (head)->next; pos != (head); pos = pos->next)
+
+#define list_for_each_safe(pos, n, head) \
+	for (pos = (head)->next, n = pos->next; pos != (head); \
+		pos = n, n = pos->next)
+
+#define list_for_each_entry(pos, head, member)				\
+	for (pos = list_entry((head)->next, typeof(*pos), member);	\
+	     &pos->member != (head); 					\
+	     pos = list_entry(pos->member.next, typeof(*pos), member))
+
+#define list_for_each_entry_safe(pos, n, head, member)			\
+	for (pos = list_entry((head)->next, typeof(*pos), member),	\
+		n = list_entry(pos->member.next, typeof(*pos), member);	\
+	     &pos->member != (head); 					\
+	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
 #endif
diff --git a/src/apk_hash.h b/src/apk_hash.h
index f2f4ced..f1a010c 100644
--- a/src/apk_hash.h
+++ b/src/apk_hash.h
@@ -14,20 +14,20 @@
 
 #include <malloc.h>
 #include "apk_defines.h"
+#include "apk_blob.h"
 
 typedef void *apk_hash_item;
-typedef const void *apk_hash_key;
 
-typedef unsigned long (*apk_hash_f)(apk_hash_key);
-typedef int (*apk_hash_compare_f)(apk_hash_key, apk_hash_key);
+typedef unsigned long (*apk_hash_f)(apk_blob_t);
+typedef int (*apk_hash_compare_f)(apk_blob_t, apk_blob_t);
 typedef void (*apk_hash_delete_f)(apk_hash_item);
 typedef int (*apk_hash_enumerator_f)(apk_hash_item, void *ctx);
 
 struct apk_hash_ops {
 	ptrdiff_t	node_offset;
-	apk_hash_key	(*get_key)(apk_hash_item item);
-	unsigned long	(*hash_key)(apk_hash_key key);
-	int		(*compare)(apk_hash_key key, apk_hash_key item);
+	apk_blob_t	(*get_key)(apk_hash_item item);
+	unsigned long	(*hash_key)(apk_blob_t key);
+	int		(*compare)(apk_blob_t key, apk_blob_t itemkey);
 	void		(*delete_item)(apk_hash_item item);
 };
 
@@ -40,16 +40,13 @@ struct apk_hash {
 	int num_items;
 };
 
-unsigned long apk_hash_string(const char *string);
-unsigned long apk_hash_csum(const void *);
-
 void apk_hash_init(struct apk_hash *h, const struct apk_hash_ops *ops,
 		   int num_buckets);
 void apk_hash_free(struct apk_hash *h);
 
 int apk_hash_foreach(struct apk_hash *h, apk_hash_enumerator_f e, void *ctx);
-apk_hash_item apk_hash_get(struct apk_hash *h, apk_hash_key key);
+apk_hash_item apk_hash_get(struct apk_hash *h, apk_blob_t key);
 void apk_hash_insert(struct apk_hash *h, apk_hash_item item);
-void apk_hash_delete(struct apk_hash *h, apk_hash_key key);
+void apk_hash_delete(struct apk_hash *h, apk_blob_t key);
 
 #endif
diff --git a/src/apk_package.h b/src/apk_package.h
index 6f13e94..ea8ef24 100644
--- a/src/apk_package.h
+++ b/src/apk_package.h
@@ -57,7 +57,7 @@ struct apk_package {
 	unsigned int installed_size, size;
 
 	/* for installed packages only */
-	struct hlist_node installed_pkgs_list;
+	struct list_head installed_pkgs_list;
 	struct hlist_head owned_files;
 	struct hlist_head scripts;
 };
diff --git a/src/blob.c b/src/blob.c
index f166a7a..4fea730 100644
--- a/src/blob.c
+++ b/src/blob.c
@@ -71,6 +71,26 @@ int apk_blob_splitstr(apk_blob_t blob, const char *split, apk_blob_t *l, apk_blo
 	}
 }
 
+unsigned long apk_blob_hash(apk_blob_t blob)
+{
+	unsigned long hash = 5381;
+	int i;
+
+        for (i = 0; i < blob.len; i++)
+		hash = hash * 33 + blob.ptr[i];
+
+	return hash;
+}
+
+int apk_blob_compare(apk_blob_t a, apk_blob_t b)
+{
+	if (a.len == b.len)
+		return memcmp(a.ptr, b.ptr, a.len);
+	if (a.len < b.len)
+		return -1;
+	return 1;
+}
+
 int apk_blob_for_each_segment(apk_blob_t blob, const char *split,
 			      int (*cb)(void *ctx, apk_blob_t blob), void *ctx)
 {
diff --git a/src/database.c b/src/database.c
index 2376249..0795a0b 100644
--- a/src/database.c
+++ b/src/database.c
@@ -33,51 +33,53 @@ struct install_ctx {
 	struct hlist_node **file_pkg_node;
 };
 
-static apk_hash_key pkg_name_get_key(apk_hash_item item)
+static apk_blob_t pkg_name_get_key(apk_hash_item item)
 {
-	return ((struct apk_name *) item)->name;
+	return APK_BLOB_STR(((struct apk_name *) item)->name);
 }
 
 static const struct apk_hash_ops pkg_name_hash_ops = {
 	.node_offset = offsetof(struct apk_name, hash_node),
 	.get_key = pkg_name_get_key,
-	.hash_key = (apk_hash_f) apk_hash_string,
-	.compare = (apk_hash_compare_f) strcmp,
+	.hash_key = apk_blob_hash,
+	.compare = apk_blob_compare,
 	.delete_item = (apk_hash_delete_f) apk_name_free,
 };
 
-static apk_hash_key pkg_info_get_key(apk_hash_item item)
+static apk_blob_t pkg_info_get_key(apk_hash_item item)
 {
-	return ((struct apk_package *) item)->csum;
+	return APK_BLOB_BUF(((struct apk_package *) item)->csum);
 }
 
-static int cmpcsum(apk_hash_key a, apk_hash_key b)
+static unsigned long csum_hash(apk_blob_t csum)
 {
-	return memcmp(a, b, sizeof(csum_t));
+	/* Checksum's highest bits have the most "randomness", use that
+	 * directly as hash */
+	return *(unsigned long *)csum.ptr;
 }
 
 static const struct apk_hash_ops pkg_info_hash_ops = {
 	.node_offset = offsetof(struct apk_package, hash_node),
 	.get_key = pkg_info_get_key,
-	.hash_key = (apk_hash_f) apk_hash_csum,
-	.compare = cmpcsum,
+	.hash_key = csum_hash,
+	.compare = apk_blob_compare,
 	.delete_item = (apk_hash_delete_f) apk_pkg_free,
 };
 
-static apk_hash_key apk_db_dir_get_key(apk_hash_item item)
+static apk_blob_t apk_db_dir_get_key(apk_hash_item item)
 {
-	return ((struct apk_db_dir *) item)->dirname;
+	return APK_BLOB_STR(((struct apk_db_dir *) item)->dirname);
 }
 
 static const struct apk_hash_ops dir_hash_ops = {
 	.node_offset = offsetof(struct apk_db_dir, hash_node),
 	.get_key = apk_db_dir_get_key,
-	.hash_key = (apk_hash_f) apk_hash_string,
-	.compare = (apk_hash_compare_f) strcmp,
+	.hash_key = apk_blob_hash,
+	.compare = apk_blob_compare,
 	.delete_item = (apk_hash_delete_f) free,
 };
 
-struct apk_name *apk_db_get_name(struct apk_database *db, const char *name)
+struct apk_name *apk_db_get_name(struct apk_database *db, apk_blob_t name)
 {
 	struct apk_name *pn;
 
@@ -89,7 +91,7 @@ struct apk_name *apk_db_get_name(struct apk_database *db, const char *name)
 	if (pn == NULL)
 		return NULL;
 
-	pn->name = strdup(name);
+	pn->name = apk_blob_cstr(name);
 	apk_hash_insert(&db->available.names, pn);
 
 	return pn;
@@ -137,15 +139,12 @@ static struct apk_db_dir *apk_db_dir_get(struct apk_database *db,
 {
 	struct apk_db_dir *dir;
 	apk_blob_t bparent;
-	char *cstr;
 	int i;
 
 	if (name.len && name.ptr[name.len-1] == '/')
 		name.len--;
 
-	cstr = apk_blob_cstr(name);
-	dir = (struct apk_db_dir *) apk_hash_get(&db->installed.dirs, cstr);
-	free(cstr);
+	dir = (struct apk_db_dir *) apk_hash_get(&db->installed.dirs, name);
 	if (dir != NULL)
 		return dir;
 
@@ -249,7 +248,6 @@ static int apk_db_read_fdb(struct apk_database *db, struct apk_istream *is)
 	struct apk_package *pkg = NULL;
 	struct apk_db_dir *dir = NULL;
 	struct apk_db_file *file = NULL;
-	struct hlist_node **pkg_node = &db->installed.packages.first;
 	struct hlist_node **file_dir_node = NULL;
 	struct hlist_node **file_pkg_node = NULL;
 
@@ -281,10 +279,9 @@ static int apk_db_read_fdb(struct apk_database *db, struct apk_istream *is)
 						  l.len, l.ptr);
 					return -1;
 				}
-				if (!hlist_hashed(&pkg->installed_pkgs_list)) {
+				if (!list_hashed(&pkg->installed_pkgs_list)) {
 					db->installed.stats.packages++;
-					hlist_add_after(&pkg->installed_pkgs_list, pkg_node);
-					pkg_node = &pkg->installed_pkgs_list.next;
+					list_add_tail(&pkg->installed_pkgs_list, &db->installed.packages);
 				}
 				dir = NULL;
 				file_dir_node = NULL;
@@ -336,11 +333,11 @@ static int apk_db_write_fdb(struct apk_database *db, int fd)
 	struct apk_package *pkg;
 	struct apk_db_dir *dir;
 	struct apk_db_file *file;
-	struct hlist_node *c1, *c2;
+	struct hlist_node *c2;
 	char buf[1024];
 	int n;
 
-	hlist_for_each_entry(pkg, c1, &db->installed.packages, installed_pkgs_list) {
+	list_for_each_entry(pkg, &db->installed.packages, installed_pkgs_list) {
 		n = 0;
 		buf[n++] = 'P';
 		n += apk_hexdump_format(sizeof(buf)-n, &buf[n],
@@ -392,10 +389,9 @@ static int apk_db_write_scriptdb(struct apk_database *db, int fd)
 	struct apk_package *pkg;
 	struct apk_script *script;
 	struct apk_script_header hdr;
-	struct hlist_node *c1, *c2;
+	struct hlist_node *c2;
 
-	hlist_for_each_entry(pkg, c1, &db->installed.packages,
-			     installed_pkgs_list) {
+	list_for_each_entry(pkg, &db->installed.packages, installed_pkgs_list) {
 		hlist_for_each_entry(script, c2, &pkg->scripts, script_list) {
 			memcpy(hdr.csum, pkg->csum, sizeof(csum_t));
 			hdr.type = script->type;
@@ -416,7 +412,8 @@ static int apk_db_read_scriptdb(struct apk_database *db, struct apk_istream *is)
 
 	while (is->read(is, &hdr, sizeof(hdr)) == sizeof(hdr)) {
 		pkg = apk_db_get_pkg(db, hdr.csum);
-		apk_pkg_add_script(pkg, is, hdr.type, hdr.size);
+		if (pkg != NULL)
+			apk_pkg_add_script(pkg, is, hdr.type, hdr.size);
 	}
 
 	return 0;
@@ -485,6 +482,12 @@ static int apk_db_read_state(struct apk_database *db)
 		is->close(is);
 	}
 
+	blob = apk_blob_from_file("etc/apk/repositories");
+	if (!APK_BLOB_IS_NULL(blob)) {
+		apk_blob_for_each_segment(blob, "\n", apk_db_add_repository, db);
+		free(blob.ptr);
+	}
+
 	return 0;
 }
 
@@ -504,6 +507,7 @@ int apk_db_open(struct apk_database *db, const char *root)
 	apk_hash_init(&db->available.names, &pkg_name_hash_ops, 1000);
 	apk_hash_init(&db->available.packages, &pkg_info_hash_ops, 4000);
 	apk_hash_init(&db->installed.dirs, &dir_hash_ops, 1000);
+	list_init(&db->installed.packages);
 
 	if (root != NULL) {
 		db->root = strdup(root);
@@ -515,7 +519,7 @@ int apk_db_open(struct apk_database *db, const char *root)
 		}
 	}
 	if (apk_repository != NULL)
-		apk_db_add_repository(db, apk_repository);
+		apk_db_add_repository(db, APK_BLOB_STR(apk_repository));
 
 	dirs = APK_BLOB_STR("etc:-etc/init.d");
 	apk_blob_for_each_segment(dirs, ":", add_protected_path, db);
@@ -575,7 +579,7 @@ static void apk_db_pkg_add(struct apk_database *db, struct apk_package *pkg)
 {
 	struct apk_package *idb;
 
-	idb = apk_hash_get(&db->available.packages, pkg->csum);
+	idb = apk_hash_get(&db->available.packages, APK_BLOB_BUF(pkg->csum));
 	if (idb == NULL) {
 		pkg->id = db->pkg_id++;
 		apk_hash_insert(&db->available.packages, pkg);
@@ -588,7 +592,8 @@ static void apk_db_pkg_add(struct apk_database *db, struct apk_package *pkg)
 
 struct apk_package *apk_db_get_pkg(struct apk_database *db, csum_t sum)
 {
-	return apk_hash_get(&db->available.packages, sum);
+	return apk_hash_get(&db->available.packages,
+			    APK_BLOB_PTR_LEN((void*) sum, sizeof(csum_t)));
 }
 
 int apk_db_pkg_add_file(struct apk_database *db, const char *file)
@@ -603,7 +608,7 @@ int apk_db_pkg_add_file(struct apk_database *db, const char *file)
 	return TRUE;
 }
 
-int apk_db_index_read(struct apk_database *db, int fd, int repo)
+int apk_db_index_read(struct apk_database *db, struct apk_istream *is, int repo)
 {
 	struct apk_package *pkg;
 	char buf[1024];
@@ -612,7 +617,7 @@ int apk_db_index_read(struct apk_database *db, int fd, int repo)
 
 	r = APK_BLOB_PTR_LEN(buf, 0);
 	while (1) {
-		n = read(fd, &r.ptr[r.len], sizeof(buf) - r.len);
+		n = is->read(is, &r.ptr[r.len], sizeof(buf) - r.len);
 		if (n <= 0)
 			break;
 		r.len += n;
@@ -650,27 +655,29 @@ void apk_db_index_write(struct apk_database *db, int fd)
 	apk_hash_foreach(&db->available.packages, write_index_entry, (void *) fd);
 }
 
-int apk_db_add_repository(struct apk_database *db, const char *repo)
+int apk_db_add_repository(apk_database_t _db, apk_blob_t repository)
 {
+	struct apk_database *db = _db.db;
+	struct apk_istream *is;
 	char tmp[256];
-	int fd, r;
+	int r;
 
 	if (db->num_repos >= APK_MAX_REPOS)
 		return -1;
 
 	r = db->num_repos++;
 	db->repos[r] = (struct apk_repository){
-		.url = strdup(repo)
+		.url = apk_blob_cstr(repository)
 	};
 
-	snprintf(tmp, sizeof(tmp), "%s/APK_INDEX", repo);
-	fd = open(tmp, O_RDONLY);
-	if (fd < 0) {
+	snprintf(tmp, sizeof(tmp), "%s/APK_INDEX", db->repos[r].url);
+	is = apk_istream_from_file(tmp);
+	if (is == NULL) {
 		apk_error("Failed to open index file %s", tmp);
 		return -1;
 	}
-	apk_db_index_read(db, fd, r);
-	close(fd);
+	apk_db_index_read(db, is, r);
+	is->close(is);
 
 	return 0;
 }
@@ -823,6 +830,7 @@ static void apk_db_purge_pkg(struct apk_database *db,
 		db->installed.stats.files--;
 	}
 	db->installed.stats.packages--;
+	list_del(&pkg->installed_pkgs_list);
 }
 
 int apk_db_install_pkg(struct apk_database *db,
@@ -883,7 +891,7 @@ int apk_db_install_pkg(struct apk_database *db,
 	bs->close(bs, csum);
 
 	db->installed.stats.packages++;
-	hlist_add_head(&newpkg->installed_pkgs_list, &db->installed.packages);
+	list_add_tail(&newpkg->installed_pkgs_list, &db->installed.packages);
 
 	if (memcmp(csum, newpkg->csum, sizeof(csum)) != 0)
 		apk_warning("%s-%s: checksum does not match",
diff --git a/src/hash.c b/src/hash.c
index 447601e..b4bbc90 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -12,22 +12,6 @@
 #include "apk_defines.h"
 #include "apk_hash.h"
 
-unsigned long apk_hash_string(const char *str)
-{
-	unsigned long hash = 5381;
-	int c;
-
-	while ((c = *str++) != 0)
-		hash = hash * 33 + c;
-
-	return hash;
-}
-
-unsigned long apk_hash_csum(const void *ptr)
-{
-	return *(const unsigned long *) ptr;
-}
-
 void apk_hash_init(struct apk_hash *h, const struct apk_hash_ops *ops,
 		   int num_buckets)
 {
@@ -59,13 +43,13 @@ int apk_hash_foreach(struct apk_hash *h, apk_hash_enumerator_f e, void *ctx)
 	return 0;
 }
 
-apk_hash_item apk_hash_get(struct apk_hash *h, apk_hash_key key)
+apk_hash_item apk_hash_get(struct apk_hash *h, apk_blob_t key)
 {
 	ptrdiff_t offset = h->ops->node_offset;
 	unsigned long hash;
 	apk_hash_node *pos;
 	apk_hash_item item;
-	apk_hash_key itemkey;
+	apk_blob_t itemkey;
 
 	hash = h->ops->hash_key(key) % h->buckets->num;
 	hlist_for_each(pos, &h->buckets->item[hash]) {
@@ -80,7 +64,7 @@ apk_hash_item apk_hash_get(struct apk_hash *h, apk_hash_key key)
 
 void apk_hash_insert(struct apk_hash *h, apk_hash_item item)
 {
-	apk_hash_key key;
+	apk_blob_t key;
 	unsigned long hash;
 	apk_hash_node *node;
 
@@ -91,7 +75,7 @@ void apk_hash_insert(struct apk_hash *h, apk_hash_item item)
 	h->num_items++;
 }
 
-void apk_hash_delete(struct apk_hash *h, apk_hash_key key)
+void apk_hash_delete(struct apk_hash *h, apk_blob_t key)
 {
 }
 
diff --git a/src/package.c b/src/package.c
index 3430d19..27300c7 100644
--- a/src/package.c
+++ b/src/package.c
@@ -25,6 +25,17 @@
 #include "apk_database.h"
 #include "apk_state.h"
 
+static struct apk_package *apk_pkg_new(void)
+{
+	struct apk_package *pkg;
+
+	pkg = calloc(1, sizeof(struct apk_package));
+	if (pkg != NULL)
+		list_init(&pkg->installed_pkgs_list);
+
+	return pkg;
+}
+
 int apk_pkg_parse_name(apk_blob_t apkname,
 		       apk_blob_t *name,
 		       apk_blob_t *version)
@@ -67,7 +78,6 @@ static void parse_depend(struct apk_database *db,
 {
 	struct apk_dependency *dep;
 	struct apk_name *name;
-	char *cname;
 
 	while (blob.len && blob.ptr[0] == ' ')
 		blob.ptr++, blob.len--;
@@ -78,10 +88,7 @@ static void parse_depend(struct apk_database *db,
 	if (blob.len == 0)
 		return;
 
-	cname = apk_blob_cstr(blob);
-	name = apk_db_get_name(db, cname);
-	free(cname);
-
+	name = apk_db_get_name(db, blob);
 	dep = apk_dependency_array_add(depends);
 	*dep = (struct apk_dependency){
 		.prefer_upgrade = 0,
@@ -185,13 +192,9 @@ struct read_info_ctx {
 static int add_info(struct apk_database *db, struct apk_package *pkg,
 		    char field, apk_blob_t value)
 {
-	char *str;
-
 	switch (field) {
 	case 'P':
-		str = apk_blob_cstr(value);
-		pkg->name = apk_db_get_name(db, str);
-		free(str);
+		pkg->name = apk_db_get_name(db, value);
 		break;
 	case 'V':
 		pkg->version = apk_blob_cstr(value);
@@ -272,7 +275,7 @@ static int read_info_entry(void *ctx, const struct apk_file_info *ae,
 	struct apk_package *pkg = ri->pkg;
 	const int bsize = 4 * 1024;
 	apk_blob_t name, version;
-	char *slash, *str;
+	char *slash;
 	int i;
 
 	/* Meta info and scripts */
@@ -298,11 +301,8 @@ static int read_info_entry(void *ctx, const struct apk_file_info *ae,
 				       &name, &version) < 0)
 			return -1;
 
-		if (pkg->name == NULL) {
-			str = apk_blob_cstr(name);
-			pkg->name = apk_db_get_name(db, str);
-			free(str);
-		}
+		if (pkg->name == NULL)
+			pkg->name = apk_db_get_name(db, name);
 		if (pkg->version == NULL)
 			pkg->version = apk_blob_cstr(version);
 
@@ -332,7 +332,7 @@ struct apk_package *apk_pkg_read(struct apk_database *db, const char *file)
 	struct stat st;
 	int fd;
 
-	ctx.pkg = calloc(1, sizeof(struct apk_package));
+	ctx.pkg = apk_pkg_new();
 	if (ctx.pkg == NULL)
 		return NULL;
 
@@ -367,7 +367,7 @@ struct apk_package *apk_pkg_read(struct apk_database *db, const char *file)
 	/* Add implicit busybox dependency if there is scripts */
 	if (ctx.has_install) {
 		struct apk_dependency dep = {
-			.name = apk_db_get_name(db, "busybox"),
+			.name = apk_db_get_name(db, APK_BLOB_STR("busybox")),
 		};
 		apk_deps_add(&ctx.pkg->depends, &dep);
 	}
@@ -402,7 +402,7 @@ void apk_pkg_free(struct apk_package *pkg)
 
 int apk_pkg_get_state(struct apk_package *pkg)
 {
-	if (hlist_hashed(&pkg->installed_pkgs_list))
+	if (list_hashed(&pkg->installed_pkgs_list))
 		return APK_STATE_INSTALL;
 	return APK_STATE_NO_INSTALL;
 }
@@ -497,7 +497,7 @@ struct apk_package *apk_pkg_parse_index_entry(struct apk_database *db, apk_blob_
 {
 	struct read_info_ctx ctx;
 
-	ctx.pkg = calloc(1, sizeof(struct apk_package));
+	ctx.pkg = apk_pkg_new();
 	if (ctx.pkg == NULL)
 		return NULL;
 
diff --git a/src/state.c b/src/state.c
index 119bebc..24ecda9 100644
--- a/src/state.c
+++ b/src/state.c
@@ -152,8 +152,7 @@ static int apk_state_commit_deps(struct apk_state *state,
 int apk_state_commit(struct apk_state *state,
 		     struct apk_database *db)
 {
-	struct apk_package *pkg;
-	struct hlist_node *c, *n;
+	struct apk_package *pkg, *n;
 	int r;
 
 	/* Check all dependencies */
@@ -162,7 +161,7 @@ int apk_state_commit(struct apk_state *state,
 		return r;
 
 	/* And purge all installed packages that were not considered */
-	hlist_for_each_entry_safe(pkg, c, n, &db->installed.packages, installed_pkgs_list)
+	list_for_each_entry_safe(pkg, n, &db->installed.packages, installed_pkgs_list)
 		apk_state_commit_name(state, db, pkg->name);
 
 	return 0;
diff --git a/src/ver.c b/src/ver.c
index 8d62f3a..71e3d01 100644
--- a/src/ver.c
+++ b/src/ver.c
@@ -34,7 +34,6 @@ static int ver_main(int argc, char **argv)
 	struct apk_database db;
 	struct apk_name *name;
 	struct apk_package *pkg, *upg, *tmp;
-	struct hlist_node *c;
 	int i, r;
 
 	if (argc == 2) {
@@ -47,7 +46,7 @@ static int ver_main(int argc, char **argv)
 	if (apk_db_open(&db, apk_root) < 0)
 		return -1;
 
-	hlist_for_each_entry(pkg, c, &db.installed.packages, installed_pkgs_list) {
+	list_for_each_entry(pkg, &db.installed.packages, installed_pkgs_list) {
 		name = pkg->name;
 		upg = pkg;
 		for (i = 0; i < name->pkgs->num; i++) {
-- 
cgit v1.2.3-70-g09d2