Fix the inet socket file to support fcntl()'s F_GETFL and F_SETFL

This commit is contained in:
LI Qing 2020-01-06 03:18:15 +00:00 committed by Tate, Hongliang Tian
parent a84803e951
commit 040fe89661
2 changed files with 54 additions and 1 deletions

@ -3,7 +3,7 @@ use super::*;
mod recv; mod recv;
mod send; mod send;
use fs::{File, FileRef, IoctlCmd}; use fs::{AccessMode, CreationFlags, File, FileRef, IoctlCmd, StatusFlags};
use std::any::Any; use std::any::Any;
use std::io::{Read, Seek, SeekFrom, Write}; use std::io::{Read, Seek, SeekFrom, Write};
@ -111,6 +111,30 @@ impl File for SocketFile {
Ok(()) Ok(())
} }
fn get_access_mode(&self) -> Result<AccessMode> {
Ok(AccessMode::O_RDWR)
}
fn get_status_flags(&self) -> Result<StatusFlags> {
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 { fn as_any(&self) -> &Any {
self self
} }

@ -2,6 +2,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/wait.h> #include <sys/wait.h>
@ -250,11 +251,39 @@ int test_sendmsg_recvmsg_connectionless() {
return ret; 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[] = { static test_case_t test_cases[] = {
TEST_CASE(test_read_write), TEST_CASE(test_read_write),
TEST_CASE(test_send_recv), TEST_CASE(test_send_recv),
TEST_CASE(test_sendmsg_recvmsg), TEST_CASE(test_sendmsg_recvmsg),
TEST_CASE(test_sendmsg_recvmsg_connectionless), TEST_CASE(test_sendmsg_recvmsg_connectionless),
TEST_CASE(test_fcntl_setfl_and_getfl),
}; };
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {