@@ -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