-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsetup_rootfs
More file actions
executable file
·144 lines (107 loc) · 4.01 KB
/
setup_rootfs
File metadata and controls
executable file
·144 lines (107 loc) · 4.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/bin/sh -ex
dest_img="$1"
[ ! -d "$ROOTFS_BUILD_DIR" ] || rm -rf "$ROOTFS_BUILD_DIR"
mkdir "$ROOTFS_BUILD_DIR"
# being on a tmpfs inside the mount namespace is really nice.
# it can limit size of the file system, cleanup is free, and - of course - it's super fast.
# but mke2fs has problems with it, so no: mount -t tmpfs none "$ROOTFS_BUILD_DIR".
# however, not using a tmpfs leads other problems
mount -t tmpfs -o noatime none "$ROOTFS_BUILD_DIR"
bsdtar -xpf "$BASE_ROOTFS_TAR" -C "$ROOTFS_BUILD_DIR"
mkdir -p "$ROOTFS_BUILD_DIR/boot"
run_mounted() {
# exporting in a loop is a hassle
{
[ ! -f .env.rootfs-customization ] || grep -v '^#' .env.rootfs-customization
echo ./customize_rootfs
echo "$ROOTFS_BUILD_DIR"
} | xargs -od '\n' env
}
# this includes /proc/sys/fs/binfmt_misc, which allows running the binaries inside
mount --rbind /proc/ "$ROOTFS_BUILD_DIR/proc"
# /dev/shm, /dev/random, /dev/urandom and the likes are required for GPG and such
mount --rbind /dev "$ROOTFS_BUILD_DIR/dev"
mount --bind . "$ROOTFS_BUILD_DIR/mnt"
mount --bind "$PACMAN_CACHE_DIR/pkg" "$ROOTFS_BUILD_DIR/var/cache/pacman/pkg"
mount --bind "$PACMAN_CACHE_DIR/sync" "$ROOTFS_BUILD_DIR/var/lib/pacman/sync"
mount --bind /etc/resolv.conf "$ROOTFS_BUILD_DIR/etc/resolv.conf"
if [ -n "$EFI_MNT" ]; then
mkdir -p "$ROOTFS_BUILD_DIR/efi"
mount -t tmpfs -o noatime none "$ROOTFS_BUILD_DIR/efi"
fi
fork_pipe_wait() {
local fd cmd="$1"
local pipe wait_pipe
pipe="$(mktemp -u rootfs-builder-$$-cleanup-pipe.XXXXXXXXXX)"
mkfifo "$pipe"
( ( cat <"$pipe" >/dev/null ; eval "$cmd" ; ) & ) &
# TODO cat has to open the pipe first
sleep 3
exec {fd}<>"$pipe"
if [ $# -gt 1 ]; then
eval "$2=$fd"
fi
rm "$pipe"
}
subshell_ppid() {
# even $( sh -c 'echo $PPID' ) or sh .. | read doesn't necessarily yield the correct result (depending on the shell)
# this grep sees another file than the awk that follows:
# grep PPid < /proc/self/status | awk '{ print $2 }'
# awk '/^PPid:/ { print $2 }' < /proc/self/status
awk '/^PPid:/ { "grep PPid /proc/"$2"/status" | getline ; print $2 }' < /proc/self/status
}
umount_secondaries() {
umount "$ROOTFS_BUILD_DIR/etc/resolv.conf"
umount "$ROOTFS_BUILD_DIR/var/cache/pacman/pkg"
umount "$ROOTFS_BUILD_DIR/mnt"
umount -l "$ROOTFS_BUILD_DIR/dev"
umount -l "$ROOTFS_BUILD_DIR/proc"
}
cleanup_mnt() {
# if any processes are still in the mount namespace, umount fails with 'target busy'
# pacman forks a gpg-agent
set +x
# $$ returns the pid of the shell and doesn't change in subshells
local own_pid="$(subshell_ppid)"
# double-forked, so PPID is not sane ($$ would likely be)
local pppid="$1"
local pids="$(ls /proc/ | grep '[0-9]' | grep -v "^$pppid\$" | grep -v "^$own_pid\$")"
local own_mnt_ns="$(stat -Lc '%i' /proc/self/ns/mnt)"
for pid in $pids; do
mnt_ns="/proc/$pid/ns/mnt"
[ -r "$mnt_ns" ] || continue
[ "$(stat -Lc '%i' "$mnt_ns")" == "$own_mnt_ns" ] || continue
echo "killing stray process $pid - $(tr '\0' ' ' < "/proc/$pid/cmdline")"
kill "$pid"
done
# umount to be able to do rmdir
if mountpoint -q "$ROOTFS_BUILD_DIR/etc/resolv.conf"; then
umount_secondaries
fi
if mountpoint -q "$ROOTFS_BUILD_DIR/efi"; then
umount "$ROOTFS_BUILD_DIR/efi"
fi
umount "$ROOTFS_BUILD_DIR"
rmdir "$ROOTFS_BUILD_DIR"
}
fork_pipe_wait "cleanup_mnt $$"
# TODO the whole point of mountns was to be able to utilise cleanup
# "fork" another mount namespace for ./run_mounted to run in.
# have the cleanup func run in there (no relying on parent pids or such).
# wait for cleanup using fds
run_mounted
umount_secondaries
if [ -n "$EFI_MNT" ]; then
mkfs.vfat -i "${EFI_UUID//-/}" -F 32 "$EFI_IMG"
# there should be no hidden files here
mcopy -i "$EFI_IMG" -spQ "$ROOTFS_BUILD_DIR"/efi/* ::
umount "$ROOTFS_BUILD_DIR/efi"
fi
apparent_size="$(du -xsm "$ROOTFS_BUILD_DIR" | awk '{ print $1 }')"
# this can fail because of the host FS
mke2fs -F -L "system" -U "$ROOTFS_UUID" -d "$ROOTFS_BUILD_DIR" \
-O "^has_journal" \
-m 2 \
-t ext4 \
"$dest_img" \
$(( apparent_size * 105 / 100 + ROOTFS_WIGGLEROOM_MB ))M 2>&1