1use core::time::Duration;
4
5pub use crate::bindings::descriptor as RawFd;
6use crate::{
7 error::{ArgumentError, RawTwzError, TwzError},
8 Result,
9};
10
11bitflags::bitflags! {
12 #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
14pub struct FdFlags : crate::bindings::fd_flags {
15 const IS_TERMINAL = crate::bindings::FD_IS_TERMINAL;
17}
18}
19
20#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Default)]
21#[repr(u32)]
22pub enum FdKind {
24 #[default]
25 Regular = crate::bindings::fd_kind_FdKind_Regular,
26 Directory = crate::bindings::fd_kind_FdKind_Directory,
27 SymLink = crate::bindings::fd_kind_FdKind_SymLink,
28 Other = u32::MAX,
29}
30
31impl From<u32> for FdKind {
32 fn from(value: u32) -> Self {
33 match value {
34 crate::bindings::fd_kind_FdKind_Regular => Self::Regular,
35 crate::bindings::fd_kind_FdKind_Directory => Self::Directory,
36 crate::bindings::fd_kind_FdKind_SymLink => Self::SymLink,
37 _ => Self::Other,
38 }
39 }
40}
41
42impl Into<u32> for FdKind {
43 fn into(self) -> u32 {
44 match self {
45 Self::Regular => crate::bindings::fd_kind_FdKind_Regular,
46 Self::Directory => crate::bindings::fd_kind_FdKind_Directory,
47 Self::SymLink => crate::bindings::fd_kind_FdKind_SymLink,
48 Self::Other => u32::MAX,
49 }
50 }
51}
52
53#[derive(Copy, Clone, Debug, Default)]
55pub struct FdInfo {
56 pub flags: FdFlags,
58 pub size: u64,
60 pub kind: FdKind,
62 pub id: twizzler_types::ObjID,
64 pub created: Duration,
66 pub accessed: Duration,
68 pub modified: Duration,
70 pub unix_mode: u32,
72}
73
74impl From<crate::bindings::fd_info> for FdInfo {
75 fn from(value: crate::bindings::fd_info) -> Self {
76 Self {
77 flags: FdFlags::from_bits_truncate(value.flags),
78 size: value.len,
79 kind: FdKind::from(value.kind),
80 id: value.id,
81 created: value.created.into(),
82 accessed: value.accessed.into(),
83 modified: value.modified.into(),
84 unix_mode: value.unix_mode,
85 }
86 }
87}
88
89impl From<FdInfo> for crate::bindings::fd_info {
90 fn from(value: FdInfo) -> Self {
91 Self {
92 flags: value.flags.bits(),
93 len: value.size,
94 kind: value.kind.into(),
95 id: value.id,
96 created: value.created.into(),
97 accessed: value.accessed.into(),
98 modified: value.modified.into(),
99 unix_mode: value.unix_mode,
100 }
101 }
102}
103
104impl From<Result<RawFd>> for crate::bindings::open_result {
105 fn from(value: Result<RawFd>) -> Self {
106 match value {
107 Ok(fd) => Self {
108 fd,
109 err: RawTwzError::success().raw(),
110 },
111 Err(e) => Self {
112 fd: 0,
113 err: e.raw(),
114 },
115 }
116 }
117}
118
119impl From<crate::bindings::open_result> for Result<RawFd> {
120 fn from(value: crate::bindings::open_result) -> Self {
121 let raw = RawTwzError::new(value.err);
122 if raw.is_success() {
123 Ok(value.fd)
124 } else {
125 Err(raw.error())
126 }
127 }
128}
129
130pub fn twz_rt_fd_get_info(fd: RawFd) -> Result<FdInfo> {
132 let mut info = core::mem::MaybeUninit::uninit();
133 unsafe {
134 if crate::bindings::twz_rt_fd_get_info(fd, info.as_mut_ptr()) {
135 return Ok(info.assume_init().into());
136 }
137 }
138 Err(TwzError::Argument(ArgumentError::BadHandle))
139}
140
141pub use crate::bindings::name_entry as NameEntry;
142
143impl Default for NameEntry {
144 fn default() -> Self {
145 Self {
146 name: [0; Self::NAME_MAX_LEN],
147 name_len: 0,
148 linkname_len: 0,
149 info: FdInfo::default().into(),
150 }
151 }
152}
153
154impl NameEntry {
155 pub const NAME_MAX_LEN: usize = crate::bindings::NAME_ENTRY_LEN as usize;
156 pub fn new(iname: &[u8], info: crate::bindings::fd_info) -> Self {
157 let nl = iname.len().min(Self::NAME_MAX_LEN);
158 let mut name = [0; Self::NAME_MAX_LEN];
159 name[0..nl].copy_from_slice(&iname[0..nl]);
160 Self {
161 name,
162 info,
163 name_len: nl as u32,
164 linkname_len: 0,
165 }
166 }
167
168 pub fn new_symlink(iname: &[u8], ilinkname: &[u8], info: crate::bindings::fd_info) -> Self {
169 let nl = iname.len().min(Self::NAME_MAX_LEN);
170 let linknl = ilinkname.len().min(Self::NAME_MAX_LEN - nl);
171 let mut name = [0; Self::NAME_MAX_LEN];
172 name[0..nl].copy_from_slice(&iname[0..nl]);
173 name[nl..(nl + linknl)].copy_from_slice(&ilinkname[0..linknl]);
174 Self {
175 name,
176 info,
177 name_len: nl as u32,
178 linkname_len: linknl as u32,
179 }
180 }
181
182 pub fn name_bytes(&self) -> &[u8] {
183 &self.name[0..self.name_len as usize]
184 }
185
186 pub fn linkname_bytes(&self) -> &[u8] {
187 &self.name[self.name_len as usize..(self.name_len + self.linkname_len) as usize]
188 }
189}
190
191pub fn twz_rt_fd_enumerate_names(
195 fd: RawFd,
196 entries: &mut [NameEntry],
197 off: usize,
198) -> Result<usize> {
199 unsafe {
200 crate::bindings::twz_rt_fd_enumerate_names(fd, entries.as_mut_ptr(), entries.len(), off)
201 .into()
202 }
203}
204
205pub fn twz_rt_fd_copen(
207 name: &core::ffi::CStr,
208 create: crate::bindings::create_options,
209 flags: u32,
210) -> Result<RawFd> {
211 let info = crate::bindings::open_info {
212 name: name.as_ptr().cast(),
213 len: name.count_bytes(),
214 create,
215 flags,
216 };
217 unsafe { crate::bindings::twz_rt_fd_open(info).into() }
218}
219
220pub fn twz_rt_fd_open(
222 name: &str,
223 create: crate::bindings::create_options,
224 flags: u32,
225) -> Result<RawFd> {
226 let info = crate::bindings::open_info {
227 name: name.as_ptr().cast(),
228 len: name.len(),
229 create,
230 flags,
231 };
232 unsafe { crate::bindings::twz_rt_fd_open(info).into() }
233}
234
235pub fn twz_rt_fd_remove(name: &str) -> Result<()> {
237 unsafe {
238 RawTwzError::new(crate::bindings::twz_rt_fd_remove(
239 name.as_ptr().cast(),
240 name.len(),
241 ))
242 .result()
243 }
244}
245
246pub fn twz_rt_fd_mkns(name: &str) -> Result<()> {
248 unsafe {
249 RawTwzError::new(crate::bindings::twz_rt_fd_mkns(
250 name.as_ptr().cast(),
251 name.len(),
252 ))
253 .result()
254 }
255}
256
257pub fn twz_rt_fd_symlink(name: &str, target: &str) -> Result<()> {
259 unsafe {
260 RawTwzError::new(crate::bindings::twz_rt_fd_symlink(
261 name.as_ptr().cast(),
262 name.len(),
263 target.as_ptr().cast(),
264 target.len(),
265 ))
266 .result()
267 }
268}
269
270pub fn twz_rt_fd_readlink(name: &str, buf: &mut [u8]) -> Result<usize> {
271 let mut len: u64 = 0;
272 unsafe {
273 RawTwzError::new(crate::bindings::twz_rt_fd_readlink(
274 name.as_ptr().cast(),
275 name.len(),
276 buf.as_mut_ptr().cast(),
277 buf.len(),
278 &mut len,
279 ))
280 .result()?;
281 }
282 Ok(len as usize)
283}
284
285#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
286#[repr(u32)]
287pub enum OpenAnonKind {
288 Pipe = crate::bindings::open_anon_kind_AnonKind_Pipe,
289 SocketConnect = crate::bindings::open_anon_kind_AnonKind_SocketConnect,
290 SocketBind = crate::bindings::open_anon_kind_AnonKind_SocketBind,
291}
292
293impl TryFrom<u32> for OpenAnonKind {
294 type Error = ();
295
296 fn try_from(val: u32) -> core::result::Result<OpenAnonKind, Self::Error> {
297 match val {
298 crate::bindings::open_anon_kind_AnonKind_Pipe => Ok(Self::Pipe),
299 crate::bindings::open_anon_kind_AnonKind_SocketConnect => Ok(Self::SocketConnect),
300 crate::bindings::open_anon_kind_AnonKind_SocketBind => Ok(Self::SocketBind),
301 _ => Err(()),
302 }
303 }
304}
305
306impl From<OpenAnonKind> for u32 {
307 fn from(val: OpenAnonKind) -> u32 {
308 match val {
309 OpenAnonKind::Pipe => crate::bindings::open_anon_kind_AnonKind_Pipe,
310 OpenAnonKind::SocketBind => crate::bindings::open_anon_kind_AnonKind_SocketBind,
311 OpenAnonKind::SocketConnect => crate::bindings::open_anon_kind_AnonKind_SocketConnect,
312 }
313 }
314}
315
316#[derive(Clone, Copy)]
317#[repr(transparent)]
318pub struct SocketAddress(pub(crate) crate::bindings::socket_address);
319
320impl SocketAddress {
321 fn new_v4(octets: [u8; 4], port: u16) -> Self {
322 Self(crate::bindings::socket_address {
323 kind: crate::bindings::addr_kind_AddrKind_Ipv4,
324 addr_octets: crate::bindings::socket_address_addrs { v4: octets },
325 port,
326 flowinfo: 0,
327 scope_id: 0,
328 })
329 }
330
331 fn new_v6(octets: [u8; 16], port: u16, flowinfo: u32, scope_id: u32) -> Self {
332 Self(crate::bindings::socket_address {
333 kind: crate::bindings::addr_kind_AddrKind_Ipv6,
334 addr_octets: crate::bindings::socket_address_addrs { v6: octets },
335 port,
336 flowinfo,
337 scope_id,
338 })
339 }
340
341 fn v4_octets(&self) -> [u8; 4] {
342 assert!(self.is_v4());
343 unsafe { self.0.addr_octets.v4 }
344 }
345
346 fn v6_octets(&self) -> [u8; 16] {
347 assert!(!self.is_v4());
348 unsafe { self.0.addr_octets.v6 }
349 }
350
351 fn is_v4(&self) -> bool {
352 self.0.kind == crate::bindings::addr_kind_AddrKind_Ipv4
353 }
354}
355
356impl From<SocketAddress> for core::net::IpAddr {
357 fn from(value: SocketAddress) -> Self {
358 if value.is_v4() {
359 Self::V4(core::net::Ipv4Addr::from_octets(value.v4_octets()))
360 } else {
361 Self::V6(core::net::Ipv6Addr::from_octets(value.v6_octets()))
362 }
363 }
364}
365
366impl From<SocketAddress> for core::net::SocketAddr {
367 fn from(value: SocketAddress) -> Self {
368 if value.is_v4() {
369 Self::V4(core::net::SocketAddrV4::new(
370 core::net::Ipv4Addr::from_octets(value.v4_octets()),
371 value.0.port,
372 ))
373 } else {
374 Self::V6(core::net::SocketAddrV6::new(
375 core::net::Ipv6Addr::from_octets(value.v6_octets()),
376 value.0.port,
377 value.0.flowinfo,
378 value.0.scope_id,
379 ))
380 }
381 }
382}
383
384impl From<core::net::Ipv4Addr> for SocketAddress {
385 fn from(value: core::net::Ipv4Addr) -> Self {
386 Self::new_v4(value.octets(), 0)
387 }
388}
389
390impl From<core::net::Ipv6Addr> for SocketAddress {
391 fn from(value: core::net::Ipv6Addr) -> Self {
392 Self::new_v6(value.octets(), 0, 0, 0)
393 }
394}
395
396impl From<core::net::SocketAddrV4> for SocketAddress {
397 fn from(value: core::net::SocketAddrV4) -> Self {
398 Self::new_v4(value.ip().octets(), value.port())
399 }
400}
401
402impl From<core::net::SocketAddrV6> for SocketAddress {
403 fn from(value: core::net::SocketAddrV6) -> Self {
404 Self::new_v6(
405 value.ip().octets(),
406 value.port(),
407 value.flowinfo(),
408 value.scope_id(),
409 )
410 }
411}
412
413impl From<core::net::SocketAddr> for SocketAddress {
414 fn from(value: core::net::SocketAddr) -> Self {
415 match value {
416 core::net::SocketAddr::V4(v4) => v4.into(),
417 core::net::SocketAddr::V6(v6) => v6.into(),
418 }
419 }
420}
421
422impl From<core::net::IpAddr> for SocketAddress {
423 fn from(value: core::net::IpAddr) -> Self {
424 match value {
425 core::net::IpAddr::V4(v4) => v4.into(),
426 core::net::IpAddr::V6(v6) => v6.into(),
427 }
428 }
429}
430
431pub fn twz_rt_fd_open_socket_bind(mut addr: SocketAddress, flags: u32) -> Result<RawFd> {
433 unsafe {
434 crate::bindings::twz_rt_fd_open_anon(
435 OpenAnonKind::SocketBind.into(),
436 flags,
437 ((&mut addr.0) as *mut crate::bindings::socket_address).cast(),
438 core::mem::size_of::<crate::bindings::socket_address>(),
439 )
440 .into()
441 }
442}
443
444pub fn twz_rt_fd_open_socket_connect(mut addr: SocketAddress, flags: u32) -> Result<RawFd> {
446 unsafe {
447 crate::bindings::twz_rt_fd_open_anon(
448 OpenAnonKind::SocketConnect.into(),
449 flags,
450 ((&mut addr.0) as *mut crate::bindings::socket_address).cast(),
451 core::mem::size_of::<crate::bindings::socket_address>(),
452 )
453 .into()
454 }
455}
456
457pub fn twz_rt_fd_open_pipe(flags: u32) -> Result<RawFd> {
459 unsafe {
460 crate::bindings::twz_rt_fd_open_anon(
461 OpenAnonKind::Pipe.into(),
462 flags,
463 core::ptr::null_mut(),
464 0,
465 )
466 .into()
467 }
468}
469
470pub fn twz_rt_fd_dup(fd: RawFd) -> Result<RawFd> {
472 let mut new_fd = core::mem::MaybeUninit::<RawFd>::uninit();
473 unsafe {
474 let e = crate::bindings::twz_rt_fd_cmd(
475 fd,
476 crate::bindings::FD_CMD_DUP,
477 core::ptr::null_mut(),
478 new_fd.as_mut_ptr().cast(),
479 );
480 let raw = RawTwzError::new(e);
481 if raw.is_success() {
482 Ok(new_fd.assume_init())
483 } else {
484 Err(raw.error())
485 }
486 }
487}
488
489pub fn twz_rt_fd_sync(fd: RawFd) {
491 unsafe {
492 crate::bindings::twz_rt_fd_cmd(
493 fd,
494 crate::bindings::FD_CMD_SYNC,
495 core::ptr::null_mut(),
496 core::ptr::null_mut(),
497 );
498 }
499}
500
501pub fn twz_rt_fd_truncate(fd: RawFd, mut len: u64) -> Result<()> {
503 unsafe {
504 let e = crate::bindings::twz_rt_fd_cmd(
505 fd,
506 crate::bindings::FD_CMD_TRUNCATE,
507 (&mut len as *mut u64).cast(),
508 core::ptr::null_mut(),
509 );
510 let raw = RawTwzError::new(e);
511 if !raw.is_success() {
512 return Err(raw.error());
513 }
514 }
515 Ok(())
516}
517
518pub fn twz_rt_fd_close(fd: RawFd) {
520 unsafe { crate::bindings::twz_rt_fd_close(fd) }
521}