#!/bin/sh set -e # exit on failure IFS=$(printf '\n\t') # smarter ifs apprun() { export PATH="$APPDIR"/bin:"$PATH" export LD_LIBRARY_PATH="$APPDIR"/lib64:"$APPDIR"/lib:"$LD_LIBRARY_PATH" exec "$APPDIR/$(basename "$ARGV0")" "$@" } # shellcheck disable=SC2086,SC2155 header() { APPDIR="/tmp/dwarf_$(basename "$0")$(echo "$0"|md5sum|head -c5)" export APPDIR APPIMAGE="$(realpath "$0")" ARGV0="$0" OWD="$PWD" args="-o offset=auto -o tidy_strategy=swap -o workers=4" [ ! -d "$APPDIR" ] && mkdir "$APPDIR" && dwarfs $args "$0" "$APPDIR" 2>/dev/null "$APPDIR/AppRun" "$@" res=$? fusermount -quz "$APPDIR" rmdir "$APPDIR" 2>/dev/null exit $res } printfunc() { echo '#!/bin/sh' type "$1" | sed 's/^ *//' | tail -n+4 | head -n-1 } unappimage() { a=$(readelf -h "$1" | sed '13!d;s/[^0-9]//g') b=$(readelf -h "$1" | sed '18!d;s/[^0-9]//g') c=$(readelf -h "$1" | sed '19!d;s/[^0-9]//g') o=$(echo "$a" + "$b" \* "$c" | bc) unsquashfs -o "$o" "$1" } zzexe() { [ "$1" = "-p" ] && p="$2" && shift 2 # save prefix if present zstdmt -cq19 "$@" | ifne sponge "$1" printfunc zzexe_header | cat - "$1" | ifne sponge "$1" sed -i -e "1s/);$/${1##*[./]})/" -e "6s/^/$p /" "$1" exit } zzexe_header() { dir=$(dirname "$0") out=$(mktemp -t .zzXXXX.) awk 'f;/^exit \$res$/{f=1}' "$0" | head -c-1 | zstd -cd > "$out" chmod +x "$out" ln -s "$out" "$dir" trap : 0 1 2 3 6 14 15 "$dir/$(basename "$out")" "$@" res=$? rm "$out" "$dir/$(basename "$out")" exit $res } case "$1" in -a ) printfunc apprun > "$2" chmod +x "$2" exit ;; -b ) printfunc apprun | sed '4s#/#/bin/#' > "$2" chmod +x "$2" exit ;; -d ) awk 'f;/^exit \$res$/{f=1}' "$2" | head -c-1 | zstd -cd | ifne sponge "$2" d=dwarfs-root; dwarfsck -d0 -i"$2" && mkdir $d && dwarfsextract -o $d -i "$2" exit ;; -p ) zzexe "$@" ;; -z) shift zzexe "$@" ;; --version | -v ) tput setaf 2; echo appdwarf 2022.07.19 tput setaf 6; echo Built by July 🏳️‍🌈; exit ;; -* | '' ) echo "Usage: appdwarf [option] [APP/FILE/FOLDER/URL] [compression options]" echo " -a [file] Write example AppRun to file and exit" echo " -b [file] Write example AppRun with bin subdir to file and exit" echo " -d [file] Decompress an appdwarf image or zzexe'd file" echo echo " -p [prefix] zzexe a file with prefix" echo " -z zzexe a file" echo echo " -h, --help Print this help text" echo " -v, --version Print the appdwarf version"; exit ;; esac if [ ! -d "$1" ]; then # directory doesn't exist, see if this is an appimage if [ ! -f "$1" ]; then # file doesn't exist, see if this is a url if ! echo "$1" | grep / ; then # AppImageHub echo "Checking AppImageHub for this program..." app=https://github.com/AppImage/appimage.github.io/raw/master/apps/$1.md shift set -- "$(curl -L "$app" | grep -o https.\*releases | sed 's|/releases$||')" "$@" elif ! echo "$1" | grep https ; then # GitHub in Author/Repo format app=$1 shift set -- "https://github.com/$app" "$@" fi if echo "$1" | grep 'https://github.com/[^/]*/[^/]*/*$'; then # GitHub url echo "Assuming this is a GitHub repo..." app="$(echo "${1%/}"/releases | sed 's|github.com|api.github.com/repos|')" shift set -- "$(curl "$app" | grep -v arm | grep -om1 https.\*AppImage)" "$@" fi app=$(basename "$1") # actually try to get the appimage if aria2c -x16 -s16 "$1" -o "$app" || wget "$1" -O "$app"; then shift set -- "$app" "$@" else tput setaf 1; echo "No valid remote or local input found. Exiting..." >&2 rm -f "$app"; exit 1 fi fi rm -rf squashfs-root # this is a file, but it might be an existing dwarfs image if dwarfsck -d0 -i"$1"; then echo "Existing dwarfs image found. Adding header..." set -- "$@" --recompress=none elif unappimage "$1"; then echo "AppImage found. Converting..." app="$(basename "$1" .AppImage)" rm -rf "$1" "$app" shift set -- "$app" "$@" mv squashfs-root "$1" else tput setaf 4; echo "$1 is not an AppImage, it will be zzexe'd" zzexe "$@" fi fi head="$(mktemp)" printfunc header > "$head" mkdwarfs -o "$(realpath "$1").sh" -B5 --header "$head" -i "$@" rm "$head" chmod +x "$(realpath "$1").sh"