first commit
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/backups/
|
||||
152
README.md
Normal file
152
README.md
Normal file
@@ -0,0 +1,152 @@
|
||||
# ROCKNIX Backup & Restore
|
||||
|
||||
Backup and restore script for ROCKNIX emulator configurations. Allows syncing optimal settings between multiple consoles via SSH.
|
||||
|
||||
## Features
|
||||
|
||||
- **Specific backup**: Full backup including all device/user-specific settings
|
||||
- **Generic backup**: Portable backup with device-specific settings filtered out
|
||||
- **Selective restore**: Choose which components to restore via interactive dialog
|
||||
- **Safety backup**: Automatically saves current settings before restoring
|
||||
- **Device detection**: Automatically identifies the target ROCKNIX device
|
||||
- **SSH support**: Password and key-based authentication
|
||||
|
||||
## Requirements
|
||||
|
||||
```bash
|
||||
# Fedora/RHEL
|
||||
sudo dnf install tar dialog rsync sshpass
|
||||
|
||||
# Debian/Ubuntu
|
||||
sudo apt install tar dialog rsync sshpass
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Backup
|
||||
|
||||
```bash
|
||||
# Specific backup (includes all settings)
|
||||
./backup-rocknix.sh
|
||||
|
||||
# Generic backup (portable between devices)
|
||||
./backup-rocknix.sh --type generic
|
||||
|
||||
# Custom host and output directory
|
||||
./backup-rocknix.sh --host myconsole.local --output /path/to/backups
|
||||
```
|
||||
|
||||
### Restore
|
||||
|
||||
```bash
|
||||
# Interactive restore (lists available backups)
|
||||
./restore-rocknix.sh
|
||||
|
||||
# Restore specific backup file
|
||||
./restore-rocknix.sh --backup backups/rocknix-config-specific-rg-cubexx-20260714-113010.tar.gz
|
||||
|
||||
# Restore all components without prompting
|
||||
./restore-rocknix.sh --backup backup.tar.gz --all
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
### backup-rocknix.sh
|
||||
|
||||
| Option | Description | Default |
|
||||
|-------------------|-------------------------|------------------|
|
||||
| `--host HOST` | Console hostname/IP | `rgcubexx.local` |
|
||||
| `--user USER` | SSH username | `root` |
|
||||
| `--password PASS` | SSH password | (prompts) |
|
||||
| `--output DIR` | Backup output directory | `backups/` |
|
||||
| `--type TYPE` | `specific` or `generic` | `specific` |
|
||||
| `--help` | Show help | |
|
||||
|
||||
### restore-rocknix.sh
|
||||
|
||||
| Option | Description | Default |
|
||||
|-------------------|----------------------------|------------------|
|
||||
| `--host HOST` | Target console hostname/IP | `rgcubexx.local` |
|
||||
| `--user USER` | SSH username | `root` |
|
||||
| `--password PASS` | SSH password | (prompts) |
|
||||
| `--backup FILE` | Backup file to restore | (interactive) |
|
||||
| `--all` | Restore all components | `false` |
|
||||
| `--help` | Show help | |
|
||||
|
||||
## Components
|
||||
|
||||
The following components can be backed up and restored:
|
||||
|
||||
| Component | Description |
|
||||
|--------------------------|--------------------------------------------|
|
||||
| `retroarch-core-options` | RetroArch global core options |
|
||||
| `retroarch-opt` | Per-core `.opt` files |
|
||||
| `retroarch-rmp` | Button remaps `.rmp` files |
|
||||
| `retroarch-config` | Per-core overrides (`config/`) |
|
||||
| `shaders` | Shader packs and presets |
|
||||
| `ppsspp` | PPSSPP (PSP) settings |
|
||||
| `drastic` | DraStic (NDS) settings |
|
||||
| `other-emu` | Flycast, DuckStation, Yabasanshiro configs |
|
||||
|
||||
## Backup Types
|
||||
|
||||
### Specific Backup
|
||||
|
||||
Includes all settings, including device-specific values like:
|
||||
- Screen resolution and scaling
|
||||
- Video/audio drivers
|
||||
- Input mappings
|
||||
- Account credentials (RetroAchievements, cloud sync)
|
||||
|
||||
Best for: Backing up the same device or identical hardware.
|
||||
|
||||
### Generic Backup
|
||||
|
||||
Filters out device-specific settings for portability:
|
||||
- Screen dimensions (`video_fullscreen_x/y`)
|
||||
- Scale factors (`menu_scale_factor`)
|
||||
- Drivers (`video_driver`, `audio_driver`)
|
||||
- Credentials and tokens
|
||||
|
||||
Best for: Sharing configs between different devices or users.
|
||||
|
||||
## Configuration
|
||||
|
||||
Edit `config.sh` to customize:
|
||||
|
||||
- `ROCKNIX_HOST`: Default console hostname
|
||||
- `ROCKNIX_STORAGE`: Storage path on device (default: `/storage`)
|
||||
- `BACKUP_DIR`: Local backup directory
|
||||
- `SPECIFIC_FILES`: List of files to back up
|
||||
- `GENERIC_EXCLUDES`: Files excluded from generic backups
|
||||
- `GENERIC_SETTINGS_FILTER`: Settings patterns removed from generic backups
|
||||
|
||||
## Examples
|
||||
|
||||
```bash
|
||||
# First-time setup: create a specific backup
|
||||
./backup-rocknix.sh --host rgcubexx.local
|
||||
|
||||
# Clone settings to another device of the same model
|
||||
./backup-rocknix.sh --type generic
|
||||
./restore-rocknix.sh --host rgcubexx2.local --backup backups/rocknix-config-generic-*.tar.gz
|
||||
|
||||
# List available backups
|
||||
./restore-rocknix.sh # Shows interactive menu
|
||||
```
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
rocknix-backup/
|
||||
├── backup-rocknix.sh # Backup script
|
||||
├── restore-rocknix.sh # Restore script
|
||||
├── lib-common.sh # Shared functions (SSH, rsync, logging)
|
||||
├── config.sh # Default configuration
|
||||
├── backups/ # Backup files (*.tar.gz)
|
||||
└── PRE-ANALISIS-ROCKNIX.md # Technical analysis document
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
203
backup-rocknix.sh
Executable file
203
backup-rocknix.sh
Executable file
@@ -0,0 +1,203 @@
|
||||
#!/usr/bin/env bash
|
||||
# backup-rocknix.sh - Backup script for ROCKNIX configurations
|
||||
#
|
||||
# Usage:
|
||||
# ./backup-rocknix.sh [OPTIONS]
|
||||
#
|
||||
# Options:
|
||||
# --host HOST Console host (default: rgeubexx.local)
|
||||
# --user USER SSH user (default: root)
|
||||
# --output DIR Output directory for backups
|
||||
# --type TYPE Backup type: specific or generic (default: specific)
|
||||
# --help Show help
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "$SCRIPT_DIR/lib-common.sh"
|
||||
|
||||
# Default values
|
||||
BACKUP_TYPE="specific"
|
||||
|
||||
# Parse arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--host)
|
||||
ROCKNIX_HOST="$2"
|
||||
shift 2
|
||||
;;
|
||||
--user)
|
||||
ROCKNIX_USER="$2"
|
||||
shift 2
|
||||
;;
|
||||
--password)
|
||||
ROCKNIX_PASSWORD="$2"
|
||||
shift 2
|
||||
;;
|
||||
--output)
|
||||
BACKUP_DIR="$2"
|
||||
shift 2
|
||||
;;
|
||||
--type)
|
||||
BACKUP_TYPE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--help)
|
||||
echo "Usage: $0 [OPTIONS]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --host HOST Console host (default: $ROCKNIX_HOST)"
|
||||
echo " --user USER SSH user (default: $ROCKNIX_USER)"
|
||||
echo " --password PASS SSH password"
|
||||
echo " --output DIR Output directory"
|
||||
echo " --type TYPE Backup type: specific, generic (default: specific)"
|
||||
echo " --help Show this help"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
log ERROR "Unknown option: $1"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Verify valid type
|
||||
if [[ "$BACKUP_TYPE" != "specific" && "$BACKUP_TYPE" != "generic" ]]; then
|
||||
log ERROR "Invalid backup type: $BACKUP_TYPE (use: specific, generic)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check dependencies
|
||||
check_deps || exit 1
|
||||
|
||||
# Ask for password if not configured
|
||||
ask_password || exit 1
|
||||
|
||||
# Verify SSH connection
|
||||
ssh_check "$ROCKNIX_HOST" "$ROCKNIX_USER" || exit 1
|
||||
|
||||
# Detect device
|
||||
DEVICE=$(detect_device "$ROCKNIX_HOST" "$ROCKNIX_USER" 2>/dev/null || echo "unknown")
|
||||
DEVICE_SLUG=$(echo "$DEVICE" | tr ' ' '-' | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
# Create backups directory
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
|
||||
# Create temporary directory
|
||||
TMP_DIR=$(create_tmp_dir "rocknix-backup")
|
||||
trap 'cleanup_tmp "$TMP_DIR"' EXIT
|
||||
|
||||
log INFO "Starting ${BACKUP_TYPE} backup..."
|
||||
log INFO "Device: ${DEVICE}"
|
||||
log INFO "Host: ${ROCKNIX_USER}@${ROCKNIX_HOST}"
|
||||
|
||||
# Select file list based on type
|
||||
if [[ "$BACKUP_TYPE" == "specific" ]]; then
|
||||
FILES_TO_BACKUP=("${SPECIFIC_FILES[@]}")
|
||||
else
|
||||
# For generic, exclude device-specific files
|
||||
FILES_TO_BACKUP=()
|
||||
for file in "${SPECIFIC_FILES[@]}"; do
|
||||
skip=false
|
||||
for exclude in "${GENERIC_EXCLUDES[@]}"; do
|
||||
if [[ "$file" == "$exclude" ]]; then
|
||||
skip=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [[ "$skip" == "false" ]]; then
|
||||
FILES_TO_BACKUP+=("$file")
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Download files
|
||||
log INFO "Downloading files..."
|
||||
DOWNLOADED=0
|
||||
FAILED=0
|
||||
|
||||
for file in "${FILES_TO_BACKUP[@]}"; do
|
||||
local_path="${TMP_DIR}/${file}"
|
||||
remote_path="${file}"
|
||||
|
||||
# Create local directory
|
||||
mkdir -p "$(dirname "$local_path")"
|
||||
|
||||
# Download
|
||||
if [[ -d "${local_path}" ]] || [[ "$file" == */ ]]; then
|
||||
# It's a directory
|
||||
mkdir -p "$local_path"
|
||||
if download_dir "$remote_path" "$local_path" "$ROCKNIX_HOST" "$ROCKNIX_USER" &>/dev/null; then
|
||||
DOWNLOADED=$((DOWNLOADED + 1))
|
||||
log DEBUG "Downloaded: ${file}"
|
||||
else
|
||||
FAILED=$((FAILED + 1))
|
||||
log WARN "Could not download: ${file}"
|
||||
fi
|
||||
else
|
||||
# It's a file
|
||||
if download_file "$remote_path" "$local_path" "$ROCKNIX_HOST" "$ROCKNIX_USER" &>/dev/null; then
|
||||
DOWNLOADED=$((DOWNLOADED + 1))
|
||||
log DEBUG "Downloaded: ${file}"
|
||||
else
|
||||
FAILED=$((FAILED + 1))
|
||||
log WARN "Could not download: ${file}"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
log INFO "Downloaded: ${DOWNLOADED} files"
|
||||
|
||||
# For generic backup, filter device/user-specific settings
|
||||
if [[ "$BACKUP_TYPE" == "generic" ]]; then
|
||||
log INFO "Filtering device/user-specific settings..."
|
||||
|
||||
# Filter retroarch-core-options.cfg if it exists
|
||||
if [[ -f "${TMP_DIR}/.config/retroarch/retroarch-core-options.cfg" ]]; then
|
||||
filter_specific_settings \
|
||||
"${TMP_DIR}/.config/retroarch/retroarch-core-options.cfg" \
|
||||
"${TMP_DIR}/.config/retroarch/retroarch-core-options.cfg.filtered"
|
||||
mv "${TMP_DIR}/.config/retroarch/retroarch-core-options.cfg.filtered" \
|
||||
"${TMP_DIR}/.config/retroarch/retroarch-core-options.cfg"
|
||||
fi
|
||||
|
||||
# Filter overrides (.cfg files)
|
||||
find "${TMP_DIR}/.config/retroarch/config/" -name "*.cfg" -type f 2>/dev/null | while read -r cfg_file; do
|
||||
filter_specific_settings "$cfg_file" "${cfg_file}.filtered"
|
||||
mv "${cfg_file}.filtered" "$cfg_file"
|
||||
done
|
||||
fi
|
||||
|
||||
# Create backup filename
|
||||
TIMESTAMP=$(date '+%Y%m%d-%H%M%S')
|
||||
BACKUP_NAME="rocknix-config-${BACKUP_TYPE}-${DEVICE_SLUG}-${TIMESTAMP}.tar.gz"
|
||||
BACKUP_FILE="${BACKUP_DIR}/${BACKUP_NAME}"
|
||||
|
||||
# Compress
|
||||
log INFO "Compressing backup..."
|
||||
tar -czf "$BACKUP_FILE" -C "$TMP_DIR" .
|
||||
|
||||
# Verify
|
||||
if [[ -f "$BACKUP_FILE" ]]; then
|
||||
BACKUP_SIZE=$(du -h "$BACKUP_FILE" | cut -f1)
|
||||
BACKUP_FILES=$(tar -tzf "$BACKUP_FILE" | wc -l)
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo -e "${GREEN} Backup completed successfully${NC}"
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo ""
|
||||
echo -e " Type: ${CYAN}${BACKUP_TYPE}${NC}"
|
||||
echo -e " Device: ${CYAN}${DEVICE}${NC}"
|
||||
echo -e " File: ${CYAN}${BACKUP_NAME}${NC}"
|
||||
echo -e " Location: ${CYAN}${BACKUP_DIR}${NC}"
|
||||
echo -e " Size: ${CYAN}${BACKUP_SIZE}${NC}"
|
||||
echo -e " Files: ${CYAN}${BACKUP_FILES}${NC}"
|
||||
echo ""
|
||||
echo -e " ${YELLOW}To restore, run:${NC}"
|
||||
echo -e " ${CYAN}./restore-rocknix.sh --backup ${BACKUP_FILE}${NC}"
|
||||
echo ""
|
||||
else
|
||||
log ERROR "Could not create backup file"
|
||||
exit 1
|
||||
fi
|
||||
86
config.sh
Executable file
86
config.sh
Executable file
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env bash
|
||||
# config.sh - Default configuration for ROCKNIX backup/restore
|
||||
|
||||
# ROCKNIX console host
|
||||
ROCKNIX_HOST="${ROCKNIX_HOST:-rgcubexx.local}"
|
||||
ROCKNIX_USER="${ROCKNIX_USER:-root}"
|
||||
ROCKNIX_PASSWORD="${ROCKNIX_PASSWORD:-}"
|
||||
ROCKNIX_STORAGE="${ROCKNIX_STORAGE:-/storage}"
|
||||
|
||||
# Local backup directory (resolved in lib-common.sh)
|
||||
BACKUP_DIR="${BACKUP_DIR:-backups}"
|
||||
|
||||
# Files to back up (relative to /storage)
|
||||
# Specific backup (includes everything)
|
||||
SPECIFIC_FILES=(
|
||||
# RetroArch global
|
||||
".config/retroarch/retroarch.cfg"
|
||||
".config/retroarch/retroarch-core-options.cfg"
|
||||
".config/retroarch/retroarch32bit-append.cfg"
|
||||
".config/retroarch/retroarch64bit-append.cfg"
|
||||
|
||||
# RetroArch .opt (per-core options at root level)
|
||||
".config/retroarch/Flycast.opt"
|
||||
".config/retroarch/Supafaust.opt"
|
||||
".config/retroarch/ParaLLEl N64.opt"
|
||||
|
||||
# RetroArch .rmp (remaps at root level)
|
||||
".config/retroarch/TATE-MAME 2003-Plus.rmp"
|
||||
|
||||
# RetroArch overrides (complete directory)
|
||||
".config/retroarch/config/"
|
||||
|
||||
# Shaders
|
||||
"shaders/"
|
||||
|
||||
# PPSSPP
|
||||
".config/ppsspp/PSP/SYSTEM/ppsspp.ini"
|
||||
".config/ppsspp/PSP/SYSTEM/controls.ini"
|
||||
|
||||
# DraStic
|
||||
".config/drastic/config/"
|
||||
|
||||
# Other emulators
|
||||
".config/game/configs/"
|
||||
".config/flycast/emu.cfg"
|
||||
".config/flycast/flycast.gptk"
|
||||
".config/flycast/mappings/"
|
||||
".config/duckstation/settings.ini"
|
||||
".config/yabasanshiro/.config"
|
||||
)
|
||||
|
||||
# Generic backup: exclude files with device/user-specific settings
|
||||
GENERIC_EXCLUDES=(
|
||||
".config/retroarch/retroarch.cfg"
|
||||
".config/retroarch/retroarch32bit-append.cfg"
|
||||
".config/retroarch/retroarch64bit-append.cfg"
|
||||
)
|
||||
|
||||
# Settings patterns to filter from overrides in generic backup
|
||||
GENERIC_SETTINGS_FILTER=(
|
||||
"menu_scale_factor"
|
||||
"menu_widget_scale_factor"
|
||||
"video_fullscreen_x"
|
||||
"video_fullscreen_y"
|
||||
"video_windowed_position_width"
|
||||
"video_windowed_position_height"
|
||||
"video_refresh_rate"
|
||||
"custom_viewport_width"
|
||||
"custom_viewport_height"
|
||||
"video_driver"
|
||||
"audio_driver"
|
||||
"input_driver"
|
||||
"input_joypad_driver"
|
||||
"cheevos_username"
|
||||
"cheevos_password"
|
||||
"cheevos_token"
|
||||
"cheevos_custom_host"
|
||||
"google_drive_refresh_token"
|
||||
"webdav_password"
|
||||
"webdav_username"
|
||||
"kiosk_mode_password"
|
||||
"content_show_settings_password"
|
||||
"netplay_ip_address"
|
||||
"netplay_ip_port"
|
||||
"netplay_password"
|
||||
)
|
||||
343
lib-common.sh
Executable file
343
lib-common.sh
Executable file
@@ -0,0 +1,343 @@
|
||||
#!/usr/bin/env bash
|
||||
# lib-common.sh - Shared functions for ROCKNIX backup/restore
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Script directory
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# Load configuration
|
||||
source "$SCRIPT_DIR/config.sh"
|
||||
|
||||
# Resolve BACKUP_DIR relative to script
|
||||
case "$BACKUP_DIR" in
|
||||
/*) ;; # Absolute path, do nothing
|
||||
*) BACKUP_DIR="${SCRIPT_DIR}/${BACKUP_DIR}" ;;
|
||||
esac
|
||||
|
||||
# Colores
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Logging
|
||||
log() {
|
||||
local level="$1"
|
||||
shift
|
||||
local msg="$*"
|
||||
local timestamp
|
||||
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
|
||||
case "$level" in
|
||||
INFO) echo -e "${GREEN}[${timestamp}] INFO:${NC} $msg" ;;
|
||||
WARN) echo -e "${YELLOW}[${timestamp}] WARN:${NC} $msg" ;;
|
||||
ERROR) echo -e "${RED}[${timestamp}] ERROR:${NC} $msg" >&2 ;;
|
||||
DEBUG) echo -e "${BLUE}[${timestamp}] DEBUG:${NC} $msg" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Check dependencies
|
||||
check_deps() {
|
||||
local missing=()
|
||||
for dep in tar dialog rsync sshpass; do
|
||||
if ! command -v "$dep" &>/dev/null; then
|
||||
missing+=("$dep")
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${#missing[@]} -gt 0 ]]; then
|
||||
log ERROR "Missing dependencies: ${missing[*]}"
|
||||
log INFO "Install with: sudo dnf install ${missing[*]}"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# Ask for password if not configured
|
||||
ask_password() {
|
||||
if [[ -z "$ROCKNIX_PASSWORD" ]]; then
|
||||
read -s -p "Password for ${ROCKNIX_USER}@${ROCKNIX_HOST}: " ROCKNIX_PASSWORD
|
||||
echo ""
|
||||
if [[ -z "$ROCKNIX_PASSWORD" ]]; then
|
||||
log ERROR "Empty password"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
export ROCKNIX_PASSWORD
|
||||
}
|
||||
|
||||
# Build SSH connection string
|
||||
ssh_target() {
|
||||
local host="${1:-$ROCKNIX_HOST}"
|
||||
local user="${2:-$ROCKNIX_USER}"
|
||||
echo "${user}@${host}"
|
||||
}
|
||||
|
||||
# Verify SSH connection
|
||||
ssh_check() {
|
||||
local host="${1:-$ROCKNIX_HOST}"
|
||||
local user="${2:-$ROCKNIX_USER}"
|
||||
local target
|
||||
target=$(ssh_target "$host" "$user")
|
||||
|
||||
log INFO "Checking connection to ${target}..."
|
||||
|
||||
if [[ -n "$ROCKNIX_PASSWORD" ]]; then
|
||||
if sshpass -p "$ROCKNIX_PASSWORD" ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no "$target" "echo ok" &>/dev/null; then
|
||||
log INFO "Connection successful"
|
||||
return 0
|
||||
fi
|
||||
else
|
||||
if ssh -o ConnectTimeout=5 -o BatchMode=yes "$target" "echo ok" &>/dev/null; then
|
||||
log INFO "Connection successful"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
log ERROR "Could not connect to ${target}"
|
||||
log INFO "Make sure SSH is enabled on the ROCKNIX console"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Execute remote command
|
||||
remote_exec() {
|
||||
local cmd="$1"
|
||||
local host="${2:-$ROCKNIX_HOST}"
|
||||
local user="${3:-$ROCKNIX_USER}"
|
||||
local target
|
||||
target=$(ssh_target "$host" "$user")
|
||||
|
||||
if [[ -n "$ROCKNIX_PASSWORD" ]]; then
|
||||
sshpass -p "$ROCKNIX_PASSWORD" ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no "$target" "$cmd" 2>&1
|
||||
else
|
||||
ssh -o ConnectTimeout=10 "$target" "$cmd" 2>&1
|
||||
fi
|
||||
}
|
||||
|
||||
# List remote files
|
||||
remote_list() {
|
||||
local remote_path="$1"
|
||||
local host="${2:-$ROCKNIX_HOST}"
|
||||
local user="${3:-$ROCKNIX_USER}"
|
||||
|
||||
remote_exec "ls -la ${ROCKNIX_STORAGE}/${remote_path}/ 2>/dev/null" "$host" "$user"
|
||||
}
|
||||
|
||||
# Download entire directory via rsync
|
||||
download_dir() {
|
||||
local remote_path="$1"
|
||||
local local_path="$2"
|
||||
local host="${3:-$ROCKNIX_HOST}"
|
||||
local user="${4:-$ROCKNIX_USER}"
|
||||
local target
|
||||
target=$(ssh_target "$host" "$user")
|
||||
|
||||
mkdir -p "$local_path"
|
||||
|
||||
local rsync_opts=(-avz --timeout=30 -e "ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10")
|
||||
|
||||
if [[ -n "$ROCKNIX_PASSWORD" ]]; then
|
||||
sshpass -p "$ROCKNIX_PASSWORD" rsync "${rsync_opts[@]}" \
|
||||
"${target}:${ROCKNIX_STORAGE}/${remote_path}/" \
|
||||
"${local_path}/" 2>&1
|
||||
else
|
||||
rsync "${rsync_opts[@]}" \
|
||||
"${target}:${ROCKNIX_STORAGE}/${remote_path}/" \
|
||||
"${local_path}/" 2>&1
|
||||
fi
|
||||
}
|
||||
|
||||
# Upload entire directory via rsync
|
||||
upload_dir() {
|
||||
local local_path="$1"
|
||||
local remote_path="$2"
|
||||
local host="${3:-$ROCKNIX_HOST}"
|
||||
local user="${4:-$ROCKNIX_USER}"
|
||||
local target
|
||||
target=$(ssh_target "$host" "$user")
|
||||
|
||||
local rsync_opts=(-avz --timeout=30 -e "ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10")
|
||||
|
||||
if [[ -n "$ROCKNIX_PASSWORD" ]]; then
|
||||
sshpass -p "$ROCKNIX_PASSWORD" rsync "${rsync_opts[@]}" \
|
||||
"${local_path}/" \
|
||||
"${target}:${ROCKNIX_STORAGE}/${remote_path}/" 2>&1
|
||||
else
|
||||
rsync "${rsync_opts[@]}" \
|
||||
"${local_path}/" \
|
||||
"${target}:${ROCKNIX_STORAGE}/${remote_path}/" 2>&1
|
||||
fi
|
||||
}
|
||||
|
||||
# Download a single file
|
||||
download_file() {
|
||||
local remote_file="$1"
|
||||
local local_file="$2"
|
||||
local host="${3:-$ROCKNIX_HOST}"
|
||||
local user="${4:-$ROCKNIX_USER}"
|
||||
local target
|
||||
target=$(ssh_target "$host" "$user")
|
||||
|
||||
mkdir -p "$(dirname "$local_file")"
|
||||
|
||||
local rsync_opts=(-avz --timeout=30 -e "ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10")
|
||||
|
||||
if [[ -n "$ROCKNIX_PASSWORD" ]]; then
|
||||
sshpass -p "$ROCKNIX_PASSWORD" rsync "${rsync_opts[@]}" \
|
||||
"${target}:${ROCKNIX_STORAGE}/${remote_file}" \
|
||||
"${local_file}" 2>&1
|
||||
else
|
||||
rsync "${rsync_opts[@]}" \
|
||||
"${target}:${ROCKNIX_STORAGE}/${remote_file}" \
|
||||
"${local_file}" 2>&1
|
||||
fi
|
||||
}
|
||||
|
||||
# Upload a single file
|
||||
upload_file() {
|
||||
local local_file="$1"
|
||||
local remote_file="$2"
|
||||
local host="${3:-$ROCKNIX_HOST}"
|
||||
local user="${4:-$ROCKNIX_USER}"
|
||||
local target
|
||||
target=$(ssh_target "$host" "$user")
|
||||
|
||||
local rsync_opts=(-avz --timeout=30 -e "ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10")
|
||||
|
||||
if [[ -n "$ROCKNIX_PASSWORD" ]]; then
|
||||
sshpass -p "$ROCKNIX_PASSWORD" rsync "${rsync_opts[@]}" \
|
||||
"${local_file}" \
|
||||
"${target}:${ROCKNIX_STORAGE}/${remote_file}" 2>&1
|
||||
else
|
||||
rsync "${rsync_opts[@]}" \
|
||||
"${local_file}" \
|
||||
"${target}:${ROCKNIX_STORAGE}/${remote_file}" 2>&1
|
||||
fi
|
||||
}
|
||||
|
||||
# Direct backup via tar over SSH (no temporary files)
|
||||
backup_via_ssh() {
|
||||
local files=("$@")
|
||||
local host="${ROCKNIX_HOST}"
|
||||
local user="${ROCKNIX_USER}"
|
||||
local target
|
||||
target=$(ssh_target "$host" "$user")
|
||||
|
||||
# Build remote tar command
|
||||
local tar_args=""
|
||||
for file in "${files[@]}"; do
|
||||
tar_args="${tar_args} ${ROCKNIX_STORAGE}/${file}"
|
||||
done
|
||||
|
||||
# Execute remote tar and compress locally
|
||||
if [[ -n "$ROCKNIX_PASSWORD" ]]; then
|
||||
sshpass -p "$ROCKNIX_PASSWORD" ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no "$target" \
|
||||
"tar czf - -C ${ROCKNIX_STORAGE} ${tar_args}" 2>/dev/null
|
||||
else
|
||||
ssh -o ConnectTimeout=10 "$target" \
|
||||
"tar czf - -C ${ROCKNIX_STORAGE} ${tar_args}" 2>/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
# Detect ROCKNIX device
|
||||
detect_device() {
|
||||
local host="${1:-$ROCKNIX_HOST}"
|
||||
local user="${2:-$ROCKNIX_USER}"
|
||||
local target
|
||||
target=$(ssh_target "$host" "$user")
|
||||
|
||||
log INFO "Detecting device..." >&2
|
||||
|
||||
local device_info
|
||||
if [[ -n "$ROCKNIX_PASSWORD" ]]; then
|
||||
device_info=$(sshpass -p "$ROCKNIX_PASSWORD" ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no "$target" \
|
||||
"cat ${ROCKNIX_STORAGE}/device_info_ROCKNIX_*.txt 2>/dev/null" 2>/dev/null || true)
|
||||
else
|
||||
device_info=$(ssh -o ConnectTimeout=5 "$target" \
|
||||
"cat ${ROCKNIX_STORAGE}/device_info_ROCKNIX_*.txt 2>/dev/null" 2>/dev/null || true)
|
||||
fi
|
||||
|
||||
if [[ -n "$device_info" ]]; then
|
||||
local device_name
|
||||
device_name=$(echo "$device_info" | grep "^DEVICE_NAME=" | cut -d'=' -f2 | tr -d '"')
|
||||
local cfw_version
|
||||
cfw_version=$(echo "$device_info" | grep "^CFW_VERSION=" | cut -d'=' -f2 | tr -d '"')
|
||||
|
||||
if [[ -n "$device_name" ]]; then
|
||||
log INFO "Device: ${device_name} (ROCKNIX ${cfw_version})" >&2
|
||||
echo "${device_name}"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
log WARN "Could not detect device" >&2
|
||||
echo "Unknown"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Create temporary directory
|
||||
create_tmp_dir() {
|
||||
local prefix="${1:-rocknix-backup}"
|
||||
local tmp_dir
|
||||
tmp_dir=$(mktemp -d "/tmp/${prefix}-XXXXXX")
|
||||
echo "$tmp_dir"
|
||||
}
|
||||
|
||||
# Clean up temporary directory
|
||||
cleanup_tmp() {
|
||||
local tmp_dir="$1"
|
||||
if [[ -d "$tmp_dir" ]]; then
|
||||
rm -rf "$tmp_dir"
|
||||
fi
|
||||
}
|
||||
|
||||
# Get human-readable size
|
||||
human_size() {
|
||||
local bytes="$1"
|
||||
if [[ $bytes -ge 1073741824 ]]; then
|
||||
echo "$(echo "scale=1; $bytes/1073741824" | bc)G"
|
||||
elif [[ $bytes -ge 1048576 ]]; then
|
||||
echo "$(echo "scale=1; $bytes/1048576" | bc)M"
|
||||
elif [[ $bytes -ge 1024 ]]; then
|
||||
echo "$(echo "scale=1; $bytes/1024" | bc)K"
|
||||
else
|
||||
echo "${bytes}B"
|
||||
fi
|
||||
}
|
||||
|
||||
# Filter device-specific settings from file
|
||||
filter_specific_settings() {
|
||||
local input_file="$1"
|
||||
local output_file="$2"
|
||||
|
||||
cp "$input_file" "$output_file"
|
||||
|
||||
for setting in "${GENERIC_SETTINGS_FILTER[@]}"; do
|
||||
sed -i "/^${setting} = /d" "$output_file"
|
||||
done
|
||||
}
|
||||
|
||||
# Show contents of a backup file
|
||||
show_backup_contents() {
|
||||
local backup_file="$1"
|
||||
|
||||
if [[ ! -f "$backup_file" ]]; then
|
||||
log ERROR "File not found: $backup_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
log INFO "Backup contents:"
|
||||
tar -tzf "$backup_file" | head -50
|
||||
|
||||
local total_files
|
||||
total_files=$(tar -tzf "$backup_file" | wc -l)
|
||||
local total_size
|
||||
total_size=$(du -h "$backup_file" | cut -f1)
|
||||
|
||||
echo ""
|
||||
echo -e "${CYAN}Total: ${total_files} archivos, ${total_size}${NC}"
|
||||
}
|
||||
393
restore-rocknix.sh
Executable file
393
restore-rocknix.sh
Executable file
@@ -0,0 +1,393 @@
|
||||
#!/usr/bin/env bash
|
||||
# restore-rocknix.sh - Restore script for ROCKNIX configurations
|
||||
#
|
||||
# Usage:
|
||||
# ./restore-rocknix.sh [OPTIONS]
|
||||
#
|
||||
# Options:
|
||||
# --host HOST Target console host
|
||||
# --user USER SSH user (default: root)
|
||||
# --backup FILE .tar.gz backup file to restore
|
||||
# --all Restore all components without prompting
|
||||
# --help Show help
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "$SCRIPT_DIR/lib-common.sh"
|
||||
|
||||
# Default values
|
||||
BACKUP_FILE=""
|
||||
RESTORE_ALL=false
|
||||
|
||||
# Parse arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--host)
|
||||
ROCKNIX_HOST="$2"
|
||||
shift 2
|
||||
;;
|
||||
--user)
|
||||
ROCKNIX_USER="$2"
|
||||
shift 2
|
||||
;;
|
||||
--password)
|
||||
ROCKNIX_PASSWORD="$2"
|
||||
shift 2
|
||||
;;
|
||||
--backup)
|
||||
BACKUP_FILE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--all)
|
||||
RESTORE_ALL=true
|
||||
shift
|
||||
;;
|
||||
--help)
|
||||
echo "Usage: $0 [OPTIONS]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --host HOST Target console host"
|
||||
echo " --user USER SSH user (default: $ROCKNIX_USER)"
|
||||
echo " --password PASS SSH password"
|
||||
echo " --backup FILE .tar.gz backup file to restore"
|
||||
echo " --all Restore all components"
|
||||
echo " --help Show this help"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
log ERROR "Unknown option: $1"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Check dependencies
|
||||
check_deps || exit 1
|
||||
|
||||
# Ask for password if not configured
|
||||
ask_password || exit 1
|
||||
|
||||
# If no backup specified, list available ones
|
||||
if [[ -z "$BACKUP_FILE" ]]; then
|
||||
log INFO "Searching for backups in ${BACKUP_DIR}..."
|
||||
|
||||
if [[ ! -d "$BACKUP_DIR" ]]; then
|
||||
log ERROR "Backup directory not found: $BACKUP_DIR"
|
||||
log INFO "Run first: ./backup-rocknix.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BACKUPS=($(find "$BACKUP_DIR" -name "rocknix-config-*.tar.gz" -type f | sort -r))
|
||||
|
||||
if [[ ${#BACKUPS[@]} -eq 0 ]]; then
|
||||
log ERROR "No backups found in ${BACKUP_DIR}"
|
||||
log INFO "Run first: ./backup-rocknix.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${CYAN}Available backups:${NC}"
|
||||
echo ""
|
||||
|
||||
for i in "${!BACKUPS[@]}"; do
|
||||
local backup="${BACKUPS[$i]}"
|
||||
local name=$(basename "$backup")
|
||||
local size=$(du -h "$backup" | cut -f1)
|
||||
local date=$(stat -c %y "$backup" 2>/dev/null | cut -d'.' -f1)
|
||||
|
||||
echo -e " ${GREEN}$((i+1))${NC}) ${name}"
|
||||
echo -e " Size: ${size} | Date: ${date}"
|
||||
done
|
||||
|
||||
echo ""
|
||||
read -p "Select backup (1-${#BACKUPS[@]}): " choice
|
||||
|
||||
if [[ "$choice" -lt 1 || "$choice" -gt ${#BACKUPS[@]} ]]; then
|
||||
log ERROR "Invalid selection"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BACKUP_FILE="${BACKUPS[$((choice-1))]}"
|
||||
fi
|
||||
|
||||
# Verify backup file exists
|
||||
if [[ ! -f "$BACKUP_FILE" ]]; then
|
||||
log ERROR "Backup file not found: $BACKUP_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Show backup contents
|
||||
show_backup_contents "$BACKUP_FILE"
|
||||
|
||||
# Verify connection with target console
|
||||
echo ""
|
||||
ssh_check "$ROCKNIX_HOST" "$ROCKNIX_USER" || exit 1
|
||||
|
||||
# Detect target device
|
||||
DEVICE=$(detect_device "$ROCKNIX_HOST" "$ROCKNIX_USER" 2>/dev/null || echo "unknown")
|
||||
log INFO "Target device: ${DEVICE}"
|
||||
|
||||
# Check backup type
|
||||
BACKUP_NAME=$(basename "$BACKUP_FILE")
|
||||
if [[ "$BACKUP_NAME" == *"generic"* ]]; then
|
||||
log WARN "This is a GENERIC backup (without device-specific settings)"
|
||||
log WARN "Make sure the target device is compatible"
|
||||
echo ""
|
||||
read -p "Continue? (y/N): " confirm
|
||||
if [[ "$confirm" != "s" && "$confirm" != "S" ]]; then
|
||||
log INFO "Restore cancelled"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Create temporary directory
|
||||
TMP_DIR=$(create_tmp_dir "rocknix-restore")
|
||||
trap 'cleanup_tmp "$TMP_DIR"' EXIT
|
||||
|
||||
# Extract backup
|
||||
log INFO "Extracting backup..."
|
||||
tar -xzf "$BACKUP_FILE" -C "$TMP_DIR"
|
||||
|
||||
# Select components to restore
|
||||
if [[ "$RESTORE_ALL" == "false" ]]; then
|
||||
echo ""
|
||||
echo -e "${CYAN}Which components do you want to restore?${NC}"
|
||||
echo ""
|
||||
|
||||
COMPONENTS=(
|
||||
"retroarch-core-options:RetroArch core-options"
|
||||
"retroarch-opt:RetroArch .opt (core options)"
|
||||
"retroarch-rmp:RetroArch .rmp (remaps)"
|
||||
"retroarch-config:RetroArch overrides (config/)"
|
||||
"shaders:Shaders"
|
||||
"ppsspp:PPSSPP"
|
||||
"drastic:DraStic"
|
||||
"other-emu:Other emulators"
|
||||
)
|
||||
|
||||
SELECTION=()
|
||||
|
||||
for i in "${!COMPONENTS[@]}"; do
|
||||
IFS=':' read -r key label <<< "${COMPONENTS[$i]}"
|
||||
|
||||
# Determine if there are files of this type
|
||||
case "$key" in
|
||||
retroarch-core-options)
|
||||
[[ -f "${TMP_DIR}/.config/retroarch/retroarch-core-options.cfg" ]] && available=true || available=false
|
||||
;;
|
||||
retroarch-opt)
|
||||
find "${TMP_DIR}/.config/retroarch/" -maxdepth 1 -name "*.opt" -type f 2>/dev/null | grep -q . && available=true || available=false
|
||||
;;
|
||||
retroarch-rmp)
|
||||
find "${TMP_DIR}/.config/retroarch/" -maxdepth 1 -name "*.rmp" -type f 2>/dev/null | grep -q . && available=true || available=false
|
||||
;;
|
||||
retroarch-config)
|
||||
[[ -d "${TMP_DIR}/.config/retroarch/config/" ]] && available=true || available=false
|
||||
;;
|
||||
shaders)
|
||||
[[ -d "${TMP_DIR}/shaders/" ]] && available=true || available=false
|
||||
;;
|
||||
ppsspp)
|
||||
[[ -f "${TMP_DIR}/.config/ppsspp/PSP/SYSTEM/ppsspp.ini" ]] && available=true || available=false
|
||||
;;
|
||||
drastic)
|
||||
[[ -d "${TMP_DIR}/.config/drastic/config/" ]] && available=true || available=false
|
||||
;;
|
||||
other-emu)
|
||||
[[ -d "${TMP_DIR}/.config/game/" ]] || \
|
||||
[[ -d "${TMP_DIR}/.config/flycast/" ]] || \
|
||||
[[ -f "${TMP_DIR}/.config/duckstation/settings.ini" ]] || \
|
||||
[[ -f "${TMP_DIR}/.config/yabasanshiro/.config" ]] && available=true || available=false
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ "$available" == "true" ]]; then
|
||||
SELECTION+=("$key" "$label" "on")
|
||||
else
|
||||
SELECTION+=("$key" "$label" "off")
|
||||
fi
|
||||
done
|
||||
|
||||
CHOICES=$(dialog --checklist "Components to restore:" \
|
||||
20 60 12 \
|
||||
"${SELECTION[@]}" \
|
||||
3>&1 1>&2 2>&3)
|
||||
|
||||
# If user cancels
|
||||
if [[ $? -ne 0 ]]; then
|
||||
log INFO "Restore cancelled"
|
||||
exit 0
|
||||
fi
|
||||
else
|
||||
# Restore all
|
||||
CHOICES="retroarch-core-options retroarch-opt retroarch-rmp retroarch-config shaders ppsspp drastic other-emu"
|
||||
fi
|
||||
|
||||
# Confirm restore
|
||||
echo ""
|
||||
echo -e "${YELLOW}Restore the following components on ${ROCKNIX_HOST}?${NC}"
|
||||
for choice in $CHOICES; do
|
||||
case "$choice" in
|
||||
retroarch-core-options) echo " - RetroArch core-options" ;;
|
||||
retroarch-opt) echo " - RetroArch .opt" ;;
|
||||
retroarch-rmp) echo " - RetroArch .rmp" ;;
|
||||
retroarch-config) echo " - RetroArch overrides" ;;
|
||||
shaders) echo " - Shaders" ;;
|
||||
ppsspp) echo " - PPSSPP" ;;
|
||||
drastic) echo " - DraStic" ;;
|
||||
other-emu) echo " - Other emulators" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo ""
|
||||
read -p "Confirm restore? (y/N): " confirm
|
||||
if [[ "$confirm" != "s" && "$confirm" != "S" ]]; then
|
||||
log INFO "Restore cancelled"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Create safety backup on target console
|
||||
log INFO "Creating safety backup on console..."
|
||||
SAFETY_DIR="${TMP_DIR}/safety"
|
||||
mkdir -p "$SAFETY_DIR"
|
||||
|
||||
# Download current files before overwriting
|
||||
for choice in $CHOICES; do
|
||||
case "$choice" in
|
||||
retroarch-core-options)
|
||||
download_file ".config/retroarch/retroarch-core-options.cfg" \
|
||||
"${SAFETY_DIR}/retroarch-core-options.cfg" \
|
||||
"$ROCKNIX_HOST" "$ROCKNIX_USER" 2>/dev/null || true
|
||||
;;
|
||||
# Add others if needed
|
||||
esac
|
||||
done
|
||||
|
||||
log INFO "Safety backup created"
|
||||
|
||||
# Restore files
|
||||
log INFO "Restoring files..."
|
||||
RESTORED=0
|
||||
FAILED=0
|
||||
|
||||
for choice in $CHOICES; do
|
||||
log INFO "Restoring: ${choice}..."
|
||||
|
||||
case "$choice" in
|
||||
retroarch-core-options)
|
||||
if [[ -f "${TMP_DIR}/.config/retroarch/retroarch-core-options.cfg" ]]; then
|
||||
if upload_file "${TMP_DIR}/.config/retroarch/retroarch-core-options.cfg" \
|
||||
".config/retroarch/retroarch-core-options.cfg" \
|
||||
"$ROCKNIX_HOST" "$ROCKNIX_USER" &>/dev/null; then
|
||||
RESTORED=$((RESTORED + 1))
|
||||
else
|
||||
FAILED=$((FAILED + 1))
|
||||
log WARN "Error restoring retroarch-core-options.cfg"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
retroarch-opt)
|
||||
for opt_file in "${TMP_DIR}/.config/retroarch/"*.opt; do
|
||||
if [[ -f "$opt_file" ]]; then
|
||||
filename=$(basename "$opt_file")
|
||||
if upload_file "$opt_file" \
|
||||
".config/retroarch/${filename}" \
|
||||
"$ROCKNIX_HOST" "$ROCKNIX_USER" &>/dev/null; then
|
||||
RESTORED=$((RESTORED + 1))
|
||||
else
|
||||
FAILED=$((FAILED + 1))
|
||||
fi
|
||||
fi
|
||||
done
|
||||
;;
|
||||
retroarch-rmp)
|
||||
for rmp_file in "${TMP_DIR}/.config/retroarch/"*.rmp; do
|
||||
if [[ -f "$rmp_file" ]]; then
|
||||
filename=$(basename "$rmp_file")
|
||||
if upload_file "$rmp_file" \
|
||||
".config/retroarch/${filename}" \
|
||||
"$ROCKNIX_HOST" "$ROCKNIX_USER" &>/dev/null; then
|
||||
RESTORED=$((RESTORED + 1))
|
||||
else
|
||||
FAILED=$((FAILED + 1))
|
||||
fi
|
||||
fi
|
||||
done
|
||||
;;
|
||||
retroarch-config)
|
||||
if [[ -d "${TMP_DIR}/.config/retroarch/config/" ]]; then
|
||||
if upload_dir "${TMP_DIR}/.config/retroarch/config/" \
|
||||
".config/retroarch/config/" \
|
||||
"$ROCKNIX_HOST" "$ROCKNIX_USER" &>/dev/null; then
|
||||
RESTORED=$((RESTORED + 1))
|
||||
else
|
||||
FAILED=$((FAILED + 1))
|
||||
log WARN "Error restoring config/"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
shaders)
|
||||
if [[ -d "${TMP_DIR}/shaders/" ]]; then
|
||||
if upload_dir "${TMP_DIR}/shaders/" \
|
||||
"shaders/" \
|
||||
"$ROCKNIX_HOST" "$ROCKNIX_USER" &>/dev/null; then
|
||||
RESTORED=$((RESTORED + 1))
|
||||
else
|
||||
FAILED=$((FAILED + 1))
|
||||
log WARN "Error restoring shaders/"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
ppsspp)
|
||||
if [[ -f "${TMP_DIR}/.config/ppsspp/PSP/SYSTEM/ppsspp.ini" ]]; then
|
||||
upload_file "${TMP_DIR}/.config/ppsspp/PSP/SYSTEM/ppsspp.ini" \
|
||||
".config/ppsspp/PSP/SYSTEM/ppsspp.ini" \
|
||||
"$ROCKNIX_HOST" "$ROCKNIX_USER" 2>/dev/null && RESTORED=$((RESTORED + 1)) || FAILED=$((FAILED + 1))
|
||||
fi
|
||||
if [[ -f "${TMP_DIR}/.config/ppsspp/PSP/SYSTEM/controls.ini" ]]; then
|
||||
upload_file "${TMP_DIR}/.config/ppsspp/PSP/SYSTEM/controls.ini" \
|
||||
".config/ppsspp/PSP/SYSTEM/controls.ini" \
|
||||
"$ROCKNIX_HOST" "$ROCKNIX_USER" 2>/dev/null && RESTORED=$((RESTORED + 1)) || FAILED=$((FAILED + 1))
|
||||
fi
|
||||
;;
|
||||
drastic)
|
||||
if [[ -d "${TMP_DIR}/.config/drastic/config/" ]]; then
|
||||
if upload_dir "${TMP_DIR}/.config/drastic/config/" \
|
||||
".config/drastic/config/" \
|
||||
"$ROCKNIX_HOST" "$ROCKNIX_USER" &>/dev/null; then
|
||||
RESTORED=$((RESTORED + 1))
|
||||
else
|
||||
FAILED=$((FAILED + 1))
|
||||
log WARN "Error restoring drastic/config/"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
other-emu)
|
||||
for emu_path in ".config/game/configs" ".config/flycast" ".config/duckstation" ".config/yabasanshiro"; do
|
||||
if [[ -e "${TMP_DIR}/${emu_path}" ]]; then
|
||||
upload_dir "${TMP_DIR}/${emu_path}/" "${emu_path}/" \
|
||||
"$ROCKNIX_HOST" "$ROCKNIX_USER" 2>/dev/null && RESTORED=$((RESTORED + 1)) || FAILED=$((FAILED + 1))
|
||||
fi
|
||||
done
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Clean up temporary safety backup
|
||||
cleanup_tmp "${SAFETY_DIR}" 2>/dev/null || true
|
||||
|
||||
# Summary
|
||||
echo ""
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo -e "${GREEN} Restore completed${NC}"
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo ""
|
||||
echo -e " Device: ${CYAN}${DEVICE}${NC}"
|
||||
echo -e " Restored: ${CYAN}${RESTORED}${NC}"
|
||||
if [[ $FAILED -gt 0 ]]; then
|
||||
echo -e " Failed: ${RED}${FAILED}${NC}"
|
||||
fi
|
||||
echo ""
|
||||
echo -e " ${YELLOW}Note: Restart the console to apply changes${NC}"
|
||||
echo ""
|
||||
Reference in New Issue
Block a user