Skip to content
Open

Hooks #666

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions data/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ all:
install:
install -d $(DESTDIR)$(MANDIR)/man5
install -m644 xbps.d.5 $(DESTDIR)$(MANDIR)/man5
install -m644 xbps.hook.5 $(DESTDIR)$(MANDIR)/man5
install -d $(DESTDIR)$(MANDIR)/man7
install -m644 xbps.7 $(DESTDIR)$(MANDIR)/man7
install -d $(DESTDIR)$(PKGCONFIGDIR)
Expand Down
187 changes: 187 additions & 0 deletions data/xbps.hook.5
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
.Dd December 22, 2025
.Dt XBPS.HOOK 5
.Os
.Sh NAME
.Nm xbps.hook
.Nd XBPS hook configuration
.Sh SYNOPSIS
.Bl -item -compact
.It
/etc/xbps.d/hooks/*.hook
.It
/usr/share/xbps.d/hooks/*.hook
.El
.Sh DESCRIPTION
The
.Nm
files are
.So .ini Sc Ns -style
configuration files to define hooks that execute commands at certain points of
the xbps transactions
.Po
package updates,
installs,
and removals.
.Pc
.Pp
Comments can be put anywhere in the file
and using hashmarks
.Pq Sq # ,
or
semi-colons
.Pq Sq \&; ,
and are continued to the end of the line.
.Sh [HOOK] SECTION OPTIONS
The
.Ic Hook
section is required and defines when the hook is executed and the command that
is being executed as part of the hook.
.Bl -tag -width -x
.It Sy Name = Ar name
Set the hook name used for logging.
.It Ic When = Ar option ...
Defines when the hook is executed.
The following values are supported
and multiple values can be set by
separating them with a space or defining
the
.Sy When
option multiple times.
Valid options are:
.Bl -tag -width -x
.It Ic PreTransaction
Before all packages are installed,
updated,
or removed.
.It Ic PostTransaction
After all packages are installed,
updated,
or removed.
.El
.It Sy Exec = Ar command Op Ar args ...
Command that is executed.
The
.Ar command
and
.Ar args
are split into words according to
.Sx WORD SPLITTING .
.El
.Sh [MATCH] SECTION OPTIONS
A hook is executed if it's
.Ic Match
section matches the current transaction.
.Bl -tag -width -x
.It Ic Package = Ar pkgname | Ar pkgpattern
Matches if
.Ar pkgname
or packages matching
.Ar pkgpattern
are installed,
updated,
removed,
reinstalled,
or configured in the transaction.
.It Ic PackageInstall = Ar pkgname | Ar pkgpattern
Matches if
.Ar pkgname
or packages matching
.Ar pkgpattern
are installed in the transaction.
.It Ic PackageUpdate = Ar pkgname | Ar pkgpattern
Matches if
.Ar pkgname
or packages matching
.Ar pkgpattern
are updated in the transaction.
.It Ic PackageRemove = Ar pkgname | Ar pkgpattern
Matches if
.Ar pkgname
or packages matching
.Ar pkgpattern
are removed in the transaction.
.It Ic PackageReinstall = Ar pkgname | Ar pkgpattern
Matches if
.Ar pkgname
or packages matching
.Ar pkgpattern
are reinstalled in the transaction.
.It Ic PackageConfigure = Ar pkgname | Ar pkgpattern
Matches if
.Ar pkgname
or packages matching
.Ar pkgpattern
are configured in the transaction.
.It Ic Path = Ar path | Ar pattern
Matches if
.Ar path
or paths matching
.Ar pattern
are created,
modified,
or deleted.
.It Ic PathCreated = Ar path | Ar pattern
Matches if
.Ar path
or paths matching
.Ar pattern
are created in the transaction.
.It Ic PathModified = Ar path | Ar pattern
Matches if
.Ar path
or paths matching
.Ar pattern
are modified in the transaction.
.It Ic PathDeleted = Ar path | Ar pattern
Matches if
.Ar path
or paths matching
.Ar pattern
are deleted in the transaction.
.El
.Sh WORD SPLITTING
Options which support multiple free text values will be split into separate
words.
The word boundaries are spaces
.Pq Sq \~
and tabs
.Pq Sq \et .
.Pp
If a word contains a literal space
.Pq Sq \~
or tab
.Pq Sq \et ,
use a backslash
.Pq Sq \e
to escape the character.
.Sh EXAMPLES
The following example restarts the
.Ic sshd
service after the
.Ic ssh
package was updated.
.Bd -literal -offset indent
[Hook]
Name = Restart sshd.
When = PostTransaction
Exec = sv restart /var/service/sshd

[Match]
PackageUpdate = ssh
.Ed
.Pp
This example hook will sign the
.Pa systemd-bootx64.efi
file whenever it is updated or installed.
.Bd -literal -offset indent
[Hook]
Name = Sign the bootloader file.
When = PostTransaction
Exec = sbsign --key /etc/kernel/secure-boot.key.pem \e
--cert /etc/kernel/secure-boot.cert.pem \e
--output /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed \e
/usr/lib/systemd/boot/efi/systemd-bootx64.efi

[Match]
PathModified = /usr/lib/systemd/boot/efi/systemd-bootx64.efi
.Ed
10 changes: 9 additions & 1 deletion include/xbps_api_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@ char HIDDEN *xbps_get_remote_repo_string(const char *);
int HIDDEN xbps_repo_sync(struct xbps_handle *, const char *);
int HIDDEN xbps_file_hash_check_dictionary(struct xbps_handle *,
xbps_dictionary_t, const char *, const char *);
int HIDDEN xbps_file_exec(struct xbps_handle *, const char *, ...);
int HIDDEN xbps_file_exec(const struct xbps_handle *, const char *, ...);
int HIDDEN xbps_file_exec_argv(const struct xbps_handle *xhp, const char **argv);
int HIDDEN xbps_file_execp_argv(const struct xbps_handle *xhp, const char **argv);
void HIDDEN xbps_set_cb_fetch(struct xbps_handle *, off_t, off_t, off_t,
const char *, bool, bool, bool);
int HIDDEN xbps_set_cb_state(struct xbps_handle *, xbps_state_t, int,
Expand All @@ -128,4 +130,10 @@ struct xbps_repo HIDDEN *xbps_regget_repo(struct xbps_handle *,
const char *);
int HIDDEN xbps_conf_init(struct xbps_handle *);

struct xbps_hooks;
struct xbps_hooks *xbps_hooks_init(struct xbps_handle *xhp);
int xbps_hooks_pre_transaction(struct xbps_handle *xhp, struct xbps_hooks *hooks);
int xbps_hooks_post_transaction(struct xbps_handle *xhp, struct xbps_hooks *hooks);
void xbps_hooks_free(struct xbps_hooks *hooks);

#endif /* !_XBPS_API_IMPL_H_ */
18 changes: 15 additions & 3 deletions lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ endif
LIBFETCH_INCS = fetch/common.h
LIBFETCH_GEN = fetch/ftperr.h fetch/httperr.h

INIH_OBJS = external/inih/ini.o
INIH_CPPFLAGS = -DINI_HANDLER_LINENO=1 -DINI_CALL_HANDLER_ON_NEW_SECTION=1
INIH_CFLAGS= -Wno-error=cast-qual
ifdef HAVE_VISIBILITY
INIH_CFLAGS+= -fvisibility=hidden
endif

# External code used by libxbps
EXTOBJS = external/dewey.o external/fexec.o external/mkpath.o

Expand All @@ -51,7 +58,7 @@ OBJS += plist_remove.o plist_fetch.o util.o util_path.o util_hash.o
OBJS += repo.o repo_sync.o
OBJS += rpool.o cb_util.o proplib_wrapper.o
OBJS += package_alternatives.o
OBJS += conf.o log.o
OBJS += conf.o log.o hooks.o
OBJS += $(EXTOBJS) $(COMPAT_OBJS)
# unnecessary unless pkgdb format changes
# OBJS += pkgdb_conversion.o
Expand All @@ -76,11 +83,16 @@ $(LIBPROP_OBJS): %.o: %.c
${SILENT}$(CC) $(CPPFLAGS) $(LIBPROP_CPPFLAGS) \
$(CFLAGS) $(LIBPROP_CFLAGS) -c $< -o $@

$(INIH_OBJS): %.o: %.c
@printf " [CC]\t\t$@\n"
${SILENT}$(CC) $(CPPFLAGS) $(INIH_CPPFLAGS) \
$(CFLAGS) $(INIH_CFLAGS) -c $< -o $@

$(OBJS): %.o: %.c
@printf " [CC]\t\t$@\n"
${SILENT}$(CC) $(CPPFLAGS) $(CFLAGS) $(SHAREDLIB_CFLAGS) -c $< -o $@

libxbps.so: $(LIBFETCH_OBJS) $(LIBPROP_OBJS) $(OBJS)
libxbps.so: $(LIBFETCH_OBJS) $(LIBPROP_OBJS) $(INIH_OBJS) $(OBJS)
@printf " [CCLD]\t\t$@\n"
${SILENT}$(CC) $^ $(CFLAGS) $(LDFLAGS) -o $(LIBXBPS_SHLIB)
@-ln -sf $(LIBXBPS_SHLIB) libxbps.so.$(LIBXBPS_MAJOR)
Expand All @@ -106,5 +118,5 @@ uninstall:

.PHONY: clean
clean:
-rm -f libxbps* $(OBJS) $(LIBFETCH_OBJS) $(LIBPROP_OBJS)
-rm -f libxbps* $(OBJS) $(LIBFETCH_OBJS) $(LIBPROP_OBJS) $(INIH_OBJS)
-rm -f $(LIBFETCH_GEN)
66 changes: 63 additions & 3 deletions lib/external/fexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
#include "xbps_api_impl.h"

static int
pfcexec(struct xbps_handle *xhp, const char *file, const char **argv)
pfcexec(const struct xbps_handle *xhp, const char *file, const char **argv)
{
pid_t child;
int status;
Expand Down Expand Up @@ -86,7 +86,54 @@ pfcexec(struct xbps_handle *xhp, const char *file, const char **argv)
}

static int
vfcexec(struct xbps_handle *xhp, const char *arg, va_list ap)
pfcexecp(const struct xbps_handle *xhp, const char *file, const char **argv)
{
pid_t child;
int status;

child = fork();
switch (child) {
case 0:
/*
* If rootdir != / and uid==0 and bin/sh exists,
* change root directory and exec command.
*/
if (strcmp(xhp->rootdir, "/")) {
if ((geteuid() == 0) && (access("bin/sh", X_OK) == 0)) {
if (chroot(xhp->rootdir) == -1) {
xbps_dbg_printf("%s: chroot() "
"failed: %s\n", *argv, strerror(errno));
_exit(errno);
}
if (chdir("/") == -1) {
xbps_dbg_printf("%s: chdir() "
"failed: %s\n", *argv, strerror(errno));
_exit(errno);
}
}
}
umask(022);
(void)execvp(file, __UNCONST(argv));
_exit(errno);
/* NOTREACHED */
case -1:
return -1;
}

while (waitpid(child, &status, 0) < 0) {
if (errno != EINTR)
return -1;
}

if (!WIFEXITED(status))
return -1;

return WEXITSTATUS(status);
}


static int
vfcexec(const struct xbps_handle *xhp, const char *arg, va_list ap)
{
const char **argv;
size_t argv_size, argc;
Expand Down Expand Up @@ -122,8 +169,9 @@ vfcexec(struct xbps_handle *xhp, const char *arg, va_list ap)
return retval;
}


int HIDDEN
xbps_file_exec(struct xbps_handle *xhp, const char *arg, ...)
xbps_file_exec(const struct xbps_handle *xhp, const char *arg, ...)
{
va_list ap;
int result;
Expand All @@ -134,3 +182,15 @@ xbps_file_exec(struct xbps_handle *xhp, const char *arg, ...)

return result;
}

int HIDDEN
xbps_file_exec_argv(const struct xbps_handle *xhp, const char **argv)
{
return pfcexecp(xhp, argv[0], argv);
}

int HIDDEN
xbps_file_execp_argv(const struct xbps_handle *xhp, const char **argv)
{
return pfcexecp(xhp, argv[0], argv);
}
Loading
Loading