relibc/header/sys_ioctl/redox/
mod.rs1use core::{mem, ptr, slice};
2use redox_rt::proc::FdGuard;
3use syscall;
4
5use crate::{
6 error::{Errno, Result},
7 header::{bits_winsize::winsize, errno::EINVAL, fcntl, termios},
8 platform::{
9 Pal, Sys,
10 types::{c_int, c_ulong, c_ulonglong, c_void, pid_t},
11 },
12};
13
14use super::constants::*;
15
16mod drm;
17
18fn dup_read<T>(fd: c_int, name: &str, t: &mut T) -> syscall::Result<usize> {
21 let dup = FdGuard::new(redox_rt::sys::dup(fd as usize, name.as_bytes())?);
22
23 let size = mem::size_of::<T>();
24
25 let bytes = dup.read(unsafe { slice::from_raw_parts_mut(t as *mut T as *mut u8, size) })?;
26
27 Ok(bytes / size)
28}
29
30fn dup_write<T>(fd: c_int, name: &str, t: &T) -> Result<usize> {
32 let dup = FdGuard::new(redox_rt::sys::dup(fd as usize, name.as_bytes())?);
33
34 let size = mem::size_of::<T>();
35
36 let bytes = dup.write(unsafe { slice::from_raw_parts(t as *const T as *const u8, size) })?;
37
38 Ok(bytes / size)
39}
40
41#[derive(Debug)]
42enum IoctlBuffer {
43 None,
44 Read(*mut c_void, usize), Write(*const c_void, usize), ReadWrite(*mut c_void, usize),
47}
48
49impl IoctlBuffer {
50 unsafe fn read<T>(&self) -> Result<T> {
51 let (ptr, size) = match *self {
52 Self::Write(ptr, size) => (ptr, size),
53 Self::ReadWrite(ptr, size) => (ptr as *const c_void, size),
54 _ => {
55 return Err(Errno(EINVAL));
56 }
57 };
58 if size == mem::size_of::<T>() {
59 let value = unsafe { ptr::read(ptr as *const T) };
60 Ok(value)
61 } else {
62 Err(Errno(EINVAL))
63 }
64 }
65
66 unsafe fn write<T>(&mut self, value: T) -> Result<()> {
67 let (ptr, size) = match *self {
68 Self::Read(ptr, size) | Self::ReadWrite(ptr, size) => (ptr, size),
69 _ => {
70 return Err(Errno(EINVAL));
71 }
72 };
73 if size == mem::size_of::<T>() {
74 unsafe { ptr::write(ptr as *mut T, value) };
75 Ok(())
76 } else {
77 Err(Errno(EINVAL))
78 }
79 }
80}
81
82pub unsafe fn ioctl_inner(fd: c_int, request: c_ulong, out: *mut c_void) -> Result<c_int> {
83 match request {
84 FIONBIO => {
85 let mut flags = Sys::fcntl(fd, fcntl::F_GETFL, 0)?;
86 flags = if unsafe { *(out as *mut c_int) } == 0 {
87 flags & !fcntl::O_NONBLOCK
88 } else {
89 flags | fcntl::O_NONBLOCK
90 };
91 Sys::fcntl(fd, fcntl::F_SETFL, flags as c_ulonglong)?;
92 }
93 TCGETS => {
94 let termios = unsafe { &mut *(out as *mut termios::termios) };
95 dup_read(fd, "termios", termios)?;
96 }
97 TCSETS | TCSETSW | TCSETSF => {
99 let termios = unsafe { &*(out as *const termios::termios) };
100 dup_write(fd, "termios", termios)?;
101 }
102 TCFLSH => {
103 let queue = out as c_int;
104 dup_write(fd, "flush", &queue)?;
105 }
106 TIOCSCTTY => {
107 todo_skip!(0, "ioctl TIOCSCTTY");
108 }
109 TIOCGPGRP => {
110 let pgrp = unsafe { &mut *(out as *mut pid_t) };
111 dup_read(fd, "pgrp", pgrp)?;
112 }
113 TIOCSPGRP => {
114 let pgrp = unsafe { &*(out as *const pid_t) };
115 dup_write(fd, "pgrp", pgrp)?;
116 }
117 TIOCGWINSZ => {
118 let winsize = unsafe { &mut *(out as *mut winsize) };
119 dup_read(fd, "winsize", winsize)?;
120 }
121 TIOCSWINSZ => {
122 let winsize = unsafe { &*(out as *const winsize) };
123 dup_write(fd, "winsize", winsize)?;
124 }
125 TIOCGPTLCK => {
126 let lock = unsafe { &mut *(out as *mut c_int) };
127 dup_read(fd, "ptlock", lock)?;
128 }
129 TIOCSPTLCK => {
130 let lock = unsafe { &*(out as *const c_int) };
131 dup_write(fd, "ptlock", lock)?;
132 }
133 TIOCGPTN => {
134 let name = unsafe { &mut *(out as *mut c_int) };
135 dup_read(fd, "ptsname", name)?;
136 }
137 TCSBRK => {
138 todo_skip!(0, "ioctl TCSBRK");
139 }
140 TCXONC => {
141 todo_skip!(0, "ioctl TCXONC");
142 }
143 SIOCATMARK => {
144 todo_skip!(0, "ioctl SIOCATMARK");
145 }
146 _ => {
147 let dir = (request >> 30) & 0b11;
149 let size = ((request >> 16) & 0x3FFF) as usize;
150 let name = (((request >> 8) & 0xFF) as u8) as char;
151 let func = (request & 0xFF) as u8;
152 match name {
153 'd' => {
154 let buf = match dir {
155 0b10 => IoctlBuffer::Read(out, size),
156 0b01 => IoctlBuffer::Write(out, size),
157 0b11 => IoctlBuffer::ReadWrite(out, size),
158 _ => IoctlBuffer::None,
159 };
160 return unsafe { drm::ioctl(fd, func, buf) };
161 }
162 _ => {
163 return Err(Errno(EINVAL));
164 }
165 }
166 }
167 }
168 Ok(0)
169}