|
| 1 | +use crate::handle::HandleRights; |
| 2 | +use crate::sys::sys_impl::oshandle::OsHandle; |
| 3 | +use crate::wasi::Result; |
| 4 | +use std::cell::{Cell, RefCell, RefMut}; |
| 5 | +use std::io; |
| 6 | +use yanix::dir::Dir; |
| 7 | + |
| 8 | +#[derive(Debug)] |
| 9 | +pub(crate) struct OsDir { |
| 10 | + pub(crate) rights: Cell<HandleRights>, |
| 11 | + pub(crate) handle: OsHandle, |
| 12 | + // When the client makes a `fd_readdir` syscall on this descriptor, |
| 13 | + // we will need to cache the `libc::DIR` pointer manually in order |
| 14 | + // to be able to seek on it later. While on Linux, this is handled |
| 15 | + // by the OS, BSD Unixes require the client to do this caching. |
| 16 | + // |
| 17 | + // This comes directly from the BSD man pages on `readdir`: |
| 18 | + // > Values returned by telldir() are good only for the lifetime |
| 19 | + // > of the DIR pointer, dirp, from which they are derived. |
| 20 | + // > If the directory is closed and then reopened, prior values |
| 21 | + // > returned by telldir() will no longer be valid. |
| 22 | + stream_ptr: RefCell<Dir>, |
| 23 | +} |
| 24 | + |
| 25 | +impl OsDir { |
| 26 | + pub(crate) fn new(rights: HandleRights, handle: OsHandle) -> io::Result<Self> { |
| 27 | + let rights = Cell::new(rights); |
| 28 | + // We need to duplicate the handle, because `opendir(3)`: |
| 29 | + // Upon successful return from fdopendir(), the file descriptor is under |
| 30 | + // control of the system, and if any attempt is made to close the file |
| 31 | + // descriptor, or to modify the state of the associated description other |
| 32 | + // than by means of closedir(), readdir(), readdir_r(), or rewinddir(), |
| 33 | + // the behaviour is undefined. |
| 34 | + let stream_ptr = Dir::from(handle.try_clone()?)?; |
| 35 | + let stream_ptr = RefCell::new(stream_ptr); |
| 36 | + Ok(Self { |
| 37 | + rights, |
| 38 | + handle, |
| 39 | + stream_ptr, |
| 40 | + }) |
| 41 | + } |
| 42 | + /// Returns the `Dir` stream pointer associated with this `OsDir`. |
| 43 | + pub(crate) fn stream_ptr(&self) -> Result<RefMut<Dir>> { |
| 44 | + Ok(self.stream_ptr.borrow_mut()) |
| 45 | + } |
| 46 | +} |
0 commit comments