From 92a503ba90adf9a319b25306414e4012a1214260 Mon Sep 17 00:00:00 2001 From: edef Date: Thu, 28 Apr 2022 20:27:51 +0000 Subject: ripple/fossil/mount: don't serve short reads FUSE doesn't actually respect the usual read() contract, so this resulted in us serving truncated files. Change-Id: I8bdb0bd7f03162fb78774f3f84daeefc5ba5e3b1 --- ripple/fossil/src/bin/mount.rs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'ripple/fossil') diff --git a/ripple/fossil/src/bin/mount.rs b/ripple/fossil/src/bin/mount.rs index 3335c1f..2e6945b 100644 --- a/ripple/fossil/src/bin/mount.rs +++ b/ripple/fossil/src/bin/mount.rs @@ -215,8 +215,27 @@ impl fuser::Filesystem for Filesystem { offset as u64 ); - let mut buffer = vec![0; size]; - let n = contents.read(&mut buffer).unwrap(); + // NOTE: FUSE read() doesn't actually work like you expect. + // If you return a short read, it *will* simply treat that + // as the file being short. `contents` is an `io::Read`, + // which adheres to the usual contract, so we partially + // reimplement `read_exact` here. + let mut buffer = vec![0u8; size]; + let n = { + let mut buffer = &mut buffer[..]; + let mut total = 0; + loop { + match contents.read(buffer).unwrap() { + 0 => break, + n => { + buffer = &mut buffer[n..]; + total += n; + } + } + } + total + }; + reply.data(&buffer[..n]); } _ => reply.error(EINVAL), -- cgit 1.4.1