Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Spec couche 0 — Crate air-sys-types

Spécification technique — Version 0.1 (partielle, à compléter)

⚠️ Statut du document

Cette spec couvre les types fondamentaux de la crate air-sys-types, identifiés au fil des spécifications des familles de syscalls. Les types sont regroupés par famille d’origine. Le total estimé est d’environ ~187 types publics dans la crate complète.

Ce document liste les types et leurs signatures. Une spec complète détaillerait pour chaque type ses méthodes, invariants, conversions, et tests. Travail à reprendre : produire la spec exhaustive type par type, en parallèle de l’implémentation effective.

Vue d’ensemble de la crate

La crate air-sys-types est la fondation absolue du stack Air : tous les autres modules dépendent d’elle. Elle expose :

  • Les newtypes fondamentaux : Errno, Pid, Tid, etc.
  • Les wrappers RAII pour les ressources kernel : OwnedFd, BorrowedFd, Mapping, etc.
  • Les bitflags pour les flags kernel : OpenFlags, CloneFlags, etc.
  • Les enums typés pour les sémantiques kernel : Signal, Capability, etc.
  • Les structures de données mirroring kernel : StatxResult, SignalFdInfo, etc.

Principes de la crate.

  1. Pas d’allocation par défaut. Les types fondamentaux (Errno, Pid, etc.) sont des newtypes sur des types primitifs, sans allocation.

  2. #[repr(transparent)] ou #[repr(C)] selon les besoins. Les types qui doivent avoir un layout kernel-compatible utilisent #[repr(C)]. Les newtypes simples utilisent #[repr(transparent)].

  3. Conversions explicites. Les conversions entre types (par exemple, Pid::as_raw() -> i32) sont explicites via méthodes nommées, pas via From/Into implicites.

  4. Validation à la construction. Les types qui ont des invariants (par exemple, Pid qui est NonZeroI32) valident à la construction et exposent des méthodes try_new qui retournent Option ou Result.

  5. Documentation extensive. Chaque type a un docstring qui explique son rôle, ses invariants, et son lien avec le kernel.

Types fondamentaux (universels)

Errno

#![allow(unused)]
fn main() {
#[repr(transparent)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Errno(NonZeroI32);

impl Errno {
    // ~140 constantes correspondant aux codes errno standards
    pub const EPERM: Self;
    pub const ENOENT: Self;
    pub const ESRCH: Self;
    pub const EINTR: Self;
    pub const EIO: Self;
    // ... etc.
    
    pub const fn as_raw(self) -> i32;
    pub const fn name(self) -> &'static str;
    pub const fn description(self) -> &'static str;
}

impl core::fmt::Display for Errno { /* ... */ }
impl core::error::Error for Errno {}
}

Cf. ADR-019 pour le contexte.

Jeu d’errno piloté par les besoins (extension additive du sceau). Le socle n’expose que les constantes effectivement référencées — par le code couche 0 ou par un contrat couche 1 landé qui doit mapper l’errno par nom. Le prompt 074 a ainsi ajouté EXDEV/EPIPE/ELOOP/ECONNRESET/ ETIMEDOUT (+ alias EWOULDBLOCK ≡ EAGAIN), pilotés par les contrats air-base-lib (§1 mapping) et air-filesystem (# Errors). Valeurs asm-generic, identiques x86_64/aarch64. La liste name()/description() exhaustive (~140) viendra avec la PR dédiée ADR-019.

File descriptors

#![allow(unused)]
fn main() {
pub struct OwnedFd { /* ... */ }
pub struct BorrowedFd<'fd> { /* ... */ }
pub type RawFd = i32;

impl OwnedFd {
    pub fn as_fd(&self) -> BorrowedFd<'_>;
    pub fn into_raw_fd(self) -> RawFd;
    pub unsafe fn from_raw_fd(fd: RawFd) -> Self;
}

impl<'fd> BorrowedFd<'fd> {
    pub fn as_raw_fd(&self) -> RawFd;
    pub unsafe fn borrow_raw(fd: RawFd) -> Self;
}

impl Drop for OwnedFd {
    fn drop(&mut self) { /* appelle close(fd), ignore erreur */ }
}
}

Discipline : tout FD géré par Air passe par OwnedFd/BorrowedFd. Pas de RawFd à nu sauf dans les APIs raw.

DirFd

#![allow(unused)]
fn main() {
pub enum DirFd<'fd> {
    Cwd,
    Fd(BorrowedFd<'fd>),
}
}

Base pour les opérations *at (cf. ADR-021 convention 1).

Types de la famille process

#![allow(unused)]
fn main() {
pub struct Pid(NonZeroI32);
pub struct Tid(NonZeroI32);

pub struct PidFd { /* OwnedFd interne */ }
pub struct PidFdReceiver { /* ... */ }
pub struct TidReceiver { /* ... */ }

pub enum WaitTarget<'fd> {
    AnyChild,
    Pid(Pid),
    ProcessGroup(Pid),
    AnyProcessGroup,
    PidFd(BorrowedFd<'fd>),
}

pub struct WaitOptions(i32);  // bitflags
pub struct WaitStatus {
    pub pid: Pid,
    pub uid: u32,
    pub event: WaitEvent,
}

pub enum WaitEvent {
    Exited { code: i32 },
    Killed { signal: Signal, core_dumped: bool },
    Stopped { signal: Signal },
    Continued,
    Trapped { signal: Signal },
}

pub struct CloneFlags(u64);  // bitflags
pub struct CloneArgs { /* ... */ }
pub enum CloneResult { /* ... */ }

pub struct Signal(NonZeroI32);
pub struct SignalMask { /* ... */ }

pub enum Capability { /* énum des capabilities Linux */ }
pub struct CapabilityMask(u64);
pub struct CapabilitySet { /* ... */ }
pub enum CapabilityTarget { /* ... */ }

pub enum Resource { /* énum des limites Linux */ }
pub struct Rlimit { /* ... */ }
pub enum RlimitValue { Finite(u64), Infinity }

pub enum DumpableMode { /* ... */ }
pub struct ExecveatFlags(i32);  // bitflags
pub struct PidFdOpenFlags(u32);  // bitflags
}

~20 types pour cette famille.

Types de la famille fs

#![allow(unused)]
fn main() {
pub struct OpenFlags(u64);  // bitflags
pub type Mode = u32;
pub struct OpenHow { /* ... */ }
pub struct ResolveFlags(u64);  // bitflags

pub struct StatxResult { /* ... */ }
pub struct StatxMask(u32);  // bitflags
pub struct StatxFlags(u32);  // bitflags
pub struct StatxTimestamp { /* ... */ }

pub struct AccessMode(u32);  // bitflags
pub struct AccessFlags(i32);  // bitflags

pub struct RenameFlags(u32);  // bitflags
pub struct FallocateMode(i32);  // bitflags

pub enum SeekWhence { Set, Current, End, Data, Hole }

pub struct DirEntry { /* ... */ } // name: Vec<u8> (octets) — ADR-048
pub enum DirEntryType { /* ... */ }
pub struct DirEntryIter<'buf> { /* ... */ }

pub enum UtimeValue { Now, Omit, Time(StatxTimestamp) }

pub struct FdFlags(i32);  // bitflags
pub struct StatusFlags(i32);  // bitflags
pub struct FileLock { /* ... */ }
pub struct Seals(u32);  // bitflags

pub struct FileHandle { /* ... */ }
pub struct NameToHandleFlags(i32);  // bitflags

pub struct IoSlice<'data> { /* ... */ }
pub struct IoSliceMut<'data> { /* ... */ }
}

~25 types pour cette famille.

Types de la famille mem

#![allow(unused)]
fn main() {
pub struct Mapping {
    addr: NonNull<u8>,
    length: usize,
}
pub struct MappingPointer { /* ... */ }

pub struct ProtectionFlags(i32);  // bitflags
pub struct MapFlags(i32);  // bitflags
pub struct MremapFlags(i32);  // bitflags

pub enum MadviseAdvice { /* ~25 variants */ }

pub struct MlockFlags(u32);  // bitflags
pub struct MlockallFlags(i32);  // bitflags

pub struct MemfdFlags(u32);  // bitflags
pub struct MsyncFlags(i32);  // bitflags

pub struct RemoteIoSlice { /* ... */ }
}

~10 types pour cette famille.

Types du module io_uring

Placement des types (ADR-022 / ADR-028). Ce document spécifie la crate air-sys-types. Pour io_uring, seuls les types pure-données (sans comportement, ni FD/mmap, ni durée de vie liée à un anneau) y vivent ; les types stateful / couplés (anneau, builders, jetons, complétions, miroirs #[repr(C)], gardes RAII) vivent dans air-sys-syscall::io_uring par encapsulation. La règle se tranche Temps par Temps, au fil de l’implémentation.

Note (nommage, ADR-029). Noms de façade explicites, sans abréviation. Les anciens noms abrégés (IoUringOp, RawSqe, RawCqe, RawOp, FdPool, RegisteredBuffer, ProvidedBuffers) sont remplacés ; les miroirs kernel gardent les noms hérités courts.

#![allow(unused)]
fn main() {
// PLACEMENT (ADR-022/028). Seuls `SetupFlags`, `CompletionFlags` et
// `IoUringOpcode` vivent dans `air-sys-types` (types purs, livrés au Temps 1).
// TOUS les autres types ci-dessous vivent dans `air-sys-syscall::io_uring`
// (stateful / couplés — encapsulation) ; listés ici pour mémoire, spécifiés dans
// les specs `io-uring-*.md`. Les Temps ultérieurs placeront leurs types selon la
// même règle (purs ici, couplés dans air-sys-syscall).
pub struct IoUring { /* ... */ }
pub struct IoUringBuilder { /* ... */ }
pub struct IoUringParams { /* ... */ }
pub struct IoUringCapabilities { /* ... */ }
pub struct SetupFlags(u32);  // bitflags

pub struct Completion { /* ... */ }
pub struct CompletionFlags(u32);  // bitflags
pub struct CompletionIter<'ring> { /* ... */ }
pub struct SubmitOptions { /* ... */ }

pub struct SubmissionToken(/* opaque : index de slot + génération */);
pub struct MultishotToken(/* opaque */);

pub enum IoUringOpcode { /* énum des opérations */ }
pub enum CancelTarget { /* token / fd / op / any */ }

// Ressources fixes (Temps 3a)
pub struct FixedFdTable { /* ... */ }
pub struct FixedSlot<'t> { /* ... */ }
pub enum FixedSlotTarget { /* Index(u32) | Alloc */ }
pub struct RegisteredBuffers { /* ... */ }
pub struct RegisteredBufferSlice<'b> { /* ... */ }
pub struct Personality(/* id */);
pub struct WorkQueueWorkerLimits { /* ... */ }
pub struct NapiConfig { /* ... */ }
pub enum ClockSource { /* Monotonic | Boottime | Realtime */ }

// Buffers fournis ring-mapped (Temps 3b)
pub struct ProvidedBufferRing { /* ... */ }
pub struct ProvidedBuffer<'r> { /* guard RAII */ }
pub struct ProvidedBufferRingOptions { /* ... */ }
pub struct ProvidedBufferRingStatus { /* ... */ }

// Linked / multishot / réseau zero-copy
pub struct LinkedChainBuilder<'ring> { /* ... */ }
pub struct ChainTokens { /* ... */ }
pub struct ZeroCopyFlags(u32);  // bitflags

// Multi-thread (Temps 3e)
pub struct LockedIoUring { /* ... */ }
pub struct RingPool { /* ... */ }
pub struct RingHandle { /* ... */ }
pub struct SqpollIoUring { /* ... */ }

// Confinement (Temps 3f)
pub struct RestrictionSet { /* ... */ }
pub enum Restriction { /* ... */ }
pub enum RegisterOp { /* ... */ }
pub struct SqeFlagSet { /* ... */ }

// Accès brut niveau 1 (Temps 4) — type verbeux, champs = noms kernel
#[repr(C)]
pub struct RawSubmissionQueueEntry { /* 64 octets ; champs user_data, res… */ }

#[repr(C)]
pub struct RawCompletionQueueEntry { /* 16 ou 32 octets */ }

pub struct RawOpcode(pub u8);
pub const RAW_USER_DATA_TAG: u64 = 1 << 63;

pub struct TimeoutFlags(u32);  // bitflags
pub struct PollEvents(u32);  // bitflags
pub enum EpollOp { /* ... */ }
pub struct EpollEvent { /* ... */ }
}

Dans air-sys-types : 3 types (Temps 1 — SetupFlags, CompletionFlags, IoUringOpcode). Les autres vivent dans air-sys-syscall::io_uring ou ne sont pas encore implémentés.

Types de la famille signal

#![allow(unused)]
fn main() {
pub struct SignalFdInfo { /* ... */ }
pub struct SignalFdFlags(i32);  // bitflags

pub struct SignalQueueInfo { /* ... */ }
pub enum SignalValue { Integer(i32), Pointer(u64) }

// Sous-module synchronous_handler
pub enum FatalSignal { Segv, Bus, Fpe, Ill }
pub struct SignalInfo { /* ... */ }
pub struct PreviousHandler { /* opaque */ }
}

~6 types pour cette famille.

Types de la famille time

#![allow(unused)]
fn main() {
pub enum Clock {
    Realtime, Monotonic, ProcessCpuTime, ThreadCpuTime,
    MonotonicRaw, RealtimeCoarse, MonotonicCoarse,
    Boottime, RealtimeAlarm, BoottimeAlarm, Tai,
}

pub struct Instant {
    clock: Clock,
    seconds: i64,
    nanoseconds: u32,
}

pub struct Timespec { /* interne */ }

pub struct TimerFd { /* OwnedFd interne */ }
pub struct TimerFdSpecification {
    pub initial: Duration,
    pub interval: Duration,
}
pub struct TimerFdFlags(i32);  // bitflags
pub struct TimerSetFlags(i32);  // bitflags

pub enum SleepDeadline {
    Relative(Duration),
    AbsoluteInstant(Instant),
}

pub enum SleepError {
    Interrupted { remaining: Duration },
    Other(Errno),
}
}

~9 types pour cette famille.

Types de la famille net

#![allow(unused)]
fn main() {
pub enum SocketDomain { /* ... */ }
pub enum SocketType { /* ... */ }
pub enum SocketAddr {
    Unix(UnixSocketAddr),
    Inet(InetSocketAddr),
    Inet6(Inet6SocketAddr),
    // ...
}

pub struct UnixSocketAddr { /* ... */ }
pub struct InetSocketAddr { /* ... */ }
pub struct Inet6SocketAddr { /* ... */ }

pub struct MessageFlags(i32);  // bitflags
pub struct AcceptFlags(i32);  // bitflags
pub struct AcceptResult { /* ... */ }

pub struct SendMessageRequest { /* ... */ }
pub struct ReceiveMessageRequest { /* ... */ }
pub struct SendMessageResult { /* ... */ }
pub struct ReceiveMessageResult { /* ... */ }
pub enum ShutdownMode { Read, Write, Both }

pub enum AncillarySent { /* ... */ }
pub enum AncillaryReceived { /* ... */ }

pub enum SocketOptionLevel { /* ... */ }
pub enum LingerOption { Disabled, Enabled(Duration) }

pub struct UnixCredentials { /* ... */ }
}

~20 types pour cette famille.

Types de la famille ipc

#![allow(unused)]
fn main() {
pub struct EventFd { /* OwnedFd interne */ }
pub struct EventFdFlags(i32);  // bitflags

pub struct PipeFlags(i32);  // bitflags
pub struct SpliceFlags(u32);  // bitflags
}

~4 types pour cette famille.

Types de la famille security

#![allow(unused)]
fn main() {
pub struct SeccompFilter { /* ... */ }
pub struct SeccompRule { /* ... */ }
pub enum SeccompAction { /* ... */ }
pub enum SeccompMode { /* ... */ }
pub struct SeccompFilterFlags(u32);  // bitflags

pub struct SyscallNumber(i32);
pub struct SyscallArgumentCondition { /* ... */ }
pub enum ConditionOp { /* ... */ }

pub struct LandlockRuleset { /* ... */ }
pub struct LandlockAccessFs(u64);  // bitflags
}

~10 types pour cette famille.

Types de la famille system

#![allow(unused)]
fn main() {
pub struct UtsName {
    pub sysname: CString,
    pub nodename: CString,
    pub release: CString,
    pub version: CString,
    pub machine: CString,
    pub domainname: CString,
}

pub struct SystemInfo { /* ... */ }
pub struct GetrandomFlags(u32);  // bitflags
}

3 types pour cette famille.

Récapitulatif global

FamilleNombre approximatif de types
Fondamentaux5 (Errno, OwnedFd, BorrowedFd, RawFd, DirFd)
process20
fs25
mem10
io_uring (dans air-sys-types)3 (Temps 1)
signal6
time9
net20
ipc4
security10
system3

Total estimé : ~140-160 types publics.

La spec finale aurait peut-être un peu plus de types selon les besoins qui émergent à l’implémentation. L’estimation initiale de ~187 types reste raisonnable.

Travail à reprendre

TODO : produire une spec exhaustive de air-sys-types :

Pour chaque type, documenter :

  • Représentation interne (#[repr(...)]).
  • Constructeurs (new, try_new, etc.) et invariants.
  • Méthodes principales (as_raw, from_raw, conversions).
  • Implémentations de traits (Debug, Display, Error, Clone, Copy, etc.).
  • Tests à prévoir (constructions, invariants, conversions).
  • Lien avec les types kernel équivalents.

Cette spec exhaustive est probablement à produire en parallèle de l’implémentation effective de la crate, plutôt qu’en amont, parce que des ajustements émergeront naturellement.


Licence du document : MPL 2.0 Statut : Spec partielle de la crate air-sys-types. À compléter en parallèle de l’implémentation.