feat: reconexão do disco, pausa por desconexão, sessões automáticas e organização (0.4.0)
Release / Cria a release (push) Canceled after 0s
Release / CLI (linux-aarch64) (push) Canceled after 0s
Release / CLI (linux-x86_64) (push) Canceled after 0s
Release / CLI (macos-aarch64) (push) Canceled after 0s
Release / CLI (macos-x86_64) (push) Canceled after 0s
Release / CLI (windows-x86_64) (push) Canceled after 0s
Release / App desktop (linux-x86_64) (push) Canceled after 0s
Release / App desktop (macos-aarch64) (push) Canceled after 0s
Release / App desktop (macos-x86_64) (push) Canceled after 0s
Release / App desktop (windows-x86_64) (push) Canceled after 0s
Release / Publica a release (push) Canceled after 0s

- Reconhece o mesmo disco por tamanho + impressão digital quando volta com outro nome.
- Varredura pausa sozinha (sem perder nada) se o dispositivo parar de responder.
- Sessões salvas automaticamente (atômico) e listadas em Recentes.
- Organização ao recuperar (pastas, tipo, data, tudo junto) e checagem de espaço livre.
- Botão de escolher a origem também em sessões pausadas.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas RayanandClaude Sonnet 5.5 committed 2026-10-18 19:32:00 -03:00
1 parent 97f940f261
commit 4bb2397e3b
19 files changed
+1011 -97

No files matched your search

+24 -5
View File
@@ -25,23 +25,33 @@ pub fn carve_range(
cfg: &CarveCfg,
cancelled: &(dyn Fn() -> bool + Sync),
ev: &mut dyn CarveEvents,
) -> bool {
) -> CarveEnd {
let end = end.min(src.size());
let mut pos = (*next).max(start);
// Alinha ao setor.
pos = pos.div_ceil(SECTOR) * SECTOR;
let mut buf = vec![0u8; CHUNK + LOOKAHEAD];
let mut skip_until = 0u64;
let mut fails = 0u32;
while pos < end {
if cancelled() {
*next = pos;
return false;
return CarveEnd::Cancelled;
}
let want = ((end - pos) as usize).min(CHUNK + LOOKAHEAD);
let got = match read_full(src, pos, &mut buf[..want]) {
Ok(n) => n,
Ok(n) => {
fails = 0;
n
}
Err(_) => {
// Setor ruim: pula um bloco inteiro e segue (a imagem forense trata isso melhor).
// Várias falhas seguidas = dispositivo sumiu: para com o ponto de retomada salvo.
fails += 1;
if fails >= 4 {
*next = pos - (fails as u64 - 1) * CHUNK as u64;
return CarveEnd::IoLost;
}
// Setor ruim isolado: pula um bloco inteiro e segue (a imagem forense trata isso melhor).
pos += CHUNK as u64;
ev.advance(CHUNK as u64);
*next = pos;
@@ -84,7 +94,16 @@ pub fn carve_range(
*next = pos;
}
*next = end;
true
CarveEnd::Done
}
/// Como o carving de um intervalo terminou.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CarveEnd {
Done,
Cancelled,
/// Várias leituras seguidas falharam: o dispositivo provavelmente foi desconectado.
IoLost,
}
/// Receptor de eventos do carving.