#!/system/bin/sh # magisk-fstab - Systemless fstab tool for magisk # Copyright (C) 2025 Leonard Kugis # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # Do NOT assume where your module will be located. # ALWAYS use $MODDIR if you need to know where this script and module is placed. # This will make sure your module will still work if Magisk changes its mount point in the future MODDIR=${0%/*} export LOG_FILE="${MODDIR}/magisk-fstab.log" LOG_MAX_LINES=1000 BOOTWAIT_MAX_COUNT=20 BOOTWAIT_COUNT_INTERVAL=15 CONF_MAIN="${MODDIR}/config/main.conf" CONF_FSTAB="${MODDIR}/config/fstab.conf" # --- single-run lock (prevents concurrent starts) --------------------------- LOCKDIR="${MODDIR}/.runlock" PIDFILE="${LOCKDIR}/pid" acquire_lock() { # Versuche Lock-Verzeichnis atomar anzulegen if mkdir "${LOCKDIR}" 2>/dev/null; then # Lock bekommen echo "$$" > "${PIDFILE}" # Bei Exit Lock säubern trap 'rc=$?; rm -f "${PIDFILE}"; rmdir "${LOCKDIR}" 2>/dev/null; exit $rc' INT TERM EXIT return 0 fi # Lock existiert -> prüfen, ob stale if [ -f "${PIDFILE}" ]; then oldpid="$(cat "${PIDFILE}" 2>/dev/null)" if [ -n "${oldpid}" ] && [ -d "/proc/${oldpid}" ]; then # Anderer Prozess läuft noch -> sauber beenden echo "Another instance already running (pid ${oldpid}). Exiting." >>"${LOG_FILE}" 2>&1 return 1 fi fi # Stale Lock entfernen und erneut versuchen echo "Stale lock detected, cleaning up..." >>"${LOG_FILE}" 2>&1 rm -f "${PIDFILE}" 2>/dev/null rmdir "${LOCKDIR}" 2>/dev/null if mkdir "${LOCKDIR}" 2>/dev/null; then echo "$$" > "${PIDFILE}" trap 'rc=$?; rm -f "${PIDFILE}"; rmdir "${LOCKDIR}" 2>/dev/null; exit $rc' INT TERM EXIT return 0 else echo "Failed to acquire lock after cleanup. Exiting." >>"${LOG_FILE}" 2>&1 return 1 fi } # Lock holen; wenn nicht möglich, still beenden acquire_lock || exit 0 # --------------------------------------------------------------------------- # Check if configs are readable if [ ! -r "$CONF_MAIN" ]; then echo "File '$CONF_MAIN' not readable." >>"${LOG_FILE}" 2>&1 exit 2 fi if [ ! -r "$CONF_FSTAB" ]; then echo "File '$CONF_FSTAB' not readable." >>"${LOG_FILE}" 2>&1 exit 2 fi # Read main config . "${CONF_MAIN}" >>"${LOG_FILE}" 2>&1 # wait for system boot to complete bootwait_count=0 while [ "$(getprop sys.boot_completed)" != "1" ] && [ ${bootwait_count} -lt ${BOOTWAIT_MAX_COUNT} ]; do sleep ${BOOTWAIT_COUNT_INTERVAL} bootwait_count=$((bootwait_count + 1)) done if [ ${bootwait_count} -ge ${BOOTWAIT_MAX_COUNT} ]; then echo "Boot wait timeout" >>"${LOG_FILE}" 2>&1 exit 1 fi # prevent log file from growing too large tail -n "${LOG_MAX_LINES}" "${LOG_FILE}" >"${LOG_FILE}.tmp" 2>/dev/null mv "${LOG_FILE}.tmp" "${LOG_FILE}" 2>/dev/null echo "=== $(date) ===" >>"${LOG_FILE}" 2>&1 if [ -f "${CONF_FSTAB}" ]; then /system/bin/sh "${MODDIR}/fstab.sh" --su-options "${su_options}" --log-file "${LOG_FILE}" "${CONF_FSTAB}" & else echo "${CONF_FSTAB} not found." >>"${LOG_FILE}" 2>&1 fi wait # Lock wird durch trap am Ende automatisch freigegeben