diff --git a/src/libos/src/net/socket_file/mod.rs b/src/libos/src/net/socket_file/mod.rs index dc89a3bc..2232e339 100644 --- a/src/libos/src/net/socket_file/mod.rs +++ b/src/libos/src/net/socket_file/mod.rs @@ -3,7 +3,7 @@ use super::*; mod recv; mod send; -use fs::{File, FileRef, IoctlCmd}; +use fs::{AccessMode, CreationFlags, File, FileRef, IoctlCmd, StatusFlags}; use std::any::Any; use std::io::{Read, Seek, SeekFrom, Write}; @@ -111,6 +111,30 @@ impl File for SocketFile { Ok(()) } + fn get_access_mode(&self) -> Result { + Ok(AccessMode::O_RDWR) + } + + fn get_status_flags(&self) -> Result { + let ret = try_libc!(libc::ocall::fcntl_arg0(self.fd(), libc::F_GETFL)); + Ok(StatusFlags::from_bits_truncate(ret as u32)) + } + + fn set_status_flags(&self, new_status_flags: StatusFlags) -> Result<()> { + let valid_flags_mask = StatusFlags::O_APPEND + | StatusFlags::O_ASYNC + | StatusFlags::O_DIRECT + | StatusFlags::O_NOATIME + | StatusFlags::O_NONBLOCK; + let raw_status_flags = (new_status_flags & valid_flags_mask).bits(); + try_libc!(libc::ocall::fcntl_arg1( + self.fd(), + libc::F_SETFL, + raw_status_flags as c_int + )); + Ok(()) + } + fn as_any(&self) -> &Any { self } diff --git a/test/server/main.c b/test/server/main.c index 89f6b950..d1bd9f18 100644 --- a/test/server/main.c +++ b/test/server/main.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -250,11 +251,39 @@ int test_sendmsg_recvmsg_connectionless() { return ret; } + +int test_fcntl_setfl_and_getfl() { + int ret = 0; + int child_pid = 0; + int client_fd = -1; + int original_flags, actual_flags; + + client_fd = connect_with_child(8804, &child_pid); + if (client_fd < 0) + THROW_ERROR("connect failed"); + original_flags = fcntl(client_fd, F_GETFL, 0); + if (original_flags < 0) + THROW_ERROR("fcntl getfl failed"); + + ret = fcntl(client_fd, F_SETFL, original_flags | O_NONBLOCK); + if (ret < 0) + THROW_ERROR("fcntl setfl failed"); + + actual_flags = fcntl(client_fd, F_GETFL, 0); + if (actual_flags != (original_flags | O_NONBLOCK)) + THROW_ERROR("check the getfl value after setfl failed"); + + ret = wait_for_child_exit(child_pid); + + return ret; +} + static test_case_t test_cases[] = { TEST_CASE(test_read_write), TEST_CASE(test_send_recv), TEST_CASE(test_sendmsg_recvmsg), TEST_CASE(test_sendmsg_recvmsg_connectionless), + TEST_CASE(test_fcntl_setfl_and_getfl), }; int main(int argc, const char* argv[]) {