Image and custody
internal/image.Image
type Image interface {
ReadAt(p []byte, off int64) (int, error)
WriteAt(p []byte, off int64) (int, error)
Size() int64
Path() string
}
rawimage.go implements this over os.File. Open opens read-write. OpenReadOnly is for detect.
readonly.go adds a ReadOnly wrapper. Its WriteAt always returns ErrReadOnly. detect wraps its image in that as a second guard.
Live mode, once built, will use the same interface backed by a single target file. Filesystem and technique code never branches on mode. See Modes.
internal/custody
Every write goes through internal/custody.
custody.Wrap(img) returns a Recorder. That is the Image interface plus EventsSnapshot. It wraps a real Image, SHA-256-hashes and records each WriteAt, then passes it on.
Callers wrap once and pass the result everywhere. Nothing downstream needs to know custody exists.
log.go combines a recorded event with the command’s context into a Record, then appends it to the custody log.
Because custody is a decorator over Image, recording is structural. Every WriteAt on the wrapped image is hashed and recorded, whoever calls it. There is no flag to skip it.
What the user sees
Every successful hide and clear writes an entry to the chain-of-custody log, in both modes. There is no flag to turn it off. detect is read-only. It never writes to the target and never touches the log.
On success, hide and clear also print their custody record as one JSON object on standard output. It includes the technique, technique-specific detail, and the affected byte count.
If the output fails after the filesystem change, the command reports the failure. It does not claim the change was rolled back.