From d0edeec8fb8fa5abee8b3065cea5e4882d0c51c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Tue, 19 May 2020 11:39:21 +0300 Subject: [PATCH] make the atom functions not use global state This greatly helps with memory management on applications that may want to daemonize and open/close database several times. Also the lifetime and "owner" of memory for all data is now explicitly bound to owning struct apk_database, which might be helpful when writing language bindings. As side effect, the interned "atoms" are unique only within what apk_database, so comparing packages from different apk_database may not work as expected. Fixes #10697 --- src/Makefile | 2 +- src/apk.c | 1 - src/apk_atom.h | 33 ++++++++++++++++++++ src/apk_blob.h | 5 --- src/apk_database.h | 2 ++ src/apk_io.h | 3 +- src/app_add.c | 6 ++-- src/app_audit.c | 4 +-- src/app_fetch.c | 4 +-- src/app_index.c | 27 ++++++++-------- src/app_info.c | 2 +- src/app_list.c | 30 +++++++----------- src/app_stats.c | 4 +-- src/app_upgrade.c | 2 +- src/app_version.c | 2 +- src/atom.c | 64 ++++++++++++++++++++++++++++++++++++++ src/blob.c | 76 ---------------------------------------------- src/commit.c | 4 +-- src/database.c | 36 +++++++++++----------- src/hash.c | 3 +- src/io.c | 11 +++---- src/lua-apk.c | 1 - src/package.c | 18 +++++------ src/solver.c | 24 +++++++-------- 24 files changed, 185 insertions(+), 179 deletions(-) create mode 100644 src/apk_atom.h create mode 100644 src/atom.c diff --git a/src/Makefile b/src/Makefile index 4a055ce..3bbd51e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -18,7 +18,7 @@ ZLIB_LIBS := $(shell $(PKG_CONFIG) --libs zlib) # Dynamic library libapk.so.$(VERSION)-objs := \ common.o database.o package.o commit.o solver.o \ - version.o blob.o hash.o print.o \ + version.o atom.o blob.o hash.o print.o \ io.o io_url.o io_gunzip.o io_archive.o libapk.so.$(VERSION)-libs := libfetch/libfetch.a diff --git a/src/apk.c b/src/apk.c index 8fbc3e8..79aef3e 100644 --- a/src/apk.c +++ b/src/apk.c @@ -518,7 +518,6 @@ int main(int argc, char **argv) memset(&dbopts, 0, sizeof(dbopts)); list_init(&dbopts.repository_list); - apk_atom_init(); umask(0); setup_terminal(); diff --git a/src/apk_atom.h b/src/apk_atom.h new file mode 100644 index 0000000..1b6ad6c --- /dev/null +++ b/src/apk_atom.h @@ -0,0 +1,33 @@ +/* apk_atom.h - Alpine Package Keeper (APK) + * + * Copyright (C) 2005-2008 Natanael Copa + * Copyright (C) 2008-2020 Timo Teräs + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#ifndef APK_ATOM_H +#define APK_ATOM_H + +#include "apk_hash.h" +#include "apk_blob.h" + +extern apk_blob_t apk_atom_null; + +struct apk_atom_pool { + struct apk_hash hash; +}; + +void apk_atom_init(struct apk_atom_pool *); +void apk_atom_free(struct apk_atom_pool *); +apk_blob_t *apk_atom_get(struct apk_atom_pool *atoms, apk_blob_t blob, int duplicate); + +static inline apk_blob_t *apk_atomize(struct apk_atom_pool *atoms, apk_blob_t blob) { + return apk_atom_get(atoms, blob, 0); +} +static inline apk_blob_t *apk_atomize_dup(struct apk_atom_pool *atoms, apk_blob_t blob) { + return apk_atom_get(atoms, blob, 1); +} + +#endif diff --git a/src/apk_blob.h b/src/apk_blob.h index 84bd143..008666e 100644 --- a/src/apk_blob.h +++ b/src/apk_blob.h @@ -25,7 +25,6 @@ struct apk_blob { }; typedef struct apk_blob apk_blob_t; typedef int (*apk_blob_cb)(void *ctx, apk_blob_t blob); -extern apk_blob_t apk_null_blob; #define BLOB_FMT "%.*s" #define BLOB_PRINTF(b) (int)(b).len, (b).ptr @@ -130,10 +129,6 @@ void apk_blob_pull_base64(apk_blob_t *b, apk_blob_t to); void apk_blob_pull_hexdump(apk_blob_t *b, apk_blob_t to); int apk_blob_pull_blob_match(apk_blob_t *b, apk_blob_t match); -void apk_atom_init(void); -apk_blob_t *apk_blob_atomize(apk_blob_t blob); -apk_blob_t *apk_blob_atomize_dup(apk_blob_t blob); - #if defined(__GLIBC__) && !defined(__UCLIBC__) extern size_t strlcpy(char *dest, const char *src, size_t size); #endif diff --git a/src/apk_database.h b/src/apk_database.h index dc6525f..3488031 100644 --- a/src/apk_database.h +++ b/src/apk_database.h @@ -12,6 +12,7 @@ #include "apk_version.h" #include "apk_hash.h" +#include "apk_atom.h" #include "apk_archive.h" #include "apk_package.h" #include "apk_io.h" @@ -166,6 +167,7 @@ struct apk_database { struct apk_repository repos[APK_MAX_REPOS]; struct apk_repository_tag repo_tags[APK_MAX_TAGS]; struct apk_id_cache id_cache; + struct apk_atom_pool atoms; struct { struct apk_hash names; diff --git a/src/apk_io.h b/src/apk_io.h index e4759b0..18b8ecc 100644 --- a/src/apk_io.h +++ b/src/apk_io.h @@ -16,6 +16,7 @@ #include "apk_defines.h" #include "apk_blob.h" #include "apk_hash.h" +#include "apk_atom.h" struct apk_id_cache { int root_fd; @@ -167,7 +168,7 @@ int apk_blob_to_file(int atfd, const char *file, apk_blob_t b, unsigned int flag #define APK_FI_XATTR_CSUM(x) (((x) & 0xff) << 8) #define APK_FI_CSUM(x) (((x) & 0xff)) int apk_fileinfo_get(int atfd, const char *filename, unsigned int flags, - struct apk_file_info *fi); + struct apk_file_info *fi, struct apk_atom_pool *atoms); void apk_fileinfo_hash_xattr(struct apk_file_info *fi); void apk_fileinfo_free(struct apk_file_info *fi); diff --git a/src/app_add.c b/src/app_add.c index fb6e0e0..1f6c875 100644 --- a/src/app_add.c +++ b/src/app_add.c @@ -100,9 +100,9 @@ static struct apk_package *create_virtual_package(struct apk_database *db, struc if (virtpkg == NULL) return 0; virtpkg->name = name; - virtpkg->version = apk_blob_atomize_dup(APK_BLOB_STR(ver)); + virtpkg->version = apk_atomize_dup(&db->atoms, APK_BLOB_STR(ver)); virtpkg->description = strdup("virtual meta package"); - virtpkg->arch = apk_blob_atomize(APK_BLOB_STR("noarch")); + virtpkg->arch = apk_atomize(&db->atoms, APK_BLOB_STR("noarch")); mdctx = EVP_MD_CTX_new(); EVP_DigestInit_ex(mdctx, apk_checksum_default(), NULL); @@ -135,7 +135,7 @@ static int add_main(void *ctx, struct apk_database *db, struct apk_string_array apk_blob_pull_dep(&b, db, &virtdep); if (APK_BLOB_IS_NULL(b) || virtdep.conflict || virtdep.result_mask != APK_DEPMASK_ANY || - virtdep.version != &apk_null_blob) { + virtdep.version != &apk_atom_null) { apk_error("%s: bad package specifier"); return -1; } diff --git a/src/app_audit.c b/src/app_audit.c index fb2a0ee..011a26c 100644 --- a/src/app_audit.c +++ b/src/app_audit.c @@ -107,7 +107,7 @@ static int audit_file(struct audit_ctx *actx, APK_FI_NOFOLLOW | APK_FI_XATTR_CSUM(dbf->acl->xattr_csum.type ?: APK_CHECKSUM_DEFAULT) | APK_FI_CSUM(dbf->csum.type), - &fi) != 0) + &fi, &db->atoms) != 0) return -EPERM; if (dbf->csum.type != APK_CHECKSUM_NONE && @@ -183,7 +183,7 @@ static int audit_directory_tree_item(void *ctx, int dirfd, const char *name) int reason = 0; if (bdir.len + bent.len + 1 >= sizeof(atctx->path)) return 0; - if (apk_fileinfo_get(dirfd, name, APK_FI_NOFOLLOW, &fi) < 0) return 0; + if (apk_fileinfo_get(dirfd, name, APK_FI_NOFOLLOW, &fi, &db->atoms) < 0) return 0; memcpy(&atctx->path[atctx->pathlen], bent.ptr, bent.len); atctx->pathlen += bent.len; diff --git a/src/app_fetch.c b/src/app_fetch.c index 8e73c0e..e6f4fbe 100644 --- a/src/app_fetch.c +++ b/src/app_fetch.c @@ -145,7 +145,7 @@ static int fetch_package(apk_hash_item item, void *pctx) } if (!(ctx->flags & FETCH_STDOUT)) { - if (apk_fileinfo_get(ctx->outdir_fd, filename, APK_CHECKSUM_NONE, &fi) == 0 && + if (apk_fileinfo_get(ctx->outdir_fd, filename, APK_CHECKSUM_NONE, &fi, &db->atoms) == 0 && fi.size == pkg->size) return 0; } @@ -227,7 +227,7 @@ static void mark_name_flags(struct apk_database *db, const char *match, struct a struct fetch_ctx *ctx = (struct fetch_ctx *) pctx; struct apk_dependency dep = (struct apk_dependency) { .name = name, - .version = &apk_null_blob, + .version = &apk_atom_null, .result_mask = APK_DEPMASK_ANY, }; diff --git a/src/app_index.c b/src/app_index.c index 4c0b0d1..53e53b0 100644 --- a/src/app_index.c +++ b/src/app_index.c @@ -27,7 +27,7 @@ struct index_ctx { const char *index; const char *output; const char *description; - apk_blob_t *rewrite_arch; + const char *rewrite_arch; time_t index_mtime; int method; unsigned short index_flags; @@ -64,7 +64,7 @@ static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int opt ictx->output = optarg; break; case OPT_INDEX_rewrite_arch: - ictx->rewrite_arch = apk_blob_atomize(APK_BLOB_STR(optarg)); + ictx->rewrite_arch = optarg; break; case OPT_INDEX_no_warnings: ictx->index_flags |= APK_INDEXF_NO_WARNINGS; @@ -86,7 +86,7 @@ static int index_read_file(struct apk_database *db, struct index_ctx *ictx) if (ictx->index == NULL) return 0; - if (apk_fileinfo_get(AT_FDCWD, ictx->index, APK_CHECKSUM_NONE, &fi) < 0) + if (apk_fileinfo_get(AT_FDCWD, ictx->index, APK_CHECKSUM_NONE, &fi, &db->atoms) < 0) return 0; ictx->index_mtime = fi.mtime; @@ -121,6 +121,7 @@ static int index_main(void *ctx, struct apk_database *db, struct apk_string_arra struct index_ctx *ictx = (struct index_ctx *) ctx; struct apk_package *pkg; char **parg; + apk_blob_t *rewrite_arch = NULL; if (isatty(STDOUT_FILENO) && ictx->output == NULL && !(apk_force & APK_FORCE_BINARY_STDOUT)) { @@ -137,8 +138,11 @@ static int index_main(void *ctx, struct apk_database *db, struct apk_string_arra return r; } + if (ictx->rewrite_arch) + rewrite_arch = apk_atomize(&db->atoms, APK_BLOB_STR(ictx->rewrite_arch)); + foreach_array_item(parg, args) { - if (apk_fileinfo_get(AT_FDCWD, *parg, APK_CHECKSUM_NONE, &fi) < 0) { + if (apk_fileinfo_get(AT_FDCWD, *parg, APK_CHECKSUM_NONE, &fi, &db->atoms) < 0) { apk_warning("File '%s' is unaccessible", *parg); continue; } @@ -174,15 +178,11 @@ static int index_main(void *ctx, struct apk_database *db, struct apk_string_arra foreach_array_item(p, name->providers) { pkg = p->pkg; - if (pkg->name != name) - continue; - if (apk_blob_compare(bver, *pkg->version) != 0) - continue; - if (pkg->size != fi.size) - continue; + if (pkg->name != name) continue; + if (apk_blob_compare(bver, *pkg->version) != 0) continue; + if (pkg->size != fi.size) continue; pkg->filename = strdup(*parg); - if (ictx->rewrite_arch != NULL) - pkg->arch = ictx->rewrite_arch; + if (rewrite_arch) pkg->arch = rewrite_arch; found = TRUE; break; } @@ -197,8 +197,7 @@ static int index_main(void *ctx, struct apk_database *db, struct apk_string_arra errors++; } else { newpkgs++; - if (ictx->rewrite_arch != NULL) - pkg->arch = ictx->rewrite_arch; + if (rewrite_arch) pkg->arch = rewrite_arch; } apk_sign_ctx_free(&sctx); } diff --git a/src/app_info.c b/src/app_info.c index 41d6a99..b444b80 100644 --- a/src/app_info.c +++ b/src/app_info.c @@ -125,7 +125,7 @@ static void info_who_owns(struct info_ctx *ctx, struct apk_database *db, if (apk_verbosity < 1) { dep = (struct apk_dependency) { .name = pkg->name, - .version = apk_blob_atomize(APK_BLOB_NULL), + .version = &apk_atom_null, .result_mask = APK_DEPMASK_ANY, }; apk_deps_add(&deps, &dep); diff --git a/src/app_list.c b/src/app_list.c index ab5c846..24d1a88 100644 --- a/src/app_list.c +++ b/src/app_list.c @@ -67,33 +67,25 @@ static const struct apk_package *is_upgradable(struct apk_name *name, const stru { struct apk_provider *p; struct apk_package *ipkg; - apk_blob_t *latest = apk_blob_atomize(APK_BLOB_STR("")); + apk_blob_t no_version = APK_BLOB_STR(""); + apk_blob_t *latest = &no_version; + int r; - if (name == NULL) - return NULL; + if (!name) return NULL; ipkg = apk_pkg_get_installed(name); - if (ipkg == NULL) - return NULL; + if (!ipkg) return NULL; - if (pkg0 == NULL) - { - foreach_array_item(p, name->providers) - { + if (!pkg0) { + foreach_array_item(p, name->providers) { pkg0 = p->pkg; - int r; - - if (pkg0 == ipkg) - continue; - + if (pkg0 == ipkg) continue; r = apk_version_compare_blob(*pkg0->version, *latest); - if (r == APK_VERSION_GREATER) - latest = pkg0->version; + if (r == APK_VERSION_GREATER) latest = pkg0->version; } - } - else + } else { latest = pkg0->version; - + } return apk_version_compare_blob(*ipkg->version, *latest) == APK_VERSION_LESS ? ipkg : NULL; } diff --git a/src/app_stats.c b/src/app_stats.c index 583e4c6..7e60494 100644 --- a/src/app_stats.c +++ b/src/app_stats.c @@ -24,8 +24,6 @@ static int list_count(struct list_head *h) static int stats_main(void *ctx, struct apk_database *db, struct apk_string_array *args) { - extern struct apk_hash atom_hash; - printf( "installed:\n" " packages: %d\n" @@ -46,7 +44,7 @@ static int stats_main(void *ctx, struct apk_database *db, struct apk_string_arra list_count(&db->installed.triggers), db->available.names.num_items, db->available.packages.num_items, - atom_hash.num_items + db->atoms.hash.num_items ); return 0; } diff --git a/src/app_upgrade.c b/src/app_upgrade.c index 0c8d4dd..7e5347f 100644 --- a/src/app_upgrade.c +++ b/src/app_upgrade.c @@ -174,7 +174,7 @@ static int upgrade_main(void *ctx, struct apk_database *db, struct apk_string_ar foreach_array_item(dep, world) { if (dep->result_mask == APK_DEPMASK_CHECKSUM) { dep->result_mask = APK_DEPMASK_ANY; - dep->version = apk_blob_atomize(APK_BLOB_NULL); + dep->version = &apk_atom_null; } } } else { diff --git a/src/app_version.c b/src/app_version.c index df2506c..2dc3bcd 100644 --- a/src/app_version.c +++ b/src/app_version.c @@ -121,7 +121,7 @@ static void ver_print_package_status(struct apk_database *db, const char *match, struct apk_provider *p0; char pkgname[41]; const char *opstr; - apk_blob_t *latest = apk_blob_atomize(APK_BLOB_STR("")); + apk_blob_t *latest = apk_atomize(&db->atoms, APK_BLOB_STR("")); unsigned int latest_repos = 0; int i, r = -1; unsigned short tag, allowed_repos; diff --git a/src/atom.c b/src/atom.c new file mode 100644 index 0000000..e2ff83e --- /dev/null +++ b/src/atom.c @@ -0,0 +1,64 @@ +/* apk_atom.c - Alpine Package Keeper (APK) + * + * Copyright (C) 2005-2008 Natanael Copa + * Copyright (C) 2008-2020 Timo Teräs + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#include "apk_atom.h" + +apk_blob_t apk_atom_null = APK_BLOB_NULL; + +struct apk_atom_hashnode { + struct hlist_node hash_node; + apk_blob_t blob; +}; + +static apk_blob_t atom_hash_get_key(apk_hash_item item) +{ + return ((struct apk_atom_hashnode *) item)->blob; +} + +static struct apk_hash_ops atom_ops = { + .node_offset = offsetof(struct apk_atom_hashnode, hash_node), + .get_key = atom_hash_get_key, + .hash_key = apk_blob_hash, + .compare = apk_blob_compare, + .delete_item = (apk_hash_delete_f) free, +}; + +void apk_atom_init(struct apk_atom_pool *atoms) +{ + apk_hash_init(&atoms->hash, &atom_ops, 10000); +} + +void apk_atom_free(struct apk_atom_pool *atoms) +{ + apk_hash_free(&atoms->hash); +} + +apk_blob_t *apk_atom_get(struct apk_atom_pool *atoms, apk_blob_t blob, int duplicate) +{ + struct apk_atom_hashnode *atom; + unsigned long hash = apk_hash_from_key(&atoms->hash, blob); + + if (blob.len < 0 || !blob.ptr) return &apk_atom_null; + + atom = (struct apk_atom_hashnode *) apk_hash_get_hashed(&atoms->hash, blob, hash); + if (atom) return &atom->blob; + + if (duplicate) { + char *ptr; + atom = malloc(sizeof(*atom) + blob.len); + ptr = (char*) (atom + 1); + memcpy(ptr, blob.ptr, blob.len); + atom->blob = APK_BLOB_PTR_LEN(ptr, blob.len); + } else { + atom = malloc(sizeof(*atom)); + atom->blob = blob; + } + apk_hash_insert_hashed(&atoms->hash, atom, hash); + return &atom->blob; +} diff --git a/src/blob.c b/src/blob.c index 72b9fd6..1a63686 100644 --- a/src/blob.c +++ b/src/blob.c @@ -15,11 +15,6 @@ #include "apk_blob.h" #include "apk_hash.h" -struct apk_blob_atom { - struct hlist_node hash_node; - apk_blob_t blob; -}; - char *apk_blob_cstr(apk_blob_t blob) { char *cstr; @@ -640,77 +635,6 @@ err: *b = APK_BLOB_NULL; } -static apk_blob_t atom_hash_get_key(apk_hash_item item) -{ - return ((struct apk_blob_atom *) item)->blob; -} - -struct apk_hash atom_hash; -static struct apk_hash_ops atom_ops = { - .node_offset = offsetof(struct apk_blob_atom, hash_node), - .get_key = atom_hash_get_key, - .hash_key = apk_blob_hash, - .compare = apk_blob_compare, - .delete_item = (apk_hash_delete_f) free, -}; - -apk_blob_t apk_null_blob = {0,0}; - -#ifdef VALGRIND -static void apk_atom_fini(void) -{ - apk_hash_free(&atom_hash); -} -#endif - -void apk_atom_init(void) -{ -#ifdef VALGRIND - atexit(apk_atom_fini); -#endif - apk_hash_init(&atom_hash, &atom_ops, 10000); -} - -apk_blob_t *apk_blob_atomize(apk_blob_t blob) -{ - struct apk_blob_atom *atom; - unsigned long hash = apk_hash_from_key(&atom_hash, blob); - - if (blob.len < 0 || blob.ptr == NULL) - return &apk_null_blob; - - atom = (struct apk_blob_atom *) apk_hash_get_hashed(&atom_hash, blob, hash); - if (atom != NULL) - return &atom->blob; - - atom = malloc(sizeof(*atom)); - atom->blob = blob; - apk_hash_insert_hashed(&atom_hash, atom, hash); - - return &atom->blob; -} - -apk_blob_t *apk_blob_atomize_dup(apk_blob_t blob) -{ - struct apk_blob_atom *atom; - unsigned long hash = apk_hash_from_key(&atom_hash, blob); - char *ptr; - - if (blob.len < 0 || blob.ptr == NULL) - return &apk_null_blob; - atom = (struct apk_blob_atom *) apk_hash_get_hashed(&atom_hash, blob, hash); - if (atom != NULL) - return &atom->blob; - - atom = malloc(sizeof(*atom) + blob.len); - ptr = (char*) (atom + 1); - memcpy(ptr, blob.ptr, blob.len); - atom->blob = APK_BLOB_PTR_LEN(ptr, blob.len); - apk_hash_insert_hashed(&atom_hash, atom, hash); - - return &atom->blob; -} - #if defined(__GLIBC__) && !defined(__UCLIBC__) size_t strlcpy(char *dst, const char *src, size_t size) { diff --git a/src/commit.c b/src/commit.c index 8c337e3..b82607c 100644 --- a/src/commit.c +++ b/src/commit.c @@ -453,8 +453,8 @@ static void print_conflicts(struct print_state *ps, struct apk_package *pkg) foreach_array_item(p, d->name->providers) { if (!p->pkg->marked) continue; - if (d->version == &apk_null_blob && - p->version == &apk_null_blob) + if (d->version == &apk_atom_null && + p->version == &apk_atom_null) continue; if (once && p->pkg == pkg && p->version == d->version) { diff --git a/src/database.c b/src/database.c index 65d07e2..d113d6a 100644 --- a/src/database.c +++ b/src/database.c @@ -225,7 +225,7 @@ struct apk_name *apk_db_get_name(struct apk_database *db, apk_blob_t name) return pn; } -static struct apk_db_acl *apk_db_acl_atomize(mode_t mode, uid_t uid, gid_t gid, const struct apk_checksum *xattr_csum) +static struct apk_db_acl *apk_db_acl_atomize(struct apk_database *db, mode_t mode, uid_t uid, gid_t gid, const struct apk_checksum *xattr_csum) { struct apk_db_acl acl = { .mode = mode & 07777, .uid = uid, .gid = gid }; apk_blob_t *b; @@ -233,7 +233,7 @@ static struct apk_db_acl *apk_db_acl_atomize(mode_t mode, uid_t uid, gid_t gid, if (xattr_csum && xattr_csum->type != APK_CHECKSUM_NONE) acl.xattr_csum = *xattr_csum; - b = apk_blob_atomize_dup(APK_BLOB_STRUCT(acl)); + b = apk_atomize_dup(&db->atoms, APK_BLOB_STRUCT(acl)); return (struct apk_db_acl *) b->ptr; } @@ -518,8 +518,7 @@ struct apk_package *apk_db_pkg_add(struct apk_database *db, struct apk_package * struct apk_package *idb; struct apk_dependency *dep; - if (pkg->license == NULL) - pkg->license = apk_blob_atomize(APK_BLOB_NULL); + if (!pkg->license) pkg->license = &apk_atom_null; /* Set as "cached" if installing from specified file, and * for virtual packages */ @@ -848,7 +847,7 @@ int apk_db_index_read(struct apk_database *db, struct apk_istream *is, int repo) else xattr_csum.type = APK_CHECKSUM_NONE; - acl = apk_db_acl_atomize(mode, uid, gid, &xattr_csum); + acl = apk_db_acl_atomize(db, mode, uid, gid, &xattr_csum); if (field == 'M') diri->acl = acl; else @@ -1501,6 +1500,7 @@ void apk_db_init(struct apk_database *db) apk_hash_init(&db->available.packages, &pkg_info_hash_ops, 10000); apk_hash_init(&db->installed.dirs, &dir_hash_ops, 20000); apk_hash_init(&db->installed.files, &file_hash_ops, 200000); + apk_atom_init(&db->atoms); list_init(&db->installed.packages); list_init(&db->installed.triggers); apk_dependency_array_init(&db->world); @@ -1517,8 +1517,8 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) apk_blob_t blob; int r, fd, write_arch = FALSE; - apk_default_acl_dir = apk_db_acl_atomize(0755, 0, 0, NULL); - apk_default_acl_file = apk_db_acl_atomize(0644, 0, 0, NULL); + apk_default_acl_dir = apk_db_acl_atomize(db, 0755, 0, 0, NULL); + apk_default_acl_file = apk_db_acl_atomize(db, 0644, 0, 0, NULL); if (apk_flags & APK_SIMULATE) { dbopts->open_flags &= ~(APK_OPENF_CREATE | APK_OPENF_WRITE); @@ -1553,16 +1553,16 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) db->permanent = 0; if (dbopts->root && dbopts->arch) { - db->arch = apk_blob_atomize(APK_BLOB_STR(dbopts->arch)); + db->arch = apk_atomize(&db->atoms, APK_BLOB_STR(dbopts->arch)); write_arch = TRUE; } else { apk_blob_t arch; arch = apk_blob_from_file(db->root_fd, apk_arch_file); if (!APK_BLOB_IS_NULL(arch)) { - db->arch = apk_blob_atomize_dup(apk_blob_trim(arch)); + db->arch = apk_atomize_dup(&db->atoms, apk_blob_trim(arch)); free(arch.ptr); } else { - db->arch = apk_blob_atomize(APK_BLOB_STR(APK_DEFAULT_ARCH)); + db->arch = apk_atomize(&db->atoms, APK_BLOB_STR(APK_DEFAULT_ARCH)); write_arch = TRUE; } } @@ -1820,6 +1820,7 @@ void apk_db_close(struct apk_database *db) apk_hash_free(&db->available.names); apk_hash_free(&db->installed.files); apk_hash_free(&db->installed.dirs); + apk_atom_free(&db->atoms); if (db->root_proc_dir) { umount2(db->root_proc_dir, MNT_DETACH|UMOUNT_NOFOLLOW); @@ -1867,12 +1868,12 @@ int apk_db_get_tag_id(struct apk_database *db, apk_blob_t tag) db->num_repo_tags++; if (tag.ptr[0] == '@') { - db->repo_tags[i].tag = *apk_blob_atomize_dup(tag); + db->repo_tags[i].tag = *apk_atomize_dup(&db->atoms, tag); } else { char *tmp = alloca(tag.len + 1); tmp[0] = '@'; memcpy(&tmp[1], tag.ptr, tag.len); - db->repo_tags[i].tag = *apk_blob_atomize_dup(APK_BLOB_PTR_LEN(tmp, tag.len+1)); + db->repo_tags[i].tag = *apk_atomize_dup(&db->atoms, APK_BLOB_PTR_LEN(tmp, tag.len+1)); } db->repo_tags[i].plain_name = db->repo_tags[i].tag; @@ -2551,7 +2552,7 @@ static int apk_db_install_archive_entry(void *_ctx, apk_message("%s", ae->name); /* Extract the file with temporary name */ - file->acl = apk_db_acl_atomize(ae->mode, ae->uid, ae->gid, &ae->xattr_csum); + file->acl = apk_db_acl_atomize(db, ae->mode, ae->uid, ae->gid, &ae->xattr_csum); r = apk_archive_entry_extract( db->root_fd, ae, format_tmpname(pkg, file, tmpname_file), @@ -2592,7 +2593,7 @@ static int apk_db_install_archive_entry(void *_ctx, diri = apk_db_install_directory_entry(ctx, name); apk_db_dir_prepare(db, diri->dir, ae->mode); } - apk_db_diri_set(diri, apk_db_acl_atomize(ae->mode, ae->uid, ae->gid, &ae->xattr_csum)); + apk_db_diri_set(diri, apk_db_acl_atomize(db, ae->mode, ae->uid, ae->gid, &ae->xattr_csum)); } ctx->installed_size += ctx->current_file_size; @@ -2628,7 +2629,7 @@ static void apk_db_purge_pkg(struct apk_database *db, if ((diri->dir->protect_mode == APK_PROTECT_NONE) || (apk_flags & APK_PURGE) || (file->csum.type != APK_CHECKSUM_NONE && - apk_fileinfo_get(db->root_fd, name, APK_FI_NOFOLLOW | file->csum.type, &fi) == 0 && + apk_fileinfo_get(db->root_fd, name, APK_FI_NOFOLLOW | file->csum.type, &fi, &db->atoms) == 0 && apk_checksum_compare(&file->csum, &fi.csum) == 0)) unlinkat(db->root_fd, name, 0); if (apk_verbosity >= 3) @@ -2684,7 +2685,7 @@ static void apk_db_migrate_files(struct apk_database *db, cstype = ofile->csum.type; cstype |= APK_FI_NOFOLLOW; - r = apk_fileinfo_get(db->root_fd, name, cstype, &fi); + r = apk_fileinfo_get(db->root_fd, name, cstype, &fi, &db->atoms); if (ofile && ofile->diri->pkg->name == NULL) { /* File was from overlay, delete the * packages version */ @@ -2702,7 +2703,8 @@ static void apk_db_migrate_files(struct apk_database *db, if (ofile == NULL || ofile->csum.type != file->csum.type) apk_fileinfo_get(db->root_fd, name, - APK_FI_NOFOLLOW | file->csum.type, &fi); + APK_FI_NOFOLLOW | file->csum.type, + &fi, &db->atoms); if ((apk_flags & APK_CLEAN_PROTECTED) || (file->csum.type != APK_CHECKSUM_NONE && apk_checksum_compare(&file->csum, &fi.csum) == 0)) { diff --git a/src/hash.c b/src/hash.c index 28301d4..6835ddf 100644 --- a/src/hash.c +++ b/src/hash.c @@ -93,6 +93,7 @@ void apk_hash_delete_hashed(struct apk_hash *h, apk_blob_t key, unsigned long ha if (h->ops->compare_item(item, key) == 0) { hlist_del(pos, &h->buckets->item[hash]); h->ops->delete_item(item); + h->num_items--; break; } } @@ -103,9 +104,9 @@ void apk_hash_delete_hashed(struct apk_hash *h, apk_blob_t key, unsigned long ha if (h->ops->compare(key, itemkey) == 0) { hlist_del(pos, &h->buckets->item[hash]); h->ops->delete_item(item); + h->num_items--; break; } } } } - diff --git a/src/io.c b/src/io.c index 92f1a32..9643218 100644 --- a/src/io.c +++ b/src/io.c @@ -692,7 +692,7 @@ void apk_fileinfo_hash_xattr(struct apk_file_info *fi) } int apk_fileinfo_get(int atfd, const char *filename, unsigned int flags, - struct apk_file_info *fi) + struct apk_file_info *fi, struct apk_atom_pool *atoms) { struct stat64 st; unsigned int checksum = flags & 0xff; @@ -735,7 +735,7 @@ int apk_fileinfo_get(int atfd, const char *filename, unsigned int flags, } *apk_xattr_array_add(&xattrs) = (struct apk_xattr) { .name = &buf[i], - .value = *apk_blob_atomize_dup(APK_BLOB_PTR_LEN(val, vlen)), + .value = *apk_atomize_dup(atoms, APK_BLOB_PTR_LEN(val, vlen)), }; } apk_fileinfo_hash_xattr_array(xattrs, apk_checksum_evp(xattr_checksum), &fi->xattr_csum); @@ -747,11 +747,8 @@ int apk_fileinfo_get(int atfd, const char *filename, unsigned int flags, if (r && r != ENOTSUP) return -r; } - if (checksum == APK_CHECKSUM_NONE) - return 0; - - if (S_ISDIR(st.st_mode)) - return 0; + if (checksum == APK_CHECKSUM_NONE) return 0; + if (S_ISDIR(st.st_mode)) return 0; /* Checksum file content */ if ((flags & APK_FI_NOFOLLOW) && S_ISLNK(st.st_mode)) { diff --git a/src/lua-apk.c b/src/lua-apk.c index fa153e1..f653163 100644 --- a/src/lua-apk.c +++ b/src/lua-apk.c @@ -171,7 +171,6 @@ static int Papk_db_open(lua_State *L) memset(&opts, 0, sizeof(opts)); list_init(&opts.repository_list); - apk_atom_init(); if (lua_istable(L, 1)) get_dbopts(L, 1, &opts); else diff --git a/src/package.c b/src/package.c index 4514ad7..5db77ec 100644 --- a/src/package.c +++ b/src/package.c @@ -259,7 +259,7 @@ void apk_blob_pull_dep(apk_blob_t *b, struct apk_database *db, struct apk_depend *dep = (struct apk_dependency){ .name = name, - .version = apk_blob_atomize_dup(bver), + .version = apk_atomize_dup(&db->atoms, bver), .repository_tag = tag, .result_mask = mask, .conflict = conflict, @@ -295,7 +295,7 @@ void apk_dep_from_pkg(struct apk_dependency *dep, struct apk_database *db, *dep = (struct apk_dependency) { .name = pkg->name, - .version = apk_blob_atomize_dup(b), + .version = apk_atomize_dup(&db->atoms, b), .result_mask = APK_DEPMASK_CHECKSUM, }; } @@ -323,7 +323,7 @@ int apk_dep_is_provided(struct apk_dependency *dep, struct apk_provider *p) case APK_DEPMASK_ANY: return !dep->conflict; default: - if (p->version == &apk_null_blob) + if (p->version == &apk_atom_null) return dep->conflict; if (apk_version_compare_blob_fuzzy(*p->version, *dep->version, dep->fuzzy) & dep->result_mask) @@ -779,7 +779,7 @@ int apk_pkg_add_info(struct apk_database *db, struct apk_package *pkg, pkg->name = apk_db_get_name(db, value); break; case 'V': - pkg->version = apk_blob_atomize_dup(value); + pkg->version = apk_atomize_dup(&db->atoms, value); break; case 'T': pkg->description = apk_blob_cstr(value); @@ -788,10 +788,10 @@ int apk_pkg_add_info(struct apk_database *db, struct apk_package *pkg, pkg->url = apk_blob_cstr(value); break; case 'L': - pkg->license = apk_blob_atomize_dup(value); + pkg->license = apk_atomize_dup(&db->atoms, value); break; case 'A': - pkg->arch = apk_blob_atomize_dup(value); + pkg->arch = apk_atomize_dup(&db->atoms, value); break; case 'D': apk_blob_pull_deps(&value, db, &pkg->depends); @@ -812,10 +812,10 @@ int apk_pkg_add_info(struct apk_database *db, struct apk_package *pkg, apk_blob_pull_deps(&value, db, &pkg->install_if); break; case 'o': - pkg->origin = apk_blob_atomize_dup(value); + pkg->origin = apk_atomize_dup(&db->atoms, value); break; case 'm': - pkg->maintainer = apk_blob_atomize_dup(value); + pkg->maintainer = apk_atomize_dup(&db->atoms, value); break; case 't': pkg->build_time = apk_blob_pull_uint(&value, 10); @@ -921,7 +921,7 @@ int apk_pkg_read(struct apk_database *db, const char *file, struct apk_file_info fi; int r; - r = apk_fileinfo_get(AT_FDCWD, file, APK_CHECKSUM_NONE, &fi); + r = apk_fileinfo_get(AT_FDCWD, file, APK_CHECKSUM_NONE, &fi, &db->atoms); if (r != 0) return r; diff --git a/src/solver.c b/src/solver.c index 0881196..febf52d 100644 --- a/src/solver.c +++ b/src/solver.c @@ -42,7 +42,7 @@ struct apk_solver_state { static struct apk_provider provider_none = { .pkg = NULL, - .version = &apk_null_blob + .version = &apk_atom_null }; void apk_solver_set_name_flags(struct apk_name *name, @@ -321,10 +321,10 @@ static void exclude_non_providers(struct apk_solver_state *ss, struct apk_name * foreach_array_item(p, name->providers) { if (p->pkg->name == must_provide || !p->pkg->ss.pkg_selectable || - (skip_virtuals && p->version == &apk_null_blob)) + (skip_virtuals && p->version == &apk_atom_null)) goto next; foreach_array_item(d, p->pkg->provides) - if (d->name == must_provide || (skip_virtuals && d->version == &apk_null_blob)) + if (d->name == must_provide || (skip_virtuals && d->version == &apk_atom_null)) goto next; disqualify_package(ss, p->pkg, "provides transitivity"); next: ; @@ -425,10 +425,10 @@ static void reconsider_name(struct apk_solver_state *ss, struct apk_name *name) merge_index(&dep->name->ss.merge_depends, num_options); if (merge_index(&pkg->name->ss.merge_provides, num_options)) - pkg->name->ss.has_virtual_provides |= (p->version == &apk_null_blob); + pkg->name->ss.has_virtual_provides |= (p->version == &apk_atom_null); foreach_array_item(dep, pkg->provides) if (merge_index(&dep->name->ss.merge_provides, num_options)) - dep->name->ss.has_virtual_provides |= (dep->version == &apk_null_blob); + dep->name->ss.has_virtual_provides |= (dep->version == &apk_atom_null); num_tag_not_ok += !pkg->ss.tag_ok; num_options++; @@ -630,8 +630,8 @@ static void assign_name(struct apk_solver_state *ss, struct apk_name *name, stru if (name->ss.locked) { /* If both are providing this name without version, it's ok */ - if (p.version == &apk_null_blob && - name->ss.chosen.version == &apk_null_blob) + if (p.version == &apk_atom_null && + name->ss.chosen.version == &apk_atom_null) return; if (ss->ignore_conflict) return; @@ -656,8 +656,8 @@ static void assign_name(struct apk_solver_state *ss, struct apk_name *name, stru foreach_array_item(p0, name->providers) { if (p0->pkg == p.pkg) continue; - if (p.version == &apk_null_blob && - p0->version == &apk_null_blob) + if (p.version == &apk_atom_null && + p0->version == &apk_atom_null) continue; disqualify_package(ss, p0->pkg, "conflicting provides"); } @@ -668,7 +668,7 @@ static void assign_name(struct apk_solver_state *ss, struct apk_name *name, stru static void select_package(struct apk_solver_state *ss, struct apk_name *name) { - struct apk_provider chosen = { NULL, &apk_null_blob }, *p; + struct apk_provider chosen = { NULL, &apk_atom_null }, *p; struct apk_package *pkg = NULL; struct apk_dependency *d; @@ -689,7 +689,7 @@ static void select_package(struct apk_solver_state *ss, struct apk_name *name) continue; /* Virtual packages without provider_priority cannot be autoselected, * unless there is only one provider */ - if (p->version == &apk_null_blob && + if (p->version == &apk_atom_null && p->pkg->name->auto_select_virtual == 0 && p->pkg->name->ss.requirers == 0 && (p->pkg->provider_priority == 0 && name->providers->num > 1)) @@ -934,7 +934,7 @@ static void generate_changeset(struct apk_solver_state *ss, struct apk_dependenc pkg->name->ss.installed_pkg = pkg; pkg->name->ss.installed_name = pkg->name; foreach_array_item(d, pkg->provides) - if (d->version != &apk_null_blob) + if (d->version != &apk_atom_null) d->name->ss.installed_name = pkg->name; } list_for_each_entry(ipkg, &ss->db->installed.packages, installed_pkgs_list)