strat9_abi/flag.rs
1//! ABI-level flags for syscalls and data structures.
2//!
3//! These are Strat9 OS native flags, NOT POSIX flags.
4//! POSIX shims (relibc, musl-compat) must translate from POSIX `O_*`
5//! to these flags using [`posix_oflags_to_strat9`].
6
7use bitflags::bitflags;
8
9// ── Open Flags ──────────────────────────────────────────────────────────────
10
11bitflags! {
12 /// File open flags for `SYS_OPEN` and `SYS_OPENAT`.
13 ///
14 /// These are **not** POSIX `O_*` values. Use [`posix_oflags_to_strat9`]
15 /// to convert from POSIX flags when implementing a compatibility layer.
16 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
17 pub struct OpenFlags: u32 {
18 /// Open for reading.
19 const READ = 1 << 0;
20 /// Open for writing.
21 const WRITE = 1 << 1;
22 /// Create file if it does not exist (requires `WRITE` or `APPEND`).
23 const CREATE = 1 << 2;
24 /// Truncate file to zero length on open.
25 const TRUNCATE = 1 << 3;
26 /// Append all writes to the end of the file.
27 const APPEND = 1 << 4;
28 /// Open as a directory (fails if path is not a directory).
29 const DIRECTORY = 1 << 5;
30 /// Fail if file already exists (only meaningful with `CREATE`).
31 const EXCL = 1 << 6;
32 /// Non-blocking mode: return `EAGAIN` instead of blocking.
33 const NONBLOCK = 1 << 7;
34 /// Do not follow symbolic links in the final path component.
35 const NOFOLLOW = 1 << 8;
36 /// Do not allocate a controlling terminal.
37 const NOCTTY = 1 << 9;
38 /// Synchronous writes: data + metadata flushed to disk before return.
39 const SYNC = 1 << 10;
40
41 /// Open for reading only (alias for `READ`).
42 const RDONLY = Self::READ.bits();
43 /// Open for writing only (alias for `WRITE`).
44 const WRONLY = Self::WRITE.bits();
45 /// Open for reading and writing.
46 const RDWR = Self::READ.bits() | Self::WRITE.bits();
47 }
48}
49
50// ── Memory Map Flags ────────────────────────────────────────────────────────
51
52bitflags! {
53 /// Memory mapping flags for `SYS_MMAP`.
54 ///
55 /// These are **not** POSIX `MAP_*` values. The kernel uses its own
56 /// bit layout for efficiency.
57 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
58 pub struct MapFlags: u32 {
59 /// Shared mapping: writes are visible to other processes mapping the same region.
60 const MAP_SHARED = 0x01;
61 /// Private mapping: copy-on-write semantics.
62 const MAP_PRIVATE = 0x02;
63 /// Fixed mapping: place at the exact address specified (may overwrite existing mappings).
64 const MAP_FIXED = 0x10;
65 /// Anonymous mapping: not backed by a file (requires `MAP_PRIVATE`).
66 const MAP_ANONYMOUS = 0x0020;
67 /// Do not reserve swap space for this mapping.
68 const MAP_NORESERVE = 0x40;
69 /// Populate pages on demand (prefault all pages).
70 const MAP_POPULATE = 0x8000;
71 /// Lock the mapping in memory (cannot be swapped out).
72 const MAP_LOCKED = 0x2000;
73 /// Automatically expand the mapping downward (stack growth).
74 const MAP_GROWSDOWN = 0x0100;
75 }
76}
77
78// ── IPC Call Flags ──────────────────────────────────────────────────────────
79
80bitflags! {
81 /// Flags for IPC call operations (used with `SYS_IPC_CALL`).
82 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
83 pub struct CallFlags: u32 {
84 /// Read operation (receive data).
85 const READ = 0x01;
86 /// Write operation (send data).
87 const WRITE = 0x02;
88 /// Non-blocking: return immediately if no data available.
89 const NONBLOCK = 0x04;
90 /// Peek: read data without consuming it.
91 const PEEK = 0x08;
92 /// Wait for data (blocking).
93 const WAIT = 0x10;
94 /// Do not wait (return immediately).
95 const NOWAIT = 0x20;
96 }
97}
98
99// ── Unlink Flags ────────────────────────────────────────────────────────────
100
101bitflags! {
102 /// Flags for `SYS_UNLINKAT`.
103 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
104 pub struct UnlinkFlags: u32 {
105 /// Remove a directory instead of a file.
106 const REMOVEDIR = 0o02000000;
107 }
108}
109
110// ── POSIX to Strat9 Translation ─────────────────────────────────────────────
111
112/// Translate POSIX `O_*` flags to Strat9 ABI `OpenFlags`.
113///
114/// This function is used by POSIX compatibility layers (relibc, musl-compat)
115/// to convert standard Linux/POSIX open flags to the Strat9 native format.
116///
117/// # Example
118///
119/// ```ignore
120/// let strat9_flags = posix_oflags_to_strat9(libc::O_RDONLY | libc::O_CREAT);
121/// assert!(strat9_flags.contains(OpenFlags::READ));
122/// assert!(strat9_flags.contains(OpenFlags::CREATE));
123/// ```
124pub fn posix_oflags_to_strat9(posix: u32) -> OpenFlags {
125 const O_ACCMODE: u32 = 0o3;
126 const O_RDONLY: u32 = 0o000000;
127 const O_WRONLY: u32 = 0o000001;
128 const O_RDWR: u32 = 0o000002;
129 const O_CREAT: u32 = 0o000100;
130 const O_EXCL: u32 = 0o000200;
131 const O_NOCTTY: u32 = 0o000400;
132 const O_TRUNC: u32 = 0o001000;
133 const O_APPEND: u32 = 0o002000;
134 const O_NONBLOCK: u32 = 0o004000;
135 const O_DIRECTORY: u32 = 0o0200000;
136 const O_NOFOLLOW: u32 = 0o0400000;
137 const O_SYNC: u32 = 0o04000000;
138
139 let access = posix & O_ACCMODE;
140 let mut out = OpenFlags::empty();
141
142 match access {
143 O_RDONLY => {
144 out |= OpenFlags::READ;
145 }
146 O_WRONLY => {
147 out |= OpenFlags::WRITE;
148 }
149 O_RDWR => {
150 out |= OpenFlags::READ | OpenFlags::WRITE;
151 }
152 _ => {}
153 }
154
155 if posix & O_CREAT != 0 {
156 out |= OpenFlags::CREATE;
157 }
158 if posix & O_TRUNC != 0 {
159 out |= OpenFlags::TRUNCATE;
160 }
161 if posix & O_APPEND != 0 {
162 out |= OpenFlags::APPEND;
163 }
164 if posix & O_DIRECTORY != 0 {
165 out |= OpenFlags::DIRECTORY;
166 }
167 if posix & O_EXCL != 0 {
168 out |= OpenFlags::EXCL;
169 }
170 if posix & O_NONBLOCK != 0 {
171 out |= OpenFlags::NONBLOCK;
172 }
173 if posix & O_NOFOLLOW != 0 {
174 out |= OpenFlags::NOFOLLOW;
175 }
176 if posix & O_NOCTTY != 0 {
177 out |= OpenFlags::NOCTTY;
178 }
179 if posix & O_SYNC != 0 {
180 out |= OpenFlags::SYNC;
181 }
182
183 out
184}