feat: add script for creating self-extracting archives
- 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
This commit is contained in:
78
build_sfx.sh
Executable file
78
build_sfx.sh
Executable file
@@ -0,0 +1,78 @@
|
||||
#!/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"
|
19
sfx_header.sh
Normal file
19
sfx_header.sh
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
TMPDIR="$(mktemp -d "${TMPDIR:-/tmp}/sfx.XXXXXX")"
|
||||
ARCHIVE_LINE=__ARCHIVE_LINE__
|
||||
|
||||
cleanup() {
|
||||
rm -rf "$TMPDIR"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
tail -n +$ARCHIVE_LINE "$0" | unzstd | tar -xf - -C "$TMPDIR"
|
||||
|
||||
ENTRYPOINT="$TMPDIR/__ENTRYPOINT__"
|
||||
chmod +x "$ENTRYPOINT"
|
||||
"$ENTRYPOINT" "$@"
|
||||
exit_code=$?
|
||||
exit $exit_code
|
||||
__ARCHIVE_BEGIN__
|
Reference in New Issue
Block a user