Merge pull request #29 from johndoe6345789/copilot/remove-busybox-and-cli-tools

Remove busybox and CLI dependencies for pure GUI architecture
This commit is contained in:
2026-01-02 01:51:20 +00:00
committed by GitHub
19 changed files with 419 additions and 711 deletions

View File

@@ -90,7 +90,7 @@ Modern computing is inherently networked. Instead of treating networking as an a
### Planned Components
1. **Qt6/QML GUI**
- Full-screen Wayland application
- Full-screen application
- Android-like interface design
- Desktop-oriented workflow
@@ -99,16 +99,10 @@ Modern computing is inherently networked. Instead of treating networking as an a
- Minimal resource usage
- Touch and mouse support
3. **Spark CLI Tools (C++)**
- System management utilities
- Package management
- Network configuration (WiFi, VPN, etc.)
- GUI launcher
4. **Bootstrap Utilities (Included)**
- Git for cloning spark CLI
- Sudo for proper privilege elevation
- Busybox for core system utilities and networking
3. **Network Management**
- Qt6 NetworkManager integration
- WiFi configuration UI
- VPN and advanced networking UI
## Security Considerations
@@ -121,9 +115,9 @@ Modern computing is inherently networked. Instead of treating networking as an a
## Performance
- Fast boot time (seconds, not minutes)
- Low memory footprint (~50MB base system with busybox)
- Low memory footprint (~20MB base init system)
- No unnecessary background services
- Efficient init system
- Efficient init system (no external dependencies)
## Portability

View File

@@ -1,133 +0,0 @@
# BusyBox Verification in SparkOS
This document demonstrates how SparkOS verifies that BusyBox is being used.
## Docker Container Verification
When you run the SparkOS Docker container, it automatically verifies BusyBox installation and functionality:
```bash
docker run --rm ghcr.io/johndoe6345789/sparkos:latest
```
## Expected Output
The container startup will display comprehensive BusyBox verification:
```
SparkOS Docker Test Environment
================================
Verifying BusyBox...
-------------------
✓ BusyBox is installed
BusyBox version:
BusyBox v1.36.1 (Alpine Linux) multi-call binary.
BusyBox location:
/bin/busybox
-rwxr-xr-x 1 root root 1.2M Dec 29 19:00 /bin/busybox
Shell (/bin/sh) is BusyBox:
lrwxrwxrwx 1 root root 12 Dec 29 19:00 /bin/sh -> /bin/busybox
→ /bin/sh is a symlink to: /bin/busybox
Available BusyBox applets (sample):
[
[[
acpid
addgroup
adduser
adjtimex
ar
arch
arp
arping
ash
awk
... and 300+ total applets
Networking applets (required for SparkOS):
✓ udhcpc
✓ ip
✓ ifconfig
✓ ping
✓ wget
Verifying SparkOS init binary...
--------------------------------
✓ Init binary exists
-rwxr-xr-x 1 root root 18.2K Dec 29 19:00 /sparkos/rootfs/sbin/init
File type:
/sparkos/rootfs/sbin/init: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked
Dependencies:
Static binary (no dependencies)
Root filesystem structure:
--------------------------
total 28
drwxr-xr-x 7 root root 4096 Dec 29 19:00 .
drwxr-xr-x 1 root root 4096 Dec 29 19:00 ..
drwxr-xr-x 2 root root 4096 Dec 29 19:00 bin
drwxr-xr-x 2 root root 4096 Dec 29 19:00 etc
drwxr-xr-x 3 root root 4096 Dec 29 19:00 home
drwxr-xr-x 2 root root 4096 Dec 29 19:00 sbin
drwxr-xr-x 2 root root 4096 Dec 29 19:00 usr
================================
✓ SparkOS is ready for testing!
================================
Summary:
- BusyBox: BusyBox v1.36.1 (Alpine Linux) multi-call binary.
- Init: Custom SparkOS init system
- Shell: BusyBox sh (/bin/sh)
- Networking: BusyBox udhcpc, ip, ping, wget
To test the init system:
docker run --rm <image> /sparkos/rootfs/sbin/init --help
```
## What This Proves
The verification output demonstrates:
1. **BusyBox is installed**: Shows version and location
2. **Shell is BusyBox**: `/bin/sh` is a symlink to `/bin/busybox`
3. **Multiple utilities available**: 300+ BusyBox applets (commands)
4. **Networking support**: All required networking tools are present (udhcpc, ip, ifconfig, ping, wget)
5. **Custom init system**: SparkOS init binary is statically compiled and ready
## Key BusyBox Features Used by SparkOS
- **Shell**: `sh` (BusyBox ash shell)
- **Networking**:
- `udhcpc` - DHCP client for automatic IP configuration
- `ip` / `ifconfig` - Network interface configuration
- `ping` - Network connectivity testing
- `wget` - File downloading
- **Core utilities**: `ls`, `cat`, `mkdir`, `rm`, `cp`, `mount`, etc.
- **System utilities**: Over 300 common Linux commands in a single binary
## Alpine Linux and BusyBox
SparkOS uses Alpine Linux as its Docker base image, which includes BusyBox by default. This provides:
- **Minimal footprint**: Entire system in ~5MB
- **Security**: Minimal attack surface with fewer packages
- **Performance**: Fast startup and low memory usage
- **Completeness**: All essential utilities in one binary
## Verification in Code
The verification is performed by `/sparkos/test.sh` which:
1. Checks if `busybox` command is available
2. Displays version information
3. Lists all available applets
4. Verifies critical networking applets
5. Confirms init binary is present and correct
This ensures that anyone running the SparkOS Docker container can immediately see proof that BusyBox is being used as advertised.

View File

@@ -23,9 +23,9 @@ FROM alpine:3.19
COPY scripts/docker-install-packages.sh /tmp/
RUN /tmp/docker-install-packages.sh
# Alpine Linux includes BusyBox by default
# BusyBox provides: shell (sh), networking (udhcpc, ip, ping, wget), and core utilities
# This is verified by the test.sh script which shows BusyBox version and available applets
# SparkOS Philosophy: No CLI tools, GUI-only experience
# The init system is completely self-contained with no external dependencies
# All functionality is provided through direct system calls in C
# Create minimal rootfs structure
COPY scripts/docker-setup-rootfs.sh /tmp/

111
INIT_VERIFICATION.md Normal file
View File

@@ -0,0 +1,111 @@
# SparkOS Init System Verification
This document demonstrates SparkOS's self-contained init system with no external dependencies.
## Docker Container Verification
When you run the SparkOS Docker container, it automatically verifies the init system:
```bash
docker run --rm ghcr.io/johndoe6345789/sparkos:latest
```
## Expected Output
The container startup will display comprehensive init system verification:
```
SparkOS Docker Test Environment
================================
Verifying SparkOS init binary...
--------------------------------
✓ Init binary exists
-rwxr-xr-x 1 root root 20.0K Jan 2 00:00 /sparkos/rootfs/sbin/init
File type:
/sparkos/rootfs/sbin/init: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked
Dependencies:
Static binary (no dependencies)
Root filesystem structure:
--------------------------
total 16
drwxr-xr-x 5 root root 4096 Jan 2 00:00 .
drwxr-xr-x 1 root root 4096 Jan 2 00:00 ..
drwxr-xr-x 2 root root 4096 Jan 2 00:00 etc
drwxr-xr-x 2 root root 4096 Jan 2 00:00 sbin
drwxr-xr-x 2 root root 4096 Jan 2 00:00 usr
================================
✓ SparkOS is ready for testing!
================================
Summary:
- Init: Custom SparkOS init system (no external dependencies)
- Architecture: GUI-only, no CLI/shell
- Network: Direct C implementation via ioctl
- Philosophy: Pure GUI experience, network-first
Note: SparkOS has no CLI tools (no busybox, no shell)
All functionality is provided through the Qt6 GUI
To test the init system:
docker run --rm <image> /sparkos/rootfs/sbin/init
```
## What This Proves
The verification output demonstrates:
1. **Self-contained init**: Statically linked binary with no external dependencies
2. **No CLI tools**: No busybox, no shell, no Unix utilities
3. **Minimal footprint**: Only essential files in root filesystem
4. **Pure C implementation**: All functionality (mounting, networking) via system calls
## Key Init Features
- **Filesystem mounting**: Direct mount() system calls (no mount binary)
- **Network initialization**: Direct ioctl calls (no ip/ifconfig/udhcpc)
- **Process management**: Built-in SIGCHLD handler for zombie reaping
- **GUI spawning**: Direct execve() of Qt6 GUI application
- **Overlay filesystem**: Immutable base with writable /var overlay
## SparkOS Philosophy
SparkOS eliminates traditional Unix layers:
- **No busybox**: All functionality in init or Qt6 GUI
- **No shell**: Direct kernel-to-GUI communication
- **No CLI tools**: Everything through GUI interface
- **No users/authentication**: Single-user, direct boot to GUI
- **Network-first**: Networking integrated into GUI, not CLI
## Init System Architecture
```
Init Process (PID 1)
├── Mount filesystems (proc, sys, dev, tmp)
├── Setup overlay filesystem (/var)
├── Initialize network interfaces (ioctl)
└── Spawn Qt6 GUI → Respawn on exit
```
All operations use direct system calls:
- `mount()` for filesystem mounting
- `mkdir()` for directory creation
- `socket()` + `ioctl()` for network initialization
- `fork()` + `execve()` for GUI spawning
- `waitpid()` for process reaping
## Verification in Code
The verification is performed by `/sparkos/test.sh` which:
1. Checks if init binary exists and is executable
2. Verifies it's statically linked (no dependencies)
3. Shows root filesystem structure
4. Confirms the GUI-only architecture
This ensures that anyone running the SparkOS Docker container can immediately see proof that SparkOS uses a completely self-contained init system with no external dependencies.

143
README.md
View File

@@ -45,12 +45,12 @@ A revolutionary operating system that ditches Unix conventions for a modern, net
## MVP Status
The current MVP provides:
- ✅ Custom init system written in C
-Working busybox shell environment
- ✅ Custom init system written in C (no external dependencies)
-GUI-only architecture (no CLI/shell)
- ✅ dd-able AMD64 image creation scripts
- ✅ Minimal root filesystem structure
- ✅ Build system (Makefile)
-Wired networking configuration with DHCP
-Direct network initialization via C ioctl
- ✅ DNS configuration with public fallback servers
- ✅ Docker container for testing
- ✅ Automated builds and publishing to GHCR
@@ -102,8 +102,8 @@ The UEFI-bootable disk image includes:
-**UEFI boot support** with GRUB bootloader
-**GPT partition table** with ESP (EFI System Partition)
-**Linux kernel** ready to boot
-**SparkOS init system** and busybox utilities
-**Ready to boot** - No additional setup required
-**SparkOS init system** (completely self-contained, no external dependencies)
-**Ready to boot** - Direct to Qt6 GUI, no CLI
### Using Pre-built Binary Package
@@ -156,14 +156,12 @@ The Docker image includes:
- Pre-built init system binary
- Minimal root filesystem structure
- Test environment for validation
- **BusyBox shell and utilities**: Alpine Linux base provides BusyBox (verified on startup)
- **No CLI tools**: Pure GUI-only architecture
- **Multi-architecture support**: Available for both AMD64 (x86_64) and ARM64 (aarch64) architectures
When you run the Docker image, it automatically verifies:
- BusyBox version and installation
- Available BusyBox applets (sh, ls, cat, etc.)
- Required networking tools (udhcpc, ip, ping, wget)
- Custom init system binary
- Custom init system binary (statically linked, no dependencies)
- Root filesystem structure
Images are automatically built and published to [GitHub Container Registry](https://github.com/johndoe6345789/SparkOS/pkgs/container/sparkos) on every push to main branch.
@@ -220,7 +218,7 @@ This creates a complete UEFI-bootable image with:
- EFI System Partition (ESP) with FAT32
- GRUB UEFI bootloader
- Linux kernel
- SparkOS init system and busybox
- SparkOS init system (no external dependencies)
**Traditional Method (Requires Root):**
@@ -286,31 +284,31 @@ SparkOS/
### Init System
SparkOS uses a custom init system (`/sbin/init`) that:
- Mounts essential filesystems (proc, sys, dev, tmp)
- Initializes wired networking via DHCP
- Spawns a busybox sh login shell
- Mounts essential filesystems (proc, sys, dev, tmp) via direct system calls
- Initializes network interfaces via direct C ioctl calls
- Spawns Qt6 GUI application directly
- Handles process reaping
- Respawns shell on exit
- Respawns GUI on exit
- **No external dependencies**: Completely self-contained
### Root Filesystem
Follows the Filesystem Hierarchy Standard (FHS):
- `/bin`, `/sbin`: Essential binaries
- `/etc`: System configuration
Minimal filesystem structure for GUI-only OS:
- `/sbin`: Init binary only
- `/etc`: Minimal system configuration
- `/proc`, `/sys`, `/dev`: Kernel interfaces
- `/tmp`: Temporary files
- `/usr`: User programs and libraries
- `/var`: Variable data
- `/root`: Root user home
- `/home`: User home directories
- `/usr`: Qt6 GUI application and libraries
- `/var`: Variable data (overlay mount)
- `/root`: Root home
### Networking
SparkOS provides wired networking for initial bootstrap:
- **DHCP**: Automatic IP configuration via busybox udhcpc
SparkOS provides network initialization through direct C code:
- **Interface Management**: Direct ioctl calls to bring up network interfaces
- **DNS**: Fallback to public DNS servers (8.8.8.8, 8.8.4.4, 1.1.1.1, 1.0.0.1)
- **Interface**: Primary wired interface (eth0) configured automatically
- **WiFi**: Will be configured later via spark CLI after installation
- **DHCP**: Managed by Qt6 NetworkManager in GUI
- **WiFi**: Configured through Qt6 GUI
## Development
@@ -418,63 +416,31 @@ make clean
make help
```
### Adding Binaries to Root Filesystem
### Adding Components to Root Filesystem
To create a fully functional system, you need to populate the rootfs with binaries:
To create a fully functional bootable system:
```bash
# Required binaries (statically linked recommended)
# 1. Busybox - provides shell and most utilities including networking
cp /path/to/busybox rootfs/bin/
# Required components:
# 1. Qt6 GUI application - Build with make gui
# 2. Qt6 libraries - Copy Qt6 runtime libraries to rootfs/usr/lib
# 3. Linux kernel - Include kernel binary for bootloader
# 2. Git - for cloning spark CLI
cp /path/to/git rootfs/bin/
# Note: If git is dynamically linked, you'll need to copy its libraries too
# Qt6 GUI is built and installed via:
make gui
make install # Installs to rootfs/usr/bin/sparkos-gui
# 3. Sudo - for privilege elevation
cp /path/to/sudo rootfs/bin/
# Create busybox symlinks for common utilities
cd rootfs/bin
for cmd in sh ls cat mkdir rm cp mount umount chmod chown ln \
ip ifconfig ping wget udhcpc; do
ln -sf busybox $cmd
done
cd ../..
# If using dynamically linked binaries, copy required libraries
ldd rootfs/bin/busybox # Check dependencies
ldd rootfs/bin/git # Check dependencies
ldd rootfs/bin/sudo # Check dependencies
# Copy libraries to rootfs/lib or rootfs/lib64 as needed
```
### Testing Network Connectivity
Once booted, you can test the network:
```bash
# Check interface status
ip addr show
# Test DNS resolution
ping -c 3 google.com
# Test direct IP connectivity
ping -c 3 8.8.8.8
# Download a file
wget http://example.com/file
# Note: Qt6 must be compiled with linuxfb support for framebuffer rendering
```
## Future Roadmap
- [ ] Qt6/QML full screen GUI
- [ ] Qt6/QML full screen GUI implementation
- [ ] Wayland compositor integration
- [ ] C++ CLI tools (spark command)
- [ ] Package management via spark CLI
- [ ] WiFi configuration via spark CLI
- [ ] Advanced network configuration
- [ ] Network management via Qt6 NetworkManager
- [ ] WiFi configuration through GUI
- [ ] Advanced network configuration UI
- [ ] System settings and configuration UI
## Contributing
@@ -482,6 +448,7 @@ Contributions are welcome! This is an early-stage project focused on:
1. Maintaining minimal footprint
2. Clean, readable code
3. Proper documentation
4. GUI-only architecture (no CLI/shell)
## License
@@ -490,26 +457,26 @@ See LICENSE file for details.
## Notes
This is an MVP implementation. The system currently provides:
- Basic init system with network initialization
- Shell environment
- Custom init system with direct network initialization
- GUI-only architecture (no CLI/shell)
- Build infrastructure
- Image creation tooling
- Wired networking configuration
- Self-contained init with no external dependencies
To create a fully bootable system, you'll also need:
- Linux kernel binary (`vmlinuz`)
- Essential system binaries: busybox, git, sudo
- Required libraries (if using dynamically linked binaries)
- Linux kernel binary (`vmlinuz`) with framebuffer and networking support
- Qt6 GUI application (sparkos-gui)
- Qt6 runtime libraries
- Bootloader installation (handled by scripts)
Minimum System Requirements:
- Kernel: Linux kernel with networking support
- Init: Custom SparkOS init (included)
- Shell: Busybox with networking utilities (udhcpc, ip/ifconfig, ping, wget)
- VCS: Git (for installing spark CLI)
- Security: Sudo (for privilege elevation)
- Kernel: Linux kernel with framebuffer and networking support
- Init: Custom SparkOS init (included, no dependencies)
- GUI: Qt6 application with linuxfb platform support
- Libraries: Qt6 runtime libraries for GUI
After bootstrap:
1. Use wired network to clone spark CLI via git
2. Use spark CLI to configure WiFi and other system features
3. Install additional packages as needed via spark CLI
System Philosophy:
- **No CLI tools**: Everything through Qt6 GUI
- **No shell**: Direct kernel-to-GUI communication
- **No busybox**: Self-contained init system
- **Network-first**: Networking integrated into GUI

View File

@@ -42,8 +42,8 @@ Follow the instructions in README.md to create a complete bootable system.
## System Requirements
- Linux system with kernel 3.x or later
- Busybox for shell and utilities
- Linux system with kernel 3.x or later with framebuffer support
- Qt6 runtime libraries for GUI
- For building: GCC compiler, Make
## Documentation

View File

@@ -16,9 +16,6 @@ BOOTLOADER=syslinux
# Init system
INIT=sparkos-init
# Default shell
SHELL=/bin/sh
# Compiler flags
CFLAGS=-Wall -O2 -static
LDFLAGS=-static

View File

@@ -5,8 +5,8 @@ This is a UEFI-bootable disk image with:
- EFI System Partition (ESP) with FAT32 filesystem
- GRUB UEFI bootloader
- Linux kernel
- SparkOS init system
- Busybox utilities
- SparkOS init system (self-contained, no external dependencies)
- Qt6 GUI application
The image can be written to a USB drive and booted on UEFI systems:
sudo dd if=sparkos.img of=/dev/sdX bs=4M status=progress
@@ -15,6 +15,9 @@ The image can be written to a USB drive and booted on UEFI systems:
Boot options:
- UEFI boot support (tested on x86_64 systems)
- Automatic boot after 3 seconds
- Console on tty1
- Direct boot to Qt6 GUI (no CLI)
- Console on tty1 (for debugging only)
Philosophy: GUI-only, no CLI tools, network-first
For more information, see: https://github.com/johndoe6345789/SparkOS

View File

@@ -12,15 +12,16 @@ What's Included:
✓ EFI System Partition (ESP) with FAT32 filesystem
✓ GRUB UEFI bootloader
✓ Linux kernel
✓ SparkOS init system
Busybox utilities
Basic FHS-compliant filesystem structure
✓ SparkOS init system (self-contained, no dependencies)
Qt6 GUI application
Minimal filesystem structure
Boot Support:
------------
✓ UEFI boot (x86_64 systems)
✓ Automatic boot after 3 seconds
Console on tty1
Direct boot to Qt6 GUI (no CLI)
✓ Console on tty1 (for debugging only)
Quick Start:
-----------

View File

@@ -1,43 +1,41 @@
SparkOS Root Filesystem
=======================
This is the root filesystem for SparkOS, a minimal Linux distribution.
This is the root filesystem for SparkOS, a GUI-only Linux distribution.
Minimal System Packages:
- Linux Kernel (with networking support)
- SparkOS Init System (custom)
- Busybox (shell, utilities, networking)
- Git (for installing spark CLI)
- Sudo (privilege elevation)
SparkOS Philosophy:
- GUI-Only: No CLI tools, no shell, no Unix utilities
- Network-First: Networking integrated into Qt6 GUI
- Direct Kernel Interface: Qt6 communicates directly with Linux kernel
- No Unix Baggage: No users, groups, passwords, or authentication
Minimal System:
- Linux Kernel (with networking and framebuffer support)
- SparkOS Init System (completely self-contained, no dependencies)
- Qt6 GUI Application (all user interaction)
Directory Structure:
/bin, /sbin - Essential binaries
/etc - Configuration files
/sbin - Init binary only
/etc - Minimal configuration files
/proc, /sys, /dev - Kernel interfaces
/tmp - Temporary files
/usr - User programs
/var - Variable data
/usr - Qt6 GUI application and libraries
/var - Variable data (overlay mount)
/root - Root home directory
/home/spark - Default user home directory
Default User:
Username: spark (UID 1000)
Home: /home/spark
Sudo: Full access without password
Scripts: ~/clone-sparkos.sh for installing spark CLI
Network Configuration:
/etc/network/interfaces - Wired network (DHCP)
/etc/resolv.conf - DNS configuration (8.8.8.8, 1.1.1.1)
/sbin/init-network - Network initialization script
- Managed entirely through Qt6 GUI
- Init brings up interfaces via direct ioctl calls
- DHCP and network management handled by Qt6 NetworkManager
- /etc/resolv.conf provides fallback DNS servers
Bootstrap Process:
1. System boots as 'spark' user with wired networking (DHCP)
2. Run ~/clone-sparkos.sh to install spark CLI
3. Use spark CLI to configure WiFi and system
4. Install additional packages via spark CLI
5. Use 'sudo' for any root-level operations
Boot Process:
1. Linux kernel loads
2. Init (PID 1) mounts filesystems
3. Init brings up network interfaces
4. Init spawns Qt6 GUI application
5. All user interaction through GUI
Note: This is a minimal system. You'll need to populate /bin and /usr/bin
with actual binaries (busybox, git, sudo) from a proper Linux system
or by cross-compiling.
Note: This is a minimal, GUI-only system.
No shell, no CLI tools, no busybox.
All functionality is provided through the Qt6 GUI application.

View File

@@ -1,7 +1,6 @@
#!/bin/bash
# Quick build script for SparkOS development
# Note: This script runs on the host system and uses bash for ${BASH_SOURCE}
# The target system uses busybox sh instead.
set -e
@@ -30,10 +29,9 @@ echo ""
echo "Build complete!"
echo ""
echo "Next steps to create a full bootable system:"
echo " 1. Copy busybox to rootfs/bin/"
echo " (cp /bin/busybox rootfs/bin/)"
echo " 2. Create symlinks in rootfs/bin for common utilities"
echo " (cd rootfs/bin && for cmd in sh ls cat mkdir rm cp mount; do ln -sf busybox \$cmd; done)"
echo " 3. Add a Linux kernel to rootfs/boot/vmlinuz"
echo " 4. Run: sudo make image"
echo " 1. Build Qt6 GUI: make gui"
echo " 2. Add a Linux kernel to rootfs/boot/vmlinuz"
echo " 3. Run: sudo make image"
echo ""
echo "Philosophy: No CLI tools, GUI-only experience"
echo ""

View File

@@ -1,8 +1,6 @@
#!/bin/bash
# SparkOS Image Creation Script
# Creates a bootable dd-able disk image
# Note: This script runs on the host system and uses bash for ${BASH_SOURCE}
# The target system uses busybox sh instead.
set -e

View File

@@ -86,24 +86,10 @@ mkdir -p /staging/root/{bin,sbin,etc,proc,sys,dev,tmp,usr/{bin,sbin,lib,lib64},v
cp /build/init /staging/root/sbin/init
chmod 755 /staging/root/sbin/init
# Install busybox
echo "Installing busybox..."
cp /bin/busybox /staging/root/bin/busybox
chmod 755 /staging/root/bin/busybox
# Create busybox symlinks for essential commands
for cmd in sh ls cat echo mount umount mkdir rm cp mv chmod chown ln ps kill; do
ln -sf busybox /staging/root/bin/$cmd
done
# Create system configuration files
echo "sparkos" > /staging/root/etc/hostname
echo "127.0.0.1 localhost" > /staging/root/etc/hosts
echo "127.0.1.1 sparkos" >> /staging/root/etc/hosts
echo "root:x:0:0:root:/root:/bin/sh" > /staging/root/etc/passwd
echo "spark:x:1000:1000:SparkOS User:/home/spark:/bin/sh" >> /staging/root/etc/passwd
echo "root:x:0:" > /staging/root/etc/group
echo "spark:x:1000:" >> /staging/root/etc/group
# Copy README to root partition
cp /build/config/image-readme.txt /staging/root/README.txt

View File

@@ -61,24 +61,10 @@ mkdir -p /staging/root/{bin,sbin,etc,proc,sys,dev,tmp,usr/{bin,sbin,lib,lib64},v
cp /build/init /staging/root/sbin/init
chmod 755 /staging/root/sbin/init
# Install busybox
echo "Installing busybox..."
cp /bin/busybox /staging/root/bin/busybox
chmod 755 /staging/root/bin/busybox
# Create busybox symlinks for essential commands
for cmd in sh ls cat echo mount umount mkdir rm cp mv chmod chown ln ps kill; do
ln -sf busybox /staging/root/bin/$cmd
done
# Create system configuration files
echo "sparkos" > /staging/root/etc/hostname
echo "127.0.0.1 localhost" > /staging/root/etc/hosts
echo "127.0.1.1 sparkos" >> /staging/root/etc/hosts
echo "root:x:0:0:root:/root:/bin/sh" > /staging/root/etc/passwd
echo "spark:x:1000:1000:SparkOS User:/home/spark:/bin/sh" >> /staging/root/etc/passwd
echo "root:x:0:" > /staging/root/etc/group
echo "spark:x:1000:" >> /staging/root/etc/group
# Copy README to root partition
cp /build/config/image-readme.txt /staging/root/README.txt

View File

@@ -22,7 +22,6 @@ apt-get install -y \
grub-efi-amd64-bin \
grub-common \
wget \
busybox-static \
kmod \
udev
rm -rf /var/lib/apt/lists/*

View File

@@ -143,8 +143,8 @@ Build release artifacts without needing root or special tools:
## System Requirements
- Linux system with kernel 3.x or later
- Busybox for shell and utilities
- Linux system with kernel 3.x or later with framebuffer support
- Qt6 runtime libraries for GUI
- For building: Docker or GCC compiler and Make
## Documentation

View File

@@ -1,8 +1,7 @@
#!/bin/bash
# SparkOS Setup Script
# Sets up a minimal rootfs with busybox and essential utilities
# Sets up a minimal rootfs for GUI-only SparkOS
# Note: This script runs on the host system and uses bash for ${BASH_SOURCE}
# The target system uses busybox sh instead.
set -e
@@ -16,16 +15,12 @@ echo ""
# Create directory structure
echo "Creating directory structure..."
mkdir -p "$ROOTFS_DIR"/{bin,sbin,etc,proc,sys,dev,tmp,usr/{bin,sbin,lib,lib64},var,root,home}
mkdir -p "$ROOTFS_DIR/etc"/{init.d,network}
mkdir -p "$ROOTFS_DIR"/{sbin,etc,proc,sys,dev,tmp,usr/{bin,sbin,lib,lib64},var,root}
mkdir -p "$ROOTFS_DIR/var"/{log,run}
mkdir -p "$ROOTFS_DIR/home/spark"
mkdir -p "$ROOTFS_DIR/etc/sudoers.d"
# Set permissions
chmod 1777 "$ROOTFS_DIR/tmp"
chmod 700 "$ROOTFS_DIR/root"
chmod 755 "$ROOTFS_DIR/home/spark"
# Create basic config files
echo "Creating configuration files..."
@@ -40,19 +35,6 @@ cat > "$ROOTFS_DIR/etc/hosts" << 'EOF'
::1 localhost ip6-localhost ip6-loopback
EOF
# /etc/passwd
cat > "$ROOTFS_DIR/etc/passwd" << 'EOF'
root:x:0:0:root:/root:/bin/sh
spark:x:1000:1000:SparkOS User:/home/spark:/bin/sh
EOF
# /etc/group
cat > "$ROOTFS_DIR/etc/group" << 'EOF'
root:x:0:
spark:x:1000:
sudo:x:27:spark
EOF
# /etc/fstab
cat > "$ROOTFS_DIR/etc/fstab" << 'EOF'
# <file system> <mount point> <type> <options> <dump> <pass>
@@ -62,320 +44,77 @@ devtmpfs /dev devtmpfs defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
EOF
# /etc/resolv.conf - DNS configuration
# /etc/resolv.conf - DNS configuration (managed by Qt6 GUI)
cat > "$ROOTFS_DIR/etc/resolv.conf" << 'EOF'
# SparkOS DNS Configuration
# Fallback to public DNS servers for reliability
# Managed by Qt6 GUI NetworkManager
# Fallback to public DNS servers
nameserver 8.8.8.8
nameserver 8.8.4.4
nameserver 1.1.1.1
nameserver 1.0.0.1
EOF
# /etc/sudoers - Sudo configuration
cat > "$ROOTFS_DIR/etc/sudoers" << 'EOF'
# SparkOS Sudoers Configuration
# Allow spark user to run any command without password
# Default settings
Defaults env_reset
Defaults secure_path="/bin:/sbin:/usr/bin:/usr/sbin"
# Root can run anything
root ALL=(ALL:ALL) ALL
# Spark user can run anything without password
spark ALL=(ALL:ALL) NOPASSWD: ALL
# Include sudoers.d directory
@includedir /etc/sudoers.d
EOF
chmod 0440 "$ROOTFS_DIR/etc/sudoers"
# /etc/network/interfaces - Wired network configuration
cat > "$ROOTFS_DIR/etc/network/interfaces" << 'EOF'
# SparkOS Network Configuration
# Wired networking only for bootstrapping
# Loopback interface
auto lo
iface lo inet loopback
# Primary wired interface (DHCP)
auto eth0
iface eth0 inet dhcp
EOF
# /etc/profile
cat > "$ROOTFS_DIR/etc/profile" << 'EOF'
# SparkOS System Profile
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
export PS1='SparkOS:\w\$ '
export TERM=linux
# Set HOME based on user
if [ "$(id -u)" = "0" ]; then
export HOME=/root
else
export HOME=/home/$(whoami)
fi
# Welcome message
echo "Welcome to SparkOS!"
echo "Type 'help' for available commands"
echo ""
EOF
# Create .profile for root (busybox uses .profile instead of .bashrc)
cat > "$ROOTFS_DIR/root/.profile" << 'EOF'
# SparkOS Root Shell Configuration
# Set prompt
PS1='SparkOS:\w# '
# Aliases
alias ll='ls -lah'
alias ..='cd ..'
# Environment
export EDITOR=vi
export PAGER=less
EOF
# Create .profile for spark user
cat > "$ROOTFS_DIR/home/spark/.profile" << 'EOF'
# SparkOS User Shell Configuration
# Set prompt
PS1='SparkOS:\w\$ '
# Aliases
alias ll='ls -lah'
alias ..='cd ..'
# Environment
export EDITOR=vi
export PAGER=less
EOF
# Create clone-sparkos.sh script for spark user
cat > "$ROOTFS_DIR/home/spark/clone-sparkos.sh" << 'EOF'
#!/bin/sh
# SparkOS CLI Installation Script
# This script clones the SparkOS CLI repository
echo "SparkOS CLI Installation"
echo "========================"
echo ""
SPARK_REPO="https://github.com/johndoe6345789/spark-cli.git"
INSTALL_DIR="$HOME/spark-cli"
echo "This script will clone the SparkOS CLI to: $INSTALL_DIR"
echo ""
# Check if git is available
if ! command -v git >/dev/null 2>&1; then
echo "Error: git is not installed"
echo "Please install git to continue"
exit 1
fi
# Check if directory already exists
if [ -d "$INSTALL_DIR" ]; then
echo "Warning: $INSTALL_DIR already exists"
echo -n "Do you want to remove it and re-clone? (y/N): "
read answer
if [ "$answer" = "y" ] || [ "$answer" = "Y" ]; then
rm -rf "$INSTALL_DIR"
else
echo "Installation cancelled"
exit 0
fi
fi
# Clone the repository
echo "Cloning spark CLI repository..."
if git clone "$SPARK_REPO" "$INSTALL_DIR"; then
echo ""
echo "SparkOS CLI cloned successfully!"
echo ""
echo "Next steps:"
echo " 1. cd $INSTALL_DIR"
echo " 2. Follow the installation instructions in the repository"
echo ""
else
echo ""
echo "Error: Failed to clone repository"
echo "Please check your network connection and try again"
exit 1
fi
EOF
chmod +x "$ROOTFS_DIR/home/spark/clone-sparkos.sh"
# Create a simple help script
cat > "$ROOTFS_DIR/bin/sparkos-help" << 'EOF'
#!/bin/sh
cat << 'HELP'
SparkOS - Minimal Linux Distribution
====================================
Default Packages:
- Kernel (Linux)
- Init system (custom)
- Busybox (shell and utilities)
- Git (for installing spark CLI)
- Sudo (privilege elevation)
Default User:
Username: spark
Home: /home/spark
Privileges: Full sudo access (no password required)
To run commands as root: sudo <command>
To become root: sudo -i
Available commands:
ls, cd, pwd - Navigate filesystem
cat, less - View files
mkdir, rm, cp - File operations
mount, umount - Mount filesystems
ip, ifconfig - Network configuration
ping, wget - Network testing
git - Version control
sudo - Run commands as root
poweroff, reboot - System control
help - Show this help
Network:
Wired networking (eth0) configured via DHCP
DNS: 8.8.8.8, 1.1.1.1 (Google and Cloudflare)
To check network: ping 8.8.8.8
To test DNS: ping google.com
Next Steps:
1. Install spark CLI: ~/clone-sparkos.sh
2. Use spark CLI to configure WiFi and system
3. Install additional packages as needed
For more information: https://github.com/johndoe6345789/SparkOS
HELP
EOF
chmod +x "$ROOTFS_DIR/bin/sparkos-help"
ln -sf sparkos-help "$ROOTFS_DIR/bin/help"
# Create network initialization script
cat > "$ROOTFS_DIR/sbin/init-network" << 'EOF'
#!/bin/sh
# SparkOS Network Initialization
# Brings up wired networking for system bootstrap
echo "Initializing network..."
# Bring up loopback
ip link set lo up 2>/dev/null || ifconfig lo up 2>/dev/null
# Bring up primary wired interface with DHCP
# Try eth0 first, then other common interface names
for iface in eth0 enp0s3 enp0s8 ens33; do
if ip link show "$iface" >/dev/null 2>&1; then
echo "Bringing up $iface..."
# Bring up the interface
if ip link set "$iface" up 2>/dev/null || ifconfig "$iface" up 2>/dev/null; then
# Try to get IP via DHCP using busybox udhcpc
if command -v udhcpc >/dev/null 2>&1; then
# Run udhcpc in background, it will daemonize itself
udhcpc -i "$iface" -b -t 5 2>/dev/null
fi
else
echo "Warning: Failed to bring up $iface"
fi
break
fi
done
echo "Network initialization complete"
EOF
chmod +x "$ROOTFS_DIR/sbin/init-network"
# Create README
cat > "$ROOTFS_DIR/README.txt" << 'EOF'
SparkOS Root Filesystem
=======================
This is the root filesystem for SparkOS, a minimal Linux distribution.
This is the root filesystem for SparkOS, a GUI-only Linux distribution.
Minimal System Packages:
- Linux Kernel (with networking support)
- SparkOS Init System (custom)
- Busybox (shell, utilities, networking)
- Git (for installing spark CLI)
- Sudo (privilege elevation)
SparkOS Philosophy:
- GUI-Only: No CLI tools, no shell, no Unix utilities
- Network-First: Networking integrated into Qt6 GUI
- Direct Kernel Interface: Qt6 communicates directly with Linux kernel
- No Unix Baggage: No users, groups, passwords, or authentication
Minimal System:
- Linux Kernel (with networking and framebuffer support)
- SparkOS Init System (completely self-contained, no dependencies)
- Qt6 GUI Application (all user interaction)
Directory Structure:
/bin, /sbin - Essential binaries
/etc - Configuration files
/sbin - Init binary only
/etc - Minimal configuration files
/proc, /sys, /dev - Kernel interfaces
/tmp - Temporary files
/usr - User programs
/var - Variable data
/usr - Qt6 GUI application and libraries
/var - Variable data (overlay mount)
/root - Root home directory
/home/spark - Default user home directory
Default User:
Username: spark (UID 1000)
Home: /home/spark
Sudo: Full access without password
Scripts: ~/clone-sparkos.sh for installing spark CLI
Network Configuration:
/etc/network/interfaces - Wired network (DHCP)
/etc/resolv.conf - DNS configuration (8.8.8.8, 1.1.1.1)
/sbin/init-network - Network initialization script
- Managed entirely through Qt6 GUI
- Init brings up interfaces via direct ioctl calls
- DHCP and network management handled by Qt6 NetworkManager
- /etc/resolv.conf provides fallback DNS servers
Bootstrap Process:
1. System boots as 'spark' user with wired networking (DHCP)
2. Run ~/clone-sparkos.sh to install spark CLI
3. Use spark CLI to configure WiFi and system
4. Install additional packages via spark CLI
5. Use 'sudo' for any root-level operations
Boot Process:
1. Linux kernel loads
2. Init (PID 1) mounts filesystems
3. Init brings up network interfaces
4. Init spawns Qt6 GUI application
5. All user interaction through GUI
Note: This is a minimal system. You'll need to populate /bin and /usr/bin
with actual binaries (busybox, git, sudo) from a proper Linux system
or by cross-compiling.
Note: This is a minimal, GUI-only system.
No shell, no CLI tools, no busybox.
All functionality is provided through the Qt6 GUI application.
EOF
echo ""
echo "Root filesystem structure created at: $ROOTFS_DIR"
echo ""
echo "User configuration:"
echo " - Default user: spark (UID 1000)"
echo " - Home directory: /home/spark"
echo " - Sudo access: Enabled (no password required)"
echo " - Clone script: /home/spark/clone-sparkos.sh"
echo ""
echo "Network configuration:"
echo " - Wired networking (DHCP) configured for eth0"
echo " - DNS: 8.8.8.8, 1.1.1.1, 8.8.4.4, 1.0.0.1"
echo " - Network init script: /sbin/init-network"
echo "SparkOS Configuration:"
echo " - Architecture: GUI-only, no CLI"
echo " - Init: Self-contained, no external dependencies"
echo " - Network: Direct C implementation via ioctl"
echo " - User Experience: Pure Qt6 GUI"
echo ""
echo "Next steps:"
echo " 1. Build init: make init"
echo " 2. Install init: make install"
echo " 3. Copy busybox, git, and sudo binaries to rootfs/bin/"
echo " 4. Create busybox symlinks"
echo " 5. Create bootable image: sudo make image"
echo " 3. Build Qt6 GUI: make gui"
echo " 4. Create bootable image: sudo make image"
echo ""
echo "Minimum required binaries:"
echo " - busybox (provides shell, networking, utilities)"
echo " - git (for installing spark CLI)"
echo " - sudo (for privilege elevation)"
echo ""
echo "Note: Busybox should be compiled with networking support"
echo " (CONFIG_UDHCPC, CONFIG_IFCONFIG, CONFIG_IP, CONFIG_PING, CONFIG_WGET)"
echo "Philosophy:"
echo " No busybox, no shell, no CLI tools"
echo " Everything is GUI-driven through Qt6"

View File

@@ -3,48 +3,6 @@ echo "SparkOS Docker Test Environment"
echo "================================"
echo ""
# Verify BusyBox is present and working
echo "Verifying BusyBox..."
echo "-------------------"
if command -v busybox >/dev/null 2>&1; then
echo "✓ BusyBox is installed"
echo ""
echo "BusyBox version:"
# Store version for reuse in summary
BUSYBOX_VERSION=$(busybox | head -n 1)
echo "$BUSYBOX_VERSION"
echo ""
echo "BusyBox location:"
which busybox
ls -lh "$(which busybox)"
echo ""
echo "Shell (/bin/sh) is BusyBox:"
ls -lh /bin/sh
if [ -L /bin/sh ]; then
echo " → /bin/sh is a symlink to: \"$(readlink /bin/sh)\""
fi
echo ""
echo "Available BusyBox applets (sample):"
# Store applet list once to avoid redundant executions
APPLET_LIST=$(busybox --list)
echo "$APPLET_LIST" | head -n 20
echo " ... and $(echo "$APPLET_LIST" | wc -l) total applets"
echo ""
echo "Networking applets (required for SparkOS):"
for cmd in udhcpc ip ifconfig ping wget; do
if echo "$APPLET_LIST" | grep -q "^${cmd}$"; then
echo "$cmd"
else
echo "$cmd (NOT FOUND)"
fi
done
else
echo "✗ BusyBox not found!"
echo " SparkOS requires BusyBox for shell and utilities"
exit 1
fi
echo ""
echo "Verifying SparkOS init binary..."
echo "--------------------------------"
if [ -f /sparkos/rootfs/sbin/init ]; then
@@ -75,10 +33,13 @@ echo "✓ SparkOS is ready for testing!"
echo "================================"
echo ""
echo "Summary:"
echo " - BusyBox: $BUSYBOX_VERSION"
echo " - Init: Custom SparkOS init system"
echo " - Shell: BusyBox sh (/bin/sh)"
echo " - Networking: BusyBox udhcpc, ip, ping, wget"
echo " - Init: Custom SparkOS init system (no external dependencies)"
echo " - Architecture: GUI-only, no CLI/shell"
echo " - Network: Direct C implementation via ioctl"
echo " - Philosophy: Pure GUI experience, network-first"
echo ""
echo "Note: SparkOS has no CLI tools (no busybox, no shell)"
echo " All functionality is provided through the Qt6 GUI"
echo ""
echo "To test the init system:"
echo " docker run --rm <image> /sparkos/rootfs/sbin/init --help"
echo " docker run --rm <image> /sparkos/rootfs/sbin/init"

View File

@@ -1,6 +1,11 @@
/*
* SparkOS Init - Minimal init system for SparkOS
* This is the first process that runs after the kernel boots
*
* SparkOS Philosophy: GUI-only, no CLI, network-first
* - No shell spawning or CLI utilities
* - Direct boot to Qt6 GUI
* - Network initialization via direct C system calls
*/
#include <stdio.h>
@@ -8,9 +13,17 @@
#include <unistd.h>
#include <sys/wait.h>
#include <sys/reboot.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <net/if.h>
#include <linux/if.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <arpa/inet.h>
#include <limits.h>
static void signal_handler(int sig) {
if (sig == SIGCHLD) {
@@ -33,7 +46,7 @@ static void spawn_gui() {
char *argv[] = {"/usr/bin/sparkos-gui", NULL};
char *envp[] = {
"HOME=/root",
"PATH=/bin:/sbin:/usr/bin:/usr/sbin",
"PATH=/usr/bin:/usr/sbin",
"QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0",
"QT_QPA_FB_FORCE_FULLSCREEN=1",
"QT_QPA_FONTDIR=/usr/share/fonts",
@@ -51,39 +64,128 @@ static void spawn_gui() {
waitpid(pid, &status, 0);
}
static void spawn_shell() {
pid_t pid = fork();
/*
* Initialize network interface directly via ioctl
* No dependency on busybox or CLI tools
*/
static int init_network_interface(const char *ifname) {
int sock;
struct ifreq ifr;
if (pid < 0) {
perror("fork failed");
return;
// Create socket for ioctl operations
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
perror("socket creation failed");
return -1;
}
if (pid == 0) {
// Child process - exec shell as root (fallback only)
char *argv[] = {"/bin/sh", "-l", NULL};
char *envp[] = {
"HOME=/root",
"PATH=/bin:/sbin:/usr/bin:/usr/sbin",
"TERM=linux",
"PS1=SparkOS# ",
NULL
};
execve("/bin/sh", argv, envp);
perror("failed to exec shell");
exit(1);
// Prepare interface request structure
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
ifr.ifr_name[IFNAMSIZ - 1] = '\0'; // Ensure null termination
// Get current flags
if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
close(sock);
return -1; // Interface doesn't exist
}
// Parent process - wait for shell to exit
int status;
waitpid(pid, &status, 0);
// Bring interface up
ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) {
perror("failed to bring up interface");
close(sock);
return -1;
}
close(sock);
printf("Network interface %s brought up successfully\n", ifname);
return 0;
}
/*
* Initialize networking without external dependencies
* Brings up loopback and first available ethernet interface
*/
static void init_network() {
const char *interfaces[] = {"lo", "eth0", "enp0s3", "enp0s8", "ens33", NULL};
int i;
int eth_initialized = 0;
printf("Initializing network interfaces...\n");
// Bring up loopback
if (init_network_interface("lo") == 0) {
printf("Loopback interface initialized\n");
}
// Try to bring up first available ethernet interface
for (i = 1; interfaces[i] != NULL && !eth_initialized; i++) {
if (init_network_interface(interfaces[i]) == 0) {
printf("Primary network interface %s initialized\n", interfaces[i]);
printf("Note: DHCP configuration should be handled by Qt6 GUI\n");
eth_initialized = 1;
}
}
if (!eth_initialized) {
fprintf(stderr, "Warning: No ethernet interface found or initialized\n");
fprintf(stderr, "Network configuration will be available through GUI\n");
}
}
/*
* Mount filesystem using direct mount() system call
* No dependency on mount binary
*/
static int mount_fs(const char *source, const char *target, const char *fstype, unsigned long flags) {
if (mount(source, target, fstype, flags, NULL) < 0) {
return -1;
}
return 0;
}
/*
* Create directory recursively
* No dependency on mkdir binary
*/
static int mkdir_p(const char *path) {
char tmp[PATH_MAX];
char *p = NULL;
size_t len;
len = strlen(path);
if (len >= PATH_MAX) {
errno = ENAMETOOLONG;
return -1;
}
snprintf(tmp, sizeof(tmp), "%s", path);
if (tmp[len - 1] == '/')
tmp[len - 1] = 0;
for (p = tmp + 1; *p; p++) {
if (*p == '/') {
*p = 0;
if (mkdir(tmp, 0755) < 0 && errno != EEXIST) {
return -1;
}
*p = '/';
}
}
if (mkdir(tmp, 0755) < 0 && errno != EEXIST) {
return -1;
}
return 0;
}
int main(int argc, char *argv[]) {
printf("SparkOS Init System Starting...\n");
printf("================================\n");
printf("Philosophy: GUI-Only, No CLI, Network-First\n");
printf("================================\n\n");
// Make sure we're PID 1
if (getpid() != 1) {
@@ -94,18 +196,18 @@ int main(int argc, char *argv[]) {
// Set up signal handlers
signal(SIGCHLD, signal_handler);
// Mount essential filesystems
// Mount essential filesystems using direct system calls
printf("Mounting essential filesystems...\n");
if (system("mount -t proc proc /proc 2>/dev/null") != 0) {
if (mount_fs("proc", "/proc", "proc", 0) != 0) {
fprintf(stderr, "Warning: Failed to mount /proc\n");
}
if (system("mount -t sysfs sys /sys 2>/dev/null") != 0) {
if (mount_fs("sysfs", "/sys", "sysfs", 0) != 0) {
fprintf(stderr, "Warning: Failed to mount /sys\n");
}
if (system("mount -t devtmpfs dev /dev 2>/dev/null") != 0) {
if (mount_fs("devtmpfs", "/dev", "devtmpfs", 0) != 0) {
fprintf(stderr, "Warning: Failed to mount /dev\n");
}
if (system("mount -t tmpfs tmpfs /tmp 2>/dev/null") != 0) {
if (mount_fs("tmpfs", "/tmp", "tmpfs", 0) != 0) {
fprintf(stderr, "Warning: Failed to mount /tmp\n");
}
@@ -113,37 +215,38 @@ int main(int argc, char *argv[]) {
printf("Setting up overlay filesystem for writable layer...\n");
// Create overlay directories in tmpfs
if (system("mkdir -p /tmp/overlay/var-upper /tmp/overlay/var-work 2>/dev/null") != 0) {
if (mkdir_p("/tmp/overlay/var-upper") != 0 || mkdir_p("/tmp/overlay/var-work") != 0) {
fprintf(stderr, "Warning: Failed to create overlay directories for /var\n");
}
// Mount overlay on /var for logs and runtime data
if (system("mount -t overlay overlay -o lowerdir=/var,upperdir=/tmp/overlay/var-upper,workdir=/tmp/overlay/var-work /var 2>/dev/null") != 0) {
char overlay_opts[256];
snprintf(overlay_opts, sizeof(overlay_opts),
"lowerdir=/var,upperdir=/tmp/overlay/var-upper,workdir=/tmp/overlay/var-work");
if (mount("overlay", "/var", "overlay", 0, overlay_opts) != 0) {
fprintf(stderr, "Warning: Failed to mount overlay on /var - system may be read-only\n");
} else {
printf("Overlay filesystem mounted on /var (base OS is immutable)\n");
}
// Mount tmpfs on /run for runtime data
if (system("mkdir -p /run 2>/dev/null") == 0) {
if (system("mount -t tmpfs tmpfs /run 2>/dev/null") != 0) {
if (mkdir_p("/run") == 0) {
if (mount_fs("tmpfs", "/run", "tmpfs", 0) != 0) {
fprintf(stderr, "Warning: Failed to mount /run\n");
}
}
// Initialize network (wired only for bootstrap)
printf("Initializing wired network...\n");
if (system("/sbin/init-network 2>/dev/null") != 0) {
fprintf(stderr, "Warning: Network initialization failed - check network interface availability\n");
}
// Initialize network interfaces
init_network();
printf("Starting Qt6 GUI application...\n");
printf("\nStarting Qt6 GUI application...\n");
printf("Welcome to SparkOS!\n");
printf("===================\n");
printf("Base OS: Read-only (immutable)\n");
printf("Writable: /tmp, /var (overlay), /run\n");
printf("Mode: Qt6 GUI (Network-First Architecture)\n");
printf("No Users/Authentication - Direct Boot to GUI\n\n");
printf("No Users/Authentication - Direct Boot to GUI\n");
printf("No CLI/Shell - Pure GUI Experience\n\n");
// Main loop - keep respawning GUI application
while (1) {