From 6661e7ecbcfcb3a98e5a88a4827c932f6f7cea55 Mon Sep 17 00:00:00 2001 From: Radu Marias Date: Thu, 2 May 2024 19:03:14 +0300 Subject: [PATCH] fix seek forward on read --- src/crypto.rs | 2 +- src/encryptedfs.rs | 54 ++++++++++++++++------------------------------ src/main.rs | 4 +++- src/stream_util.rs | 30 ++++++++++++++++++++++---- 4 files changed, 48 insertions(+), 42 deletions(-) diff --git a/src/crypto.rs b/src/crypto.rs index f22953cb..f5eb0193 100644 --- a/src/crypto.rs +++ b/src/crypto.rs @@ -15,7 +15,7 @@ use num_format::{Locale, ToFormattedString}; use openssl::sha::sha256; use secrecy::{ExposeSecret, SecretString, SecretVec}; use thiserror::Error; -use tracing::{debug, error, instrument}; +use tracing::{debug, error, info, instrument}; use strum_macros::{Display, EnumIter, EnumString}; use serde::{Deserialize, Serialize}; use openssl::error::ErrorStack; diff --git a/src/encryptedfs.rs b/src/encryptedfs.rs index 37641966..e9f84fb5 100644 --- a/src/encryptedfs.rs +++ b/src/encryptedfs.rs @@ -20,7 +20,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; use thiserror::Error; use tokio::sync::{Mutex, MutexGuard, RwLock}; use tokio_stream::wrappers::ReadDirStream; -use tracing::{debug, error, instrument, warn}; +use tracing::{debug, error, info, instrument, warn}; use crate::arc_hashmap::{ArcHashMap, Guard}; use crate::{crypto, expire_value, stream_util}; @@ -974,12 +974,21 @@ impl EncryptedFs { self.do_with_read_handle(handle, ReadHandleContextOperation::RecreateDecryptor { existing: ctx }).await?; ctx = guard.get(&handle).unwrap().lock().await; } - stream_util::read_seek_forward_exact(&mut ctx.decryptor.as_mut().unwrap(), offset)?; + let pos = ctx.pos; + let actual_file_size = fs::metadata(self.data_dir.join(CONTENTS_DIR).join(ino.to_string()))?.len(); + debug!(pos = pos.to_formatted_string(&Locale::en), offset = offset.to_formatted_string(&Locale::en), file_size = ctx.attr.size.to_formatted_string(&Locale::en), + actual_file_size = actual_file_size.to_formatted_string(&Locale::en), "seeking"); + let len = offset - pos; + stream_util::read_seek_forward_exact(&mut ctx.decryptor.as_mut().unwrap(), len)?; + ctx.pos += len; } if offset + buf.len() as u64 > ctx.attr.size { buf = &mut buf[..(ctx.attr.size - offset) as usize]; } - ctx.decryptor.as_mut().unwrap().read_exact(&mut buf)?; + ctx.decryptor.as_mut().unwrap().read_exact(&mut buf).map_err(|err| { + error!(err = %err, pos = ctx.pos.to_formatted_string(&Locale::en), offset = offset.to_formatted_string(&Locale::en), file_size = ctx.attr.size.to_formatted_string(&Locale::en), "reading from decryptor"); + err + })?; ctx.pos += buf.len() as u64; ctx.attr.atime = SystemTime::now(); @@ -1339,17 +1348,7 @@ impl EncryptedFs { // copy existing data until new size debug!("copying data until new size"); - let mut buf = vec![0; BUF_SIZE]; - let mut pos = 0_u64; - loop { - let len = min(buf.len(), (size - pos) as usize); - decryptor.read_exact(&mut buf[..len])?; - encryptor.write_all(&buf[..len])?; - pos += len as u64; - if pos == size { - break; - } - } + stream_util::copy_exact(&mut decryptor, &mut encryptor, size)?; debug!("rename from tmp file"); tokio::fs::rename(tmp_path, self.data_dir.join(CONTENTS_DIR).join(attr.ino.to_string())).await?; } else { @@ -1370,29 +1369,12 @@ impl EncryptedFs { // copy existing data debug!("copying existing data"); - let mut buf = vec![0; BUF_SIZE]; - let mut pos = 0_u64; - loop { - let len = min(buf.len(), (attr.size - pos) as usize); - decryptor.read_exact(&mut buf[..len])?; - encryptor.write_all(&buf[..len])?; - pos += len as u64; - if pos == attr.size { - break; - } - } + stream_util::copy_exact(&mut decryptor, &mut encryptor, attr.size)?; + attr.size = size; // now fill up with zeros until new size debug!("filling up with zeros until new size"); - let buf = vec![0; BUF_SIZE]; - loop { - let len = min(buf.len(), (size - attr.size) as usize); - encryptor.write_all(&buf[..len])?; - attr.size += len as u64; - if attr.size == size { - break; - } - } + stream_util::fill_zeros(&mut encryptor, size - attr.size)?; encryptor.finish()?; debug!("rename from tmp file"); @@ -1583,7 +1565,7 @@ impl EncryptedFs { let new_key = crypto::derive_key(&new_password, &cipher, salt)?; tokio::fs::remove_file(enc_file.clone()).await?; let mut encryptor = crypto::create_encryptor(OpenOptions::new().read(true).write(true).create(true).truncate(true).open(enc_file.clone())?, - &cipher, &new_key); + &cipher, &new_key); bincode::serialize_into(&mut encryptor, &key_store)?; Ok(()) @@ -1809,7 +1791,7 @@ impl EncryptedFs { let key = SecretVec::new(key); let key_store = KeyStore::new(key); let mut encryptor = crypto::create_encryptor(OpenOptions::new().read(true).write(true).create(true).open(path)?, - cipher, &derived_key); + cipher, &derived_key); bincode::serialize_into(&mut encryptor, &key_store)?; Ok(key_store.key) } diff --git a/src/main.rs b/src/main.rs index e4cdb293..53059610 100644 --- a/src/main.rs +++ b/src/main.rs @@ -352,7 +352,9 @@ pub fn log_init(level: Level) -> WorkerGuard { .pretty() .init() } else { - builder.init(); + builder + .pretty() + .init() } guard diff --git a/src/stream_util.rs b/src/stream_util.rs index 96e8078f..de81edcc 100644 --- a/src/stream_util.rs +++ b/src/stream_util.rs @@ -2,7 +2,7 @@ use std::cmp::min; use std::io; use std::io::{Read, Write}; use num_format::{Locale, ToFormattedString}; -use tracing::{debug, instrument}; +use tracing::{debug, error, info, instrument}; #[cfg(test)] const BUF_SIZE: usize = 256 * 1024; @@ -25,9 +25,12 @@ pub fn read_seek_forward_exact(mut r: impl Read, len: u64) -> io::Result<()> { } else { buffer.len() }; - debug!(read_len = read_len.to_formatted_string(&Locale::en), "reading"); + debug!(pos, read_len = read_len.to_formatted_string(&Locale::en), "reading"); if read_len > 0 { - r.read_exact(&mut buffer[..read_len])?; + r.read_exact(&mut buffer[..read_len]).map_err(|err| { + error!("error reading from file pos {} len {}", pos.to_formatted_string(&Locale::en), read_len.to_formatted_string(&Locale::en)); + err + })?; pos += read_len as u64; if pos == len { break; @@ -52,7 +55,7 @@ pub fn copy_exact(r: &mut impl Read, w: &mut impl Write, len: u64) -> io::Result let buf_len = min(buffer.len(), (len - read_pos) as usize); debug!("reading from file pos {} buf_len {}", read_pos.to_formatted_string(&Locale::en), buf_len.to_formatted_string(&Locale::en)); r.read_exact(&mut buffer[..buf_len]).map_err(|err| { - debug!("error reading from file pos {} len {}", read_pos.to_formatted_string(&Locale::en), buf_len.to_formatted_string(&Locale::en)); + error!("error reading from file pos {} len {}", read_pos.to_formatted_string(&Locale::en), buf_len.to_formatted_string(&Locale::en)); err })?; w.write_all(&buffer[..buf_len])?; @@ -62,4 +65,23 @@ pub fn copy_exact(r: &mut impl Read, w: &mut impl Write, len: u64) -> io::Result } } Ok(()) +} + +#[instrument(skip(w, len), fields(len = len.to_formatted_string(& Locale::en)))] +pub fn fill_zeros(w: &mut impl Write, len: u64) -> io::Result<()> { + debug!(""); + if len == 0 { + return Ok(()); + } + let mut buffer = vec![0; BUF_SIZE]; + let mut written = 0_u64; + loop { + let buf_len = min(buffer.len(), (len - written) as usize); + w.write_all(&buffer[..buf_len])?; + written += buf_len as u64; + if written == len { + break; + } + } + Ok(()) } \ No newline at end of file