firmware/general/package/wifibroadcast-ext/files/generate_backup.sh

117 lines
4.6 KiB
Bash

#!/bin/sh
#
# Script: generate_backup.sh
# Purpose: Read one or more file/directory paths (from a file list or a single argument),
# copy them into a staging area preserving their relative paths,
# remove unwanted subdirectories (specifically /overlay/root/root if backing up /overlay/root),
# and then generate a SHA1 checksum file where the filenames are shown relative to the staging root.
#
# Usage:
# ./generate_backup.sh file_list.txt
# - Reads absolute paths (files or directories) from file_list.txt.
#
# ./generate_backup.sh /some/path
# - Backs up the specified path recursively.
#
# ./generate_backup.sh
# - Defaults to backing up /overlay/root.
#
# --- Determine Input Mode ---
found_overlay_root=0
if [ $# -lt 1 ]; then
mode="single"
single_path="/overlay/root"
elif [ -f "$1" ]; then
mode="list"
list_file="$1"
elif [ -d "$1" ]; then
mode="single"
single_path="$1"
else
echo "Error: Provided argument is neither a file list nor a directory."
exit 1
fi
# --- Directories and File Names ---
BACKUP_STAGING_DIR="/tmp/backup/staging"
FINAL_BACKUP_DIR="/tmp/backup"
TAR_FILE="$FINAL_BACKUP_DIR/backup.tar"
TAR_GZ_FILE="$FINAL_BACKUP_DIR/backup.tar.gz"
CHECKSUM_FILE="$BACKUP_STAGING_DIR/checksum.txt"
# --- Prepare Staging Area ---
rm -rf "$BACKUP_STAGING_DIR" 2>/dev/null
mkdir -p "$BACKUP_STAGING_DIR" || { echo "Error: Could not create staging directory '$BACKUP_STAGING_DIR'."; exit 1; }
# --- Function: process_path ---
# Copies a file or directory into the staging area preserving its relative path.
process_path() {
filepath="$1"
[ -z "$filepath" ] && return
# Remove trailing slashes (unless the path is just "/")
if [ "$filepath" != "/" ]; then
filepath=$(echo "$filepath" | sed 's:/*$::')
fi
# Mark if the backup source is exactly /overlay/root
if [ "$filepath" = "/overlay/root" ]; then
found_overlay_root=1
fi
if [ -f "$filepath" ]; then
REL_PATH=$(echo "$filepath" | sed 's|^/||')
DEST_DIR="$BACKUP_STAGING_DIR/$(dirname "$REL_PATH")"
mkdir -p "$DEST_DIR" || { echo "Error: Could not create subdirectory for '$REL_PATH' in staging."; exit 1; }
cp "$filepath" "$DEST_DIR" || { echo "Error: Could not copy '$filepath' to staging area."; exit 1; }
elif [ -d "$filepath" ]; then
REL_PATH=$(echo "$filepath" | sed 's|^/||')
DEST_PARENT="$BACKUP_STAGING_DIR/$(dirname "$REL_PATH")"
mkdir -p "$DEST_PARENT" || { echo "Error: Could not create parent directory '$DEST_PARENT'."; exit 1; }
cp -r "$filepath" "$DEST_PARENT" || { echo "Error: Could not copy directory '$filepath' to staging area."; exit 1; }
else
echo "Error: File or directory '$filepath' does not exist."
exit 1
fi
}
# --- Process Input ---
if [ "$mode" = "list" ]; then
while IFS= read -r line; do
process_path "$line"
done < "$list_file"
elif [ "$mode" = "single" ]; then
process_path "$single_path"
fi
# --- Remove Unwanted Subfolder ---
# If /overlay/root was among the sources, then in the staging area the files are under "overlay/root".
# Remove the extra "root" folder (i.e. /tmp/backup/staging/overlay/root/root) if it exists.
if [ $found_overlay_root -eq 1 ]; then
unwanted_dir="$BACKUP_STAGING_DIR/overlay/root/root"
if [ -d "$unwanted_dir" ]; then
rm -rf "$unwanted_dir" || { echo "Error: Could not remove unwanted folder '$unwanted_dir' from staging area."; exit 1; }
fi
fi
# --- Generate Checksum File with Relative Paths ---
# We walk the staging directory and, for each file, remove the staging prefix.
# (This sed substitution technique is a common method for converting absolute paths to relative ones :contentReference[oaicite:0]{index=0}.)
> "$CHECKSUM_FILE" || { echo "Error: Cannot write to checksum file '$CHECKSUM_FILE'."; exit 1; }
find "$BACKUP_STAGING_DIR" -type f ! -name "$(basename "$CHECKSUM_FILE")" | while IFS= read -r file; do
# Remove the staging prefix to get the relative path.
rel=$(echo "$file" | sed "s|^$BACKUP_STAGING_DIR/||")
checksum=$(sha1sum "$file" | awk '{print $1}')
echo "$checksum $rel"
done > "$CHECKSUM_FILE" || { echo "Error: Failed to generate checksums."; exit 1; }
# --- Create Tar Archive and Compress ---
mkdir -p "$FINAL_BACKUP_DIR" || { echo "Error: Could not create final backup directory '$FINAL_BACKUP_DIR'."; exit 1; }
tar -C "$BACKUP_STAGING_DIR" -cvf "$TAR_FILE" . || { echo "Error: Failed to create tar file from staging directory."; exit 1; }
gzip -f "$TAR_FILE" || { echo "Error: Failed to compress tar file."; exit 1; }
echo "Backup archive successfully created at: $TAR_GZ_FILE"
exit 0