2 Commits

Author SHA1 Message Date
Cutieguwu
952e796e28 Probably won't work. 2026-01-01 15:29:13 -05:00
Cutieguwu
9198193365 Update io.rs 2026-01-01 14:37:56 -05:00
5 changed files with 24 additions and 36 deletions

View File

@@ -1,6 +1,7 @@
use std::ffi::CString;
use std::fs::{File, OpenOptions}; use std::fs::{File, OpenOptions};
use std::io::{self, Seek, SeekFrom}; use std::io::{self, Seek, SeekFrom};
use std::os::unix::fs::OpenOptionsExt; use std::os::fd::{AsRawFd, FromRawFd, IntoRawFd};
use crate::cli::CONFIG; use crate::cli::CONFIG;
@@ -20,12 +21,22 @@ pub fn get_stream_length<S: Seek>(stream: &mut S) -> io::Result<u64> {
len len
} }
/*
* IO Error Poisoning:
*
*
* Attempt 1:
*
* Wrap C calls w/ `ffi`. Most importantly, execute the `close()` through C.
*
* I cannot seem to execute `close()`... one hopes that reassigning will drop
* calling `close()` on the old fd, but I don't know.
*/
pub fn load_input() -> anyhow::Result<File> { pub fn load_input() -> anyhow::Result<File> {
OpenOptions::new() let path = CString::new(CONFIG.input.to_str().unwrap().to_owned())?;
.read(true) let flags = libc::O_RDONLY | libc::O_DIRECT;
.custom_flags(libc::O_DIRECT) Ok(unsafe { File::from_raw_fd(libc::open(path.as_ptr(), flags)) })
.open(&CONFIG.input)
.with_context(|| format!("Failed to open input file: {}", &CONFIG.input.display()))
} }
pub fn load_output() -> anyhow::Result<File> { pub fn load_output() -> anyhow::Result<File> {
@@ -61,18 +72,3 @@ pub fn load_map_write() -> anyhow::Result<File> {
) )
}) })
} }
#[repr(C, align(512))]
pub struct DirectIOBuffer(pub [u8; crate::MAX_BUFFER_SIZE]);
impl Default for DirectIOBuffer {
fn default() -> Self {
Self([crate::FB_NULL_VALUE; _])
}
}
impl From<[u8; crate::MAX_BUFFER_SIZE]> for DirectIOBuffer {
fn from(value: [u8; crate::MAX_BUFFER_SIZE]) -> Self {
Self(value)
}
}

View File

@@ -11,8 +11,6 @@ use anyhow;
const FB_SECTOR_SIZE: usize = 2048; const FB_SECTOR_SIZE: usize = 2048;
const FB_NULL_VALUE: u8 = 0; const FB_NULL_VALUE: u8 = 0;
const MAX_BUFFER_SIZE: usize = FB_SECTOR_SIZE * 16;
fn main() -> anyhow::Result<()> { fn main() -> anyhow::Result<()> {
let mut recover_tool = Recover::new()?; let mut recover_tool = Recover::new()?;
recover_tool.run()?; recover_tool.run()?;

View File

@@ -21,7 +21,6 @@ impl Default for Cluster {
impl Cluster { impl Cluster {
/// Breaks apart into a vec of clusters, /// Breaks apart into a vec of clusters,
/// each of cluster_size, excepting last. /// each of cluster_size, excepting last.
#[allow(dead_code)]
pub fn subdivide(&mut self, cluster_len: usize) -> Vec<Cluster> { pub fn subdivide(&mut self, cluster_len: usize) -> Vec<Cluster> {
let domain_len = self.domain.len(); let domain_len = self.domain.len();
let mut start = self.domain.start; let mut start = self.domain.start;
@@ -50,8 +49,6 @@ impl Cluster {
clusters clusters
} }
// This is used in unit tests at present. Ideally it probably shouldn't exist.
#[allow(dead_code)]
pub fn set_stage(&mut self, stage: Stage) -> &mut Self { pub fn set_stage(&mut self, stage: Stage) -> &mut Self {
self.stage = stage; self.stage = stage;
self self

View File

@@ -16,7 +16,6 @@ impl Default for Domain {
impl Domain { impl Domain {
/// Return length of domain in sectors. /// Return length of domain in sectors.
#[allow(dead_code)]
pub fn len(self) -> usize { pub fn len(self) -> usize {
self.end - self.start self.end - self.start
} }

View File

@@ -2,13 +2,13 @@ use std::fs::File;
use std::io::{BufWriter, Read, Seek, SeekFrom, Write}; use std::io::{BufWriter, Read, Seek, SeekFrom, Write};
use std::usize; use std::usize;
use anyhow::Context; use anyhow::{Context, anyhow};
use crate::cli::CONFIG; use crate::cli::CONFIG;
use crate::io::DirectIOBuffer;
use crate::mapping::prelude::*; use crate::mapping::prelude::*;
#[derive(Debug)] #[derive(Debug)]
#[allow(dead_code)]
pub struct Recover { pub struct Recover {
input: File, input: File,
output: BufWriter<File>, output: BufWriter<File>,
@@ -90,12 +90,11 @@ impl Recover {
/// Attempt to copy all untested blocks. /// Attempt to copy all untested blocks.
fn copy_untested(&mut self) -> anyhow::Result<()> { fn copy_untested(&mut self) -> anyhow::Result<()> {
let mut buf = DirectIOBuffer::default();
for untested in self.map.get_clusters(Stage::Untested) { for untested in self.map.get_clusters(Stage::Untested) {
// Caching. // Caching.
let mut read_position: usize; let mut read_position: usize;
let mut cluster: Cluster; let mut cluster: Cluster;
let mut buf: Vec<u8>;
let mut buf_capacity = self.get_buf_capacity() as usize; let mut buf_capacity = self.get_buf_capacity() as usize;
dbg!(untested.domain); dbg!(untested.domain);
@@ -105,6 +104,7 @@ impl Recover {
dbg!(read_position); dbg!(read_position);
buf_capacity = buf_capacity.min(untested.domain.end - read_position); buf_capacity = buf_capacity.min(untested.domain.end - read_position);
buf = vec![crate::FB_NULL_VALUE; buf_capacity];
cluster = Cluster { cluster = Cluster {
domain: Domain { domain: Domain {
@@ -114,7 +114,7 @@ impl Recover {
stage: Stage::Intact, stage: Stage::Intact,
}; };
if let Err(err) = self.input.read_exact(&mut buf.0) { if let Err(err) = self.input.read_exact(&mut buf) {
// If buf were zeroed out before every read, one could theoretically recover // If buf were zeroed out before every read, one could theoretically recover
// part of that read given the assumption that all null values from the end to // part of that read given the assumption that all null values from the end to
// the first non-null value are unread, and some further padding from the last // the first non-null value are unread, and some further padding from the last
@@ -141,7 +141,7 @@ impl Recover {
if cluster.stage == Stage::Intact { if cluster.stage == Stage::Intact {
self.output self.output
.write_all(&buf.0[0..buf_capacity]) .write_all(&buf[0..buf_capacity])
.context("Failed to write data to output file")?; .context("Failed to write data to output file")?;
} }
@@ -151,8 +151,6 @@ impl Recover {
} }
} }
drop(buf);
self.map.write_to(&mut crate::io::load_map_write()?)?; self.map.write_to(&mut crate::io::load_map_write()?)?;
Ok(()) Ok(())
@@ -161,7 +159,7 @@ impl Recover {
/// Set buffer capacity as cluster length in bytes. /// Set buffer capacity as cluster length in bytes.
/// Varies depending on the recovery stage. /// Varies depending on the recovery stage.
fn get_buf_capacity(&mut self) -> u64 { fn get_buf_capacity(&mut self) -> u64 {
crate::MAX_BUFFER_SIZE.min(CONFIG.sector_size * CONFIG.cluster_length) as u64 CONFIG.sector_size as u64 * CONFIG.cluster_length as u64
} }
/// Reloads the input and restores the seek position. /// Reloads the input and restores the seek position.