cat > /tmp/installer.sh << 'SCRIPT_EOF'
#!/bin/sh
# --- COLOR SETTINGS ---
C_RESET='\033[0m'
C_GREEN='\033[1;32m'
C_RED='\033[1;31m'
C_YELLOW='\033[1;33m'
C_CYAN='\033[1;36m'
echo -e "${C_CYAN}==================================================${C_RESET}"
echo -e "${C_CYAN} ASUSWRT CUSTOM SCRIPT INSTALLER v6.5 ${C_RESET}"
echo -e "${C_CYAN}==================================================${C_RESET}"
# --- 1. DETECTION ---
echo -e "${C_YELLOW}[*] Hunting for a USB drive...${C_RESET}"
USB_PATH=""
# Loop through all directories in the mount root
for path in /tmp/mnt/*; do
# 1. Skip if it's the 'defaults' system folder
[ "$path" = "/tmp/mnt/defaults" ] && continue
# 2. Check if it's a directory and actually listed in the mount table
if [ -d "$path" ] && grep -q "$path" /proc/mounts; then
# 3. Final check: is it writable?
if [ -w "$path" ]; then
# 4. ROBUST CHECK: Ensure at least 5MB free space
FREE_KB=$(df -k "$path" | awk 'NR==2 {print $4}')
if [ "$FREE_KB" -gt 5000 ]; then
USB_PATH="$path"
echo -e "${C_GREEN}[OK] Target found: $USB_PATH (${FREE_KB}KB free)${C_RESET}"
break
else
echo -e "${C_RED}[SKIP] $path is writable but full.${C_RESET}"
fi
fi
fi
done
if [ -z "$USB_PATH" ]; then
echo -e "${C_RED}[ERROR] No suitable writable USB drive found.${C_RESET}"
exit 1
fi
# Define pathing variables properly
ARCH_FOLDER="asusware.arm"
TARGET_DIR="$USB_PATH/$ARCH_FOLDER"
# --- 2. CLEANUP (Using v6.6 Robust Logic) ---
echo -e "${C_YELLOW}[*] Cleaning up old processes...${C_RESET}"
for name in "S99ntp-masq" "S98ont-access" "S50usb-mount-script"; do
# BusyBox compatible PID discovery
PID=$(ps | grep "$name" | grep -v grep | awk '{print $1}')
[ -n "$PID" ] && kill $PID 2>/dev/null
done
rm -rf "/tmp/ntp-masq.lock" "/tmp/ont-access.lock"
[ -d "$TARGET_DIR" ] && rm -rf "$TARGET_DIR"
echo -e "${C_GREEN}[OK] Cleanup finished.${C_RESET}"
# --- 3. CREATE STRUCTURE ---
echo -e "${C_YELLOW}[*] Creating file structure...${C_RESET}"
mkdir -p "$TARGET_DIR/etc/init.d"
mkdir -p "$TARGET_DIR/lib/ipkg/info"
mkdir -p "$TARGET_DIR/lib/ipkg/lists"
# --- 4. CREATE BOOT TRIGGER ---
cat << 'EOF' > "$TARGET_DIR/.asusrouter"
#!/bin/sh
BASE_DIR=$(dirname "$0")
if [ -z "$(ls -A /opt 2>/dev/null)" ]; then
mount -o bind "$BASE_DIR" /opt
fi
export PATH=$PATH:/opt/bin:/opt/sbin
if [ -x "/opt/etc/init.d/S50usb-mount-script" ]; then
/opt/etc/init.d/S50usb-mount-script start
fi
EOF
chmod +x "$TARGET_DIR/.asusrouter"
# --- 5. CREATE DUMMY PACKAGE DATA ---
echo "dest /opt/ /" > "$TARGET_DIR/etc/ipkg.conf"
cat << EOF > "$TARGET_DIR/lib/ipkg/info/usb-mount-script.control"
Package: usb-mount-script
Architecture: arm
Version: 1.0.0.0
Enabled: yes
EOF
# --- 6. CREATE PAYLOADS ---
# 6A. ONT ACCESS SCRIPT
cat << 'EOF' > "$TARGET_DIR/etc/init.d/S98ont-access"
#!/bin/sh
LOCKDIR="/tmp/ont-access.lock"
TAG="ONT_ACCESS"
if ! mkdir "$LOCKDIR" 2>/dev/null; then exit 0; fi
(
sleep 20
while true; do
WAN_IF=$(nvram get wan0_ifname 2>/dev/null)
[ -z "$WAN_IF" ] && WAN_IF="eth0"
if ifconfig "$WAN_IF" | grep -q "UP"; then
if ! ifconfig | grep -q "${WAN_IF}:0"; then
ifconfig "${WAN_IF}:0" 192.168.100.2 netmask 255.255.255.0 up
logger -t "$TAG" "Restored ONT/ONU Access"
fi
fi
sleep 90
done
) &
EOF
# 6B. NTP MASQUERADE SCRIPT
cat << 'EOF' > "$TARGET_DIR/etc/init.d/S99ntp-masq"
#!/bin/sh
LOCKDIR="/tmp/ntp-masq.lock"
TAG="NTP_MASQ"
if ! mkdir "$LOCKDIR" 2>/dev/null; then exit 0; fi
(
sleep 25
while true; do
WAN_IF=$(nvram get wan0_ifname 2>/dev/null)
[ -z "$WAN_IF" ] && WAN_IF="eth0"
if ifconfig "$WAN_IF" | grep -q "UP"; then
if iptables -t nat -L POSTROUTING 2>/dev/null >/dev/null; then
if ! iptables -t nat -C POSTROUTING -p udp -m udp --sport 123 -j MASQUERADE --to-ports 60000-61000 2>/dev/null; then
iptables -t nat -I POSTROUTING -p udp -m udp --sport 123 -j MASQUERADE --to-ports 60000-61000
logger -t "$TAG" "Restored Firewall Rule."
fi
fi
fi
sleep 60
done
) &
EOF
chmod +x "$TARGET_DIR/etc/init.d/S98ont-access"
chmod +x "$TARGET_DIR/etc/init.d/S99ntp-masq"
# --- 7. CREATE LAUNCHER ---
cat << 'EOF' > "$TARGET_DIR/etc/init.d/S50usb-mount-script"
#!/bin/sh
TAG="USB-MOUNT"
find_and_run() {
local attempts=0
local INIT_DIR="/opt/etc/init.d"
while [ $attempts -lt 30 ]; do
if [ -d "$INIT_DIR" ]; then
logger -t "$TAG" "Launching payloads..."
for script in "$INIT_DIR"/S[0-9][0-9]*; do
[ -e "$script" ] || continue
if [ "$(basename "$script")" != "S50usb-mount-script" ]; then
sh "$script" &
fi
done
return 0
fi
sleep 2
attempts=$((attempts + 1))
done
}
case "$1" in
start|"") find_and_run & ;;
esac
EOF
chmod +x "$TARGET_DIR/etc/init.d/S50usb-mount-script"
# --- 8. STARTUP ---
echo -e "${C_YELLOW}[*] Preparing /opt mount point...${C_RESET}"
# 8A. Safety Check: Is /opt already mounted?
if mount | grep -q "on /opt"; then
echo -e "${C_YELLOW}[!] /opt is already mounted. Attempting to unmount...${C_RESET}"
umount -l /opt 2>/dev/null
fi
# 8B. Symlink Handling
if [ ! -L "/opt" ] && [ ! -d "/opt" ]; then
# Only try to create if it's completely missing
mkdir -p /opt 2>/dev/null
fi
# If mkdir failed (read-only FS), /opt is likely a hardcoded symlink to /tmp/opt
if [ ! -d "/opt" ]; then
mkdir -p /tmp/opt
fi
# 8C. Final Mount
if mount -o bind "$TARGET_DIR" /opt; then
echo -e "${C_GREEN}[OK] Successfully mounted $TARGET_DIR to /opt${C_RESET}"
sleep 1
if [ -f "/opt/etc/init.d/S50usb-mount-script" ]; then
sh /opt/etc/init.d/S50usb-mount-script start
else
echo -e "${C_RED}[ERROR] Script not found in /opt/etc/init.d/!${C_RESET}"
fi
else
echo -e "${C_RED}[ERROR] Failed to mount /opt. The filesystem is likely locked.${C_RESET}"
exit 1
fi
echo -e "${C_CYAN}=================================================${C_RESET}"
echo -e "${C_GREEN} INSTALLATION COMPLETE ${C_RESET}"
echo -e "${C_CYAN}=================================================${C_RESET}"
SCRIPT_EOF
chmod +x /tmp/installer.sh
sh /tmp/installer.sh