liblitho 0.2.0

cli tool to flash/clone the images to storage devices
Documentation
# Litho — developer documentation

User-facing overview: [README.md](../README.md).

This document covers features in depth, library usage, architecture, build variants, protocols, and platform notes.

---

## Features (detailed)

| Feature | Description |
|---------|-------------|
| **Flash** | Write `.img` / `.iso` / `.img.xz` to a whole block device; optional post-write SHA-256 verify |
| **Clone** | Read a whole block device to an image file |
| **Query** | List storage devices (Linux `/sys/block`, Windows WMI) |
| **Device safety** | Refuse system disks, partitions, busy mounts; typed `DeviceError` |
| **Progress API** | `OperationProgress` (phase, bytes, percentage, message) |
| **Cooperative cancel** | Between block ops; TUI in-process; CLI `--cancel-file` for elevated sidecars |
| **TUI** | Device/file pickers, verify checkbox, elevation (`pkexec` / `sudo` / UAC), logging |
| **GUI protocol** | `-o gui` line protocol for [Lithographer]https://github.com/girish946/lithographer |
| **Platform traits** | `DeviceInventory`, `DevicePathOps`, `DeviceSafety`, `VolumeOps`, `PrivilegeOps`, I/O traits |

`.xz` images are **stream-decompressed** into the write loop (no temporary uncompressed file).

---

## Requirements (development)

- Rust **1.70+** (edition 2021)
- Linux or Windows for production flash/clone testing
- **Linux elevation:** `pkexec` (polkit) and/or `sudo`
- **Windows:** UAC; release CI uses OpenSSL + vcpkg `liblzma` for the sidecar stack (see Lithographer CI)
- Terminal ≥ **60×24** for TUI

---

## Build variants

### Feature flags

| Feature | Default | Behavior |
|---------|---------|----------|
| `simulated-io` | **yes** | Simulator — no real block writes; safe for `cargo test` |
| `real-io` | no | Real `flash` / `clone` via `io_backend` |

```bash
# Dev / tests (default features)
cargo build
cargo test

# Production CLI + TUI
cargo build --release --no-default-features --features real-io --bin litho --bin litho-tui
```

The TUI status line shows `(simulation — disk writes disabled)` under `simulated-io`.

GitHub Actions (and Lithographer’s sidecar script) build with `real-io`.

### Portable Linux `litho` binary (musl)

Bleeding-edge glibc hosts can produce binaries that fail on older distros (`GLIBC_2.xx not found`).

```bash
rustup target add x86_64-unknown-linux-musl
cargo build --release --target x86_64-unknown-linux-musl \
  --no-default-features --features real-io --bin litho
```

Output: `target/x86_64-unknown-linux-musl/release/litho`

Alternatively, build in an older container (e.g. `rust:1.80-slim-bookworm`).

Copy the binary into Lithographer as the sidecar when packaging:

`lithographer/src-tauri/binaries/litho` (name may include target triple — see Lithographer scripts).

`litho-tui` is usually built for the host, not as a static portable binary.

---

## CLI reference (full)

User-facing quick start is in the [README](../README.md). Extended options:

### Global options

| Option | Description |
|--------|-------------|
| `-o, --output-mode` | `terminal` (default) or `gui` |
| `--dry-run` | Validate only |
| `--cancel-file <path>` | Poll file for `cancel` line (GUI / pkexec) |
| `--yes` | Confirm automatic unmount/dismount |

### Output modes

- **`terminal`** — in-place progress bar on TTY; newline updates when piped
- **`gui`** — structured lines: `@progress …` (stdout), `@error …` (stderr), `@done ok|cancelled`. Exit code **`3`** on cooperative cancel

### Flash

```bash
sudo litho flash -f image.img -d /dev/sdX
sudo litho flash -f image.img.xz -d /dev/sdX -b 4096 --verify
sudo litho flash -f image.img -d /dev/sdX -o gui
sudo litho --dry-run flash -f image.img -d /dev/sdX
```

| Option | Description |
|--------|-------------|
| `-f, --file` | Image file |
| `-d, --device` | Target whole disk |
| `-b, --block-size` | Buffer size (default `4096`) |
| `-s, --silent` | Suppress progress |
| `--verify` | Post-write SHA-256 |

**Windows:** volumes on the target disk are dismounted after confirmation (`--yes` or TUI). Partition-table region is written last to reduce mid-flash re-mount races.

### Clone

```bash
sudo litho clone -d /dev/sdX -f backup.img -b 1048576
```

### Query

```bash
litho query
litho query --device /dev/sdb   # currently filters the full list
```

### Device validation (preflight)

Before flash/clone (including dry-run):

- Whole-disk path only (not a partition)
- Not the system disk
- No busy mounts unless auto-unmount is confirmed
- TUI/Lithographer: path must appear in the current device list

---

## TUI (developer notes)

### Privilege elevation

**Linux**

1. Unprivileged user confirms elevation in the TUI.
2. Terminal is restored; process elevates via **`pkexec`** or **`sudo`** (see `PrivilegeOps` / `platform/linux/privilege.rs`).
3. Elevated relaunch gets `--mode`, `--device`, `--image` only — **not** `--start` from the elevating path; user must Start again unless already root with `--start`.

**Windows**

- UAC via `ShellExecuteW` `runas`.
- Volume-dismount confirmation before flash/clone.
- Logs under `%LOCALAPPDATA%\litho\litho-tui.log`.

### Cooperative cancel

- Checked between block I/O operations.
- TUI: in-process `AtomicBool`.
- CLI: `--cancel-file` for cross-privilege cancel (pkexec does not reliably forward stdin/signals).
- Cancelled clone removes incomplete output; CLI exit code `3`.

### Logging

Default: `~/.cache/litho/litho-tui.log` (`$XDG_CACHE_HOME` / Windows `LOCALAPPDATA`).

```bash
litho-tui --log-level debug --log-file /tmp/litho-tui.log
# stderr: --log-file=- or LITHO_LOG_STDERR=1
```

Rotation to `.log.old` above ~5 MiB.

### Device list

- **Linux:** `/sys/block`
- **Windows:** WMI on a dedicated thread
- Fixed (non-removable) selection requires extra confirmation

---

## Library API (`liblitho`)

```toml
[dependencies]
liblitho = { path = "../litho" }  # or crates.io / git when published
log = "0.4"
```

Public flash/clone take **`&str` paths** and an optional cancel flag:

```rust
use liblitho::progress::{OperationPhase, OperationProgress};
use liblitho::{clone, flash};
use std::sync::atomic::AtomicBool;

fn on_progress(p: OperationProgress) {
    if let Some(pct) = p.percentage {
        eprintln!("{:?}: {:.1}%", p.phase, pct);
    }
}

// Clone device → file
clone(
    "/dev/sdb",
    "/tmp/backup.img",
    4096,
    false,                 // silent
    Some(on_progress),
    None,                  // Option<&AtomicBool> cancel
)?;

// Flash file → device
flash(
    "/path/to/image.img",
    "/dev/sdb",
    4096,
    false,
    false,                 // verify
    Some(|p| {
        if p.phase == OperationPhase::Verifying {
            println!("Verifying…");
        }
    }),
    None,
)?;
```

### Progress types

```rust
use liblitho::progress::{OperationPhase, OperationProgress};

// Phases: Preparing, Decompressing, Writing, Syncing, Verifying,
//         Complete, Failed, Cancelled
let p = OperationProgress::new(OperationPhase::Writing)
    .with_bytes(1024, Some(4096))
    .with_message("Writing…");
```

### Devices façade

```rust
use liblitho::devices::{
    get_storage_devices, optimal_io_block_size, validate_device_safe_for_io, DeviceError,
};

validate_device_safe_for_io("/dev/sdb")?;
let block_size = optimal_io_block_size("/dev/sdb");

for dev in get_storage_devices()? {
    println!("{} — {} {}", dev.device_name, dev.vendor_name, dev.model_name);
}
```

Prefer `io_backend::{flash_io, clone_io}` from binaries so `simulated-io` / `real-io` apply consistently.

---

## Architecture

```
liblitho
  flash / clone / progress / cancel     # portable algorithms
  devices                               # DTOs, DeviceError, thin façade → platform::Active
  platform/
    traits/                             # I/O, inventory, path, safety, volume, privilege
    linux/ | windows/ | macos/          # OS implementations
    mod.rs                              # type Active = …; PlatformDevice factory
  io_backend                            # feature-gated real vs simulated I/O

bin litho       # clap CLI + cancel watchers + output modes
bin litho-tui   # ratatui UI; privilege via platform façade
```

Design notes: [platform-segregation-plan.md](platform-segregation-plan.md).

### Platform support matrix

| Component | Linux | macOS | Windows |
|-----------|-------|-------|---------|
| Build CLI || ⚠️ ||
| Build TUI ||||
| `flash` / `clone` (real-io) | ✅ root | ⚠️ partial | ✅ Admin |
| Device listing || ❌ stubs | ✅ WMI |
| Privilege elevation | ✅ pkexec/sudo | ⚠️ stubs | ✅ UAC |
| Cooperative cancel ||||

---

## GUI protocol (`-o gui`)

Used by Lithographer. Typical events:

```
@status phase=preparing msg="…"
@progress phase=writing pct=12.5 bytes=… total=…
@error msg="…"
@done ok
@done cancelled
```

Cancel: write `cancel` to `--cancel-file` (and/or stdin when not elevated through pkexec).

---

## Safety (developer)

- Treat every path as destructive until validation passes.
- Do not enable `real-io` for automated tests that might touch real disks (`io_backend` compile-errors real-io under `cfg(test)`).
- Windows exclusive volume locks are held on the open writer (`VolumeOps::Guard`); preflight unmounts without holding that session.

---

## Related

- [Lithographer]https://github.com/girish946/lithographer — Tauri GUI
- [CHANGELOG.md]../CHANGELOG.md

## License

MIT — see `Cargo.toml`.