From 1f21fbe26dfbc982492c8b7b90f3758a910f113d Mon Sep 17 00:00:00 2001 From: William Johansson Date: Fri, 24 Apr 2015 20:22:51 +0200 Subject: Initial FreeBSD support with pkgng plugin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a basic pkgng plugin as a preparation to integrate etckeeper on FreeBSD. Currently not enabled to build automatically. To use on FreeBSD, install etckeeper manually and install the plugin with: $ cd pkgng $ make $ make install and add this line to /usr/local/etc/pkg.conf: PLUGINS [ etckeeper ] --- list-installed.d/50list-installed | 2 + pkgng/Makefile | 17 +++++ pkgng/etckeeper.c | 132 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+) create mode 100644 pkgng/Makefile create mode 100644 pkgng/etckeeper.c diff --git a/list-installed.d/50list-installed b/list-installed.d/50list-installed index 2ac569a..4a8ce70 100755 --- a/list-installed.d/50list-installed +++ b/list-installed.d/50list-installed @@ -17,5 +17,7 @@ else rpm -qa --qf "%|epoch?{%{epoch}}:{0}|:%{name}-%{version}-%{release}.%{arch}\n" | sort elif [ "$LOWLEVEL_PACKAGE_MANAGER" = pacman ]; then pacman -Q + elif [ "$LOWLEVEL_PACKAGE_MANAGER" = pkgng ]; then + pkg info -E "*" fi fi diff --git a/pkgng/Makefile b/pkgng/Makefile new file mode 100644 index 0000000..92d3c1d --- /dev/null +++ b/pkgng/Makefile @@ -0,0 +1,17 @@ +.include + +PREFIX?= /usr/local +LIBDIR= ${PREFIX}/lib/pkg/ +SHLIB_DIR?= ${LIBDIR}/ +SHLIB_NAME?= ${PLUGIN_NAME}.so + +PLUGIN_NAME= etckeeper +SRCS= etckeeper.c + +PKGFLAGS!= pkgconf --cflags pkg +CFLAGS+= ${PKGFLAGS} + +beforeinstall: + ${INSTALL} -d ${LIBDIR} + +.include diff --git a/pkgng/etckeeper.c b/pkgng/etckeeper.c new file mode 100644 index 0000000..6c54388 --- /dev/null +++ b/pkgng/etckeeper.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2015 William Johansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Based upon the pkg plugin zfssnap: + * Copyright (c) 2012 Marin Atanasov Nikolov + */ + +#include +#include +#include +#include +#include + +#include +#define PLUGIN_NAME "etckeeper" +/* TODO: make configuration param? */ +#define ETCKEEPER_PATH "/usr/local/bin/etckeeper" + +extern char **environ; + +struct pkg_plugin *self; + +static int pre_install_hook(void *data, struct pkgdb *db); +static int post_install_hook(void *data, struct pkgdb *db); + +int +pkg_plugin_init(struct pkg_plugin *p) +{ + self = p; + + pkg_plugin_set(p, PKG_PLUGIN_NAME, PLUGIN_NAME); + pkg_plugin_set(p, PKG_PLUGIN_DESC, "etckeeper plugin"); + pkg_plugin_set(p, PKG_PLUGIN_VERSION, "1.0.0"); + + /* NOTE: upgrade/deinstall is regarded as install */ + + if (pkg_plugin_hook_register(p, PKG_PLUGIN_HOOK_PRE_INSTALL, &pre_install_hook) != EPKG_OK) { + pkg_plugin_error(self, "failed to hook into the library"); + return (EPKG_FATAL); + } + + if (pkg_plugin_hook_register(p, PKG_PLUGIN_HOOK_POST_INSTALL, &post_install_hook) != EPKG_OK) { + pkg_plugin_error(self, "failed to hook into the library"); + return (EPKG_FATAL); + } + + if (pkg_plugin_hook_register(p, PKG_PLUGIN_HOOK_PRE_DEINSTALL, &pre_install_hook) != EPKG_OK) { + pkg_plugin_error(self, "failed to hook into the library"); + return (EPKG_FATAL); + } + + if (pkg_plugin_hook_register(p, PKG_PLUGIN_HOOK_POST_DEINSTALL, &post_install_hook) != EPKG_OK) { + pkg_plugin_error(self, "failed to hook into the library"); + return (EPKG_FATAL); + } + + if (pkg_plugin_hook_register(p, PKG_PLUGIN_HOOK_PRE_UPGRADE, &pre_install_hook) != EPKG_OK) { + pkg_plugin_error(self, "failed to hook into the library"); + return (EPKG_FATAL); + } + + if (pkg_plugin_hook_register(p, PKG_PLUGIN_HOOK_POST_UPGRADE, &post_install_hook) != EPKG_OK) { + pkg_plugin_error(self, "failed to hook into the library"); + return (EPKG_FATAL); + } + + return (EPKG_OK); +} + +static int +call_etckeeper(char *arg) +{ + int error, pstat; + pid_t pid; + char *argv[] = { + "etckeeper", + arg, + NULL, + }; + + if ((error = posix_spawn(&pid, ETCKEEPER_PATH, NULL, NULL, + __DECONST(char **, argv), environ)) != 0) { + errno = error; + pkg_plugin_errno(self, "Failed to spawn process", arg); + return (EPKG_FATAL); + } + while (waitpid(pid, &pstat, 0) == -1) { + if (errno != EINTR) + return (EPKG_FATAL); + } + + if ((error = WEXITSTATUS(pstat)) != 0) { + pkg_plugin_error(self, "etckeeper failed with exit code %d", error); + return (EPKG_FATAL); + } + + return (EPKG_OK); +} + +static int +pre_install_hook(void *data, struct pkgdb *db) +{ + return call_etckeeper("pre-install"); +} + +static int +post_install_hook(void *data, struct pkgdb *db) +{ + return call_etckeeper("post-install"); +} -- cgit v1.2.3