diff --git a/package/diy/maple-restore/Makefile b/package/diy/maple-restore/Makefile new file mode 100644 index 0000000000..040a9d719e --- /dev/null +++ b/package/diy/maple-restore/Makefile @@ -0,0 +1,48 @@ +# +# Copyright (C) 2026 xiexiaobao +# +# This is free software, licensed under the GPL 2.0 license. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=maple-restore +PKG_VERSION:=1.0 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=xiexiaobao +PKG_LICENSE:=GPL-2.0 + +include $(INCLUDE_DIR)/package.mk + +define Package/maple-restore + SECTION:=utils + CATEGORY:=Utilities + TITLE:=Auto-restore configs from p4 after MapleOS sysupgrade + PKGARCH:=all + DEPENDS:= +endef + +define Package/maple-restore/description + UCI defaults script that auto-restores backed-up configs from + /mnt/mmc2-4/.maple-backup/ on first boot after a maple-upgrade. + + Restores: shadow, frpc, openclash, firewall, network, dhcp, fstab, + dropbear, luci, system, uhttpd, transmission, aria2, tinyproxy, + tailscale, dockerd, crontab, and more. + + Runs exactly once via uci-defaults, then self-deletes. +endef + +define Build/Configure +endef + +define Build/Compile +endef + +define Package/maple-restore/install + $(INSTALL_DIR) $(1)/etc/uci-defaults + $(INSTALL_BIN) ./files/99-maple-restore.sh $(1)/etc/uci-defaults/99-maple-restore +endef + +$(eval $(call BuildPackage,maple-restore)) diff --git a/package/diy/maple-restore/files/99-maple-restore.sh b/package/diy/maple-restore/files/99-maple-restore.sh new file mode 100644 index 0000000000..9e8755a37a --- /dev/null +++ b/package/diy/maple-restore/files/99-maple-restore.sh @@ -0,0 +1,52 @@ +#!/bin/sh +# /etc/uci-defaults/99-maple-restore +# Auto-restore configs from p4 after MapleOS sysupgrade. +# Runs once on first boot, then deleted by uci-defaults. + +BACKUP_DIR="/mnt/mmc2-4/.maple-backup" +DONE_FILE="/etc/maple-restore.done" + +# Guard: only run once +[ -f "$DONE_FILE" ] && exit 0 + +# Guard: backup must exist +if [ ! -d "$BACKUP_DIR" ]; then + logger -t "maple-restore" "No backup found at $BACKUP_DIR, skipping" + exit 0 +fi + +# Count files to restore +RESTORED=0 +for f in $(cd "$BACKUP_DIR" && find . -type f 2>/dev/null); do + src="${BACKUP_DIR}/${f}" + dst="/${f}" + + # Skip if destination exists and is identical + [ -f "$dst" ] && cmp -s "$src" "$dst" && continue + + dst_dir=$(dirname "$dst") + mkdir -p "$dst_dir" 2>/dev/null + + # For shadow, preserve original permissions + if [ "$dst" = "/etc/shadow" ]; then + cp -a "$src" "$dst" 2>/dev/null && chmod 0640 "$dst" 2>/dev/null + else + cp -a "$src" "$dst" 2>/dev/null + fi + + RESTORED=$((RESTORED + 1)) +done + +logger -t "maple-restore" "Restored $RESTORED config files from p4 backup" + +# Restart services to pick up restored configs +for svc in frpc openclash cron dropbear; do + if [ -x "/etc/init.d/$svc" ]; then + /etc/init.d/$svc restart 2>/dev/null + logger -t "maple-restore" "Restarted $svc" + fi +done + +# Mark done +touch "$DONE_FILE" +exit 0 diff --git a/package/diy/maple-upgrade/Makefile b/package/diy/maple-upgrade/Makefile new file mode 100644 index 0000000000..8ba6bbc0bc --- /dev/null +++ b/package/diy/maple-upgrade/Makefile @@ -0,0 +1,50 @@ +# +# Copyright (C) 2026 xiexiaobao +# +# This is free software, licensed under the GPL 2.0 license. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=maple-upgrade +PKG_VERSION:=1.0 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=xiexiaobao +PKG_LICENSE:=GPL-2.0 + +include $(INCLUDE_DIR)/package.mk + +define Package/maple-upgrade + SECTION:=utils + CATEGORY:=Utilities + TITLE:=MapleOS firmware upgrade with auto-config backup + PKGARCH:=all + DEPENDS:= +endef + +define Package/maple-upgrade/description + Safely upgrade MapleOS firmware with automatic config backup to p4. + + Usage: + maple-upgrade Back up configs then sysupgrade -n + maple-upgrade -b Backup-only mode (no flash) + maple-upgrade --no-backup Direct sysupgrade -n (skip backup) + maple-upgrade -h Show help + + Backups go to /mnt/mmc2-4/.maple-backup/ and are auto-restored + by maple-restore on next boot. +endef + +define Build/Configure +endef + +define Build/Compile +endef + +define Package/maple-upgrade/install + $(INSTALL_DIR) $(1)/sbin + $(INSTALL_BIN) ./files/maple-upgrade.sh $(1)/sbin/maple-upgrade +endef + +$(eval $(call BuildPackage,maple-upgrade)) diff --git a/package/diy/maple-upgrade/files/maple-upgrade.sh b/package/diy/maple-upgrade/files/maple-upgrade.sh new file mode 100644 index 0000000000..c8321dc442 --- /dev/null +++ b/package/diy/maple-upgrade/files/maple-upgrade.sh @@ -0,0 +1,122 @@ +#!/bin/sh +# /sbin/maple-upgrade - MapleOS firmware upgrade with auto-config backup +# +# Usage: +# maple-upgrade Backup configs then sysupgrade -n +# maple-upgrade -b Backup-only mode (no flash) +# maple-upgrade --no-backup Direct sysupgrade -n (skip backup) +# maple-upgrade -h Show help + +BACKUP_DIR="/mnt/mmc2-4/.maple-backup" +BACKUP_LIST=" +/etc/shadow +/etc/config/dropbear +/etc/config/openclash +/etc/config/firewall +/etc/config/frpc +/etc/config/dhcp +/etc/config/fstab +/etc/config/network +/etc/config/luci +/etc/config/system +/etc/config/uhttpd +/etc/config/tinyproxy +/etc/config/nlbwmon +/etc/config/aria2 +/etc/config/hd-idle +/etc/config/transmission +/etc/config/ttyd +/etc/config/tailscale +/etc/config/dockerd +/etc/config/upnpd +/etc/crontabs/root +" + +SERVICES_RESTORE="frpc openclash cron dropbear" + +log() { + echo "[maple-upgrade] $*" +} + +die() { + echo "[maple-upgrade] ERROR: $*" >&2 + exit 1 +} + +show_help() { + cat <<'EOF' +MapleOS firmware upgrade with auto-config backup to p4 + +Usage: + maple-upgrade Back up configs, then sysupgrade -n + maple-upgrade -b Backup only, do not flash + maple-upgrade --no-backup Skip backup, direct sysupgrade -n + maple-upgrade -h Show this help + +Backups stored in /mnt/mmc2-4/.maple-backup/ +Auto-restored by maple-restore (uci-defaults) on first boot after upgrade. +EOF +} + +backup_configs() { + local count=0 + + # Ensure backup directory on p4 + if ! mountpoint -q /mnt/mmc2-4 2>/dev/null; then + # p4 might not be mounted yet; try to mount it + mkdir -p /mnt/mmc2-4 2>/dev/null + mount /dev/mmcblk2p4 /mnt/mmc2-4 2>/dev/null || { + die "Cannot mount p4 (/dev/mmcblk2p4) for backup. Is the partition table set up?" + } + fi + + mkdir -p "$BACKUP_DIR" || die "Cannot create $BACKUP_DIR" + + # Remove old backup + rm -rf "${BACKUP_DIR:?}"/* + + log "Backing up configs to $BACKUP_DIR ..." + + for f in $BACKUP_LIST; do + if [ -f "$f" ]; then + dir="$BACKUP_DIR$(dirname "$f")" + mkdir -p "$dir" 2>/dev/null + cp -a "$f" "${BACKUP_DIR}${f}" 2>/dev/null && count=$((count + 1)) + fi + done + + log "Backed up $count files." + [ "$count" -gt 0 ] || die "No config files were backed up!" +} + +# ---- Main ---- + +case "${1:-}" in + -h|--help) + show_help + exit 0 + ;; + -b|--backup) + backup_configs + log "Backup complete. Run 'maple-upgrade ' to upgrade." + exit 0 + ;; + --no-backup) + [ -n "$2" ] || die "Missing firmware file. Usage: maple-upgrade --no-backup " + shift + log "Skipping backup, running sysupgrade -n on $1 ..." + sysupgrade -n "$1" + ;; + "") + show_help + exit 1 + ;; + *) + FIRMWARE="$1" + [ -f "$FIRMWARE" ] || die "Firmware file not found: $FIRMWARE" + + backup_configs + log "Backup done. Running sysupgrade -n ..." + sysupgrade -n "$FIRMWARE" + ;; +esac diff --git a/r6c.config b/r6c.config index 46f2488f1e..59613d2cb3 100644 --- a/r6c.config +++ b/r6c.config @@ -208,6 +208,10 @@ CONFIG_PACKAGE_openssh-sftp-server=y # Custom branding CONFIG_PACKAGE_branding=y +# MapleOS auto-config backup/restore (sysupgrade) +CONFIG_PACKAGE_maple-upgrade=y +CONFIG_PACKAGE_maple-restore=y + # Rockchip hardware acceleration CONFIG_PACKAGE_kmod-rk_vcodec=y CONFIG_PACKAGE_kmod-rga3=y