Commit 36b5cee9 authored by Timo Teräs's avatar Timo Teräs

db, pkg: separate structure for fields of installed packages

this makes the database package entry smaller, and we propbably
get more fields to installed_package later too. this cleans up
the way scripts are stored and is a preparation for supporting
triggers. some parsing for trigger meta-data. ref #45.
parent dee6ffa4
......@@ -38,6 +38,7 @@ struct apk_db_file {
#define APK_DBDIRF_PROTECTED 0x0001
#define APK_DBDIRF_SYMLINKS_ONLY 0x0002
#define APK_DBDIRF_MODIFIED 0x0100
struct apk_db_dir {
apk_hash_node hash_node;
......@@ -111,6 +112,7 @@ struct apk_database {
struct {
struct list_head packages;
struct list_head triggers;
struct apk_hash dirs;
struct apk_hash files;
struct {
......
......@@ -20,12 +20,14 @@ struct apk_database;
struct apk_name;
#define APK_SCRIPT_INVALID -1
#define APK_SCRIPT_PRE_INSTALL 1
#define APK_SCRIPT_POST_INSTALL 2
#define APK_SCRIPT_PRE_DEINSTALL 3
#define APK_SCRIPT_POST_DEINSTALL 4
#define APK_SCRIPT_PRE_UPGRADE 5
#define APK_SCRIPT_POST_UPGRADE 6
#define APK_SCRIPT_PRE_INSTALL 0
#define APK_SCRIPT_POST_INSTALL 1
#define APK_SCRIPT_PRE_DEINSTALL 2
#define APK_SCRIPT_POST_DEINSTALL 3
#define APK_SCRIPT_PRE_UPGRADE 4
#define APK_SCRIPT_POST_UPGRADE 5
#define APK_SCRIPT_TRIGGER 6
#define APK_SCRIPT_MAX 7
#define APK_PKG_NOT_INSTALLED 0
#define APK_PKG_INSTALLED 1
......@@ -58,13 +60,6 @@ struct apk_sign_ctx {
} signature;
};
struct apk_script {
struct hlist_node script_list;
unsigned int type;
unsigned int size;
char script[];
};
#define APK_DEPMASK_REQUIRE (APK_VERSION_EQUAL|APK_VERSION_LESS|\
APK_VERSION_GREATER)
#define APK_DEPMASK_CONFLICT (0)
......@@ -76,9 +71,17 @@ struct apk_dependency {
};
APK_ARRAY(apk_dependency_array, struct apk_dependency);
struct apk_installed_package {
struct apk_package *pkg;
struct list_head installed_pkgs_list;
struct list_head trigger_pkgs_list;
struct hlist_head owned_dirs;
apk_blob_t script[APK_SCRIPT_MAX];
struct apk_string_array *triggers;
};
struct apk_package {
apk_hash_node hash_node;
unsigned repos;
struct apk_name *name;
char *version;
......@@ -87,11 +90,7 @@ struct apk_package {
size_t installed_size, size;
char *filename;
struct apk_checksum csum;
/* for installed packages only */
struct list_head installed_pkgs_list;
struct hlist_head owned_dirs;
struct hlist_head scripts;
struct apk_installed_package *ipkg;
};
APK_ARRAY(apk_package_array, struct apk_package *);
......@@ -134,12 +133,15 @@ int apk_pkg_parse_name(apk_blob_t apkname, apk_blob_t *name, apk_blob_t *version
int apk_pkg_add_info(struct apk_database *db, struct apk_package *pkg,
char field, apk_blob_t value);
int apk_pkg_get_state(struct apk_package *pkg);
void apk_pkg_set_state(struct apk_database *db, struct apk_package *pkg, int state);
int apk_pkg_add_script(struct apk_package *pkg, struct apk_istream *is,
unsigned int type, unsigned int size);
int apk_pkg_run_script(struct apk_package *pkg, int root_fd,
unsigned int type);
struct apk_installed_package *apk_pkg_install(struct apk_database *db, struct apk_package *pkg);
void apk_pkg_uninstall(struct apk_database *db, struct apk_package *pkg);
int apk_ipkg_add_script(struct apk_installed_package *ipkg,
struct apk_istream *is,
unsigned int type, unsigned int size);
int apk_ipkg_run_script(struct apk_installed_package *ipkg, int root_fd,
unsigned int type, char **argv);
struct apk_package *apk_pkg_parse_index_entry(struct apk_database *db, apk_blob_t entry);
int apk_pkg_write_index_entry(struct apk_package *pkg, struct apk_ostream *os);
......
......@@ -106,6 +106,7 @@ static int audit_backup(struct apk_database *db)
static int audit_system(struct apk_database *db)
{
struct apk_installed_package *ipkg;
struct apk_package *pkg;
struct apk_db_dir_instance *diri;
struct apk_db_file *file;
......@@ -113,8 +114,9 @@ static int audit_system(struct apk_database *db)
char name[PATH_MAX];
int done;
list_for_each_entry(pkg, &db->installed.packages, installed_pkgs_list) {
hlist_for_each_entry(diri, dn, &pkg->owned_dirs, pkg_dirs_list) {
list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) {
pkg = ipkg->pkg;
hlist_for_each_entry(diri, dn, &ipkg->owned_dirs, pkg_dirs_list) {
if (diri->dir->flags & APK_DBDIRF_PROTECTED)
continue;
......
This diff is collapsed.
......@@ -53,7 +53,7 @@ static int fix_main(void *pctx, struct apk_database *db, int argc, char **argv)
goto err;
for (j = 0; j < name->pkgs->num; j++) {
if (apk_pkg_get_state(name->pkgs->item[j]) == APK_PKG_INSTALLED)
if (name->pkgs->item[j]->ipkg != NULL)
break;
}
if (j >= name->pkgs->num) {
......
......@@ -73,10 +73,10 @@ static void verbose_print_pkg(struct apk_package *pkg, int minimal_verbosity)
static int info_list(struct info_ctx *ctx, struct apk_database *db,
int argc, char **argv)
{
struct apk_package *pkg;
struct apk_installed_package *ipkg;
list_for_each_entry(pkg, &db->installed.packages, installed_pkgs_list)
verbose_print_pkg(pkg, 1);
list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list)
verbose_print_pkg(ipkg->pkg, 1);
return 0;
}
......@@ -99,7 +99,7 @@ static int info_exists(struct info_ctx *ctx, struct apk_database *db,
for (j = 0; j < name->pkgs->num; j++) {
pkg = name->pkgs->item[j];
if (apk_pkg_get_state(pkg) == APK_PKG_INSTALLED)
if (pkg->ipkg != NULL)
break;
}
if (j >= name->pkgs->num)
......@@ -178,7 +178,7 @@ static int info_package(struct info_ctx *ctx, struct apk_database *db,
}
for (j = 0; j < name->pkgs->num; j++) {
struct apk_package *pkg = name->pkgs->item[j];
if (apk_pkg_get_state(pkg) == APK_PKG_INSTALLED)
if (pkg->ipkg != NULL)
info_subaction(ctx, pkg);
}
}
......@@ -187,14 +187,18 @@ static int info_package(struct info_ctx *ctx, struct apk_database *db,
static void info_print_contents(struct apk_package *pkg)
{
struct apk_installed_package *ipkg = pkg->ipkg;
struct apk_db_dir_instance *diri;
struct apk_db_file *file;
struct hlist_node *dc, *dn, *fc, *fn;
if (ipkg == NULL)
return;
if (apk_verbosity == 1)
printf("%s-%s contains:\n", pkg->name->name, pkg->version);
hlist_for_each_entry_safe(diri, dc, dn, &pkg->owned_dirs,
hlist_for_each_entry_safe(diri, dc, dn, &ipkg->owned_dirs,
pkg_dirs_list) {
hlist_for_each_entry_safe(file, fc, fn, &diri->owned_files,
diri_files_list) {
......@@ -241,8 +245,7 @@ static void info_print_required_by(struct apk_package *pkg)
for (j = 0; j < name0->pkgs->num; j++) {
struct apk_package *pkg0 = name0->pkgs->item[j];
if (apk_pkg_get_state(pkg0) != APK_PKG_INSTALLED ||
pkg0->depends == NULL)
if (pkg0->ipkg == NULL || pkg0->depends == NULL)
continue;
for (k = 0; k < pkg0->depends->num; k++) {
if (pkg0->depends->item[k].name != pkg->name)
......
......@@ -53,13 +53,52 @@ void apk_pkg_format_cache(struct apk_package *pkg, apk_blob_t to)
struct apk_package *apk_pkg_new(void)
{
struct apk_package *pkg;
return calloc(1, sizeof(struct apk_package));
}
pkg = calloc(1, sizeof(struct apk_package));
if (pkg != NULL)
list_init(&pkg->installed_pkgs_list);
struct apk_installed_package *apk_pkg_install(struct apk_database *db,
struct apk_package *pkg)
{
struct apk_installed_package *ipkg;
if (pkg->ipkg != NULL)
return pkg->ipkg;
pkg->ipkg = ipkg = calloc(1, sizeof(struct apk_installed_package));
ipkg->pkg = pkg;
list_init(&ipkg->installed_pkgs_list);
db->installed.stats.packages++;
list_add_tail(&ipkg->installed_pkgs_list, &db->installed.packages);
return ipkg;
}
void apk_pkg_uninstall(struct apk_database *db, struct apk_package *pkg)
{
struct apk_installed_package *ipkg = pkg->ipkg;
int i;
if (ipkg == NULL)
return;
if (db != NULL)
db->installed.stats.packages--;
return pkg;
list_del(&ipkg->installed_pkgs_list);
if (ipkg->triggers) {
list_del(&ipkg->trigger_pkgs_list);
for (i = 0; i < ipkg->triggers->num; i++)
free(ipkg->triggers->item[i]);
free(ipkg->triggers);
}
for (i = 0; i < APK_SCRIPT_MAX; i++)
if (ipkg->script[i].ptr != NULL)
free(ipkg->script[i].ptr);
free(ipkg);
pkg->ipkg = NULL;
}
int apk_pkg_parse_name(apk_blob_t apkname,
......@@ -293,6 +332,7 @@ const char *apk_script_types[] = {
[APK_SCRIPT_POST_DEINSTALL] = "post-deinstall",
[APK_SCRIPT_PRE_UPGRADE] = "pre-upgrade",
[APK_SCRIPT_POST_UPGRADE] = "post-upgrade",
[APK_SCRIPT_TRIGGER] = "trigger",
};
int apk_script_type(const char *name)
......@@ -763,15 +803,10 @@ err:
void apk_pkg_free(struct apk_package *pkg)
{
struct apk_script *script;
struct hlist_node *c, *n;
if (pkg == NULL)
return;
hlist_for_each_entry_safe(script, c, n, &pkg->scripts, script_list)
free(script);
apk_pkg_uninstall(NULL, pkg);
if (pkg->depends)
free(pkg->depends);
if (pkg->version)
......@@ -785,106 +820,84 @@ void apk_pkg_free(struct apk_package *pkg)
free(pkg);
}
int apk_pkg_get_state(struct apk_package *pkg)
{
if (list_hashed(&pkg->installed_pkgs_list))
return APK_PKG_INSTALLED;
return APK_PKG_NOT_INSTALLED;
}
void apk_pkg_set_state(struct apk_database *db, struct apk_package *pkg, int state)
{
switch (state) {
case APK_PKG_INSTALLED:
if (!list_hashed(&pkg->installed_pkgs_list)) {
db->installed.stats.packages++;
list_add_tail(&pkg->installed_pkgs_list,
&db->installed.packages);
}
break;
case APK_PKG_NOT_INSTALLED:
if (list_hashed(&pkg->installed_pkgs_list)) {
db->installed.stats.packages--;
list_del(&pkg->installed_pkgs_list);
}
break;
}
}
int apk_pkg_add_script(struct apk_package *pkg, struct apk_istream *is,
unsigned int type, unsigned int size)
int apk_ipkg_add_script(struct apk_installed_package *ipkg,
struct apk_istream *is,
unsigned int type, unsigned int size)
{
struct apk_script *script;
void *ptr;
int r;
script = malloc(sizeof(struct apk_script) + size);
script->type = type;
script->size = size;
r = is->read(is, script->script, size);
if (type >= APK_SCRIPT_MAX)
return -1;
ptr = malloc(size);
r = is->read(is, ptr, size);
if (r < 0) {
free(script);
free(ptr);
return r;
}
hlist_add_head(&script->script_list, &pkg->scripts);
return r;
if (ipkg->script[type].ptr)
free(ipkg->script[type].ptr);
ipkg->script[type].ptr = ptr;
ipkg->script[type].len = size;
return 0;
}
int apk_pkg_run_script(struct apk_package *pkg, int root_fd,
unsigned int type)
int apk_ipkg_run_script(struct apk_installed_package *ipkg, int root_fd,
unsigned int type, char **argv)
{
static const char * const environment[] = {
static char * const environment[] = {
"PATH=/usr/sbin:/usr/bin:/sbin:/bin",
NULL
};
struct apk_script *script;
struct hlist_node *c;
struct apk_package *pkg = ipkg->pkg;
char fn[PATH_MAX];
int fd, status;
pid_t pid;
char fn[PATH_MAX];
hlist_for_each_entry(script, c, &pkg->scripts, script_list) {
if (script->type != type)
continue;
if (type >= APK_SCRIPT_MAX)
return -1;
/* Avoid /tmp as it can be mounted noexec */
snprintf(fn, sizeof(fn), "var/cache/misc/%s-%s.%s",
pkg->name->name, pkg->version,
apk_script_types[type]);
if (ipkg->script[type].ptr == NULL)
return 0;
argv[0] = (char *) apk_script_types[type];
/* Avoid /tmp as it can be mounted noexec */
snprintf(fn, sizeof(fn), "var/cache/misc/%s-%s.%s",
pkg->name->name, pkg->version,
apk_script_types[type]);
fd = openat(root_fd, fn, O_CREAT|O_RDWR|O_TRUNC, 0755);
if (fd < 0) {
mkdirat(root_fd, "var/cache/misc", 0755);
fd = openat(root_fd, fn, O_CREAT|O_RDWR|O_TRUNC, 0755);
if (fd < 0) {
mkdirat(root_fd, "var/cache/misc", 0755);
fd = openat(root_fd, fn, O_CREAT|O_RDWR|O_TRUNC, 0755);
if (fd < 0)
return -errno;
}
write(fd, script->script, script->size);
close(fd);
if (fd < 0)
return -errno;
}
write(fd, ipkg->script[type].ptr, ipkg->script[type].len);
close(fd);
apk_message("Executing %s", &fn[15]);
apk_message("Executing %s", &fn[15]);
pid = fork();
if (pid == -1)
return -1;
if (pid == 0) {
fchdir(root_fd);
if (chroot(".") < 0) {
apk_error("chroot: %s", strerror(errno));
} else {
execle(fn, apk_script_types[type],
pkg->version, "", NULL, environment);
}
exit(1);
}
waitpid(pid, &status, 0);
unlinkat(root_fd, fn, 0);
if (WIFEXITED(status))
return WEXITSTATUS(status);
pid = fork();
if (pid == -1)
return -1;
if (pid == 0) {
fchdir(root_fd);
if (chroot(".") < 0) {
apk_error("chroot: %s", strerror(errno));
} else {
execve(fn, argv, environment);
}
exit(1);
}
return 0;
waitpid(pid, &status, 0);
unlinkat(root_fd, fn, 0);
if (WIFEXITED(status))
return WEXITSTATUS(status);
return -1;
}
static int parse_index_line(void *ctx, apk_blob_t line)
......
......@@ -296,7 +296,7 @@ int apk_state_lock_dependency(struct apk_state *state,
for (i = 0; i < c->num; i++) {
struct apk_package *pkg = c->pkgs[i];
if (apk_pkg_get_state(c->pkgs[i]) == APK_PKG_INSTALLED)
if (c->pkgs[i]->ipkg != NULL)
installed = pkg;
else if (pkg->filename == NULL &&
apk_db_select_repo(state->db, pkg) == NULL)
......@@ -422,8 +422,7 @@ static int for_each_broken_reverse_depency(struct apk_state *state,
ns_to_choices(state->name[name0->id]);
for (j = 0; j < ns->num; j++) {
if (apk_pkg_get_state(ns->pkgs[j])
!= APK_PKG_INSTALLED)
if (ns->pkgs[j]->ipkg == NULL)
continue;
r = call_if_dependency_broke(state,
ns->pkgs[j],
......@@ -436,7 +435,7 @@ static int for_each_broken_reverse_depency(struct apk_state *state,
for (j = 0; j < name0->pkgs->num; j++) {
pkg0 = name0->pkgs->item[j];
if (apk_pkg_get_state(pkg0) != APK_PKG_INSTALLED)
if (pkg0->ipkg == NULL)
continue;
r = call_if_dependency_broke(state,
......@@ -487,8 +486,7 @@ int apk_state_lock_name(struct apk_state *state,
struct apk_package *pkg = name->pkgs->item[i];
if (name->pkgs->item[i]->name == name &&
apk_pkg_get_state(name->pkgs->item[i])
== APK_PKG_INSTALLED)
name->pkgs->item[i]->ipkg != NULL)
oldpkg = pkg;
}
}
......
......@@ -93,7 +93,7 @@ static void ver_print_package_status(struct apk_package *pkg, const char *limit)
static int ver_main(void *ctx, struct apk_database *db, int argc, char **argv)
{
struct ver_ctx *ictx = (struct ver_ctx *) ctx;
struct apk_package *pkg;
struct apk_installed_package *ipkg;
struct apk_name *name;
int i, j, ret = 0;
......@@ -105,9 +105,9 @@ static int ver_main(void *ctx, struct apk_database *db, int argc, char **argv)
printf("%-42sAvailable:\n", "Installed:");
if (argc == 0) {
list_for_each_entry(pkg, &db->installed.packages,
list_for_each_entry(ipkg, &db->installed.packages,
installed_pkgs_list) {
ver_print_package_status(pkg, ictx->limchars);
ver_print_package_status(ipkg->pkg, ictx->limchars);
}
goto ver_exit;
}
......@@ -121,7 +121,7 @@ static int ver_main(void *ctx, struct apk_database *db, int argc, char **argv)
}
for (j = 0; j < name->pkgs->num; j++) {
struct apk_package *pkg = name->pkgs->item[j];
if (apk_pkg_get_state(pkg) == APK_PKG_INSTALLED)
if (pkg->ipkg != NULL)
ver_print_package_status(pkg, ictx->limchars);
}
}
......
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