Skip to content

Commit 2c331b4

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

1 file changed

Lines changed: 97 additions & 0 deletions

File tree

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
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 relevant spec.
47+
binfmt_dirs='/usr/lib/binfmt.d/ /etc/binfmt.d/'
48+
binfmt_basenames=''
49+
binfmt_d=''
50+
51+
# Build a list of sorted unique basenames
52+
# directories declared later in the binfmt_d list will override earlier
53+
# directories, on a per file basename basis.
54+
# `/etc/binfmt.d/foo.conf' supersedes `/usr/lib/binfmt.d/foo.conf'.
55+
# `/etc/binfmt.d/foo.conf' will always be read after `/etc/binfmt.d/bar.conf'
56+
for d in ${binfmt_dirs} ; do
57+
[ -d $d ] && for f in ${d}/*.conf ; do
58+
[ -e $f ] && binfmt_basenames="${binfmt_basenames}\n${f##*/}"
59+
done # for f in ${d}
60+
done # for d in ${binfmt_dirs}
61+
binfmt_basenames="$(printf "${binfmt_basenames}\n" | sort -u )"
62+
63+
for b in $binfmt_basenames ; do
64+
real_f=''
65+
for d in $binfmt_dirs ; do
66+
f=${d}/${b}
67+
[ -e "${f}" ] && real_f=$f
68+
done
69+
[ -e "${real_f}" ] && binfmt_d="${binfmt_d} ${real_f}"
70+
done
71+
72+
# loop through the gathered fragments, sorted globally by filename.
73+
# `/run/binfmt.d/foo.conf' will always be read after `/etc/binfmt.d/bar.conf'
74+
for FILE in $binfmt_d ; do
75+
apply_file "$FILE"
76+
done
77+
}
78+
79+
start() {
80+
printf "Starting binfmt_misc setup: "
81+
mount_binfmt_misc
82+
register_formats
83+
status=$?
84+
[ "$status" -eq 0 ] && echo "OK" || echo "FAIL"
85+
return "$status"
86+
}
87+
88+
case "$1" in
89+
start)
90+
"$1"
91+
;;
92+
*)
93+
echo "Usage: $0 {start}"
94+
exit 1
95+
esac
96+
97+
exit $?

0 commit comments

Comments
 (0)