#!/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}" }