343 lines
8.2 KiB
Bash
Executable file
343 lines
8.2 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
|
|
ALPINE="https://dl-cdn.alpinelinux.org/alpine/v3.20/releases/x86_64/alpine-minirootfs-3.20.3-x86_64.tar.gz"
|
|
CHROOTDIR="./alpine_chroot"
|
|
QEMU_STATIC_URL="https://github.com/multiarch/qemu-user-static/releases/download/v7.2.0-1/qemu-aarch64-static"
|
|
|
|
log()
|
|
{
|
|
case "$2" in
|
|
error)
|
|
printf "\e[1m\e[31mERROR:\e[0m \e[1m%s\e[0m (host)\n" "$1">&2;;
|
|
internal)
|
|
printf "\e[1m\e[96m h>\e[0m \e[1m%s\e[0m\n" "$1">&2;;
|
|
ierror)
|
|
printf "\e[1m\e[31m h>\e[0m \e[1m%s\e[0m\n" "$1">&2;;
|
|
*)
|
|
printf "\e[1m\e[92mH>>\e[0m \e[1m%s\e[0m\n" "$1">&2;;
|
|
esac
|
|
}
|
|
|
|
mkdir_if_not_exists()
|
|
{
|
|
[ -d "$1" ] && return 0
|
|
[ -f "$1" ] && rm -f "$1"
|
|
mkdir "$1"
|
|
}
|
|
|
|
umount_if_mouted()
|
|
{
|
|
[ ! -d "$1" ] && return 0
|
|
if grep -qs "$(realpath "$1")" /proc/mounts; then
|
|
umount "$1"
|
|
return $?
|
|
else
|
|
return 0
|
|
fi
|
|
}
|
|
|
|
require ()
|
|
{
|
|
which "$1" > /dev/null 2>&1 ||
|
|
{
|
|
log "$1 not found" error
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
# shellcheck disable=SC2161
|
|
# shellcheck disable=SC2086
|
|
arguments() {
|
|
while [[ $# -gt 0 ]]; do
|
|
opt="$1"
|
|
|
|
shift
|
|
|
|
case "$(echo ${opt} | tr '[:upper:]' '[:lower:]')" in
|
|
install)
|
|
install_chroot
|
|
break 2 ;;
|
|
|
|
remove)
|
|
remove_chroot
|
|
break 2 ;;
|
|
|
|
build)
|
|
build "$1"
|
|
break 2 ;;
|
|
|
|
chroot)
|
|
chroot_into
|
|
break 2 ;;
|
|
|
|
-h | -help | --help)
|
|
usage ;;
|
|
|
|
*)
|
|
log "Unknown option: $opt" error
|
|
break 2 ;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
usage() {
|
|
log "Usage commands:"
|
|
|
|
cat <<EOF
|
|
# Help screen (this)
|
|
$0 --help or $0 -h
|
|
|
|
# Setup build chroot
|
|
$0 install
|
|
|
|
# Remove build chroot
|
|
$0 uninstall
|
|
|
|
# Make image
|
|
$0 build path/to/lnibuild
|
|
|
|
# Chroot into
|
|
$0 chroot
|
|
EOF
|
|
exit 0
|
|
}
|
|
|
|
# shellcheck disable=SC2317
|
|
_shutdown()
|
|
{
|
|
detach_chroot
|
|
if [ -z ${1+x} ]; then
|
|
exit 0
|
|
else
|
|
exit "$1"
|
|
fi
|
|
}
|
|
|
|
sigterm_handler()
|
|
{
|
|
sig=$?
|
|
printf "\e[1m\e[31m>>\e[0m \e[1m%s\e[0m\n" "Shutdown signal received."
|
|
_shutdown $sig
|
|
}
|
|
|
|
trap 'trap " " SIGINT SIGTERM SIGHUP; kill 0; wait; sigterm_handler' SIGINT SIGTERM SIGHUP
|
|
|
|
|
|
# Chroot functions
|
|
require "lsof"
|
|
require "tar"
|
|
require "gzip"
|
|
require "wget"
|
|
|
|
setup_inet()
|
|
{
|
|
[ ! -d "$CHROOTDIR" ] && {
|
|
log "Rootdir [$CHROOTDIR] does not exists" ierror
|
|
return 2
|
|
}
|
|
echo "nameserver 1.1.1.1" > "$CHROOTDIR/etc/resolv.conf"
|
|
echo "makelnichroot" > "$CHROOTDIR/etc/hostname"
|
|
echo "127.0.0.1 localhost" > "$CHROOTDIR/etc/hosts"
|
|
}
|
|
|
|
prepare_chroot()
|
|
{
|
|
[ ! -d "$CHROOTDIR" ] && {
|
|
log "Rootdir [$CHROOTDIR] does not exists" ierror
|
|
return 2
|
|
}
|
|
|
|
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:\$PATH
|
|
|
|
mount --bind "$CHROOTDIR" "$CHROOTDIR"
|
|
mount -t proc proc "$CHROOTDIR/proc"
|
|
mount -t sysfs sysfs "$CHROOTDIR/sys"
|
|
mount -t devtmpfs devtmpfs "$CHROOTDIR/dev"
|
|
mount -t devpts devpts "$CHROOTDIR/dev/pts"
|
|
mount -t tmpfs devshm "$CHROOTDIR/dev/shm"
|
|
|
|
if uname -m | grep -q aarch64 || [ -f "/proc/sys/fs/binfmt_misc/qemu-aarch64" ]; then
|
|
log "Cancel qemu-aarch64-static register"
|
|
else
|
|
|
|
# shellcheck disable=SC2028
|
|
echo ':aarch64:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:'"$(realpath $CHROOTDIR/bin/qemu-aarch64-static):PF" > /proc/sys/fs/binfmt_misc/register 2> /dev/null || true
|
|
|
|
# shellcheck disable=SC2028
|
|
echo ':aarch64ld:M::\x7fELF\x02\x01\x01\x03\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\xb7\x00:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:'"$(realpath $CHROOTDIR/bin/qemu-aarch64-static):PF" > /proc/sys/fs/binfmt_misc/register 2> /dev/null || true
|
|
fi
|
|
}
|
|
|
|
detach_chroot()
|
|
{
|
|
[ ! -d "$CHROOTDIR" ] && {
|
|
log "Rootdir [$CHROOTDIR] does not exists" ierror
|
|
return 2
|
|
}
|
|
|
|
umount_if_mouted "$CHROOTDIR/sys"
|
|
umount_if_mouted "$CHROOTDIR/dev/pts"
|
|
umount_if_mouted "$CHROOTDIR/dev/shm"
|
|
umount_if_mouted "$CHROOTDIR/dev"
|
|
umount_if_mouted "$CHROOTDIR/proc"
|
|
|
|
if [ -f "/proc/sys/fs/binfmt_misc/aarch64" ]; then
|
|
echo -1 > /proc/sys/fs/binfmt_misc/aarch64 2> /dev/null
|
|
fi
|
|
if [ -f "/proc/sys/fs/binfmt_misc/aarch64ld" ]; then
|
|
echo -1 > /proc/sys/fs/binfmt_misc/aarch64ld 2> /dev/null
|
|
fi
|
|
|
|
umount_if_mouted "$CHROOTDIR"
|
|
}
|
|
|
|
install_chroot()
|
|
{
|
|
[ -d "$CHROOTDIR" ] && {
|
|
log "Chroot already installed" error
|
|
exit 1
|
|
}
|
|
mkdir "$CHROOTDIR"
|
|
[ ! -f "./alpine.tar.gz" ] && {
|
|
log "Downloading alpine rootfs tarball"
|
|
wget -q --show-progress "$ALPINE" -O "./alpine.tar.gz" || {
|
|
ec=$?
|
|
log "Failed to download rootfs tarball" error
|
|
exit "$ec"
|
|
}
|
|
}
|
|
|
|
log "Extracting alpine rootfs tarball"
|
|
tar -xzf "./alpine.tar.gz" -C "$CHROOTDIR/" || {
|
|
log "Failed to extract rootfs" error
|
|
}
|
|
setup_inet
|
|
prepare_chroot || {
|
|
log "Failed to setup chroot" error
|
|
exit 1
|
|
}
|
|
log "Updating apk repos"
|
|
chroot "$CHROOTDIR" apk update --quiet || {
|
|
log "Failed to update apk repos" error
|
|
exit 1
|
|
}
|
|
log "Installing pakages"
|
|
chroot "$CHROOTDIR" apk add --quiet shadow fish bash git debootstrap pixz losetup rsync pv wget e2fsprogs e2fsprogs-extra libarchive-tools coreutils go libusb libusb-dev pkgconfig || {
|
|
log "Failed to install packages" error
|
|
exit 1
|
|
}
|
|
chroot "$CHROOTDIR" chsh -s /usr/bin/fish root
|
|
|
|
log "Cloning makelni repo"
|
|
chroot "$CHROOTDIR" git clone --quiet "https://git.timoxa0.su/timoxa0/makelni.git" /makelni || {
|
|
log "Failed to clone makelni repo" error
|
|
exit 1
|
|
}
|
|
|
|
log "Installing qemu-aarch64-static"
|
|
{
|
|
wget -q --show-progress -N "$QEMU_STATIC_URL" -O "$CHROOTDIR/bin/qemu-aarch64-static" &&
|
|
chmod 755 "$CHROOTDIR/bin/qemu-aarch64-static"
|
|
} || {
|
|
log "Failed to install qemu-aarch64-static" error
|
|
exit 1
|
|
}
|
|
|
|
log "Installing lon-tool"
|
|
{
|
|
chroot "$CHROOTDIR" git clone --quiet https://git.timoxa0.su/timoxa0/lon-tool.git /lon-tool-src &&
|
|
chroot "$CHROOTDIR" /bin/bash -c 'cd /lon-tool-src && rev=$(git describe --abbrev=4 --dirty --always --tags) && go get git.timoxa0.su/timoxa0/lon-tool/cmd && go build -ldflags "-X git.timoxa0.su/timoxa0/lon-tool/cmd.version=$rev" -o /bin/lon-tool main.go'
|
|
|
|
} || {
|
|
log "Failed to install lon-tool" error
|
|
exit 1
|
|
}
|
|
|
|
detach_chroot || {
|
|
log "Failed to detach chroot" error
|
|
exit 1
|
|
}
|
|
log "Done!"
|
|
exit 0
|
|
}
|
|
|
|
remove_chroot()
|
|
{
|
|
[ ! -d "$CHROOTDIR" ] && {
|
|
log "Chroot not installed" error
|
|
exit 1
|
|
}
|
|
detach_chroot || {
|
|
log "Failed to umount chroot" error
|
|
exit 1
|
|
}
|
|
log "Done!"
|
|
rm -rf "${CHROOTDIR:?}/"
|
|
}
|
|
|
|
chroot_into()
|
|
{
|
|
prepare_chroot || {
|
|
log "Failed to setup chroot" error
|
|
exit 1
|
|
}
|
|
chroot "$CHROOTDIR" /usr/bin/fish
|
|
detach_chroot || {
|
|
log "Failed to detach chroot" error
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
build()
|
|
{
|
|
[ ! -d "$CHROOTDIR" ] && {
|
|
log "Chroot not installed" error
|
|
exit 1
|
|
}
|
|
|
|
local lni="$1"
|
|
[ ! -f "$lni" ] && {
|
|
log "$lni no such file" error
|
|
exit 2
|
|
}
|
|
|
|
cp "$lni" "$CHROOTDIR/tmp/lnibuild"
|
|
|
|
prepare_chroot || {
|
|
log "Failed to setup chroot" error
|
|
exit 1
|
|
}
|
|
|
|
chroot "$CHROOTDIR" /bin/bash -c "cd /makelni && ./makelni /tmp/lnibuild"
|
|
local exitcode=$?
|
|
rm "$CHROOTDIR/tmp/lnibuild"
|
|
|
|
detach_chroot || {
|
|
log "Failed to detach chroot" error
|
|
exit 1
|
|
}
|
|
|
|
[ "$exitcode" -eq "0" ] || {
|
|
log "Failed to build image" error
|
|
exit 1
|
|
}
|
|
|
|
source <( grep name "$lni" )
|
|
mv "$CHROOTDIR/makelni/out/${name}.lni" "./${name}.lni"
|
|
chown "$(stat -c '%U:%G' mklni)" "./${name}.lni"
|
|
exit 0
|
|
}
|
|
|
|
if [ "$(id -u)" != "0" ]; then
|
|
log "$0 must be run as root"
|
|
exit 3
|
|
fi
|
|
|
|
[[ "$(uname -m)" != "x86_64*" ]] || {
|
|
printf "Unsupported CPU arch\n"
|
|
exit 1
|
|
}
|
|
|
|
arguments "$*"
|
|
|