Skip to content

Commit c441518

Browse files
committed
lseek: Fixed incorrect lseek behaviour with whence Set or Cur
1 parent 0ebae3f commit c441518

File tree

1 file changed

+35
-16
lines changed

1 file changed

+35
-16
lines changed

src/fs/fuse.rs

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -724,25 +724,44 @@ impl FuseFileHandleInner {
724724
}
725725

726726
fn lseek(&mut self, offset: isize, whence: SeekWhence) -> io::Result<isize> {
727-
debug!("FUSE lseek");
727+
debug!("FUSE lseek: offset: {offset}, whence: {whence:?}");
728+
729+
// Seek on fuse file systems seems to be a little odd: All reads are referenced from the
730+
// beginning of the file, thus we have to track the offset ourself. Also, a read doesn't
731+
// move the read pointer on the remote side, so we can't get the current position using
732+
// remote lseek when referencing from `Cur` and we have to use the internally tracked
733+
// position instead.
734+
match whence {
735+
SeekWhence::End | SeekWhence::Data | SeekWhence::Hole => {
736+
if let (Some(nid), Some(fh)) = (self.fuse_nid, self.fuse_fh) {
737+
let (cmd, rsp_payload_len) = ops::Lseek::create(nid, fh, offset, whence);
738+
let rsp = get_filesystem_driver()
739+
.ok_or(Errno::Nosys)?
740+
.lock()
741+
.send_command(cmd, rsp_payload_len)?;
742+
743+
if rsp.headers.out_header.error < 0 {
744+
return Err(Errno::Io);
745+
}
728746

729-
if let (Some(nid), Some(fh)) = (self.fuse_nid, self.fuse_fh) {
730-
let (cmd, rsp_payload_len) = ops::Lseek::create(nid, fh, offset, whence);
731-
let rsp = get_filesystem_driver()
732-
.ok_or(Errno::Nosys)?
733-
.lock()
734-
.send_command(cmd, rsp_payload_len)?;
747+
let rsp_offset = rsp.headers.op_header.offset;
748+
self.offset = rsp.headers.op_header.offset.try_into().unwrap();
735749

736-
if rsp.headers.out_header.error < 0 {
737-
return Err(Errno::Io);
750+
Ok(rsp_offset.try_into().unwrap())
751+
} else {
752+
Err(Errno::Io)
753+
}
754+
}
755+
SeekWhence::Set => {
756+
self.offset = offset.try_into().map_err(|_e| Errno::Inval)?;
757+
Ok(self.offset as isize)
758+
}
759+
SeekWhence::Cur => {
760+
self.offset = (self.offset as isize + offset)
761+
.try_into()
762+
.map_err(|_e| Errno::Inval)?;
763+
Ok(self.offset as isize)
738764
}
739-
740-
let rsp_offset = rsp.headers.op_header.offset;
741-
self.offset = rsp.headers.op_header.offset.try_into().unwrap();
742-
743-
Ok(rsp_offset.try_into().unwrap())
744-
} else {
745-
Err(Errno::Io)
746765
}
747766
}
748767

0 commit comments

Comments
 (0)