- Introduces a script to build self-extracting archives with validation - Includes payload compression, placeholder replacement, and output creation - Adds a header script to extract and execute the embedded entrypoint
79 lines
2.1 KiB
Bash
Executable File
79 lines
2.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
usage() {
|
|
echo "Usage: $0 --payload-dir DIR --entrypoint FILE [--output FILE]"
|
|
echo " $0 -p DIR -e FILE [-o FILE]"
|
|
exit 1
|
|
}
|
|
|
|
# 📥 Default values
|
|
HEADER="sfx_header.sh"
|
|
PAYLOAD_DIR=""
|
|
ENTRYPOINT=""
|
|
OUTPUT="sfx.run"
|
|
|
|
# 📋 Process arguments
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--payload-dir|-p)
|
|
PAYLOAD_DIR="$2"
|
|
shift 2
|
|
;;
|
|
--entrypoint|-e)
|
|
ENTRYPOINT="$2"
|
|
shift 2
|
|
;;
|
|
--output|-o)
|
|
OUTPUT="$2"
|
|
shift 2
|
|
;;
|
|
*)
|
|
echo "❌ Unknown option: $1" >&2
|
|
usage
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# ✅ Validation
|
|
[[ -z "$PAYLOAD_DIR" || -z "$ENTRYPOINT" ]] && usage
|
|
[[ ! -d "$PAYLOAD_DIR" ]] && { echo "❌ Payload directory not found: $PAYLOAD_DIR" >&2; exit 1; }
|
|
[[ ! -f "$PAYLOAD_DIR/$ENTRYPOINT" ]] && { echo "❌ Entrypoint not found in payload: $ENTRYPOINT" >&2; exit 1; }
|
|
|
|
# 🧊 Temporary directory
|
|
BUILD_TMP="$(mktemp -d "${TMPDIR:-/tmp}/sfxbuild.XXXXXX")"
|
|
PAYLOAD_ARCHIVE="$BUILD_TMP/payload.tar.zst"
|
|
HEADER_TMP="$BUILD_TMP/sfx_header.final"
|
|
|
|
cleanup() {
|
|
rm -rf "$BUILD_TMP"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
echo "📦 Creating payload (→ $PAYLOAD_ARCHIVE)..."
|
|
tar -cf - -C "$PAYLOAD_DIR" . | tee >(wc -c > "$BUILD_TMP/raw_size") | zstd -19 -T0 -o "$PAYLOAD_ARCHIVE"
|
|
RAW_SIZE=$(numfmt --to=iec < "$BUILD_TMP/raw_size")
|
|
|
|
# 🧭 Find marker
|
|
ARCHIVE_LINE=$(grep -n '^__ARCHIVE_BEGIN__$' "$HEADER" | cut -d: -f1)
|
|
[[ ! "$ARCHIVE_LINE" =~ ^[0-9]+$ ]] && {
|
|
echo "❌ Error: Marker __ARCHIVE_BEGIN__ not found!" >&2
|
|
exit 1
|
|
}
|
|
echo "🧮 Archive starts from line $ARCHIVE_LINE"
|
|
|
|
# 🛠️ Replace placeholders
|
|
sed "s|__ARCHIVE_LINE__|$ARCHIVE_LINE|" "$HEADER" | \
|
|
sed "s|__ENTRYPOINT__|$ENTRYPOINT|" | \
|
|
sed '/^__ARCHIVE_BEGIN__$/d' > "$HEADER_TMP"
|
|
|
|
# 🔗 Combine
|
|
cat "$HEADER_TMP" "$PAYLOAD_ARCHIVE" > "$OUTPUT"
|
|
chmod +x "$OUTPUT"
|
|
|
|
# 📊 Output
|
|
FINAL_SIZE=$(du -h "$OUTPUT" | cut -f1)
|
|
echo "✅ Done: $OUTPUT"
|
|
echo " 📁 Original size: $RAW_SIZE"
|
|
echo " 📦 Output file: $FINAL_SIZE"
|