diff --git a/package/entware-rc/package b/package/entware-rc/package index 40b8432f4..4713c788c 100644 --- a/package/entware-rc/package +++ b/package/entware-rc/package @@ -6,12 +6,12 @@ archs=(rmall) pkgnames=(entware-rc) pkgdesc="Manage entware installed services" url=https://toltec-dev.org/ -pkgver=0.1-1 +pkgver=0.1.1-1 timestamp=2024-05-22T22:59:03Z section="utils" maintainer="Eeems " license=MIT -installdepends=() +installdepends=('findutils') source=( entware-rc@.service diff --git a/package/entware-rc/rcctl b/package/entware-rc/rcctl index 899ae7862..cae5b089c 100755 --- a/package/entware-rc/rcctl +++ b/package/entware-rc/rcctl @@ -55,7 +55,7 @@ elif [[ $1 == "logs" ]]; then journalctl --no-pager -all --unit "entware-rc@${2}.service" fi elif [[ $1 == "list" ]]; then - /opt/bin/find /opt/etc/init.d/ -perm '-u+x' -name 'S*' | xargs -rn1 basename + /opt/libexec/find-gnu /opt/etc/init.d/ -perm '-u+x' -name 'S*' | xargs -rn1 basename else help exit 1 diff --git a/package/launcherctl/launcherctl b/package/launcherctl/launcherctl index ff87e6a0f..4a1850f47 100755 --- a/package/launcherctl/launcherctl +++ b/package/launcherctl/launcherctl @@ -22,7 +22,7 @@ help() { } data_dir="/opt/share/launcherctl" launchers() { - /opt/bin/find "$data_dir" -type f -perm '-u+x' | xargs -rn1 basename + /opt/libexec/find-gnu "$data_dir" -type f -perm '-u+x' | xargs -rn1 basename } active_launchers() { launchers | while read -r launcher; do diff --git a/package/launcherctl/package b/package/launcherctl/package index 3b217bf3e..b43bf2456 100644 --- a/package/launcherctl/package +++ b/package/launcherctl/package @@ -5,11 +5,12 @@ pkgnames=(launcherctl) pkgdesc="Manage your installed launcher" url=https://toltec-dev.org/ -pkgver=0.0.1-3 +pkgver=0.0.2-1 timestamp=2023-12-18T03:32Z section="launchers" maintainer="Eeems " license=MIT +installdepends=('findutils' 'xochitl') source=( launcherctl diff --git a/package/toltec-bootstrap/toltecctl b/package/toltec-bootstrap/toltecctl index 5a26d3790..f1b2e64b9 100644 --- a/package/toltec-bootstrap/toltecctl +++ b/package/toltec-bootstrap/toltecctl @@ -4,6 +4,9 @@ set -euo pipefail +# Path to this script +toltecctl_path=$(realpath "$0") + # Path where Toltec resides (will be mounted to $toltec_dest) toltec_src=/home/root/.entware @@ -15,7 +18,7 @@ toltec_share=/home/root/.local/share/toltec # Path to static opkg build opkg_path=/home/root/.local/bin/opkg # Path to opkg install status file -opkg_status="/opt/lib/opkg/status" +opkg_status="$toltec_dest/lib/opkg/status" # Path to Opkg configuration opkg_conf="$toltec_src"/etc/opkg.conf @@ -123,7 +126,7 @@ get-release-version() { # 3 - unable to install standalone wget check-version() { local wget - if [[ "$(install-state)" != "yes" ]] || [[ "$(command -v wget)" != "/opt/bin/wget" ]]; then + if [[ "$(install-state)" != "yes" ]] || [[ "$(command -v wget)" != "$toltec_dest/bin/wget" ]]; then if ! install-standalone-wget; then return 2 fi @@ -197,9 +200,9 @@ add-bind-mount() { unit_name="$(basename "$unit_path")" if [[ -e $unit_path ]]; then - echo "Bind mount configuration for '$2' already exists, updating" + log INFO "Bind mount configuration for '$2' already exists, updating" else - echo "Mounting '$1' over '$2'" + log INFO "Mounting '$1' over '$2'" fi cat > "$unit_path" << UNIT @@ -234,14 +237,16 @@ remove-bind-mount() { unit_name="$(basename "$unit_path")" if [[ ! -e $unit_path ]]; then - echo "No existing bind mount for '$1'" + log INFO "No existing bind mount for '$1'" return fi - echo "Removing mount over '$1'" + log INFO "Removing mount over '$1'" systemctl disable "$unit_name" - systemctl stop "$unit_name" + # Don't error, as umount -l will handle the failure + systemctl stop "$unit_name" || true if mountpoint -q "$1"; then + log WARN "Failed to unmount '$1', lazy unmount instead" umount -l "$1" fi rm "$unit_path" @@ -460,7 +465,7 @@ reinstall-root() { if [[ -v "on_root_packages[$pkgname]" ]]; then reinstall_packages[$pkgname]=1 fi - done < <(gunzip -c /opt/var/opkg-lists/* | grep "^Package:" | awk '{print $2}') + done < <(gunzip -c "$toltec_dest"/var/opkg-lists/* | grep "^Package:" | awk '{print $2}') # Workaround: Checking the size of an empty array when the nounset option # is active may throw an error on some Bash versions, so we disable it @@ -480,6 +485,7 @@ clean-path() { sed -i "/^$bashrc_start_marker\$/,/^$bashrc_end_marker\$/d" "$bashrc_path" sed -i "/^$bashrc_old_start_marker\$/!b;n;d" "$bashrc_path" sed -i "/^$bashrc_old_start_marker\$/d" "$bashrc_path" + # TODO - rewrite this to use $toltec_dest instead of /opt sed -i '/^\(export \)\?PATH="\?\.*\/opt\/bin:\/opt\/sbin.*"\?$/d' "$bashrc_path" fi } @@ -492,7 +498,7 @@ set-path() { clean-path cat >> "$bashrc_path" << SHELL $bashrc_start_marker -PATH="/opt/bin:/opt/sbin:/home/root/.local/bin:\$PATH" +PATH="$toltec_dest/bin:$toltec_dest/sbin:/home/root/.local/bin:\$PATH" $bashrc_end_marker SHELL @@ -541,9 +547,9 @@ generate-opkg-conf() { # then run \`toltecctl generate-opkg-conf\` to regenerate this file dest root / -dest ram /opt/tmp -lists_dir ext /opt/var/opkg-lists -option tmp_dir /opt/tmp +dest ram $toltec_dest/tmp +lists_dir ext $toltec_dest/var/opkg-lists +option tmp_dir $toltec_dest/tmp CONF @@ -672,10 +678,10 @@ CONF # Re-enable Toltec install after system update reenable() { - log INFO "Mounting /opt" + log INFO "Mounting $toltec_dest" add-bind-mount "$toltec_src" "$toltec_dest" switch-branch "$(get-branch)" - log INFO "Generating /opt/etc/opkg.conf" + log INFO "Generating $toltec_dest/etc/opkg.conf" generate-opkg-conf || true log INFO "Opkg update" opkg update @@ -683,12 +689,12 @@ reenable() { reinstall-base log INFO "Reinstalling packages with files on the root partition" reinstall-root - if [ -d /opt/share/toltec/reenable.d ]; then - find /opt/share/toltec/reenable.d -maxdepth 1 -mindepth 1 -print0 \ + if [ -d "$toltec_dest"/share/toltec/reenable.d ]; then + find "$toltec_dest"/share/toltec/reenable.d -maxdepth 1 -mindepth 1 -print0 \ | xargs -0rn1 basename \ | while read -r pkg; do local script - script="/opt/lib/opkg/info/${pkg}.postinst" + script="$toltec_dest/lib/opkg/info/${pkg}.postinst" if [ -f "$script" ]; then log INFO "Reconfiguring ${pkg}" "$script" configure || true @@ -720,7 +726,7 @@ list-installed-ordered() { # Install standalone opkg binary install-standalone-opkg() { local wget - if [[ "$(install-state)" != "yes" ]] || [[ "$(command -v wget)" != "/opt/bin/wget" ]]; then + if [[ "$(install-state)" != "yes" ]] || [[ "$(command -v wget)" != "$toltec_dest/bin/wget" ]]; then if ! install-standalone-wget; then return 2 fi @@ -775,31 +781,122 @@ install-standalone-wget() { # Remove Toltec completely uninstall() { + if ! [ -d "$toltec_src" ] && ! [ -d "$toltec_dest" ]; then + log INFO "Toltec does not appear to be installed" + exit 0 + fi + # Fetch standalone opkg used to uninstall packages if ! install-standalone-opkg; then return 1 fi + local clean=true # did package uninstall complete without issue? + local success=true # did uninstall complete without issue? + local complete=false # did we actually complete the uninstall, or exit early? + + broken-state() { + echo " Your system may be in a broken state. Please review the logs" + echo " before rebooting your device. If you need assistance, you can" + echo " get help on the community discord channel." + } + + handle-error() { + local error_code=$? + log ERROR "line $1: $BASH_COMMAND" + log ERROR "Uninstall did not complete properly" + broken-state + exit $error_code + } + set -o functrace + trap 'handle-error ${LINENO}' ERR + handle-exit() { + if ! $complete && $success && $clean; then + log ERROR "Uninstall did not complete properly" + broken-state + exit 1 + fi + } + trap 'handle-exit' EXIT + + if [[ "$toltecctl_path" != *_backup ]]; then + log INFO "Creating backup of toltecctl at ${toltecctl_path}_backup" + rm -f "${toltecctl_path}_backup" + cp "$toltecctl_path" "${toltecctl_path}_backup" + fi + + if ! [ -f "$toltec_dest"/etc/opkg.conf ]; then + if [ -f "$toltec_src"/etc/opkg.conf ] && ! mountpoint -q "$toltec_dest"; then + log INFO "Mounting $toltec_dest" + add-bind-mount "$toltec_src" "$toltec_dest" + fi + log ERROR "Current install seems to be partially removed, unable to automatically removed." + broken-state + complete=true + exit 1 + fi # Remove installed packages in reverse dependency order - list-installed-ordered | while read -r pkgname; do - "$opkg_path" remove --force-removal-of-essential-packages --force-depends --force-remove "$pkgname" - done + while read -r pkgname; do + if ! "$opkg_path" remove --force-depends "$pkgname"; then + echo "Failed to remove $pkgname, forcing removal..." + "$opkg_path" remove --force-removal-of-essential-packages --force-depends --force-remove "$pkgname" + clean=false + fi + done << EOF +$(list-installed-ordered) +EOF - systemctl daemon-reload + if ! systemctl daemon-reload; then + log WARN "Failed to reload systemd state" + fi rm -f "$opkg_path" - # Remove mount point + set +e # Don't exit on error, next check will validate if it worked remove-bind-mount "$toltec_dest" - rmdir "$toltec_dest" + set -e + + case "$(install-state)" in + no) ;; + *) + log ERROR "$toltec_dest bind mount still is active" + success=false + ;; + esac + + if ! rmdir "$toltec_dest"; then + log ERROR "Failed to remove mount point" + success=false + fi # Unset PATH clean-path # Remove Toltec data - rm -r "$toltec_src" + if ! rm -r "$toltec_src"; then + log ERROR "Failed to remove toltec data directory" + success=false + fi # Re-enable xochitl if needed - systemctl enable xochitl + if ! systemctl enable xochitl; then + log ERROR "Failed to enable the user interface." + success=false + fi + if ! $clean; then + log ERROR "There were errors removing some of the toltec packages." + success=false + fi + if ! $success; then + log ERROR "Uninstall failed" + broken-state + complete=true + exit 1 + fi + if [[ "$toltecctl_path" != *_backup ]]; then + rm -f "$toltecctl_path" + fi + rm -f "${toltecctl_path}_backup" + complete=true } # The current toltec install state