@@ -80,7 +80,7 @@ impl<S: BitmapSlice + Send + Sync> PassthroughFs<S> {
8080 // changes the kernel offset while we are using it.
8181 let ( _guard, dir) = data. get_file_mut ( ) . await ;
8282
83- // alloc buff , pay attention to alian .
83+ // Allocate buffer; pay attention to alignment .
8484 let mut buffer = vec ! [ 0u8 ; BUFFER_SIZE ] ;
8585
8686 // Safe because this doesn't modify any memory and we check the return value.
@@ -180,7 +180,7 @@ impl<S: BitmapSlice + Send + Sync> PassthroughFs<S> {
180180 // changes the kernel offset while we are using it.
181181 let ( _guard, dir) = data. get_file_mut ( ) . await ;
182182
183- // alloc buff , pay attention to alian .
183+ // Allocate buffer; pay attention to alignment .
184184 let mut buffer = vec ! [ 0u8 ; BUFFER_SIZE ] ;
185185
186186 // Safe because this doesn't modify any memory and we check the return value.
@@ -1794,21 +1794,89 @@ impl Filesystem for PassthroughFs {
17941794 // Let the Arc<HandleData> in scope, otherwise fd may get invalid.
17951795 let data = self . handle_map . get ( fh, inode) . await ?;
17961796
1797- // Acquire the lock to get exclusive access, otherwise it may break do_readdir().
1798- let ( _guard, file) = data. get_file_mut ( ) . await ;
1797+ // Check file type to determine appropriate lseek handling
1798+ let st = stat_fd ( data. get_file ( ) , None ) ?;
1799+ let is_dir = ( st. st_mode & libc:: S_IFMT ) == libc:: S_IFDIR ;
1800+
1801+ if is_dir {
1802+ // Directory special handling: support SEEK_SET and SEEK_CUR with bounds checks.
1803+ // Acquire the lock to get exclusive access
1804+ let ( _guard, file) = data. get_file_mut ( ) . await ;
1805+
1806+ // Handle directory lseek operations according to POSIX standard
1807+ // This enables seekdir/telldir functionality on directories
1808+ match whence {
1809+ // SEEK_SET: set directory offset to an absolute value
1810+ x if x == libc:: SEEK_SET as u32 => {
1811+ // Validate offset bounds to prevent overflow
1812+ // Directory offsets should not exceed i64::MAX
1813+ if offset > i64:: MAX as u64 {
1814+ return Err ( io:: Error :: from_raw_os_error ( libc:: EINVAL ) . into ( ) ) ;
1815+ }
17991816
1800- // Safe because this doesn't modify any memory and we check the return value.
1801- let res = unsafe {
1802- libc:: lseek (
1803- file. as_raw_fd ( ) ,
1804- offset as libc:: off64_t ,
1805- whence as libc:: c_int ,
1806- )
1807- } ;
1808- if res < 0 {
1809- Err ( io:: Error :: last_os_error ( ) . into ( ) )
1817+ // Perform the seek operation using libc::lseek64
1818+ // This directly manipulates the file descriptor's position
1819+ let res = unsafe {
1820+ libc:: lseek64 ( file. as_raw_fd ( ) , offset as libc:: off64_t , libc:: SEEK_SET )
1821+ } ;
1822+ if res < 0 {
1823+ return Err ( io:: Error :: last_os_error ( ) . into ( ) ) ;
1824+ }
1825+ Ok ( ReplyLSeek { offset : res as u64 } )
1826+ }
1827+ // SEEK_CUR: move relative to current directory offset
1828+ x if x == libc:: SEEK_CUR as u32 => {
1829+ // Get current position using libc::lseek64 with offset 0
1830+ let cur = unsafe { libc:: lseek64 ( file. as_raw_fd ( ) , 0 , libc:: SEEK_CUR ) } ;
1831+ if cur < 0 {
1832+ return Err ( io:: Error :: last_os_error ( ) . into ( ) ) ;
1833+ }
1834+ let current = cur as u64 ;
1835+
1836+ // Compute new offset safely to prevent arithmetic overflow
1837+ if let Some ( new_offset) = current. checked_add ( offset) {
1838+ // Ensure the new offset is within valid bounds
1839+ if new_offset > i64:: MAX as u64 {
1840+ return Err ( io:: Error :: from_raw_os_error ( libc:: EINVAL ) . into ( ) ) ;
1841+ }
1842+ // Set the new offset using libc::lseek64
1843+ let res = unsafe {
1844+ libc:: lseek64 (
1845+ file. as_raw_fd ( ) ,
1846+ new_offset as libc:: off64_t ,
1847+ libc:: SEEK_SET ,
1848+ )
1849+ } ;
1850+ if res < 0 {
1851+ return Err ( io:: Error :: last_os_error ( ) . into ( ) ) ;
1852+ }
1853+ Ok ( ReplyLSeek { offset : new_offset } )
1854+ } else {
1855+ Err ( io:: Error :: from_raw_os_error ( libc:: EINVAL ) . into ( ) )
1856+ }
1857+ }
1858+ // Other whence values are invalid for directories (e.g., SEEK_END)
1859+ _ => Err ( io:: Error :: from_raw_os_error ( libc:: EINVAL ) . into ( ) ) ,
1860+ }
18101861 } else {
1811- Ok ( ReplyLSeek { offset : res as u64 } )
1862+ // File seek handling for non-directory files
1863+ // Acquire the lock to get exclusive access, otherwise it may break do_readdir().
1864+ let ( _guard, file) = data. get_file_mut ( ) . await ;
1865+
1866+ // Safe because this doesn't modify any memory and we check the return value.
1867+ // Use 64-bit seek for regular files to match kernel offsets
1868+ let res = unsafe {
1869+ libc:: lseek64 (
1870+ file. as_raw_fd ( ) ,
1871+ offset as libc:: off64_t ,
1872+ whence as libc:: c_int ,
1873+ )
1874+ } ;
1875+ if res < 0 {
1876+ Err ( io:: Error :: last_os_error ( ) . into ( ) )
1877+ } else {
1878+ Ok ( ReplyLSeek { offset : res as u64 } )
1879+ }
18121880 }
18131881 }
18141882}
0 commit comments