From 417eb4c7be225e33699822ca5831151e958d0a7a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Dec 2025 17:00:59 +0000 Subject: [PATCH 1/3] Initial plan From 1e08cc43fe24c65d4a13efffdf3860521888a9d9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Dec 2025 17:05:41 +0000 Subject: [PATCH 2/3] Add installation script with validation and progress display Co-authored-by: johndoe6345789 <224850594+johndoe6345789@users.noreply.github.com> --- README.md | 26 ++++-- scripts/install.sh | 218 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 239 insertions(+), 5 deletions(-) create mode 100755 scripts/install.sh diff --git a/README.md b/README.md index 57b765a..8f29e1b 100644 --- a/README.md +++ b/README.md @@ -102,12 +102,27 @@ sudo apt-get install syslinux parted # Build everything and create image make all sudo make image - -# Write to USB drive (CAUTION: destroys all data on target!) -sudo dd if=sparkos.img of=/dev/sdX bs=4M status=progress ``` -Replace `/dev/sdX` with your actual USB device (e.g., `/dev/sdb`). +### Installing to USB Drive + +Once you have created the `sparkos.img` file, use the installation script to write it to a USB drive or storage device: + +```bash +# Use the installation script (RECOMMENDED) +sudo ./scripts/install.sh /dev/sdX + +# The script will: +# - Validate the target drive +# - Display warnings about data destruction +# - Require confirmation before proceeding +# - Show progress during installation +# - Verify successful installation +``` + +Replace `/dev/sdX` with your actual USB device (e.g., `/dev/sdb`, `/dev/nvme1n1`). + +**⚠️ WARNING**: This will permanently erase all data on the target drive! ## Project Structure @@ -121,7 +136,8 @@ SparkOS/ ├── scripts/ # Build and setup scripts │ ├── build.sh # Quick build script │ ├── setup_rootfs.sh # Root filesystem setup -│ └── create_image.sh # Image creation script +│ ├── create_image.sh # Image creation script +│ └── install.sh # Installation script for USB drives ├── src/ # Source code │ └── init.c # Custom init system ├── rootfs/ # Root filesystem (generated) diff --git a/scripts/install.sh b/scripts/install.sh new file mode 100755 index 0000000..e4aa38a --- /dev/null +++ b/scripts/install.sh @@ -0,0 +1,218 @@ +#!/bin/bash +# SparkOS Installation Script +# Writes the SparkOS image to a target drive +# Note: This script runs on the host system and uses bash for ${BASH_SOURCE} + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +IMAGE_FILE="$PROJECT_ROOT/sparkos.img" + +# Cleanup function +cleanup() { + local exit_code=$? + if [ $exit_code -ne 0 ]; then + echo "" + echo "ERROR: Installation failed" + fi + exit $exit_code +} + +# Set trap for cleanup on exit, interrupt, or error +trap cleanup EXIT INT TERM + +# Print usage +usage() { + cat << EOF +SparkOS Installation Script +=========================== + +Usage: $0 + +Arguments: + target_drive Block device to install to (e.g., /dev/sdb, /dev/nvme1n1) + +Example: + sudo $0 /dev/sdb + sudo $0 /dev/nvme1n1 + +WARNING: This will DESTROY all data on the target drive! + +EOF + exit 1 +} + +# Print header +echo "SparkOS Installation Script" +echo "===========================" +echo "" + +# Check if running as root +if [ "$(id -u)" -ne 0 ]; then + echo "ERROR: This script must be run as root" + echo "Usage: sudo $0 " + exit 1 +fi + +# Check for target drive argument +if [ $# -eq 0 ]; then + echo "ERROR: No target drive specified" + echo "" + usage +fi + +TARGET_DRIVE="$1" + +# Validate image file exists +if [ ! -f "$IMAGE_FILE" ]; then + echo "ERROR: SparkOS image not found: $IMAGE_FILE" + echo "" + echo "Please build the image first:" + echo " make all" + echo " sudo make image" + exit 1 +fi + +# Validate target drive exists +if [ ! -e "$TARGET_DRIVE" ]; then + echo "ERROR: Target drive does not exist: $TARGET_DRIVE" + echo "" + echo "Available block devices:" + lsblk -d -o NAME,SIZE,TYPE,MODEL | grep -E '^NAME|disk' || echo " No block devices found" + exit 1 +fi + +# Validate target is a block device +if [ ! -b "$TARGET_DRIVE" ]; then + echo "ERROR: Target is not a block device: $TARGET_DRIVE" + echo "" + echo "Please specify a block device (e.g., /dev/sdb, /dev/nvme1n1)" + exit 1 +fi + +# Check for required tool +if ! command -v dd &> /dev/null; then + echo "ERROR: Required tool 'dd' is not installed" + exit 1 +fi + +# Get drive information +DRIVE_SIZE=$(lsblk -b -d -n -o SIZE "$TARGET_DRIVE" 2>/dev/null || echo "unknown") +DRIVE_MODEL=$(lsblk -d -n -o MODEL "$TARGET_DRIVE" 2>/dev/null || echo "unknown") +IMAGE_SIZE=$(stat -c%s "$IMAGE_FILE" 2>/dev/null || echo "unknown") + +# Check if target drive is large enough +if [ "$DRIVE_SIZE" != "unknown" ] && [ "$IMAGE_SIZE" != "unknown" ]; then + if [ "$DRIVE_SIZE" -lt "$IMAGE_SIZE" ]; then + echo "ERROR: Target drive is too small" + echo " Drive size: $(numfmt --to=iec-i --suffix=B $DRIVE_SIZE 2>/dev/null || echo $DRIVE_SIZE)" + echo " Image size: $(numfmt --to=iec-i --suffix=B $IMAGE_SIZE 2>/dev/null || echo $IMAGE_SIZE)" + exit 1 + fi +fi + +# Display warning and drive information +echo "⚠️ WARNING: DATA DESTRUCTION IMMINENT ⚠️" +echo "" +echo "This will completely erase all data on the target drive!" +echo "" +echo "Target drive information:" +echo " Device: $TARGET_DRIVE" +echo " Model: $DRIVE_MODEL" +if [ "$DRIVE_SIZE" != "unknown" ]; then + echo " Size: $(numfmt --to=iec-i --suffix=B $DRIVE_SIZE 2>/dev/null || echo $DRIVE_SIZE)" +fi +echo "" +echo "Image information:" +echo " File: $IMAGE_FILE" +if [ "$IMAGE_SIZE" != "unknown" ]; then + echo " Size: $(numfmt --to=iec-i --suffix=B $IMAGE_SIZE 2>/dev/null || echo $IMAGE_SIZE)" +fi +echo "" + +# Show mounted partitions on target drive +MOUNTED=$(lsblk -n -o MOUNTPOINT "$TARGET_DRIVE" 2>/dev/null | grep -v '^$' || true) +if [ -n "$MOUNTED" ]; then + echo "WARNING: The following partitions on $TARGET_DRIVE are currently mounted:" + lsblk -o NAME,MOUNTPOINT "$TARGET_DRIVE" | grep -v '^$' + echo "" + echo "Please unmount all partitions before proceeding" + exit 1 +fi + +# Require user confirmation +echo "Are you absolutely sure you want to proceed?" +echo -n "Type 'YES' (in all caps) to confirm: " +read CONFIRMATION + +if [ "$CONFIRMATION" != "YES" ]; then + echo "" + echo "Installation cancelled by user" + exit 0 +fi + +echo "" +echo "Starting installation..." +echo "" + +# Unmount any partitions (just to be safe) +for part in "$TARGET_DRIVE"*[0-9]; do + if mountpoint -q "$part" 2>/dev/null; then + echo "Unmounting $part..." + umount "$part" 2>/dev/null || true + fi +done + +# Write image to drive with progress +echo "Writing SparkOS image to $TARGET_DRIVE..." +echo "This may take several minutes..." +echo "" + +if dd if="$IMAGE_FILE" of="$TARGET_DRIVE" bs=4M status=progress conv=fsync 2>&1; then + echo "" + echo "Image write completed successfully" +else + echo "" + echo "ERROR: Failed to write image to drive" + exit 1 +fi + +# Sync to ensure all data is written +echo "" +echo "Syncing data to disk..." +sync + +# Verify installation by reading back the first few blocks +echo "Verifying installation..." +VERIFY_BLOCKS=1024 +dd if="$TARGET_DRIVE" of=/tmp/sparkos_verify.img bs=512 count=$VERIFY_BLOCKS status=none 2>/dev/null +dd if="$IMAGE_FILE" of=/tmp/sparkos_source.img bs=512 count=$VERIFY_BLOCKS status=none 2>/dev/null + +if cmp -s /tmp/sparkos_verify.img /tmp/sparkos_source.img; then + echo "✓ Verification successful - installation completed!" +else + echo "✗ Verification failed - installation may be corrupted" + rm -f /tmp/sparkos_verify.img /tmp/sparkos_source.img + exit 1 +fi + +# Clean up verification files +rm -f /tmp/sparkos_verify.img /tmp/sparkos_source.img + +echo "" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "SUCCESS! SparkOS has been installed to $TARGET_DRIVE" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" +echo "You can now:" +echo " 1. Safely remove the drive" +echo " 2. Boot from the drive" +echo " 3. Log in as user 'spark'" +echo "" +echo "First boot instructions:" +echo " - The system will boot with wired networking enabled" +echo " - Default user: spark (full sudo access)" +echo " - Run ~/clone-sparkos.sh to install spark CLI" +echo " - Use spark CLI to configure WiFi and system" +echo "" From 5fd59ce63acd410aa4065bd4207ee4f6fa0d3435 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Dec 2025 17:07:49 +0000 Subject: [PATCH 3/3] Fix security and robustness issues in install script Co-authored-by: johndoe6345789 <224850594+johndoe6345789@users.noreply.github.com> --- scripts/install.sh | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/scripts/install.sh b/scripts/install.sh index e4aa38a..6ff07d5 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -132,10 +132,10 @@ fi echo "" # Show mounted partitions on target drive -MOUNTED=$(lsblk -n -o MOUNTPOINT "$TARGET_DRIVE" 2>/dev/null | grep -v '^$' || true) +MOUNTED=$(lsblk -n -o MOUNTPOINT "$TARGET_DRIVE" 2>/dev/null | grep -v '^[[:space:]]*$' || true) if [ -n "$MOUNTED" ]; then echo "WARNING: The following partitions on $TARGET_DRIVE are currently mounted:" - lsblk -o NAME,MOUNTPOINT "$TARGET_DRIVE" | grep -v '^$' + lsblk -o NAME,MOUNTPOINT "$TARGET_DRIVE" echo "" echo "Please unmount all partitions before proceeding" exit 1 @@ -157,12 +157,16 @@ echo "Starting installation..." echo "" # Unmount any partitions (just to be safe) -for part in "$TARGET_DRIVE"*[0-9]; do - if mountpoint -q "$part" 2>/dev/null; then - echo "Unmounting $part..." - umount "$part" 2>/dev/null || true - fi -done +# Use lsblk to get actual partition names (works for all device types including NVMe) +PARTITIONS=$(lsblk -ln -o NAME "$TARGET_DRIVE" 2>/dev/null | tail -n +2 | sed 's|^|/dev/|' || true) +if [ -n "$PARTITIONS" ]; then + for part in $PARTITIONS; do + if mountpoint -q "$part" 2>/dev/null; then + echo "Unmounting $part..." + umount "$part" 2>/dev/null || true + fi + done +fi # Write image to drive with progress echo "Writing SparkOS image to $TARGET_DRIVE..." @@ -186,19 +190,25 @@ sync # Verify installation by reading back the first few blocks echo "Verifying installation..." VERIFY_BLOCKS=1024 -dd if="$TARGET_DRIVE" of=/tmp/sparkos_verify.img bs=512 count=$VERIFY_BLOCKS status=none 2>/dev/null -dd if="$IMAGE_FILE" of=/tmp/sparkos_source.img bs=512 count=$VERIFY_BLOCKS status=none 2>/dev/null +VERIFY_TMP=$(mktemp -t sparkos_verify.XXXXXXXX) +SOURCE_TMP=$(mktemp -t sparkos_source.XXXXXXXX) -if cmp -s /tmp/sparkos_verify.img /tmp/sparkos_source.img; then +# Ensure temp files are cleaned up on exit +trap "rm -f $VERIFY_TMP $SOURCE_TMP; cleanup" EXIT INT TERM + +dd if="$TARGET_DRIVE" of="$VERIFY_TMP" bs=512 count=$VERIFY_BLOCKS status=none 2>/dev/null +dd if="$IMAGE_FILE" of="$SOURCE_TMP" bs=512 count=$VERIFY_BLOCKS status=none 2>/dev/null + +if cmp -s "$VERIFY_TMP" "$SOURCE_TMP"; then echo "✓ Verification successful - installation completed!" else echo "✗ Verification failed - installation may be corrupted" - rm -f /tmp/sparkos_verify.img /tmp/sparkos_source.img + rm -f "$VERIFY_TMP" "$SOURCE_TMP" exit 1 fi # Clean up verification files -rm -f /tmp/sparkos_verify.img /tmp/sparkos_source.img +rm -f "$VERIFY_TMP" "$SOURCE_TMP" echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"