cloudfox-coreshift-core 2.33.0

Low-level Linux and Android systems primitives for CoreShift (CloudFox)
Documentation
# Fd: Owned Descriptors

`fd::Fd` is Core's owned file descriptor wrapper — the shared descriptor type
used by `reactor`, `fs`, `proc`, `socket`, `spawn`, `signal`, and `io`. It owns
the descriptor, closes it on drop, and provides safe accessor helpers.

## Construction

- `Fd::eventfd(init)` — an `eventfd` (initial counter value).
- `Fd::timerfd()` — a `timerfd`; `set_timer_oneshot(delay)` arms it once.
- `Fd::from_owned_raw_fd(fd, op)` (`unsafe`) — adopt an already-owned raw fd
  (≥ 0, caller transfers ownership) with the operation name used in errors.
- `Fd` implements `AsRawFd`; it is `Send` + `Sync` (contains `i32`).
- (Other creation sites: `inotify::init`, `uevent::open`, `socket::*`, pty
  plumbing, process pipes.)

## Manipulation

- `dup()` — owned duplication; `dup` fans a wakeup fd out across threads (the
  reactor fan-out pattern). `dup2(target)` — in-place re-target of `target`
  onto this fd's file description; returns `Result<()>`, not an owned fd.
- `set_nonblock()` / `set_cloexec()` — descriptor flags.
- `read_slice(buf)` / `write_slice(buf)` — non-blocking byte I/O, returning
  `Ok(None)` on `EAGAIN`.
- `read_u64_blocking()` / `read_u64()` / `write_u64(value)` — the eventfd
  protocol (8-byte native-endian reads/writes); the non-blocking variants
  return `Ok(None)` when nothing is pending. A **partial** u64 read is an
  `Err(EIO)` in both variants; the blocking read retries `EINTR` up to 10,000
  times before failing.
- `seek_set(offset)` — reposition.
- `set_timer_oneshot(delay)``None` disarms the timer; a zero duration is
  clamped to 1 ns.

## Companion types

- `Token` — an opaque `u64` identifying a registered descriptor in a reactor.
- `Event` — a reactor event: `token`, `readable`, `priority`, `writable`,
  `error`, `hangup`. `EPOLLERR` folds into `readable` **and** `writable`
  **and** `priority`; `EPOLLHUP` does not fold into the readiness booleans. A
  hangup-only event arrives with all readiness flags false.

`Token`/`Event` live in `fd` (they are the descriptor bookkeeping vocabulary,
shared with the `reactor` epoll engine). `Event`'s layout is pinned at 16 bytes
/ 8-alignment (compile-time asserts).

## `error` module

The crate's error vocabulary lives in `error`:

- `CoreError``Syscall { code, op }` or `Binder { code, op }`, with
  `sys()` / `binder()` constructors, `raw_os_error()`, `to_io_error()`
  (fallback `EIO` for `Binder`), `From<std::io::Error>` (op strings like
  `io:not_found`, `io:permission_denied`), `Display`, and `std::error::Error`.
- `error::errno` — libc-free errno constants: `EADDRINUSE`, `EPIPE`, `EAGAIN`,
  `EINTR`, `ENOENT`, `EACCES`, `EOVERFLOW`.

## Usage

```rust
use coreshift_core::fd::Fd;

let efd = Fd::eventfd(0)?;      // wakeup channel
let duped = efd.dup()?;         // fan out to another thread
efd.write_u64(1)?;              // signal
assert_eq!(duped.read_u64_blocking()?, 1);
```

## Contract

Every Core-created descriptor is `O_CLOEXEC`/`SOCK_CLOEXEC` unless the caller
explicitly opts out; `eventfd`/`timerfd`/`inotify`/`uevent` descriptors are
also created **non-blocking**. Ownership is never shared by value — only `dup()`
replicates a descriptor, so there is no accidental double-close. `Fd` is a
move-only type (no `Clone`/`Copy`).