diff --git a/src/libos/src/fs/dev_fs/dev_fd.rs b/src/libos/src/fs/dev_fs/dev_fd.rs new file mode 100644 index 00000000..65a5d28b --- /dev/null +++ b/src/libos/src/fs/dev_fs/dev_fd.rs @@ -0,0 +1,48 @@ +use super::*; +pub struct DevFd; + +// Implement /dev/fd as a symlink to /proc/self/fd +impl INode for DevFd { + fn read_at(&self, offset: usize, buf: &mut [u8]) -> vfs::Result { + let proc_fd = "/proc/self/fd"; + for (tgt, src) in buf.iter_mut().zip(proc_fd.as_bytes().iter()) { + *tgt = *src; + } + Ok(proc_fd.len()) + } + + fn write_at(&self, offset: usize, buf: &[u8]) -> vfs::Result { + Err(vfs::FsError::PermError) + } + + fn poll(&self) -> vfs::Result { + Ok(vfs::PollStatus { + read: true, + write: true, + error: false, + }) + } + + fn metadata(&self) -> vfs::Result { + Ok(Metadata { + dev: 1, + inode: 0, + size: 0, + blk_size: 0, + blocks: 0, + atime: Timespec { sec: 0, nsec: 0 }, + mtime: Timespec { sec: 0, nsec: 0 }, + ctime: Timespec { sec: 0, nsec: 0 }, + type_: vfs::FileType::SymLink, + mode: 0o777, + nlinks: 1, + uid: 0, + gid: 0, + rdev: 0, + }) + } + + fn as_any_ref(&self) -> &dyn Any { + self + } +} diff --git a/src/libos/src/fs/dev_fs/mod.rs b/src/libos/src/fs/dev_fs/mod.rs index f395ee81..e09b7e03 100644 --- a/src/libos/src/fs/dev_fs/mod.rs +++ b/src/libos/src/fs/dev_fs/mod.rs @@ -6,12 +6,14 @@ use rcore_fs_devfs::DevFS; use rcore_fs_mountfs::MountFS; use rcore_fs_ramfs::RamFS; +use self::dev_fd::DevFd; use self::dev_null::DevNull; use self::dev_random::DevRandom; use self::dev_sgx::DevSgx; use self::dev_shm::DevShm; use self::dev_zero::DevZero; +mod dev_fd; mod dev_null; mod dev_random; mod dev_sgx; @@ -33,6 +35,8 @@ pub fn init_devfs() -> Result> { devfs.add("sgx", dev_sgx)?; let dev_shm = Arc::new(DevShm) as _; devfs.add("shm", dev_shm)?; + let dev_fd = Arc::new(DevFd) as _; + devfs.add("fd", dev_fd); let mountable_devfs = MountFS::new(devfs); // Mount the ramfs at '/shm' let ramfs = RamFS::new(); diff --git a/test/device/main.c b/test/device/main.c index d3c87b1a..0dcd3f32 100644 --- a/test/device/main.c +++ b/test/device/main.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "test_fs.h" // ============================================================================ @@ -143,6 +144,47 @@ int test_dev_shm() { return 0; } +int test_dev_fd() { + char *file_path = "/root/hello_world"; + char *greetings = "hello"; + int fd = open(file_path, O_RDWR | O_CREAT | O_TRUNC, 00666); + if (fd < 0) { + THROW_ERROR("failed to open a file to write"); + } + + // Generate dev_fd path + char dev_fd_path[20] = "/dev/fd/"; + char *fd_str = calloc(1, 4); // 4 bytes would be enough here. + if (fd_str == NULL) { + THROW_ERROR("calloc failed"); + } + asprintf(&fd_str, "%d", fd); + strcat(dev_fd_path, fd_str); + int dev_fd = open(dev_fd_path, O_WRONLY, 0666); + if (dev_fd < 0) { + THROW_ERROR("failed to open %s", dev_fd_path); + } + + int len = write(dev_fd, greetings, strlen(greetings)); + if (len < 0) { + THROW_ERROR("failed to write to %s", dev_fd_path); + } + + char buf[10] = {0}; + len = read(fd, buf, len); + if (len < 0) { + THROW_ERROR("failed to read from %s", file_path); + } + + if (strcmp(buf, greetings)) { + THROW_ERROR("file content is wrong"); + } + + free(fd_str); + close(dev_fd); + close(fd); + return 0; +} // ============================================================================ // Test suite // ============================================================================ @@ -156,6 +198,7 @@ static test_case_t test_cases[] = { TEST_CASE(test_dev_urandom_poll), TEST_CASE(test_dev_arandom), TEST_CASE(test_dev_shm), + TEST_CASE(test_dev_fd), }; int main() {