diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/libalpm/hook.c | 156 | ||||
| -rw-r--r-- | lib/libalpm/hook.h | 32 | 
2 files changed, 188 insertions, 0 deletions
| diff --git a/lib/libalpm/hook.c b/lib/libalpm/hook.c new file mode 100644 index 00000000..c4f232b9 --- /dev/null +++ b/lib/libalpm/hook.c @@ -0,0 +1,156 @@ +/* + *  hook.c + * + *  Copyright (c) 2015 Pacman Development Team <pacman-dev@archlinux.org> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#include <errno.h> + +#include "handle.h" +#include "hook.h" +#include "log.h" +#include "util.h" + +enum _alpm_hook_op_t { +	ALPM_HOOK_OP_INSTALL = (1 << 0), +	ALPM_HOOK_OP_UPGRADE = (1 << 1), +	ALPM_HOOK_OP_REMOVE = (1 << 2), +}; + +enum _alpm_trigger_type_t { +	ALPM_HOOK_TYPE_PACKAGE = 1, +	ALPM_HOOK_TYPE_FILE, +}; + +struct _alpm_trigger_t { +	enum _alpm_hook_op_t op; +	enum _alpm_trigger_type_t type; +	alpm_list_t *targets; +}; + +struct _alpm_hook_t { +	char *name; +	alpm_list_t *triggers; +	alpm_list_t *depends; +	char *cmd; +	enum _alpm_hook_when_t when; +	int abort_on_fail; +}; + +struct _alpm_hook_cb_ctx { +	alpm_handle_t *handle; +	struct _alpm_hook_t *hook; +}; + +static void _alpm_trigger_free(struct _alpm_trigger_t *trigger) +{ +	if(trigger) { +		FREELIST(trigger->targets); +		free(trigger); +	} +} + +static void _alpm_hook_free(struct _alpm_hook_t *hook) +{ +	if(hook) { +		free(hook->name); +		free(hook->cmd); +		alpm_list_free_inner(hook->triggers, (alpm_list_fn_free) _alpm_trigger_free); +		alpm_list_free(hook->triggers); +		FREELIST(hook->depends); +		free(hook); +	} +} + +static int _alpm_hook_parse_cb(const char *file, int line, +		const char *section, char *key, char *value, void *data) +{ +	struct _alpm_hook_cb_ctx *ctx = data; +	alpm_handle_t *handle = ctx->handle; +	struct _alpm_hook_t *hook = ctx->hook; + +#define error(...) _alpm_log(handle, ALPM_LOG_ERROR, __VA_ARGS__); return 1; + +	if(!section && !key) { +		error(_("error while reading hook %s: %s\n"), file, strerror(errno)); +	} else if(!section) { +		error(_("hook %s line %d: invalid option %s\n"), file, line, key); +	} else if(!key) { +		/* beginning a new section */ +		if(strcmp(section, "Trigger") == 0) { +			struct _alpm_trigger_t *t; +			CALLOC(t, sizeof(struct _alpm_trigger_t), 1, return 1); +			hook->triggers = alpm_list_add(hook->triggers, t); +		} else if(strcmp(section, "Action") == 0) { +			/* no special processing required */ +		} else { +			error(_("hook %s line %d: invalid section %s\n"), file, line, section); +		} +	} else if(strcmp(section, "Trigger") == 0) { +		struct _alpm_trigger_t *t = hook->triggers->prev->data; +		if(strcmp(key, "Operation") == 0) { +			if(strcmp(value, "Install") == 0) { +				t->op |= ALPM_HOOK_OP_INSTALL; +			} else if(strcmp(value, "Upgrade") == 0) { +				t->op |= ALPM_HOOK_OP_UPGRADE; +			} else if(strcmp(value, "Remove") == 0) { +				t->op |= ALPM_HOOK_OP_REMOVE; +			} else { +				error(_("hook %s line %d: invalid value %s\n"), file, line, value); +			} +		} else if(strcmp(key, "Type") == 0) { +			if(strcmp(value, "Package") == 0) { +				t->type = ALPM_HOOK_TYPE_PACKAGE; +			} else if(strcmp(value, "File") == 0) { +				t->type = ALPM_HOOK_TYPE_FILE; +			} else { +				error(_("hook %s line %d: invalid value %s\n"), file, line, value); +			} +		} else if(strcmp(key, "Target") == 0) { +			char *val; +			STRDUP(val, value, return 1); +			t->targets = alpm_list_add(t->targets, val); +		} else { +			error(_("hook %s line %d: invalid option %s\n"), file, line, key); +		} +	} else if(strcmp(section, "Action") == 0) { +		if(strcmp(key, "When") == 0) { +			if(strcmp(value, "PreTransaction") == 0) { +				hook->when = ALPM_HOOK_PRE_TRANSACTION; +			} else if(strcmp(value, "PostTransaction") == 0) { +				hook->when = ALPM_HOOK_POST_TRANSACTION; +			} else { +				error(_("hook %s line %d: invalid value %s\n"), file, line, value); +			} +		} else if(strcmp(key, "Depends") == 0) { +			char *val; +			STRDUP(val, value, return 1); +			hook->depends = alpm_list_add(hook->depends, val); +		} else if(strcmp(key, "AbortOnFail") == 0) { +			hook->abort_on_fail = 1; +		} else if(strcmp(key, "Exec") == 0) { +			STRDUP(hook->cmd, value, return 1); +		} else { +			error(_("hook %s line %d: invalid option %s\n"), file, line, value); +		} +	} + +#undef error + +	return 0; +} + +/* vim: set noet: */ diff --git a/lib/libalpm/hook.h b/lib/libalpm/hook.h new file mode 100644 index 00000000..06921769 --- /dev/null +++ b/lib/libalpm/hook.h @@ -0,0 +1,32 @@ +/* + *  hook.h + * + *  Copyright (c) 2015 Pacman Development Team <pacman-dev@archlinux.org> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _ALPM_HOOK_H +#define _ALPM_HOOK_H + +#include "alpm.h" + +enum _alpm_hook_when_t { +	ALPM_HOOK_PRE_TRANSACTION = 1, +	ALPM_HOOK_POST_TRANSACTION +}; + +#endif /* _ALPM_HOOK_H */ + +/* vim: set noet: */ | 
