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 NameEntry {
144 pub const NAME_MAX_LEN: usize = crate::bindings::NAME_ENTRY_LEN as usize;
145 pub fn new(iname: &[u8], info: crate::bindings::fd_info) -> Self {
146 let nl = iname.len().min(Self::NAME_MAX_LEN);
147 let mut name = [0; Self::NAME_MAX_LEN];
148 name[0..nl].copy_from_slice(&iname[0..nl]);
149 Self {
150 name,
151 info,
152 name_len: nl as u32,
153 linkname_len: 0,
154 }
155 }
156
157 pub fn new_symlink(iname: &[u8], ilinkname: &[u8], info: crate::bindings::fd_info) -> Self {
158 let nl = iname.len().min(Self::NAME_MAX_LEN);
159 let linknl = ilinkname.len().min(Self::NAME_MAX_LEN - nl);
160 let mut name = [0; Self::NAME_MAX_LEN];
161 name[0..nl].copy_from_slice(&iname[0..nl]);
162 name[nl..(nl + linknl)].copy_from_slice(&ilinkname[0..linknl]);
163 Self {
164 name,
165 info,
166 name_len: nl as u32,
167 linkname_len: linknl as u32,
168 }
169 }
170
171 pub fn name_bytes(&self) -> &[u8] {
172 &self.name[0..self.name_len as usize]
173 }
174
175 pub fn linkname_bytes(&self) -> &[u8] {
176 &self.name[self.name_len as usize..(self.name_len + self.linkname_len) as usize]
177 }
178}
179
180pub fn twz_rt_fd_enumerate_names(
184 fd: RawFd,
185 entries: &mut [NameEntry],
186 off: usize,
187) -> Result<usize> {
188 unsafe {
189 crate::bindings::twz_rt_fd_enumerate_names(fd, entries.as_mut_ptr(), entries.len(), off)
190 .into()
191 }
192}
193
194pub fn twz_rt_fd_copen(
196 name: &core::ffi::CStr,
197 create: crate::bindings::create_options,
198 flags: u32,
199) -> Result<RawFd> {
200 let info = crate::bindings::open_info {
201 name: name.as_ptr().cast(),
202 len: name.count_bytes(),
203 create,
204 flags,
205 };
206 unsafe { crate::bindings::twz_rt_fd_open(info).into() }
207}
208
209pub fn twz_rt_fd_open(
211 name: &str,
212 create: crate::bindings::create_options,
213 flags: u32,
214) -> Result<RawFd> {
215 let info = crate::bindings::open_info {
216 name: name.as_ptr().cast(),
217 len: name.len(),
218 create,
219 flags,
220 };
221 unsafe { crate::bindings::twz_rt_fd_open(info).into() }
222}
223
224pub fn twz_rt_fd_remove(name: &str) -> Result<()> {
226 unsafe {
227 RawTwzError::new(crate::bindings::twz_rt_fd_remove(
228 name.as_ptr().cast(),
229 name.len(),
230 ))
231 .result()
232 }
233}
234
235pub fn twz_rt_fd_mkns(name: &str) -> Result<()> {
237 unsafe {
238 RawTwzError::new(crate::bindings::twz_rt_fd_mkns(
239 name.as_ptr().cast(),
240 name.len(),
241 ))
242 .result()
243 }
244}
245
246pub fn twz_rt_fd_symlink(name: &str, target: &str) -> Result<()> {
248 unsafe {
249 RawTwzError::new(crate::bindings::twz_rt_fd_symlink(
250 name.as_ptr().cast(),
251 name.len(),
252 target.as_ptr().cast(),
253 target.len(),
254 ))
255 .result()
256 }
257}
258
259pub fn twz_rt_fd_readlink(name: &str, buf: &mut [u8]) -> Result<usize> {
260 let mut len: u64 = 0;
261 unsafe {
262 RawTwzError::new(crate::bindings::twz_rt_fd_readlink(
263 name.as_ptr().cast(),
264 name.len(),
265 buf.as_mut_ptr().cast(),
266 buf.len(),
267 &mut len,
268 ))
269 .result()?;
270 }
271 Ok(len as usize)
272}
273
274#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
275#[repr(u32)]
276pub enum OpenAnonKind {
277 Pipe = crate::bindings::open_anon_kind_AnonKind_Pipe,
278 SocketConnect = crate::bindings::open_anon_kind_AnonKind_SocketConnect,
279 SocketBind = crate::bindings::open_anon_kind_AnonKind_SocketBind,
280}
281
282impl TryFrom<u32> for OpenAnonKind {
283 type Error = ();
284
285 fn try_from(val: u32) -> core::result::Result<OpenAnonKind, Self::Error> {
286 match val {
287 crate::bindings::open_anon_kind_AnonKind_Pipe => Ok(Self::Pipe),
288 crate::bindings::open_anon_kind_AnonKind_SocketConnect => Ok(Self::SocketConnect),
289 crate::bindings::open_anon_kind_AnonKind_SocketBind => Ok(Self::SocketBind),
290 _ => Err(()),
291 }
292 }
293}
294
295impl From<OpenAnonKind> for u32 {
296 fn from(val: OpenAnonKind) -> u32 {
297 match val {
298 OpenAnonKind::Pipe => crate::bindings::open_anon_kind_AnonKind_Pipe,
299 OpenAnonKind::SocketBind => crate::bindings::open_anon_kind_AnonKind_SocketBind,
300 OpenAnonKind::SocketConnect => crate::bindings::open_anon_kind_AnonKind_SocketConnect,
301 }
302 }
303}
304
305#[derive(Clone, Copy)]
306#[repr(transparent)]
307pub struct SocketAddress(pub(crate) crate::bindings::socket_address);
308
309impl SocketAddress {
310 fn new_v4(octets: [u8; 4], port: u16) -> Self {
311 Self(crate::bindings::socket_address {
312 kind: crate::bindings::addr_kind_AddrKind_Ipv4,
313 addr_octets: crate::bindings::socket_address_addrs { v4: octets },
314 port,
315 flowinfo: 0,
316 scope_id: 0,
317 })
318 }
319
320 fn new_v6(octets: [u8; 16], port: u16, flowinfo: u32, scope_id: u32) -> Self {
321 Self(crate::bindings::socket_address {
322 kind: crate::bindings::addr_kind_AddrKind_Ipv6,
323 addr_octets: crate::bindings::socket_address_addrs { v6: octets },
324 port,
325 flowinfo,
326 scope_id,
327 })
328 }
329
330 fn v4_octets(&self) -> [u8; 4] {
331 assert!(self.is_v4());
332 unsafe { self.0.addr_octets.v4 }
333 }
334
335 fn v6_octets(&self) -> [u8; 16] {
336 assert!(!self.is_v4());
337 unsafe { self.0.addr_octets.v6 }
338 }
339
340 fn is_v4(&self) -> bool {
341 self.0.kind == crate::bindings::addr_kind_AddrKind_Ipv4
342 }
343}
344
345impl From<SocketAddress> for core::net::IpAddr {
346 fn from(value: SocketAddress) -> Self {
347 if value.is_v4() {
348 Self::V4(core::net::Ipv4Addr::from_octets(value.v4_octets()))
349 } else {
350 Self::V6(core::net::Ipv6Addr::from_octets(value.v6_octets()))
351 }
352 }
353}
354
355impl From<SocketAddress> for core::net::SocketAddr {
356 fn from(value: SocketAddress) -> Self {
357 if value.is_v4() {
358 Self::V4(core::net::SocketAddrV4::new(
359 core::net::Ipv4Addr::from_octets(value.v4_octets()),
360 value.0.port,
361 ))
362 } else {
363 Self::V6(core::net::SocketAddrV6::new(
364 core::net::Ipv6Addr::from_octets(value.v6_octets()),
365 value.0.port,
366 value.0.flowinfo,
367 value.0.scope_id,
368 ))
369 }
370 }
371}
372
373impl From<core::net::Ipv4Addr> for SocketAddress {
374 fn from(value: core::net::Ipv4Addr) -> Self {
375 Self::new_v4(value.octets(), 0)
376 }
377}
378
379impl From<core::net::Ipv6Addr> for SocketAddress {
380 fn from(value: core::net::Ipv6Addr) -> Self {
381 Self::new_v6(value.octets(), 0, 0, 0)
382 }
383}
384
385impl From<core::net::SocketAddrV4> for SocketAddress {
386 fn from(value: core::net::SocketAddrV4) -> Self {
387 Self::new_v4(value.ip().octets(), value.port())
388 }
389}
390
391impl From<core::net::SocketAddrV6> for SocketAddress {
392 fn from(value: core::net::SocketAddrV6) -> Self {
393 Self::new_v6(
394 value.ip().octets(),
395 value.port(),
396 value.flowinfo(),
397 value.scope_id(),
398 )
399 }
400}
401
402impl From<core::net::SocketAddr> for SocketAddress {
403 fn from(value: core::net::SocketAddr) -> Self {
404 match value {
405 core::net::SocketAddr::V4(v4) => v4.into(),
406 core::net::SocketAddr::V6(v6) => v6.into(),
407 }
408 }
409}
410
411impl From<core::net::IpAddr> for SocketAddress {
412 fn from(value: core::net::IpAddr) -> Self {
413 match value {
414 core::net::IpAddr::V4(v4) => v4.into(),
415 core::net::IpAddr::V6(v6) => v6.into(),
416 }
417 }
418}
419
420pub fn twz_rt_fd_open_socket_bind(mut addr: SocketAddress, flags: u32) -> Result<RawFd> {
422 unsafe {
423 crate::bindings::twz_rt_fd_open_anon(
424 OpenAnonKind::SocketBind.into(),
425 flags,
426 ((&mut addr.0) as *mut crate::bindings::socket_address).cast(),
427 core::mem::size_of::<crate::bindings::socket_address>(),
428 )
429 .into()
430 }
431}
432
433pub fn twz_rt_fd_open_socket_connect(mut addr: SocketAddress, flags: u32) -> Result<RawFd> {
435 unsafe {
436 crate::bindings::twz_rt_fd_open_anon(
437 OpenAnonKind::SocketConnect.into(),
438 flags,
439 ((&mut addr.0) as *mut crate::bindings::socket_address).cast(),
440 core::mem::size_of::<crate::bindings::socket_address>(),
441 )
442 .into()
443 }
444}
445
446pub fn twz_rt_fd_open_pipe(flags: u32) -> Result<RawFd> {
448 unsafe {
449 crate::bindings::twz_rt_fd_open_anon(
450 OpenAnonKind::Pipe.into(),
451 flags,
452 core::ptr::null_mut(),
453 0,
454 )
455 .into()
456 }
457}
458
459pub fn twz_rt_fd_dup(fd: RawFd) -> Result<RawFd> {
461 let mut new_fd = core::mem::MaybeUninit::<RawFd>::uninit();
462 unsafe {
463 let e = crate::bindings::twz_rt_fd_cmd(
464 fd,
465 crate::bindings::FD_CMD_DUP,
466 core::ptr::null_mut(),
467 new_fd.as_mut_ptr().cast(),
468 );
469 let raw = RawTwzError::new(e);
470 if raw.is_success() {
471 Ok(new_fd.assume_init())
472 } else {
473 Err(raw.error())
474 }
475 }
476}
477
478pub fn twz_rt_fd_sync(fd: RawFd) {
480 unsafe {
481 crate::bindings::twz_rt_fd_cmd(
482 fd,
483 crate::bindings::FD_CMD_SYNC,
484 core::ptr::null_mut(),
485 core::ptr::null_mut(),
486 );
487 }
488}
489
490pub fn twz_rt_fd_truncate(fd: RawFd, mut len: u64) -> Result<()> {
492 unsafe {
493 let e = crate::bindings::twz_rt_fd_cmd(
494 fd,
495 crate::bindings::FD_CMD_TRUNCATE,
496 (&mut len as *mut u64).cast(),
497 core::ptr::null_mut(),
498 );
499 let raw = RawTwzError::new(e);
500 if !raw.is_success() {
501 return Err(raw.error());
502 }
503 }
504 Ok(())
505}
506
507pub fn twz_rt_fd_close(fd: RawFd) {
509 unsafe { crate::bindings::twz_rt_fd_close(fd) }
510}