Add binfmt service to sysinit runlevel

This makes binfmt processing behave like tmpfiles processing which
follows the same specification as systemd.

This fixes #48.

X-Gentoo-Bug: 545162
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=545162
This commit is contained in:
William Hubbs
2015-03-31 12:48:45 -05:00
parent 95ed066539
commit ee1768a419
7 changed files with 113 additions and 17 deletions

1
sh/.gitignore vendored
View File

@@ -8,3 +8,4 @@ init-early.sh
rc-cgroup.sh
tmpfiles.sh
migrate-to-run.sh
binfmt.sh

View File

@@ -12,9 +12,9 @@ include ${MK}/os.mk
SRCS-FreeBSD=
BIN-FreeBSD=
SRCS-Linux= cgroup-release-agent.sh.in init-early.sh.in migrate-to-run.sh.in \
rc-cgroup.sh.in
BIN-Linux= cgroup-release-agent.sh init-early.sh migrate-to-run.sh \
SRCS-Linux= binfmt.sh.in cgroup-release-agent.sh.in init-early.sh.in \
migrate-to-run.sh.in rc-cgroup.sh.in
BIN-Linux= binfmt.sh cgroup-release-agent.sh init-early.sh migrate-to-run.sh \
rc-cgroup.sh
SRCS-NetBSD=

85
sh/binfmt.sh.in Normal file
View File

@@ -0,0 +1,85 @@
#!@SHELL@
# This is a reimplementation of the systemd binfmt.d code to register
# misc binary formats with the kernel.
#
# Copyright (c) 2015 William Hubbs <w.d.hubbs@gmail.com>
# Released under the 2-clause BSD license.
#
# See the binfmt.d manpage as well:
# http://0pointer.de/public/systemd-man/binfmt.d.html
# This script should match the manpage as of 2015/03/31
#
apply_file() {
[ $# -lt 1 ] && return 0
FILE="$1"
LINENUM=0
### FILE FORMAT ###
# See https://www.kernel.org/doc/Documentation/binfmt_misc.txt
while read line; do
LINENUM=$(( LINENUM+1 ))
case $line in
\#*) continue ;;
\;*) continue ;;
esac
echo "${line}" > /proc/sys/fs/binfmt_misc/register
rc=$?
if [ $rc -ne 0 ]; then
printf "binfmt: invalid entry on line %d of \`%s'\n" \
"$LINENUM" "$FILE" >&2
error=1
fi
done <$FILE
return $rc
}
[ -e /proc/sys/fs/binfmt_misc/register ] || exit 0
error=0
if [ $# -gt 0 ]; then
while [ $# -gt 0 ]; do
apply_file "$1"
shift
done
else
# The hardcoding of these paths is intentional; we are following the
# systemd spec.
binfmt_dirs='/usr/lib/binfmt.d/ /run/binfmt.d/ /etc/binfmt.d/'
binfmt_basenames=''
binfmt_d=''
# Build a list of sorted unique basenames
# directories declared later in the binfmt_d list will override earlier
# directories, on a per file basename basis.
# `/run/binfmt.d/foo.conf' supersedes `/usr/lib/binfmt.d/foo.conf'.
# `/run/binfmt.d/foo.conf' will always be read after `/etc/binfmt.d/bar.conf'
for d in ${binfmt_dirs} ; do
[ -d $d ] && for f in ${d}/*.conf ; do
case "${f##*/}" in
systemd.conf|systemd-*.conf) continue;;
esac
[ -e $f ] && binfmt_basenames="${binfmt_basenames}\n${f##*/}"
done # for f in ${d}
done # for d in ${binfmt_dirs}
binfmt_basenames="$(printf "${binfmt_basenames}\n" | sort -u )"
for b in $binfmt_basenames ; do
real_f=''
for d in $binfmt_dirs ; do
f=${d}/${b}
[ -e "${f}" ] && real_f=$f
done
[ -e "${real_f}" ] && binfmt_d="${binfmt_d} ${real_f}"
done
# loop through the gathered fragments, sorted globally by filename.
# `/run/binfmt.d/foo.conf' will always be read after `/etc/binfmt.d/bar.conf'
for FILE in $binfmt_d ; do
apply_file "$FILE"
done
fi
exit $error
# vim: set ts=2 sw=2 sts=2 noet ft=sh: