diff options
author | edef <edef@unfathomable.blue> | 2022-04-28 20:27:51 +0000 |
---|---|---|
committer | edef <edef@unfathomable.blue> | 2022-04-28 20:29:27 +0000 |
commit | 92a503ba90adf9a319b25306414e4012a1214260 (patch) | |
tree | 0cee9173a1e0eb2aa64c05b01e7c8b4cc1e4907b /ripple | |
parent | a9ca2be90b9a927d16d5ae64c09cf664cc73536d (diff) | |
download | unf-legacy-92a503ba90adf9a319b25306414e4012a1214260.tar.zst |
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
Diffstat (limited to 'ripple')
-rw-r--r-- | ripple/fossil/src/bin/mount.rs | 23 |
1 files changed, 21 insertions, 2 deletions
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), |