Skip to content

Commit 71723e2

Browse files
committed
binfmt-misc: add service
Signed-off-by: Loukas Agorgianitis <loukas@agorgianitis.com>
1 parent 9a959bc commit 71723e2

File tree

1 file changed

+101
-0
lines changed

1 file changed

+101
-0
lines changed
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#!/bin/sh
2+
3+
# This is a reimplementation of the systemd binfmt.d code to register
4+
# misc binary formats with the kernel.
5+
#
6+
# See the binfmt.d here:
7+
# https://www.freedesktop.org/software/systemd/man/latest/binfmt.d.html
8+
#
9+
# The below code is heavily inspired by the OpenRC implementation here:
10+
# https://github.com/OpenRC/openrc/blob/master/sh/binfmt.sh.in
11+
12+
mount_binfmt_misc() {
13+
[ -e /proc/sys/fs/binfmt_misc/register ] && return
14+
mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
15+
}
16+
17+
apply_file() {
18+
[ $# -lt 1 ] && return 0
19+
FILE="$1"
20+
LINENUM=0
21+
22+
### FILE FORMAT ###
23+
# See https://www.kernel.org/doc/html/latest/admin-guide/binfmt-misc.html
24+
while read -r line; do
25+
LINENUM=$(( LINENUM+1 ))
26+
case $line in
27+
\#*) continue ;;
28+
\;*) continue ;;
29+
'') continue ;;
30+
esac
31+
32+
local reg=${line#*:}
33+
[ -e /proc/sys/fs/binfmt_misc/${reg%%:*} ] && echo -1 > /proc/sys/fs/binfmt_misc/${reg%%:*}
34+
35+
echo "${line}" > /proc/sys/fs/binfmt_misc/register
36+
rc=$?
37+
if [ $rc -ne 0 ]; then
38+
printf "binfmt: invalid entry on line %d of \`%s'\n" \
39+
"$LINENUM" "$FILE" >&2
40+
fi
41+
done <$FILE
42+
return $rc
43+
}
44+
45+
register_formats() {
46+
# The hardcoding of these paths is intentional; we are following the
47+
# systemd spec.
48+
binfmt_dirs='/usr/lib/binfmt.d/ /usr/local/lib/binfmt.d/ /run/binfmt.d/ /etc/binfmt.d/'
49+
binfmt_basenames=''
50+
binfmt_d=''
51+
52+
# Build a list of sorted unique basenames
53+
# directories declared later in the binfmt_d list will override earlier
54+
# directories, on a per file basename basis.
55+
# `/run/binfmt.d/foo.conf' supersedes `/usr/lib/binfmt.d/foo.conf'.
56+
# `/run/binfmt.d/foo.conf' will always be read after `/etc/binfmt.d/bar.conf'
57+
for d in ${binfmt_dirs} ; do
58+
[ -d $d ] && for f in ${d}/*.conf ; do
59+
case "${f##*/}" in
60+
systemd.conf|systemd-*.conf) continue;;
61+
esac
62+
[ -e $f ] && binfmt_basenames="${binfmt_basenames}\n${f##*/}"
63+
done # for f in ${d}
64+
done # for d in ${binfmt_dirs}
65+
binfmt_basenames="$(printf "${binfmt_basenames}\n" | sort -u )"
66+
67+
for b in $binfmt_basenames ; do
68+
real_f=''
69+
for d in $binfmt_dirs ; do
70+
f=${d}/${b}
71+
[ -e "${f}" ] && real_f=$f
72+
done
73+
[ -e "${real_f}" ] && binfmt_d="${binfmt_d} ${real_f}"
74+
done
75+
76+
# loop through the gathered fragments, sorted globally by filename.
77+
# `/run/binfmt.d/foo.conf' will always be read after `/etc/binfmt.d/bar.conf'
78+
for FILE in $binfmt_d ; do
79+
apply_file "$FILE"
80+
done
81+
}
82+
83+
start() {
84+
printf "Starting binfmt_misc setup: "
85+
mount_binfmt_misc
86+
register_formats
87+
status=$?
88+
[ "$status" -eq 0 ] && echo "OK" || echo "FAIL"
89+
return "$status"
90+
}
91+
92+
case "$1" in
93+
start)
94+
"$1"
95+
;;
96+
*)
97+
echo "Usage: $0 {start}"
98+
exit 1
99+
esac
100+
101+
exit $?

0 commit comments

Comments
 (0)