add support for pre and post commit hooks
This allows for instance integration of etckeeper [TT: Reorganized code a bit, and modified to use single directory commit_hooks.d with argument for script of stage.]cute-signatures
parent
28a9dcda56
commit
349c61c961
|
@ -219,6 +219,7 @@ int apk_db_write_config(struct apk_database *db);
|
|||
int apk_db_permanent(struct apk_database *db);
|
||||
int apk_db_check_world(struct apk_database *db, struct apk_dependency_array *world);
|
||||
int apk_db_fire_triggers(struct apk_database *db);
|
||||
int apk_db_run_script(struct apk_database *db, char *fn, char **argv);
|
||||
void apk_db_update_directory_permissions(struct apk_database *db);
|
||||
|
||||
struct apk_package *apk_db_pkg_add(struct apk_database *db, struct apk_package *pkg);
|
||||
|
|
|
@ -179,11 +179,8 @@ static int audit_directory_tree_item(void *ctx, int dirfd, const char *name)
|
|||
struct apk_file_info fi;
|
||||
int reason = 0;
|
||||
|
||||
if (bdir.len + bent.len + 1 >= sizeof(atctx->path))
|
||||
return -ENOMEM;
|
||||
|
||||
if (apk_fileinfo_get(dirfd, name, APK_FI_NOFOLLOW, &fi) < 0)
|
||||
return -EPERM;
|
||||
if (bdir.len + bent.len + 1 >= sizeof(atctx->path)) return 0;
|
||||
if (apk_fileinfo_get(dirfd, name, APK_FI_NOFOLLOW, &fi) < 0) return 0;
|
||||
|
||||
memcpy(&atctx->path[atctx->pathlen], bent.ptr, bent.len);
|
||||
atctx->pathlen += bent.len;
|
||||
|
@ -273,7 +270,7 @@ done:
|
|||
apk_db_dir_unref(db, child, FALSE);
|
||||
|
||||
atctx->pathlen -= bent.len;
|
||||
return reason < 0 ? reason : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int audit_directory_tree(struct audit_tree_ctx *atctx, int dirfd)
|
||||
|
|
39
src/commit.c
39
src/commit.c
|
@ -216,6 +216,40 @@ static void run_triggers(struct apk_database *db, struct apk_changeset *changese
|
|||
}
|
||||
}
|
||||
|
||||
#define PRE_COMMIT_HOOK 0
|
||||
#define POST_COMMIT_HOOK 1
|
||||
|
||||
struct apk_commit_hook {
|
||||
struct apk_database *db;
|
||||
int type;
|
||||
};
|
||||
|
||||
static int run_commit_hook(void *ctx, int dirfd, const char *file)
|
||||
{
|
||||
static char *const commit_hook_str[] = { "pre-commit", "post-commit" };
|
||||
struct apk_commit_hook *hook = (struct apk_commit_hook *) ctx;
|
||||
struct apk_database *db = hook->db;
|
||||
char fn[PATH_MAX], *argv[] = { fn, (char *) commit_hook_str[hook->type], NULL };
|
||||
|
||||
if ((apk_flags & (APK_NO_SCRIPTS | APK_SIMULATE)) != 0)
|
||||
return 0;
|
||||
|
||||
snprintf(fn, sizeof(fn), "etc/apk/commit_hooks.d" "/%s", file);
|
||||
if (apk_verbosity >= 2) apk_message("Executing: %s", fn);
|
||||
|
||||
if (apk_db_run_script(db, fn, argv) < 0 && hook->type == PRE_COMMIT_HOOK)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int run_commit_hooks(struct apk_database *db, int type)
|
||||
{
|
||||
struct apk_commit_hook hook = { .db = db, .type = type };
|
||||
return apk_dir_foreach_file(openat(db->root_fd, "etc/apk/commit_hooks.d", O_RDONLY | O_CLOEXEC),
|
||||
run_commit_hook, &hook);
|
||||
}
|
||||
|
||||
int apk_solver_commit_changeset(struct apk_database *db,
|
||||
struct apk_changeset *changeset,
|
||||
struct apk_dependency_array *world)
|
||||
|
@ -278,6 +312,9 @@ int apk_solver_commit_changeset(struct apk_database *db,
|
|||
}
|
||||
}
|
||||
|
||||
if (run_commit_hooks(db, PRE_COMMIT_HOOK) < 0)
|
||||
return -1;
|
||||
|
||||
/* Go through changes */
|
||||
foreach_array_item(change, changeset->changes) {
|
||||
r = change->old_pkg &&
|
||||
|
@ -308,6 +345,7 @@ int apk_solver_commit_changeset(struct apk_database *db,
|
|||
all_done:
|
||||
apk_dependency_array_copy(&db->world, world);
|
||||
apk_db_write_config(db);
|
||||
run_commit_hooks(db, POST_COMMIT_HOOK);
|
||||
|
||||
if (!db->performing_self_upgrade) {
|
||||
if (errors)
|
||||
|
@ -328,7 +366,6 @@ all_done:
|
|||
db->installed.stats.packages);
|
||||
}
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <mntent.h>
|
||||
#include <libgen.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <malloc.h>
|
||||
|
@ -1877,6 +1878,34 @@ int apk_db_fire_triggers(struct apk_database *db)
|
|||
return db->pending_triggers;
|
||||
}
|
||||
|
||||
int apk_db_run_script(struct apk_database *db, char *fn, char **argv)
|
||||
{
|
||||
int status;
|
||||
pid_t pid;
|
||||
static char * const environment[] = {
|
||||
"PATH=/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
NULL
|
||||
};
|
||||
|
||||
pid = fork();
|
||||
if (pid == -1) {
|
||||
apk_error("%s: fork: %s", basename(fn), strerror(errno));
|
||||
return -2;
|
||||
}
|
||||
if (pid == 0) {
|
||||
umask(0022);
|
||||
if (fchdir(db->root_fd) == 0 && chroot(".") == 0)
|
||||
execve(fn, argv, environment);
|
||||
exit(127); /* should not get here */
|
||||
}
|
||||
waitpid(pid, &status, 0);
|
||||
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
|
||||
apk_error("%s: script exited with error %d", basename(fn), WEXITSTATUS(status));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int update_permissions(apk_hash_item item, void *ctx)
|
||||
{
|
||||
struct apk_database *db = (struct apk_database *) ctx;
|
||||
|
|
7
src/io.c
7
src/io.c
|
@ -741,6 +741,7 @@ int apk_dir_foreach_file(int dirfd, apk_dir_file_cb cb, void *ctx)
|
|||
{
|
||||
struct dirent *de;
|
||||
DIR *dir;
|
||||
int ret = 0;
|
||||
|
||||
if (dirfd < 0)
|
||||
return -1;
|
||||
|
@ -759,11 +760,11 @@ int apk_dir_foreach_file(int dirfd, apk_dir_file_cb cb, void *ctx)
|
|||
(de->d_name[1] == '.' && de->d_name[2] == 0))
|
||||
continue;
|
||||
}
|
||||
cb(ctx, dirfd, de->d_name);
|
||||
ret = cb(ctx, dirfd, de->d_name);
|
||||
if (ret) break;
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct apk_istream *apk_istream_from_file_gz(int atfd, const char *file)
|
||||
|
|
|
@ -979,14 +979,9 @@ void apk_ipkg_run_script(struct apk_installed_package *ipkg,
|
|||
struct apk_database *db,
|
||||
unsigned int type, char **argv)
|
||||
{
|
||||
static char * const environment[] = {
|
||||
"PATH=/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
NULL
|
||||
};
|
||||
struct apk_package *pkg = ipkg->pkg;
|
||||
char fn[PATH_MAX];
|
||||
int fd, status, root_fd = db->root_fd;
|
||||
pid_t pid;
|
||||
int fd, root_fd = db->root_fd;
|
||||
|
||||
if (type >= APK_SCRIPT_MAX || ipkg->script[type].ptr == NULL)
|
||||
return;
|
||||
|
@ -1015,23 +1010,8 @@ void apk_ipkg_run_script(struct apk_installed_package *ipkg,
|
|||
}
|
||||
close(fd);
|
||||
|
||||
pid = fork();
|
||||
if (pid == -1)
|
||||
goto error;
|
||||
if (pid == 0) {
|
||||
umask(0022);
|
||||
if (fchdir(root_fd) == 0 && chroot(".") == 0)
|
||||
execve(fn, argv, environment);
|
||||
exit(1);
|
||||
}
|
||||
waitpid(pid, &status, 0);
|
||||
unlinkat(root_fd, fn, 0);
|
||||
apk_id_cache_reset(&db->id_cache);
|
||||
|
||||
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
|
||||
apk_error("%s: script exited with error %d", &fn[15], WEXITSTATUS(status));
|
||||
if (apk_db_run_script(db, fn, argv) < 0)
|
||||
ipkg->broken_script = 1;
|
||||
}
|
||||
return;
|
||||
error:
|
||||
apk_error("%s: failed to execute: %s", &fn[15], apk_error_str(errno));
|
||||
|
|
Loading…
Reference in New Issue