Bash toolkit for retro floppy work on Linux: create and edit disk images, archive physical floppies to files, and write images back to a USB floppy drive—without memorizing `dd`, `losetup`, and mount options.
Designed for day-to-day use with a **USB floppy drive** (removable `/dev/sdX` that changes between machines). Loop mounts are kept separate from the physical drive so you can work on `.img` files offline and only touch hardware when reading or burning.
**Tested hardware:** Mitsumi SmartDisk USB UFDD (`03ee:6901`), appearing as `/dev/sda`, FAT12 volumes, automount via udisks at `/media/$USER/<LABEL>`.
---
## Table of contents
- [What it does](#what-it-does)
- [Project layout](#project-layout)
- [Requirements](#requirements)
- [Installation](#installation)
- [Configuration](#configuration)
- [Quick start](#quick-start)
- [Command reference](#command-reference)
- [Workflows](#workflows)
- [Device selection](#device-selection)
- [Physical drive vs disk images](#physical-drive-vs-disk-images)
| **Restore** | Burn image to physical floppy with confirmation |
| **USB FDD** | Detect drive, refresh after disk swap, safe USB disconnect (`power-off`) |
| **Visibility** | List devices, attached state, full status |
All operations go through a single CLI: **`floppy`** (with subcommands). Status messages go to **stderr** so command substitution (e.g. device paths) is not corrupted.
Partial reads with warnings usually mean **damaged sectors**; image may still be useful. `floppy1982469877.img`-style random names meant the volume had no usable label—pass an explicit name: `floppy read disk -y`.
---
### C. Edit an image without hardware
```bash
floppy attach myproject
ls /media/$USER/myproject
floppy detach myproject
```
---
### D. Restore image to floppy
```bash
floppy refresh # new disk in drive
floppy burn myproject.img -d /dev/sda
```
### G. Done for the day — unplug USB drive
```bash
floppy disconnect # unmount + power off
# unplug USB cable
```
---
### E. Create a new blank floppy image for a retro project
```bash
floppy make blank -s 1440
floppy attach blank --format
# copy files into mount point
floppy detach blank
floppy burn blank.img -d /dev/sda
```
---
### F. Inspect current state
```bash
floppy list -v # attached loops + physical + archive dir
floppy status # everything including config
```
---
## Device selection
When `-d` and `FLOPPY_DEVICE` are unset, `floppy` picks a removable disk:
1. List removable `sd`/`fd` disks via `lsblk`
2. Score each (higher = more likely USB floppy):
- +100 if `MODEL` matches `FLOPPY_DEVICE_MATCH`
- +40 if `TRAN=usb`
- +30 if size is 360K / 720K / 1.4M
- +10 if volume label present
3.**Auto-select** if exactly one device, or exactly one with score ≥ 100
4. Otherwise **interactive menu**
Always use `floppy devices -v` when multiple USB storage devices are attached (thumb drives, SD readers, etc.).
- Prompts: `Write image to /dev/sdX? This will ERASE the floppy. [y/N]`
- Skipped with `-y` only when you are certain
- Targets **whole disk** (`/dev/sda`), not partitions (`/dev/sda1`)
- Unmounts before write
### Read / dump
- Prompt unless `-y`
- Refuses `0B` size (no disk inserted)
- Does not overwrite existing output without `--force`
### Permissions
Non-root users need `sudo` (or polkit via `udisksctl` for mount/unmount). Configure passwordless sudo only if you accept the security tradeoff on a dedicated retro workstation.
---
## Troubleshooting
### `floppy: no media in /dev/sda` but disk is inserted
- Run `floppy refresh`, then `floppy devices -v` (size should be `1.4M`, not `0B`)
- Re-seat the disk; try `floppy refresh --eject -w 3`
### Wrong label in `devices -v` (path shown as label)
Fixed in current code (per-field `lsblk`). Update if you see `label=/media/...`.
### `floppy read` uses random name `floppy123456789`
Volume has no FAT label; udisks mounted as `/media/user/disk`. Pass a name: `floppy read disk -y`, or set label on the FAT volume.
### `dd: Input/output error` partway through read
Common on aging floppies. Default `noerror,sync` completes with holes; warnings are printed. Use `--strict` only if you want fail-fast. Try `refresh` before retry; clean drive heads if errors persist.
### `floppy: command not found`
Run `./install.sh` or add `src` to `PATH`. Use `./floppy` from `src` when testing without install.
### `>>> using removable device` mixed into error text
Status must go to stderr (fixed). Update `lib/common.sh` if you see this on old copies.
### Automount fights `read` / `burn`
`read`, `burn`, and `dump` unmount first. Run `floppy refresh` after manual file-manager mounts.
### Leftover empty mount directory after `detach`
e.g. `/media/user/bootdisk (present, not mounted)`. Safe to remove: `rmdir` if empty.
### Device is `/dev/sda` on this machine but `/dev/sdb` elsewhere
Do not rely on fixed names; use `floppy devices` or set `FLOPPY_DEVICE` per host in config.
### Mitsumi drive shows `2880` during refresh
Internal `blockdev --getsz` probe (suppressed in output on current versions).
### `udisks power-off failed` on disconnect
Close file managers using the mount. Run `floppy detach <label>`, then `floppy disconnect` again. You can still unplug after a successful unmount if power-off fails—wait a few seconds for cache flush.
---
## Legacy wrappers
Thin scripts for muscle memory; all call `floppy`:
| Wrapper | Maps to |
|---------|---------|
| `floppy-make` | `floppy make "$@"` |
| `floppy-attach` | `floppy attach` (supports old two-arg size: `floppy-attach name 1440`) |