Compare commits

..

No commits in common. "develop-bootscripts" and "develop" have entirely different histories.

12 changed files with 954 additions and 5 deletions

17
Makefile Normal file
View file

@ -0,0 +1,17 @@
help:
@echo "make help - display tasks"
@echo " check - check androot scripts"
@echo " ensureexec - ensure all scripts are executable"
@echo " run - execute androot locally"
@echo " test - execute androot locally with diagnostic log output"
@echo " log - follow androot's log file"
check:
shellcheck *.sh
ensureexec:
chmod +x *.sh
run: ensureexec check
sudo ./androot.sh --local
test: ensureexec check
sudo env ALLOW_SHM=true DIAG=true ./androot.sh --local
log:
@PS4='';if [ -d "/tmp/androot" ]; then set -x; tail -f /tmp/androot/androot.log; elif [ -d "/data/tmp/androot" ]; then set -x; tail -f /data/tmp/androot/androot.log; else echo ":: Error: androot's log directory could not be determined (start androot first)"; exit 1; fi

View file

@ -1,6 +1,79 @@
# androot bootscripts # androot
Bootscripts for an chroot and systemd-nspawn rootfs installer Chroot and systemd-nspawn rootfs installer
# Warning # Experimental
This branch does not contain the **androot installer**, but instead so called *bootscripts*. \ **androot** is experimental software and can lead to breakage! \
These are used to "boot" into a rootfs, installed by **androot**. Only run these scripts with extensive knowledge of Linux (and Android if using Termux)!
# How to use
## Termux
### WARNING
If you want to use **androot** under Android you need a working Magisk or KernelSU installation. \
If you wish to install a (more limited) Linux distribution without root access use [*Andronix*](https://play.google.com/store/apps/details?id=studio.com.techriz.andronix) instead.
### Dependencies
- [*Magisk*](https://github.com/topjohnwu/Magisk)/[*Magisk Delta*](https://github.com/HuskyDG/magisk-files)/[*KernelSU*](https://kernelsu.org)
- curl
- bash
- chroot
- bsdtar
- tsu
### Use
`curl -sSL "https://git.staropensource.de/StarOpenSource/androot/raw/branch/master/androot.sh"|sudo bash - --download`
## Linux
### Dependencies
- curl
- bash
- chroot/systemd-nspawn
- bsdtar
### Use
`curl -sSL "https://git.staropensource.de/StarOpenSource/androot/raw/branch/master/androot.sh"|sudo bash - --download`
# Architectures
## Supported (target architectures)
- x86_64 (amd64)
- arm64 (aarch64)
## Supported (execution architectures)
- x86_64 (amd64)
- arm64 (aarch64)
- powerpc64 (ppc64,ppc64le)
- mips64
## Unsupported
- x86 (i386,i686)
- arm
- powerpc (ppc,ppcle)
- mips
# Distributions
- Arch Linux
# How does this work?
## tldr
We download & decompress a rootfs, apply some magic and make it "bootable" with the help of `chroot` or `systemd-nspawn`.
## The short answer
1. check architecture
2. ask for target architecture, execution architecture(s) and distribution
3. download rootfs
4. decompress rootfs
5. mount rootfs
6. install updates and bootscript dependencies
7. apply patches (if using chroot)
8. download bootscripts
9. unmount rootfs
10. finish and print information about how to "boot" the rootfs
## The long answer
Just read the source code.
# How to test
`make test` to run it, `make log` to view the log file.
## Recommendation
We recommend using */dev/shm* as a install location during development. Although using temporary directories \
is disallowed for normal installations we highly recommend using */dev/shm* during development as you will \
be wearing out your disk very fast otherwise. Just make sure that you have enough memory available and that you \
use */dev/shm* instead of */tmp* as your install location (*/tmp* uses your disk while */dev/shm* uses your computer memory).
# Annotations
```plain
### TOBECHANGED - this should be changed in the future
### MISIMPLEMENTED - implemented, but wrong
```

271
androot.sh Executable file
View file

@ -0,0 +1,271 @@
#!/bin/bash
# disable errors regarding androot.source as
# it is created and loaded at runtime
# shellcheck disable=SC1091
### TOBECHANGED
# disables unreachable code warnings
# shellcheck disable=SC2317
### TOBECHANGED_END
# check for root user
if [ ! "${UID}" == "0" ]; then
echo ":: Error: Not running as root user"
exit 1
fi
# determine $TMPDIR
if [ ! -d "${TMPDIR}" ]; then
if [ -d "/tmp" ]; then
export "TMPDIR=/tmp/androot"
elif [ -d "/data/tmp" ]; then
export "TMPDIR=/data/tmp/androot"
else
echo ":: Error: \$TMPDIR could not be determined"
exit 1
fi
fi
# ... and create it
mkdir -p "${TMPDIR}"
# write source file
cat << EOF > "${TMPDIR}/androot.source"
# Functions
## indicate failure
function indicate_fail() {
echo -e "\r\e[0m[\e[0;31mFAIL\e[0m]"
}
## indicate success
function indicate_ok() {
echo -e "\r\e[0m[\e[0;32m OK \e[0m]"
}
## indicate running execution
function indicate_exec() {
echo -ne "\e[0m[\e[0;34m....\e[0m] \${*}"
}
## log diagnostic message to term
function log_diag() {
if [ "\$DIAG" == "true" ]; then
echo -e "\e[0m[\e[0;35mDIAG\e[0m] \${*}"
fi
}
## log informational message to term
function log_info() {
echo -e "\r\e[0m[\e[0;32mINFO\e[0m] \${*}"
}
## log warning message to term
function log_warn() {
echo -e "\r\e[0m[\e[0;33mWARN\e[0m] \${*}"
}
## log error message to term
function log_error() {
echo -e "\r\e[0m[\e[0;31mERR!\e[0m] \${*}"
}
## log message to log file
function log_write() {
echo -e "\${*}" &>> "\${TMPDIR}/androot.log"
}
function log_execute() {
log_write ">>>> \${*}"
\${*} &>> "\${TMPDIR}/androot.log"
EXITCODE=\${?}
log_write "Exited with code \${EXITCODE}"
return \${EXITCODE}
}
## ask a question
function log_ask() {
echo -ne "\e[0m[\e[0;36mASKQ\e[0m] \${*}"
read -r ANSWER
}
## ask for password
function log_askpasswd() {
echo -ne "\e[0m[\e[0;36mASKP\e[0m] \${*}"
read -rs ANSWER
echo ""
}
## ask for yes or no (agreement)
function log_askyn() {
if [ -z "\${2}" ]; then
log_error "log_askyn requires at least two arguments"
exit 1
fi
export "ANSWER_FALLBACK=\${1}"
shift
echo -ne "\e[0m[\e[0;36mASKA\e[0m] \${*}"
read -r ANSWER
if [ "\${ANSWER,,}" == "y" ] || [ "\${ANSWER,,}" == "yes" ] || [ "\${ANSWER,,}" == "true" ] || [ "\${ANSWER}" == "" ]; then
export "ANSWER=true"
elif [ "\${ANSWER,,}" == "n" ] || [ "\${ANSWER,,}" == "no" ] || [ "\${ANSWER,,}" == "false" ]; then
export "ANSWER=false"
else
export "ANSWER=\$ANSWER_FALLBACK"
fi
}
## chroot into rootfs
function chroot_env() {
CHROOTDIR=\${1}
shift
log_execute env LD_PRELOAD= chroot "\${CHROOTDIR}" env TMPDIR=/tmp PATH=/usr/sbin:/usr/sbin/vendor_perl:/usr/local/sbin:/usr/local/sbin/vendor_perl:/usr/bin:/usr/bin/vendor_perl:/usr/local/bin:/usr/local/bin/vendor_perl:/usr/local/games ANDROID_ROOT= ANDROID_DATA= PREFIX= \${@}
return ${?}
}
# Language
## set language to C, useful for bug reports
export "LANG=C.UTF-8"
export "LANGUAGE=\${LANG}"
export "LC_ALL=\${LANG}"
export "LC_CTYPE=\${LANG}"
export "LC_NUMERIC=\${LANG}"
export "LC_TIME=\${LANG}"
export "LC_COLLATE=\${LANG}"
export "LC_MONETARY=\${LANG}"
export "LC_MESSAGES=\${LANG}"
export "LC_PAPER=\${LANG}"
export "LC_NAME=\${LANG}"
export "LC_ADDRESS=\${LANG}"
export "LC_TELEPHONE=\${LANG}"
export "LC_MEASUREMENT=\${LANG}"
export "LC_IDENTIFICATION=\${LANG}"
# Variables
## diagnostic mode
export "DIAG=${DIAG}"
## allow /dev/shm setting
export "ALLOW_SHM=${ALLOW_SHM}"
## temporary directory
export "TMPDIR=${TMPDIR}"
## androot installer branch
export "BRANCH=develop"
## unsafe commits list url
export "UNSAFE_COMMITS_LIST=https://fs.staropensource.de/vinf/unsafe/androot-\${BRANCH}"
# Download URLs
## rootfs archives
export "DOWNLOADSERVER=https://fs.staropensource.de/androot"
## bootscripts repository
export "DOWNLOADSERVER_BOOTSCRIPTS=https://git.staropensource.de/StarOpenSource/androot.git"
## installer scripts url
export "DOWNLOADSERVER_RAW=https://git.staropensource.de/StarOpenSource/androot/raw/branch/\${BRANCH}"
# Function variables
## get architecture
case "$(uname -m)" in
# 64-bit architectures (supported)
x86_64|amd64)
export "ARCH=x86_64" ;;
aarch64|aarch64_be|armv8b|armv8l)
export "ARCH=arm64" ;;
ppc64|ppc64le)
export "ARCH=powerpc64" ;;
mips64)
export "ARCH=mips64" ;;
# 32-bit architectures (unsupported)
x86|i386|i686)
export "ARCH=x86" ;;
arm)
export "ARCH=arm" ;;
powerpc|ppc|ppcle)
export "ARCH=powerpc" ;;
mips)
export "ARCH=mips" ;;
*)
export "ARCH=unknown" ;;
esac
## check if androot is running on android
if [ -d "/system" ] && [ -d "/data" ] && [ -d "/data/data" ] && [ ! -d "/home" ] && [ ! -d "/root" ]; then
export "IS_ANDROID=true"
else
export "IS_ANDROID=false"
fi
EOF
# display banner
echo -e "\e[0;33m ______ __ __ ____ ____ _____ _____ ______"
echo -e "\e[0;33m/\\ _ \\/\\ \\/\\ \\/\\ _\`\\ /\\ _\`\\ /\\ __\`\\/\\ __\`\\/\\__ _\\"
echo -e "\e[0;33m\\ \\ \\L\\ \\ \\ \`\\\\ \\ \\ \\/\\ \\ \\ \\L\\ \\ \\ \\/\\ \\ \\ \\/\\ \\/_/\\ \\/"
echo -e "\e[0;33m \\ \\ __ \\ \\ , \` \\ \\ \\ \\ \\ \\ , /\\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\"
echo -e "\e[0;33m \\ \\ \\/\\ \\ \\ \\\`\\ \\ \\ \\_\\ \\ \\ \\\\ \\\\ \\ \\_\\ \\ \\ \\_\\ \\ \\ \\ \\"
echo -e "\e[0;33m \\ \\_\\ \\_\\ \\_\\ \\_\\ \\____/\\ \\_\\ \\_\\ \\_____\\ \\_____\\ \\ \\_\\"
echo -e "\e[0;33m \\/_/\\/_/\\/_/\\/_/\\/___/ \\/_/\\/ /\\/_____/\\/_____/ \\/_/"
# load source file
source "${TMPDIR}/androot.source"
# clear/create log file
## if in diagnostic mode, print newlines
## makes reading the log file much
## easier while using "make log"
if [ "${DIAG}" == "true" ]; then log_write "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; fi
log_write "#### System information"
log_write "architecture ${ARCH}"
log_write "is_android ${IS_ANDROID}"
log_write "download_server ${DOWNLOADSERVER}"
log_write "download_server_bootscripts ${DOWNLOADSERVER_BOOTSCRIPTS}"
log_write "download_server_raw ${DOWNLOADSERVER_RAW}"
log_write "args ${*}"
log_write "diag ${DIAG}"
log_write "#### System information"
# print diagnostic messages
log_diag "Diagnostic mode enabled"
log_diag "Arguments: ${*}"
# check for supported architecture
case "${ARCH}" in
"unknown")
log_error "androot failed to detect your architecture. If you believe this is a bug, create a issue at \"https://git.staropensource.de/StarOpenSource/androot\"."
exit 1
;;
"x86"|"arm"|"powerpc"|"mips")
log_error "androot does not support legacy 32-bit systems, please use a 64-bit system instead."
exit 1
;;
esac
# run a androot script and exit if failed
function run_script() {
# $@ is used intentionally here, so ignore error
# shellcheck disable=SC2068
if ! $@; then
exit 1
fi
}
case "${1}" in
"--local")
# use scripts from cwd
log_diag "Using local mode"
run_script ./prepare.sh
run_script ./rootfsinstall.sh --download
run_script ./rootfsinstall.sh --decompress
run_script ./mount.sh --mount
run_script ./bootscriptdl.sh --download
run_script ./bootscriptdl.sh --configure
run_script ./bootscriptdl.sh --install-qemu
run_script ./systeminstall.sh --configure
run_script ./systeminstall.sh --update
run_script ./patch.sh
exit 0
run_script ./mount.sh --unmount
run_script ./finish.sh
;;
"--download")
# download scripts from the interwebz and execute them
log_diag "Using download mode"
indicate_exec "Downloading files"
indicate_fail
log_error "Unimplemented."
exit 1
;;
"--help"|"-h")
log_diag "Displaying help"
log_info "Available arguments:"
log_info "--local [execute androot from cwd] --download [download androot scripts and execute] --help [display args and vars]"
log_info "Available environment variables:"
log_info "DIAG [displays diagnostic messages, true/false] ALLOW_SHM [allows using /dev/shm as a location, true/false]"
;;
*)
log_diag "i thought putting a little \"advertisement parody\" in here would be funny"
log_error "StarOpenSource is happy to present the latest and greatest version of --help! --help now uses cutting edge technology to display the most useful help to you, and that for only zero dollars!"
;;
esac

59
bootscriptdl.sh Executable file
View file

@ -0,0 +1,59 @@
#!/bin/bash
# disable errors regarding androot.source as
# it is created and loaded at runtime
# shellcheck disable=SC1091
source "${TMPDIR}/androot.source"
source "${TMPDIR}/androot.env"
log_diag "rootfsinstall is now executing, with arguments \"${*}\""
case "${1}" in
"--download")
log_diag "Using download mode"
indicate_exec "Downloading bootscripts"
log_write "#### download bootscripts repository"
if ! log_execute git clone --quiet --verbose -b "${BRANCH}-bootscripts" "${DOWNLOADSERVER_BOOTSCRIPTS}" "${LOCATION}/bootscripts"; then
indicate_fail
exit 1
fi
indicate_ok
;;
"--configure")
log_diag "Using configure mode"
indicate_exec "Configuring bootscript scripts"
log_execute cd "${LOCATION}/bootscripts/" ||{ indicate_fail; exit 1; }
log_write "#### writing bootscripts config.env"
cat << EOF >> "${LOCATION}/bootscripts/config.env"
COMMIT=$(git rev-parse HEAD)
LOCATION=${LOCATION}
ARCHITECTURE=${ARCH_TARGET}
IS_ANDROID=${IS_ANDROID}
EOF
indicate_ok
;;
"--install-qemu")
log_diag "Using install-qemu mode"
for ARCH_DOWNLOAD in ${ARCH_EXECUTORS}; do
indicate_exec "Installing qemu-static for ${ARCH_DOWNLOAD}"
log_write "#### download qemu-static for ${ARCH_DOWNLOAD}"
if ! log_execute wget "${DOWNLOADSERVER}/qemu-static/${ARCH_DOWNLOAD}.tar.gz" --no-verbose -O "${TMPDIR}/${ARCH_DOWNLOAD}.tar.gz"; then
indicate_fail;
exit 1
fi
log_write "#### extract qemu-static for ${ARCH_DOWNLOAD}"
if ! log_execute mkdir -p "${LOCATION}/bootscripts/qemu-static/${ARCH_DOWNLOAD}"; then
indicate_fail;
exit 1
fi
if ! log_execute bsdtar -xf "${TMPDIR}/${ARCH_DOWNLOAD}.tar.gz" -C "${LOCATION}/bootscripts/qemu-static/${ARCH_DOWNLOAD}/"; then
indicate_fail;
exit 1
fi
indicate_ok
done
;;
*)
log_error "--download or --decompress required"
exit 1
;;
esac

68
mount.sh Executable file
View file

@ -0,0 +1,68 @@
#!/bin/bash
# disable errors regarding androot.source as
# it is created and loaded at runtime
# shellcheck disable=SC1091
source "${TMPDIR}/androot.source"
source "${TMPDIR}/androot.env"
log_diag "mount is now executing, with arguments \"${*}\""
# to avoid repetition
function mountf() {
# $@ is used intentionally here, so ignore error
# shellcheck disable=SC2068
if ! log_execute mount ${@}; then
indicate_fail
exit 1
fi
}
# to avoid repetition
function umountf() {
# $@ is used intentionally here, so ignore error
# shellcheck disable=SC2068
if ! log_execute umount ${@}; then
indicate_fail
exit 1
fi
}
case "${1}" in
"--mount")
log_diag "Using mount mode"
mkdir -p "${LOCATION}/mountdir"
# remount /data on android to enable
# suid and exec flags
if [ "${IS_ANDROID}" == "true" ]; then
indicate_exec "Remounting /data"
mount_fail "/data (remount)" "/data" -o remount,suid,exec
indicate_ok
fi
indicate_exec "Mounting rootfs"
mountf --bind "${LOCATION}/rootfs" "${LOCATION}/mountdir" -o rw,suid,dev,exec,auto,nouser,async
indicate_ok
indicate_exec "Binding directories"
# mount /dev BEFORE /dev/pts
mountf --bind "/dev" "${LOCATION}/mountdir/dev"
mountf --bind "/dev/pts" "${LOCATION}/mountdir/dev/pts"
mountf --bind "/sys" "${LOCATION}/mountdir/sys"
mountf --bind "/proc" "${LOCATION}/mountdir/proc"
indicate_ok
;;
"--unmount")
log_diag "Using unmount mode"
indicate_exec "Unmounting binds"
# unmount /dev AFTER /dev/pts
umountf "${LOCATION}/mountdir/dev/pts"
umountf "${LOCATION}/mountdir/dev"
umountf "${LOCATION}/mountdir/sys"
umountf "${LOCATION}/mountdir/proc"
indicate_ok
indicate_exec "Unmounting rootfs"
umountf "${LOCATION}/mountdir"
indicate_ok
;;
*)
log_error "--mount or --unmount required"
exit 1
;;
esac

38
patch.sh Executable file
View file

@ -0,0 +1,38 @@
#!/bin/bash
# disable errors regarding androot.source as
# it is created and loaded at runtime
# shellcheck disable=SC1091
source "${TMPDIR}/androot.source"
source "${TMPDIR}/androot.env"
log_diag "patch is now executing, with arguments \"${*}\""
case "${ARCH_TARGET}" in
"x86_64") ;;
"arm64") ;;
"powerpc64") ;;
"mips64") ;;
*)
log_error "Internal inconsistency detected: Invalid target architecture \"${ARCH_TARGET}\""
exit 1
;;
esac
indicate_exec "Patching rootfs"
case "${DISTRIBUTION}" in
"archlinux")
if ! log_execute wget "${DOWNLOADSERVER}/patches/archlinux/fakeroot-tcp-${ARCH_TARGET}.pkg.tar.zst" --no-verbose -O "${LOCATION}/mountdir/fakeroot-tcp-${ARCH_TARGET}.pkg.tar.zst"; then
indicate_fail;
exit 1
fi
if ! chroot_env "${LOCATION}/mountdir" "pacman -U --noconfirm /fakeroot-tcp-${ARCH_TARGET}.pkg.tar.zst"; then
indicate_fail
exit 1
fi
;;
*)
indicate_fail
log_error "Internal inconsistency detected: Invalid distribution \"${DISTRIBUTION}\""
exit 1
;;
esac
indicate_ok

182
prepare.sh Executable file
View file

@ -0,0 +1,182 @@
#!/bin/bash
# disable errors regarding androot.source as
# it is created and loaded at runtime
# shellcheck disable=SC1091
source "${TMPDIR}/androot.source"
log_diag "prepare is now executing, with arguments \"${*}\""
# ask for target architecture
function arch_target() {
log_info ""
log_info "Please select your target architecture"
log_info "Note: The target architecture may be different from the current"
log_info " architecture as it will be emulated with qemu-static (with"
log_info " a slight performance penality)."
log_info "Available target architectures: x86_64, arm64"
log_ask "Target architecture: "
case "${ANSWER}" in
"x86_64") ;;
"arm64") ;;
*)
log_error "Invalid target architecture \"${ANSWER}\", please retry."
arch_target
return
;;
esac
echo "ARCH_TARGET=\"${ANSWER}\"" > "${TMPDIR}/androot.env"
}
# ask for execution architecture(s)
function arch_executors() {
log_info ""
log_info "Please specify the execution architecture(s)"
log_info "Note: A qemu-static binary is downloaded for each execution"
log_info " architecture. If you intend on running the rootfs on this"
log_info " machine only, leave this field empty. Multiple architectures"
log_info " can be specified, if you want."
log_info "Available execution architectures: x86_64, arm64, powerpc64, mips64"
log_ask "Execution architecture(s): "
if [ "${ANSWER}" == "" ]; then
echo "ARCH_EXECUTORS=${ARCH}" >> "${TMPDIR}/androot.env"
return
fi
for ARCHITECTURE in ${ANSWER}; do
case "${ARCHITECTURE}" in
"x86_64") ;;
"arm64") ;;
"powerpc64") ;;
"mips64") ;;
*)
log_error "Invalid execution architecture \"${ARCHITECTURE}\", please retry."
arch_executors
return
;;
esac
done
if [[ "${ANSWER}" == *"${ARCH_TARGET}"* ]]; then
export "ANSWER=x86_64 ${ANSWER}"
fi
echo "ARCH_EXECUTORS=\"${ANSWER}\"" >> "${TMPDIR}/androot.env"
}
# ask for target distribution
function distribution() {
log_info ""
log_info "Please select the target distribution"
log_info "Note: Each distribution you select here will be compatible"
log_info " with every target architecture, unless noted."
log_info "Available distributions: archlinux"
log_ask "Target distribution: "
case "${ANSWER}" in
"archlinux") ;;
*)
log_error "Invalid distribution \"${ANSWER}\", please retry."
distribution
return
;;
esac
echo "DISTRIBUTION=\"${ANSWER}\"" >> "${TMPDIR}/androot.env"
}
# ask for install location
function location() {
log_info ""
log_info "Please enter the install location"
log_info "Note: The installation location is not"
log_info " permanent and you can freely move"
log_info " the rootfs directory around as much"
log_info " as you want."
log_ask "Location: "
# check against invalid paths
case "${ANSWER}" in
"") # doing nothing is illegal
log_error "Please enter something >.<"
location
return
;;
/tmp*) # disallow /tmp as disk space issues might haunt us
log_error "Using /tmp is unsupported as you may run into disk space issues very quickly, please retry."
location
return
;;
/dev/shm/*) # disallow /dev/shm too, except if ALLOW_SHM is true
if [ ! "${ALLOW_SHM}" == "true" ]; then
log_error "Using /dev/shm is unsupported as you may run into disk space issues very quickly, please retry."
location
return
fi
;;
/dev|/proc|/run|/sys|/dev/*|/proc/*|/run/*|/sys/*) # disallow THESE directories
log_error "Are you really trying that?"
location
return
;;
/) # just do "rm -rf --no-preserve-root /" instead
log_error "you're making a recipe for desaster."
location
return
;;
"uwu"|"owo"|"~nya"|"~ nya"|"~ahh"|"~ ahh") # reference
log_error "eww!"
location
return
;;
"I'd like to interject for a moment") # reference
log_write "#### $(whoami) wants to interject for a moment"
log_error "I'd just like to interject for a moment. What you're referring to as Linux,"
log_error "is in fact, GNU/Linux, or as I've recently taken to calling it, GNU plus Linux."
log_error "Linux is not an operating system unto itself, but rather another free component"
log_error "of a fully functioning GNU system made useful by the GNU corelibs, shell"
log_error "utilities and vital system components comprising a full OS as defined by POSIX."
log_error "Many computer users run a modified version of the GNU system every day,"
log_error "without realizing it. Through a peculiar turn of events, the version of GNU"
log_error "which is widely used today is often called \"Linux\", and many of its users are"
log_error "not aware that it is basically the GNU system, developed by the GNU Project."
log_error "There really is a Linux, and these people are using it, but it is just a"
log_error "part of the system they use. Linux is the kernel: the program in the system"
log_error "that allocates the machine's resources to the other programs that you run."
log_error "The kernel is an essential part of an operating system, but useless by itself;"
log_error "it can only function in the context of a complete operating system. Linux is"
log_error "normally used in combination with the GNU operating system: the whole system"
log_error "is basically GNU with Linux added, or GNU/Linux. All the so-called \"Linux\""
log_error "distributions are really distributions of GNU/Linux."
location
return
;;
"UP UP DOWN DOWN LEFT RIGHT LEFT RIGHT B A START") # reference
log_error "This is a installer script, not a game."
location
return
;;
esac
# checks
if [ -a "${ANSWER}" ] && [ ! -d "${ANSWER}" ]; then
log_error "The location exists but is not a directory."
location
return
fi
if [ -d "${ANSWER}" ]; then
if [ -n "$(ls -A "${ANSWER}")" ]; then
log_error "The location directory is not empty."
location
return
fi
else
# create directory
indicate_exec "Creating location directory"
if ! mkdir -p "${ANSWER}/rootfs"; then
indicate_fail
exit 1
fi
indicate_ok
fi
echo "LOCATION=\"${ANSWER}\"" >> "${TMPDIR}/androot.env"
}
arch_target
arch_executors
distribution
location
log_write "#### rootfs configuration\n$(cat "${TMPDIR}/androot.env")\n#### rootfs configuration"

14
rootfsbuilder/.gitignore vendored Normal file
View file

@ -0,0 +1,14 @@
# directories
archlinux-x86_64
archlinux-arm64
# downloaded rootfs
archlinux-arm64-rootfs.tar.gz
# archived rootfs
archlinux-x86_64.tar
archlinux-arm64.tar
# compressed rootfs
archlinux-x86_64.tar.gz
archlinux-arm64.tar.gz

View file

@ -0,0 +1,57 @@
#!/bin/bash
set -euo pipefail
shopt -s inherit_errexit
if [ ! "${UID}" == "0" ]; then
echo ":: Error: root user required"
exit 1
fi
DISTRIBUTION=archlinux
ARCH=arm64
echo ":: Generating rootfs for ${DISTRIBUTION}-${ARCH}"
if [ -f "./${DISTRIBUTION}-${ARCH}.tar.gz" ]; then
echo ":: Removing ${DISTRIBUTION}-${ARCH}.tar.gz"
rm -rf "./${DISTRIBUTION}-${ARCH}.tar.gz"
fi
if [ -f "./${DISTRIBUTION}-${ARCH}.tar" ]; then
echo ":: Removing ${DISTRIBUTION}-${ARCH}.tar"
rm -rf "./${DISTRIBUTION}-${ARCH}.tar"
fi
if [ -d "./${DISTRIBUTION}-${ARCH}" ]; then
echo ":: Removing ${DISTRIBUTION}-${ARCH}"
rm -rf "./${DISTRIBUTION}-${ARCH}"
fi
if [ -f "./${DISTRIBUTION}-${ARCH}-rootfs.tar" ]; then
echo ":: Removing ${DISTRIBUTION}-${ARCH}-rootfs.tar"
rm -rf "./${DISTRIBUTION}-${ARCH}-rootfs.tar"
fi
mkdir -p "./${DISTRIBUTION}-${ARCH}"
cd "./${DISTRIBUTION}-${ARCH}"
echo ":: Downloading rootfs"
wget "http://os.archlinuxarm.org/os/ArchLinuxARM-aarch64-latest.tar.gz" -O "../${DISTRIBUTION}-${ARCH}-rootfs.tar.gz"
echo ":: Decompressing rootfs"
bsdtar -xpf "../${DISTRIBUTION}-${ARCH}-rootfs.tar.gz" -C "."
rm -rf "../${DISTRIBUTION}-${ARCH}-rootfs.tar.gz"
echo ":: Binding"
mount --bind /dev "./dev"
mount --bind /dev/pts "./dev/pts"
mount --bind /dev/shm "./dev/shm"
mount --bind /sys "./sys"
mount --bind /proc "./proc"
mount --bind /run "./run"
echo ":: Removing packages"
cp "$(which qemu-aarch64-static)" "./bin/qemu-aarch64-static"
echo -e "pacman -R --noconfirm dhcpcd linux-aarch64 nano net-tools netctl openssh vi which\npacman -R \$(pacman -Qdtq) --recursive --unneeded --noconfirm" > "./clean.sh"
chmod +x "./clean.sh"
chroot . /bin/qemu-aarch64-static /bin/bash -c /clean.sh
echo ":: Removing files"
rm -rf "./clean.sh" "./bin/qemu-aarch64-static" "./boot/*"
echo ":: Unmounting"
bash -c "umount ./{dev/pts,dev/shm,dev,sys,proc,run};exit 0"
echo ":: Archiving rootfs"
tar --acls -cpf "../${DISTRIBUTION}-${ARCH}.tar" ./*
cd ..
rm -rf "./${DISTRIBUTION}-${ARCH}"
echo ":: Compressing rootfs"
gzip --best ${DISTRIBUTION}-${ARCH}.tar
rm -rf "./${DISTRIBUTION}-${ARCH}.tar"
echo ":: Generated rootfs for ${DISTRIBUTION}-${ARCH}"

View file

@ -0,0 +1,36 @@
#!/bin/bash
set -euo pipefail
shopt -s inherit_errexit
if [ ! "${UID}" == "0" ]; then
echo ":: Error: root user required"
exit 1
fi
DISTRIBUTION=archlinux
ARCH=x86_64
echo ":: Generating rootfs for ${DISTRIBUTION}-${ARCH}"
if [ -f "./${DISTRIBUTION}-${ARCH}.tar.gz" ]; then
echo ":: Removing ${DISTRIBUTION}-${ARCH}.tar.gz"
rm -rf "./${DISTRIBUTION}-${ARCH}.tar.gz"
fi
if [ -f "./${DISTRIBUTION}-${ARCH}.tar" ]; then
echo ":: Removing ${DISTRIBUTION}-${ARCH}.tar"
rm -rf "./${DISTRIBUTION}-${ARCH}.tar"
fi
if [ -d "./${DISTRIBUTION}-${ARCH}" ]; then
echo ":: Removing ${DISTRIBUTION}-${ARCH}"
rm -rf "./${DISTRIBUTION}-${ARCH}"
fi
mkdir -p "./${DISTRIBUTION}-${ARCH}"
cd "./${DISTRIBUTION}-${ARCH}"
echo ":: Installing system"
pacstrap -c -G -K -M . base archlinux-keyring
echo ":: Unmounting (safety measure)"
bash -c "umount ./{dev/pts,dev/shm,dev,sys,proc,run};exit 0"
echo ":: Archiving rootfs"
tar --acls -cpf "../${DISTRIBUTION}-${ARCH}.tar" ./*
cd ..
rm -rf "./${DISTRIBUTION}-${ARCH}"
echo ":: Compressing rootfs"
gzip --best ${DISTRIBUTION}-${ARCH}.tar
rm -rf "./${DISTRIBUTION}-${ARCH}.tar"
echo ":: Generated rootfs for ${DISTRIBUTION}-${ARCH}"

89
rootfsinstall.sh Executable file
View file

@ -0,0 +1,89 @@
#!/bin/bash
# disable errors regarding androot.source as
# it is created and loaded at runtime
# shellcheck disable=SC1091
source "${TMPDIR}/androot.source"
source "${TMPDIR}/androot.env"
log_diag "rootfsinstall is now executing, with arguments \"${*}\""
case "${1}" in
"--download")
log_diag "Using download mode"
# check if rootfs has been downloaded already
if [ -f "${TMPDIR}/rootfs.tar.gz" ] && [ -f "${TMPDIR}/rootfs.env" ]; then
# load rootfs info
source "${TMPDIR}/rootfs.env"
# check if downloaded rootfs and rootfs configuration match
if [ "${ARCH_TARGET_WRITTEN}" == "${ARCH_TARGET}" ] && [ "${DISTRIBUTION_WRITTEN}" == "${DISTRIBUTION}" ]; then
# ask if downloaded rootfs should be reused
log_write "#### found existing rootfs archive"
log_askyn "true" "androot found a existing rootfs archive matching your configuration, do you want to use it? "
if [ "${ANSWER}" == "true" ]; then
# yes, skip download
log_write "#### skipping download"
exit 0
else
# no, remove rootfs and continue
log_write "#### removing existing rootfs archive"
rm -rf "${TMPDIR}/rootfs.tar.gz"
fi
else
# downloaded rootfs and rootfs configuration
# do not matchremove and continue
log_write "#### removing existing rootfs archive"
log_diag "Removing existing rootfs archive (not matching)"
rm -rf "${TMPDIR}/rootfs.tar.gz"
fi
fi
indicate_exec "Downloading rootfs"
# check for internal inconsistencies or
# external modifications to androot.env
case "${ARCH_TARGET}" in
"x86_64") ;;
"arm64") ;;
*)
log_write "#### invalid architecture \"${ARCH_TARGET}\""
indicate_fail
log_error "Internal inconsistency detected: Invalid target architecture \"${ARCH_TARGET}\""
exit 1
;;
esac
case "${DISTRIBUTION}" in
"archlinux") ;;
*)
log_write "#### invalid distribution \"${DISTRIBUTION}\""
indicate_fail
log_error "Internal inconsistency detected: Invalid distribution \"${DISTRIBUTION}\""
exit 1
;;
esac
# download rootfs from download server
if ! log_execute wget "${DOWNLOADSERVER}/rootfs/${DISTRIBUTION}-${ARCH_TARGET}.tar.gz" --no-verbose -O "${TMPDIR}/rootfs.tar.gz"; then
indicate_fail
exit 1
fi
if [ ! -f "${TMPDIR}/rootfs.tar.gz" ]; then
# rootfs is missing (somehow)
log_write "#### rootfs not present"
indicate_fail
fi
# write rootfs configuration into file if the same rootfs config is used again
echo -e "ARCH_TARGET_WRITTEN=${ARCH_TARGET}\nDISTRIBUTION_WRITTEN=${DISTRIBUTION}" > "${TMPDIR}/rootfs.env"
indicate_ok
;;
"--decompress")
log_diag "Using decompress mode"
indicate_exec "Decompressing archive"
log_write "#### decompress rootfs"
if ! log_execute bsdtar -xpf "${TMPDIR}/rootfs.tar.gz" -C "${LOCATION}/rootfs"; then
indicate_fail
exit 1
fi
indicate_ok
;;
*)
log_error "--download or --decompress required"
exit 1
;;
esac

45
systeminstall.sh Executable file
View file

@ -0,0 +1,45 @@
#!/bin/bash
# disable errors regarding androot.source as
# it is created and loaded at runtime
# shellcheck disable=SC1091
source "${TMPDIR}/androot.source"
source "${TMPDIR}/androot.env"
log_diag "systeminstall is now executing, with arguments \"${*}\""
case "${1}" in
"--configure")
log_diag "Using configure mode"
indicate_exec "Configuring rootfs"
if ! log_execute rm -rf "${LOCATION}/rootfs/etc/resolv.conf"; then indicate_fail; exit 1; fi
echo "nameserver 1.1.1.1" > "${LOCATION}/rootfs/etc/resolv.conf"
if [ "${DISTRIBUTION}" == "archlinux" ]; then
if ! chroot_env "${LOCATION}/mountdir" "pacman-key --init"; then
indicate_fail
exit 1
fi
if ! chroot_env "${LOCATION}/mountdir" "pacman-key --populate"; then
indicate_fail
exit 1
fi
OUTPUT=$(sed "s/\#Server \= https\:\/\/geo\.mirror\.pkgbuild\.com\/\\\$repo\/os\/\\\$arch/Server \= https\:\/\/geo\.mirror\.pkgbuild\.com\/\\\$repo\/os\/\\\$arch/g" < "${LOCATION}/rootfs/etc/pacman.d/mirrorlist")
echo "${OUTPUT}" &> "${LOCATION}/rootfs/etc/pacman.d/mirrorlist"
fi
indicate_ok
;;
"--update")
log_diag "Using update mode"
indicate_exec "Updating rootfs"
if [ "${DISTRIBUTION}" == "archlinux" ]; then
if ! chroot_env "${LOCATION}/mountdir" "pacman -Syu --noconfirm"; then
indicate_fail
exit 1
fi
fi
indicate_ok
;;
*)
log_error "--configure or --update required"
exit 1
;;
esac