hash, db: use apk_blob_t and list_*
parent
1a7f3e3678
commit
f0609951b9
|
@ -23,7 +23,7 @@ static int add_main(int argc, char **argv)
|
||||||
|
|
||||||
for (i = 0; i < argc; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
struct apk_dependency dep = {
|
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);
|
apk_deps_add(&db.world, &dep);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ typedef struct apk_blob apk_blob_t;
|
||||||
#define APK_BLOB_IS_NULL(blob) (blob.ptr == NULL)
|
#define APK_BLOB_IS_NULL(blob) (blob.ptr == NULL)
|
||||||
|
|
||||||
#define APK_BLOB_NULL ((apk_blob_t){0, 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_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_LEN(beg,len) ((apk_blob_t){(len), (beg)})
|
||||||
#define APK_BLOB_PTR_PTR(beg,end) APK_BLOB_PTR_LEN((beg),(end)-(beg)+1)
|
#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_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);
|
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 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 apk_blob_for_each_segment(apk_blob_t blob, const char *split,
|
||||||
int (*cb)(void *ctx, apk_blob_t blob), void *ctx);
|
int (*cb)(void *ctx, apk_blob_t blob), void *ctx);
|
||||||
|
|
|
@ -71,7 +71,7 @@ struct apk_database {
|
||||||
} available;
|
} available;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct hlist_head packages;
|
struct list_head packages;
|
||||||
struct apk_hash dirs;
|
struct apk_hash dirs;
|
||||||
struct {
|
struct {
|
||||||
unsigned files;
|
unsigned files;
|
||||||
|
@ -81,7 +81,12 @@ struct apk_database {
|
||||||
} installed;
|
} 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);
|
void apk_name_free(struct apk_name *pkgname);
|
||||||
|
|
||||||
int apk_db_create(const char *root);
|
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);
|
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);
|
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);
|
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_recalculate_and_commit(struct apk_database *db);
|
||||||
|
|
||||||
int apk_db_install_pkg(struct apk_database *db,
|
int apk_db_install_pkg(struct apk_database *db,
|
||||||
|
|
|
@ -169,4 +169,73 @@ static inline struct hlist_node **hlist_tail_ptr(struct hlist_head *h)
|
||||||
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
|
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
|
||||||
pos = n)
|
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
|
#endif
|
||||||
|
|
|
@ -14,20 +14,20 @@
|
||||||
|
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include "apk_defines.h"
|
#include "apk_defines.h"
|
||||||
|
#include "apk_blob.h"
|
||||||
|
|
||||||
typedef void *apk_hash_item;
|
typedef void *apk_hash_item;
|
||||||
typedef const void *apk_hash_key;
|
|
||||||
|
|
||||||
typedef unsigned long (*apk_hash_f)(apk_hash_key);
|
typedef unsigned long (*apk_hash_f)(apk_blob_t);
|
||||||
typedef int (*apk_hash_compare_f)(apk_hash_key, apk_hash_key);
|
typedef int (*apk_hash_compare_f)(apk_blob_t, apk_blob_t);
|
||||||
typedef void (*apk_hash_delete_f)(apk_hash_item);
|
typedef void (*apk_hash_delete_f)(apk_hash_item);
|
||||||
typedef int (*apk_hash_enumerator_f)(apk_hash_item, void *ctx);
|
typedef int (*apk_hash_enumerator_f)(apk_hash_item, void *ctx);
|
||||||
|
|
||||||
struct apk_hash_ops {
|
struct apk_hash_ops {
|
||||||
ptrdiff_t node_offset;
|
ptrdiff_t node_offset;
|
||||||
apk_hash_key (*get_key)(apk_hash_item item);
|
apk_blob_t (*get_key)(apk_hash_item item);
|
||||||
unsigned long (*hash_key)(apk_hash_key key);
|
unsigned long (*hash_key)(apk_blob_t key);
|
||||||
int (*compare)(apk_hash_key key, apk_hash_key item);
|
int (*compare)(apk_blob_t key, apk_blob_t itemkey);
|
||||||
void (*delete_item)(apk_hash_item item);
|
void (*delete_item)(apk_hash_item item);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -40,16 +40,13 @@ struct apk_hash {
|
||||||
int num_items;
|
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,
|
void apk_hash_init(struct apk_hash *h, const struct apk_hash_ops *ops,
|
||||||
int num_buckets);
|
int num_buckets);
|
||||||
void apk_hash_free(struct apk_hash *h);
|
void apk_hash_free(struct apk_hash *h);
|
||||||
|
|
||||||
int apk_hash_foreach(struct apk_hash *h, apk_hash_enumerator_f e, void *ctx);
|
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_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
|
#endif
|
||||||
|
|
|
@ -57,7 +57,7 @@ struct apk_package {
|
||||||
unsigned int installed_size, size;
|
unsigned int installed_size, size;
|
||||||
|
|
||||||
/* for installed packages only */
|
/* for installed packages only */
|
||||||
struct hlist_node installed_pkgs_list;
|
struct list_head installed_pkgs_list;
|
||||||
struct hlist_head owned_files;
|
struct hlist_head owned_files;
|
||||||
struct hlist_head scripts;
|
struct hlist_head scripts;
|
||||||
};
|
};
|
||||||
|
|
20
src/blob.c
20
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 apk_blob_for_each_segment(apk_blob_t blob, const char *split,
|
||||||
int (*cb)(void *ctx, apk_blob_t blob), void *ctx)
|
int (*cb)(void *ctx, apk_blob_t blob), void *ctx)
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,51 +33,53 @@ struct install_ctx {
|
||||||
struct hlist_node **file_pkg_node;
|
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 = {
|
static const struct apk_hash_ops pkg_name_hash_ops = {
|
||||||
.node_offset = offsetof(struct apk_name, hash_node),
|
.node_offset = offsetof(struct apk_name, hash_node),
|
||||||
.get_key = pkg_name_get_key,
|
.get_key = pkg_name_get_key,
|
||||||
.hash_key = (apk_hash_f) apk_hash_string,
|
.hash_key = apk_blob_hash,
|
||||||
.compare = (apk_hash_compare_f) strcmp,
|
.compare = apk_blob_compare,
|
||||||
.delete_item = (apk_hash_delete_f) apk_name_free,
|
.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 = {
|
static const struct apk_hash_ops pkg_info_hash_ops = {
|
||||||
.node_offset = offsetof(struct apk_package, hash_node),
|
.node_offset = offsetof(struct apk_package, hash_node),
|
||||||
.get_key = pkg_info_get_key,
|
.get_key = pkg_info_get_key,
|
||||||
.hash_key = (apk_hash_f) apk_hash_csum,
|
.hash_key = csum_hash,
|
||||||
.compare = cmpcsum,
|
.compare = apk_blob_compare,
|
||||||
.delete_item = (apk_hash_delete_f) apk_pkg_free,
|
.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 = {
|
static const struct apk_hash_ops dir_hash_ops = {
|
||||||
.node_offset = offsetof(struct apk_db_dir, hash_node),
|
.node_offset = offsetof(struct apk_db_dir, hash_node),
|
||||||
.get_key = apk_db_dir_get_key,
|
.get_key = apk_db_dir_get_key,
|
||||||
.hash_key = (apk_hash_f) apk_hash_string,
|
.hash_key = apk_blob_hash,
|
||||||
.compare = (apk_hash_compare_f) strcmp,
|
.compare = apk_blob_compare,
|
||||||
.delete_item = (apk_hash_delete_f) free,
|
.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;
|
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)
|
if (pn == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
pn->name = strdup(name);
|
pn->name = apk_blob_cstr(name);
|
||||||
apk_hash_insert(&db->available.names, pn);
|
apk_hash_insert(&db->available.names, pn);
|
||||||
|
|
||||||
return 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;
|
struct apk_db_dir *dir;
|
||||||
apk_blob_t bparent;
|
apk_blob_t bparent;
|
||||||
char *cstr;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (name.len && name.ptr[name.len-1] == '/')
|
if (name.len && name.ptr[name.len-1] == '/')
|
||||||
name.len--;
|
name.len--;
|
||||||
|
|
||||||
cstr = apk_blob_cstr(name);
|
dir = (struct apk_db_dir *) apk_hash_get(&db->installed.dirs, name);
|
||||||
dir = (struct apk_db_dir *) apk_hash_get(&db->installed.dirs, cstr);
|
|
||||||
free(cstr);
|
|
||||||
if (dir != NULL)
|
if (dir != NULL)
|
||||||
return dir;
|
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_package *pkg = NULL;
|
||||||
struct apk_db_dir *dir = NULL;
|
struct apk_db_dir *dir = NULL;
|
||||||
struct apk_db_file *file = 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_dir_node = NULL;
|
||||||
struct hlist_node **file_pkg_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);
|
l.len, l.ptr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (!hlist_hashed(&pkg->installed_pkgs_list)) {
|
if (!list_hashed(&pkg->installed_pkgs_list)) {
|
||||||
db->installed.stats.packages++;
|
db->installed.stats.packages++;
|
||||||
hlist_add_after(&pkg->installed_pkgs_list, pkg_node);
|
list_add_tail(&pkg->installed_pkgs_list, &db->installed.packages);
|
||||||
pkg_node = &pkg->installed_pkgs_list.next;
|
|
||||||
}
|
}
|
||||||
dir = NULL;
|
dir = NULL;
|
||||||
file_dir_node = 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_package *pkg;
|
||||||
struct apk_db_dir *dir;
|
struct apk_db_dir *dir;
|
||||||
struct apk_db_file *file;
|
struct apk_db_file *file;
|
||||||
struct hlist_node *c1, *c2;
|
struct hlist_node *c2;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
int n;
|
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;
|
n = 0;
|
||||||
buf[n++] = 'P';
|
buf[n++] = 'P';
|
||||||
n += apk_hexdump_format(sizeof(buf)-n, &buf[n],
|
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_package *pkg;
|
||||||
struct apk_script *script;
|
struct apk_script *script;
|
||||||
struct apk_script_header hdr;
|
struct apk_script_header hdr;
|
||||||
struct hlist_node *c1, *c2;
|
struct hlist_node *c2;
|
||||||
|
|
||||||
hlist_for_each_entry(pkg, c1, &db->installed.packages,
|
list_for_each_entry(pkg, &db->installed.packages, installed_pkgs_list) {
|
||||||
installed_pkgs_list) {
|
|
||||||
hlist_for_each_entry(script, c2, &pkg->scripts, script_list) {
|
hlist_for_each_entry(script, c2, &pkg->scripts, script_list) {
|
||||||
memcpy(hdr.csum, pkg->csum, sizeof(csum_t));
|
memcpy(hdr.csum, pkg->csum, sizeof(csum_t));
|
||||||
hdr.type = script->type;
|
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)) {
|
while (is->read(is, &hdr, sizeof(hdr)) == sizeof(hdr)) {
|
||||||
pkg = apk_db_get_pkg(db, hdr.csum);
|
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;
|
return 0;
|
||||||
|
@ -485,6 +482,12 @@ static int apk_db_read_state(struct apk_database *db)
|
||||||
is->close(is);
|
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;
|
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.names, &pkg_name_hash_ops, 1000);
|
||||||
apk_hash_init(&db->available.packages, &pkg_info_hash_ops, 4000);
|
apk_hash_init(&db->available.packages, &pkg_info_hash_ops, 4000);
|
||||||
apk_hash_init(&db->installed.dirs, &dir_hash_ops, 1000);
|
apk_hash_init(&db->installed.dirs, &dir_hash_ops, 1000);
|
||||||
|
list_init(&db->installed.packages);
|
||||||
|
|
||||||
if (root != NULL) {
|
if (root != NULL) {
|
||||||
db->root = strdup(root);
|
db->root = strdup(root);
|
||||||
|
@ -515,7 +519,7 @@ int apk_db_open(struct apk_database *db, const char *root)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (apk_repository != NULL)
|
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");
|
dirs = APK_BLOB_STR("etc:-etc/init.d");
|
||||||
apk_blob_for_each_segment(dirs, ":", add_protected_path, db);
|
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;
|
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) {
|
if (idb == NULL) {
|
||||||
pkg->id = db->pkg_id++;
|
pkg->id = db->pkg_id++;
|
||||||
apk_hash_insert(&db->available.packages, pkg);
|
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)
|
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)
|
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;
|
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;
|
struct apk_package *pkg;
|
||||||
char buf[1024];
|
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);
|
r = APK_BLOB_PTR_LEN(buf, 0);
|
||||||
while (1) {
|
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)
|
if (n <= 0)
|
||||||
break;
|
break;
|
||||||
r.len += n;
|
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);
|
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];
|
char tmp[256];
|
||||||
int fd, r;
|
int r;
|
||||||
|
|
||||||
if (db->num_repos >= APK_MAX_REPOS)
|
if (db->num_repos >= APK_MAX_REPOS)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
r = db->num_repos++;
|
r = db->num_repos++;
|
||||||
db->repos[r] = (struct apk_repository){
|
db->repos[r] = (struct apk_repository){
|
||||||
.url = strdup(repo)
|
.url = apk_blob_cstr(repository)
|
||||||
};
|
};
|
||||||
|
|
||||||
snprintf(tmp, sizeof(tmp), "%s/APK_INDEX", repo);
|
snprintf(tmp, sizeof(tmp), "%s/APK_INDEX", db->repos[r].url);
|
||||||
fd = open(tmp, O_RDONLY);
|
is = apk_istream_from_file(tmp);
|
||||||
if (fd < 0) {
|
if (is == NULL) {
|
||||||
apk_error("Failed to open index file %s", tmp);
|
apk_error("Failed to open index file %s", tmp);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
apk_db_index_read(db, fd, r);
|
apk_db_index_read(db, is, r);
|
||||||
close(fd);
|
is->close(is);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -823,6 +830,7 @@ static void apk_db_purge_pkg(struct apk_database *db,
|
||||||
db->installed.stats.files--;
|
db->installed.stats.files--;
|
||||||
}
|
}
|
||||||
db->installed.stats.packages--;
|
db->installed.stats.packages--;
|
||||||
|
list_del(&pkg->installed_pkgs_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
int apk_db_install_pkg(struct apk_database *db,
|
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);
|
bs->close(bs, csum);
|
||||||
|
|
||||||
db->installed.stats.packages++;
|
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)
|
if (memcmp(csum, newpkg->csum, sizeof(csum)) != 0)
|
||||||
apk_warning("%s-%s: checksum does not match",
|
apk_warning("%s-%s: checksum does not match",
|
||||||
|
|
24
src/hash.c
24
src/hash.c
|
@ -12,22 +12,6 @@
|
||||||
#include "apk_defines.h"
|
#include "apk_defines.h"
|
||||||
#include "apk_hash.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,
|
void apk_hash_init(struct apk_hash *h, const struct apk_hash_ops *ops,
|
||||||
int num_buckets)
|
int num_buckets)
|
||||||
{
|
{
|
||||||
|
@ -59,13 +43,13 @@ int apk_hash_foreach(struct apk_hash *h, apk_hash_enumerator_f e, void *ctx)
|
||||||
return 0;
|
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;
|
ptrdiff_t offset = h->ops->node_offset;
|
||||||
unsigned long hash;
|
unsigned long hash;
|
||||||
apk_hash_node *pos;
|
apk_hash_node *pos;
|
||||||
apk_hash_item item;
|
apk_hash_item item;
|
||||||
apk_hash_key itemkey;
|
apk_blob_t itemkey;
|
||||||
|
|
||||||
hash = h->ops->hash_key(key) % h->buckets->num;
|
hash = h->ops->hash_key(key) % h->buckets->num;
|
||||||
hlist_for_each(pos, &h->buckets->item[hash]) {
|
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)
|
void apk_hash_insert(struct apk_hash *h, apk_hash_item item)
|
||||||
{
|
{
|
||||||
apk_hash_key key;
|
apk_blob_t key;
|
||||||
unsigned long hash;
|
unsigned long hash;
|
||||||
apk_hash_node *node;
|
apk_hash_node *node;
|
||||||
|
|
||||||
|
@ -91,7 +75,7 @@ void apk_hash_insert(struct apk_hash *h, apk_hash_item item)
|
||||||
h->num_items++;
|
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)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,17 @@
|
||||||
#include "apk_database.h"
|
#include "apk_database.h"
|
||||||
#include "apk_state.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,
|
int apk_pkg_parse_name(apk_blob_t apkname,
|
||||||
apk_blob_t *name,
|
apk_blob_t *name,
|
||||||
apk_blob_t *version)
|
apk_blob_t *version)
|
||||||
|
@ -67,7 +78,6 @@ static void parse_depend(struct apk_database *db,
|
||||||
{
|
{
|
||||||
struct apk_dependency *dep;
|
struct apk_dependency *dep;
|
||||||
struct apk_name *name;
|
struct apk_name *name;
|
||||||
char *cname;
|
|
||||||
|
|
||||||
while (blob.len && blob.ptr[0] == ' ')
|
while (blob.len && blob.ptr[0] == ' ')
|
||||||
blob.ptr++, blob.len--;
|
blob.ptr++, blob.len--;
|
||||||
|
@ -78,10 +88,7 @@ static void parse_depend(struct apk_database *db,
|
||||||
if (blob.len == 0)
|
if (blob.len == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cname = apk_blob_cstr(blob);
|
name = apk_db_get_name(db, blob);
|
||||||
name = apk_db_get_name(db, cname);
|
|
||||||
free(cname);
|
|
||||||
|
|
||||||
dep = apk_dependency_array_add(depends);
|
dep = apk_dependency_array_add(depends);
|
||||||
*dep = (struct apk_dependency){
|
*dep = (struct apk_dependency){
|
||||||
.prefer_upgrade = 0,
|
.prefer_upgrade = 0,
|
||||||
|
@ -185,13 +192,9 @@ struct read_info_ctx {
|
||||||
static int add_info(struct apk_database *db, struct apk_package *pkg,
|
static int add_info(struct apk_database *db, struct apk_package *pkg,
|
||||||
char field, apk_blob_t value)
|
char field, apk_blob_t value)
|
||||||
{
|
{
|
||||||
char *str;
|
|
||||||
|
|
||||||
switch (field) {
|
switch (field) {
|
||||||
case 'P':
|
case 'P':
|
||||||
str = apk_blob_cstr(value);
|
pkg->name = apk_db_get_name(db, value);
|
||||||
pkg->name = apk_db_get_name(db, str);
|
|
||||||
free(str);
|
|
||||||
break;
|
break;
|
||||||
case 'V':
|
case 'V':
|
||||||
pkg->version = apk_blob_cstr(value);
|
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;
|
struct apk_package *pkg = ri->pkg;
|
||||||
const int bsize = 4 * 1024;
|
const int bsize = 4 * 1024;
|
||||||
apk_blob_t name, version;
|
apk_blob_t name, version;
|
||||||
char *slash, *str;
|
char *slash;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Meta info and scripts */
|
/* Meta info and scripts */
|
||||||
|
@ -298,11 +301,8 @@ static int read_info_entry(void *ctx, const struct apk_file_info *ae,
|
||||||
&name, &version) < 0)
|
&name, &version) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (pkg->name == NULL) {
|
if (pkg->name == NULL)
|
||||||
str = apk_blob_cstr(name);
|
pkg->name = apk_db_get_name(db, name);
|
||||||
pkg->name = apk_db_get_name(db, str);
|
|
||||||
free(str);
|
|
||||||
}
|
|
||||||
if (pkg->version == NULL)
|
if (pkg->version == NULL)
|
||||||
pkg->version = apk_blob_cstr(version);
|
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;
|
struct stat st;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
ctx.pkg = calloc(1, sizeof(struct apk_package));
|
ctx.pkg = apk_pkg_new();
|
||||||
if (ctx.pkg == NULL)
|
if (ctx.pkg == NULL)
|
||||||
return 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 */
|
/* Add implicit busybox dependency if there is scripts */
|
||||||
if (ctx.has_install) {
|
if (ctx.has_install) {
|
||||||
struct apk_dependency dep = {
|
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);
|
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)
|
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_INSTALL;
|
||||||
return APK_STATE_NO_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;
|
struct read_info_ctx ctx;
|
||||||
|
|
||||||
ctx.pkg = calloc(1, sizeof(struct apk_package));
|
ctx.pkg = apk_pkg_new();
|
||||||
if (ctx.pkg == NULL)
|
if (ctx.pkg == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|
|
@ -152,8 +152,7 @@ static int apk_state_commit_deps(struct apk_state *state,
|
||||||
int apk_state_commit(struct apk_state *state,
|
int apk_state_commit(struct apk_state *state,
|
||||||
struct apk_database *db)
|
struct apk_database *db)
|
||||||
{
|
{
|
||||||
struct apk_package *pkg;
|
struct apk_package *pkg, *n;
|
||||||
struct hlist_node *c, *n;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* Check all dependencies */
|
/* Check all dependencies */
|
||||||
|
@ -162,7 +161,7 @@ int apk_state_commit(struct apk_state *state,
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
/* And purge all installed packages that were not considered */
|
/* 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);
|
apk_state_commit_name(state, db, pkg->name);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -34,7 +34,6 @@ static int ver_main(int argc, char **argv)
|
||||||
struct apk_database db;
|
struct apk_database db;
|
||||||
struct apk_name *name;
|
struct apk_name *name;
|
||||||
struct apk_package *pkg, *upg, *tmp;
|
struct apk_package *pkg, *upg, *tmp;
|
||||||
struct hlist_node *c;
|
|
||||||
int i, r;
|
int i, r;
|
||||||
|
|
||||||
if (argc == 2) {
|
if (argc == 2) {
|
||||||
|
@ -47,7 +46,7 @@ static int ver_main(int argc, char **argv)
|
||||||
if (apk_db_open(&db, apk_root) < 0)
|
if (apk_db_open(&db, apk_root) < 0)
|
||||||
return -1;
|
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;
|
name = pkg->name;
|
||||||
upg = pkg;
|
upg = pkg;
|
||||||
for (i = 0; i < name->pkgs->num; i++) {
|
for (i = 0; i < name->pkgs->num; i++) {
|
||||||
|
|
Loading…
Reference in New Issue