Add support for ioctl TCGETS/TCSETS

This commit is contained in:
Hui, Chunyang 2021-04-28 12:00:30 +00:00 committed by Zongmin.Gu
parent 6be3e7efba
commit f77e2c5e89
7 changed files with 96 additions and 1 deletions

@ -25,3 +25,20 @@ pub struct IfReq {
pub ifr_name: [u8; IFNAMSIZ],
pub ifr_union: [u8; 24],
}
type TcflagT = u32;
type CcT = u8;
type SpeedT = u32;
const NCCS: usize = 32;
#[derive(Debug)]
#[repr(C)]
pub struct Termios {
pub c_iflag: TcflagT,
pub c_oflag: TcflagT,
pub c_cflag: TcflagT,
pub c_lflag: TcflagT,
pub c_line: CcT,
pub c_cc: [CcT; NCCS],
pub c_ispeed: SpeedT,
pub c_ospeed: SpeedT,
}

@ -26,6 +26,9 @@ impl_ioctl_nums_and_cmds! {
// Format:
// ioctl_name => (ioctl_num, ioctl_type_arg)
// Get terminal attributes
TCGETS => (0x5401, mut Termios), // ignore
TCSETS => (0x5402, Termios),
// Get window size
TIOCGWINSZ => (0x5413, mut WinSize),
// Set window size

@ -203,6 +203,11 @@ impl File for INodeFile {
}
fn ioctl(&self, cmd: &mut IoctlCmd) -> Result<i32> {
match cmd {
IoctlCmd::TCGETS(_) => return_errno!(ENOTTY, "not tty device"),
IoctlCmd::TCSETS(_) => return_errno!(ENOTTY, "not tty device"),
_ => {}
};
let cmd_num = cmd.cmd_num();
let cmd_argp = cmd.arg_ptr() as usize;
self.inode.io_control(cmd_num, cmd_argp)?;

@ -87,6 +87,10 @@ impl File for PipeReader {
fn as_any(&self) -> &dyn Any {
self
}
fn ioctl(&self, cmd: &mut IoctlCmd) -> Result<i32> {
ioctl_inner(cmd)
}
}
pub struct PipeWriter {
@ -150,6 +154,10 @@ impl File for PipeWriter {
fn as_any(&self) -> &dyn Any {
self
}
fn ioctl(&self, cmd: &mut IoctlCmd) -> Result<i32> {
ioctl_inner(cmd)
}
}
impl fmt::Debug for PipeReader {
@ -202,3 +210,12 @@ impl PipeType for FileRef {
.ok_or_else(|| errno!(EBADF, "not a pipe writer"))
}
}
fn ioctl_inner(cmd: &mut IoctlCmd) -> Result<i32> {
match cmd {
IoctlCmd::TCGETS(_) => return_errno!(ENOTTY, "not tty device"),
IoctlCmd::TCSETS(_) => return_errno!(ENOTTY, "not tty device"),
_ => return_errno!(ENOSYS, "not supported"),
};
unreachable!();
}

@ -171,6 +171,8 @@ impl File for StdoutFile {
fn ioctl(&self, cmd: &mut IoctlCmd) -> Result<i32> {
let can_delegate_to_host = match cmd {
IoctlCmd::TCGETS(_) => true,
IoctlCmd::TCSETS(_) => true,
IoctlCmd::TIOCGWINSZ(_) => true,
IoctlCmd::TIOCSWINSZ(_) => true,
_ => false,
@ -320,6 +322,8 @@ impl File for StdinFile {
fn ioctl(&self, cmd: &mut IoctlCmd) -> Result<i32> {
let can_delegate_to_host = match cmd {
IoctlCmd::TCGETS(_) => true,
IoctlCmd::TCSETS(_) => true,
IoctlCmd::TIOCGWINSZ(_) => true,
IoctlCmd::TIOCSWINSZ(_) => true,
_ => false,

@ -2,7 +2,7 @@ include ../test_common.mk
SGX_SDK ?= /opt/intel/sgxsdk
EXTRA_C_FLAGS := -I$(SGX_SDK)/include
EXTRA_C_FLAGS := -I$(SGX_SDK)/include -g
ifdef OCCLUM_DISABLE_DCAP
EXTRA_C_FLAGS += -DOCCLUM_DISABLE_DCAP

@ -36,6 +36,54 @@ int test_tty_ioctl_TIOCGWINSZ(void) {
return 0;
}
int test_ioctl_TCGETS_TCSETS(void) {
struct termios term;
// FIXME: /dev/tty should be opened. But it has not been implemented in Occlum yet.
// So we just skip this test if STDOUT is redirected.
if (!isatty(STDOUT_FILENO)) {
printf("Warning: test_tty_ioctl_TIOCGWINSZ is skipped\n");
return 0;
}
if (ioctl(STDOUT_FILENO, TCGETS, &term) < 0) {
THROW_ERROR("failed to ioctl TCGETS");
}
if (ioctl(STDOUT_FILENO, TCSETS, &term) < 0) {
THROW_ERROR("failed to ioctl TCSETS");
}
const char *file_path = "/root/test_ioctl.txt";
int flags = O_RDONLY | O_CREAT | O_TRUNC;
int mode = 00666;
int fd = open(file_path, flags, mode);
if (fd < 0) {
THROW_ERROR("failed to open test file");
}
int pipefds[2];
int ret = pipe(pipefds);
if (ret != 0) {
THROW_ERROR("failed to create pipe");
}
ret = ioctl(fd, TCGETS, &term);
if (ret != -1 || errno != ENOTTY) {
THROW_ERROR("failed catch error");
}
ret = ioctl(pipefds[0], TCGETS, &term);
if (ret != -1 || errno != ENOTTY) {
THROW_ERROR("failed catch error");
}
close(fd);
close(pipefds[0]);
close(pipefds[1]);
return 0;
}
// ============================================================================
// Test cases for SGX ioctls
// ============================================================================
@ -463,6 +511,7 @@ int test_ioctl_FIONBIO(void) {
static test_case_t test_cases[] = {
TEST_CASE(test_tty_ioctl_TIOCGWINSZ),
TEST_CASE(test_ioctl_TCGETS_TCSETS),
TEST_CASE(test_sgx_ioctl_SGXIOC_IS_EDMM_SUPPORTED),
TEST_CASE(test_sgx_ioctl_SGXIOC_GET_EPID_GROUP_ID),
TEST_CASE(test_sgx_ioctl_SGXIOC_GEN_EPID_QUOTE),