lib_unknown/sys/unix/syscall.rs
1//! Unix 裸调用的高层封装:各平台调用号(`constants`)、标志位(`flags`)、`ptrace` 请求号(`ptrace_req`)、统一错误(`SysResult` / `SysErr`)与常用调用封装(`sys_*`)。
2//!
3//! 需要启用 `"sys-unix"` 特性。
4
5use core::error::Error;
6use core::ffi::CStr;
7use core::fmt::{Debug, Display, Formatter};
8
9use crate::sys::syscall::*;
10// 实现示例
11// #[inline(always)]
12// pub unsafe fn syscall0(n: usize) -> isize {
13// let ret: isize;
14//
15// // =========================================================================
16// // Linux & Android
17// // =========================================================================
18//
19// #[cfg(all(
20// any(target_os = "linux", target_os = "android"),
21// target_arch = "x86_64"
22// ))]
23// unsafe {
24// core::arch::asm!(
25// "syscall",
26// in("rax") n,
27// lateout("rax") ret,
28// lateout("rcx") _, // syscall 指令硬件语义:rcx 保存返回地址,被内核覆盖
29// lateout("r11") _, // syscall 指令硬件语义:r11 保存 RFLAGS,被内核覆盖
30// options(nostack) // syscall 不触碰用户栈;内核可能修改 EFLAGS,故不加 preserves_flags
31// );
32// }
33//
34// #[cfg(all(
35// any(target_os = "linux", target_os = "android"),
36// target_arch = "aarch64"
37// ))]
38// unsafe {
39// core::arch::asm!(
40// "svc #0",
41// in("x8") n,
42// lateout("x0") ret,
43// options(nostack) // Linux aarch64 syscall ABI 只保证修改 x0,其余寄存器保留
44// );
45// }
46//
47// #[cfg(all(
48// any(target_os = "linux", target_os = "android"),
49// target_arch = "riscv64"
50// ))]
51// unsafe {
52// core::arch::asm!(
53// "ecall",
54// in("a7") n,
55// lateout("a0") ret,
56// options(nostack) // 同理,Linux riscv64 syscall 只保证修改 a0
57// );
58// }
59//
60// #[cfg(all(any(target_os = "linux", target_os = "android"), target_arch = "x86"))]
61// unsafe {
62// core::arch::asm!(
63// "int 0x80",
64// in("eax") n,
65// lateout("eax") ret,
66// options(nostack)
67// );
68// }
69//
70// // =========================================================================
71// // macOS (Darwin)
72// // =========================================================================
73//
74// #[cfg(all(target_os = "macos", target_arch = "x86_64"))]
75// unsafe {
76// let sys_num = n | 0x2000000;
77// core::arch::asm!(
78// "syscall",
79// "jnc 1f",
80// "neg rax",
81// "1:",
82// in("rax") sys_num,
83// lateout("rax") ret,
84// lateout("rcx") _,
85// lateout("r11") _,
86// options(nostack)
87// );
88// }
89//
90// #[cfg(all(target_os = "macos", target_arch = "aarch64"))]
91// unsafe {
92// core::arch::asm!(
93// "svc #0x80",
94// "b.cc 1f",
95// "neg x0, x0",
96// "1:",
97// in("x16") n,
98// lateout("x0") ret,
99// options(nostack)
100// );
101// }
102//
103// // =========================================================================
104// // Windows (NT内核)
105// // =========================================================================
106//
107// #[cfg(all(target_os = "windows", target_arch = "x86_64"))]
108// unsafe {
109// core::arch::asm!(
110// "syscall",
111// in("rax") n,
112// lateout("rax") ret,
113// lateout("rcx") _,
114// lateout("r11") _,
115// lateout("r10") _,
116// lateout("rdx") _,
117// lateout("r8") _,
118// lateout("r9") _,
119// options(nostack)
120// );
121// }
122//
123// #[cfg(all(target_os = "windows", target_arch = "x86"))]
124// unsafe {
125// core::arch::asm!(
126// "int 0x2e",
127// in("eax") n,
128// lateout("eax") ret,
129// lateout("ecx") _,
130// lateout("edx") _,
131// options(nostack)
132// );
133// }
134//
135// #[cfg(all(target_os = "windows", target_arch = "aarch64"))]
136// unsafe {
137// core::arch::asm!(
138// "svc #0",
139// in("x8") n,
140// lateout("x0") ret,
141// options(nostack)
142// );
143// }
144//
145// unsupported_target!("syscall0");
146//
147// ret
148// }
149
150// =========================================================================
151// Linux x86_64
152// =========================================================================
153/// Linux x86_64 平台的裸系统调用号。
154///
155/// # Feature Requirement
156///
157/// 需要启用 `"sys-unix"` 特性。
158#[cfg(all(
159 any(target_os = "linux", target_os = "android"),
160 target_arch = "x86_64"
161))]
162pub mod constants {
163 pub const READ: usize = 0;
164 pub const WRITE: usize = 1;
165 pub const OPEN: usize = 2;
166 pub const CLOSE: usize = 3;
167 pub const LSEEK: usize = 8;
168 pub const MMAP: usize = 9;
169 pub const MPROTECT: usize = 10;
170 pub const MUNMAP: usize = 11;
171 pub const BRK: usize = 12;
172 pub const RT_SIGACTION: usize = 13;
173 pub const RT_SIGPROCMASK: usize = 14;
174 pub const IOCTL: usize = 16;
175 pub const DUP: usize = 32;
176 pub const DUP2: usize = 33;
177 pub const NANOSLEEP: usize = 35;
178 pub const GETPID: usize = 39;
179 pub const SOCKET: usize = 41;
180 pub const CONNECT: usize = 42;
181 pub const ACCEPT: usize = 43;
182 pub const SENDTO: usize = 44;
183 pub const RECVFROM: usize = 45;
184 pub const BIND: usize = 49;
185 pub const LISTEN: usize = 50;
186 pub const SETSOCKOPT: usize = 54;
187 pub const GETSOCKOPT: usize = 55;
188 pub const CLONE: usize = 56;
189 pub const FORK: usize = 57;
190 pub const EXECVE: usize = 59;
191 pub const EXIT: usize = 60;
192 pub const WAIT4: usize = 61;
193 pub const KILL: usize = 62;
194 pub const FCNTL: usize = 72;
195 pub const FSYNC: usize = 74;
196 pub const GETCWD: usize = 79;
197 pub const CHDIR: usize = 80;
198 pub const MKDIR: usize = 83;
199 pub const UNLINK: usize = 87;
200 pub const GETUID: usize = 102;
201 pub const GETPPID: usize = 110;
202 pub const PRCTL: usize = 157;
203 pub const GETTID: usize = 186;
204 pub const GETDENTS64: usize = 217;
205 pub const CLOCK_GETTIME: usize = 228;
206 pub const EPOLL_WAIT: usize = 232;
207 pub const EPOLL_CTL: usize = 233;
208 pub const OPENAT: usize = 257;
209 pub const MKDIRAT: usize = 258;
210 pub const NEWFSTATAT: usize = 262;
211 pub const UNLINKAT: usize = 263;
212 pub const RENAMEAT: usize = 264;
213 pub const READLINKAT: usize = 267;
214 pub const EPOLL_CREATE1: usize = 291;
215 pub const DUP3: usize = 292;
216 pub const PIPE2: usize = 293;
217 pub const STATX: usize = 332;
218
219 pub const PTRACE: usize = 101;
220}
221
222// =========================================================================
223// Linux x86 (32-bit)
224// =========================================================================
225/// Linux x86(32 位)平台的裸系统调用号。
226///
227/// # Feature Requirement
228///
229/// 需要启用 `"sys-unix"` 特性。
230#[cfg(all(any(target_os = "linux", target_os = "android"), target_arch = "x86"))]
231pub mod constants {
232 pub const EXIT: usize = 1;
233 pub const FORK: usize = 2;
234 pub const READ: usize = 3;
235 pub const WRITE: usize = 4;
236 pub const OPEN: usize = 5;
237 pub const CLOSE: usize = 6;
238 pub const UNLINK: usize = 10;
239 pub const EXECVE: usize = 11;
240 pub const CHDIR: usize = 12;
241 pub const LSEEK: usize = 19;
242 pub const GETPID: usize = 20;
243 pub const GETUID: usize = 24;
244 pub const KILL: usize = 37;
245 pub const MKDIR: usize = 39;
246 pub const BRK: usize = 45;
247 pub const IOCTL: usize = 54;
248 pub const FCNTL: usize = 55;
249 pub const DUP2: usize = 63;
250 pub const GETPPID: usize = 64;
251 pub const MUNMAP: usize = 91;
252 pub const SOCKETCALL: usize = 102;
253 pub const WAIT4: usize = 114;
254 pub const FSYNC: usize = 118;
255 pub const CLONE: usize = 120;
256 pub const MPROTECT: usize = 125;
257 pub const NANOSLEEP: usize = 162;
258 pub const GETCWD: usize = 183;
259 pub const MMAP2: usize = 192;
260 pub const GETDENTS64: usize = 220;
261 pub const GETTID: usize = 224;
262 pub const EPOLL_CTL: usize = 255;
263 pub const EPOLL_WAIT: usize = 256;
264 pub const CLOCK_GETTIME: usize = 265;
265 pub const OPENAT: usize = 295;
266 pub const MKDIRAT: usize = 296;
267 pub const NEWFSTATAT: usize = 300;
268 pub const UNLINKAT: usize = 301;
269 pub const RENAMEAT: usize = 302;
270 pub const READLINKAT: usize = 305;
271 pub const EPOLL_CREATE1: usize = 329;
272 pub const DUP3: usize = 330;
273 pub const PIPE2: usize = 331;
274 pub const SOCKET: usize = 359;
275 pub const BIND: usize = 361;
276 pub const CONNECT: usize = 362;
277 pub const LISTEN: usize = 363;
278 pub const ACCEPT: usize = 364;
279 pub const GETSOCKOPT: usize = 365;
280 pub const SETSOCKOPT: usize = 366;
281 pub const STATX: usize = 383;
282 pub const PTRACE: usize = 26;
283}
284
285// =========================================================================
286// Linux aarch64 / riscv64 (asm-generic)
287// =========================================================================
288/// Linux aarch64 / riscv64 平台的裸系统调用号(asm-generic)。
289///
290/// # Feature Requirement
291///
292/// 需要启用 `"sys-unix"` 特性。
293#[cfg(all(
294 any(target_os = "linux", target_os = "android"),
295 any(target_arch = "aarch64", target_arch = "riscv64")
296))]
297pub mod constants {
298 pub const GETCWD: usize = 17;
299 pub const EPOLL_CREATE1: usize = 20;
300 pub const EPOLL_CTL: usize = 21;
301 pub const DUP3: usize = 24;
302 pub const FCNTL: usize = 25;
303 pub const IOCTL: usize = 29;
304 pub const MKDIRAT: usize = 34;
305 pub const UNLINKAT: usize = 35;
306 pub const RENAMEAT: usize = 38;
307 pub const CHDIR: usize = 49;
308 pub const OPENAT: usize = 56;
309 pub const CLOSE: usize = 57;
310 pub const PIPE2: usize = 59;
311 pub const GETDENTS64: usize = 61;
312 pub const LSEEK: usize = 62;
313 pub const READ: usize = 63;
314 pub const WRITE: usize = 64;
315 pub const READLINKAT: usize = 78;
316 pub const NEWFSTATAT: usize = 79;
317 pub const FSYNC: usize = 82;
318 pub const EXIT: usize = 93;
319 pub const CLOCK_GETTIME: usize = 113;
320 pub const KILL: usize = 129;
321 pub const RT_SIGACTION: usize = 134;
322 pub const RT_SIGPROCMASK: usize = 135;
323 pub const PRCTL: usize = 167;
324 pub const GETPID: usize = 172;
325 pub const GETPPID: usize = 173;
326 pub const GETUID: usize = 174;
327 pub const GETTID: usize = 178;
328 pub const SOCKET: usize = 198;
329 pub const BIND: usize = 200;
330 pub const LISTEN: usize = 201;
331 pub const ACCEPT: usize = 202;
332 pub const CONNECT: usize = 203;
333 pub const GETSOCKOPT: usize = 209;
334 pub const SETSOCKOPT: usize = 208;
335 pub const BRK: usize = 214;
336 pub const MUNMAP: usize = 215;
337 pub const CLONE: usize = 220;
338 pub const EXECVE: usize = 221;
339 pub const MMAP: usize = 222;
340 pub const MPROTECT: usize = 226;
341 pub const WAIT4: usize = 260;
342 pub const STATX: usize = 291;
343 pub const PTRACE: usize = 117;
344}
345
346// =========================================================================
347// macOS (Darwin) XNU BSD Syscalls
348// =========================================================================
349/// macOS(Darwin XNU)平台的 BSD 系统调用号。
350///
351/// # Feature Requirement
352///
353/// 需要启用 `"sys-unix"` 特性。
354#[cfg(target_os = "macos")]
355pub mod constants {
356 pub const EXIT: usize = 1;
357 pub const FORK: usize = 2;
358 pub const READ: usize = 3;
359 pub const WRITE: usize = 4;
360 pub const OPEN: usize = 5;
361 pub const CLOSE: usize = 6;
362 pub const WAIT4: usize = 7;
363 pub const UNLINK: usize = 10;
364 pub const CHDIR: usize = 12;
365 pub const GETPID: usize = 20;
366 pub const GETUID: usize = 24;
367 pub const KILL: usize = 37;
368 pub const GETPPID: usize = 39;
369 pub const SIGACTION: usize = 46;
370 pub const IOCTL: usize = 54;
371 pub const EXECVE: usize = 59;
372 pub const MUNMAP: usize = 73;
373 pub const MPROTECT: usize = 74;
374 pub const DUP2: usize = 90;
375 pub const FCNTL: usize = 92;
376 pub const FSYNC: usize = 95;
377 pub const SOCKET: usize = 97;
378 pub const CONNECT: usize = 98;
379 pub const BIND: usize = 104;
380 pub const SETSOCKOPT: usize = 105;
381 pub const LISTEN: usize = 106;
382 pub const GETSOCKOPT: usize = 118;
383 pub const MKDIR: usize = 136;
384 pub const RMDIR: usize = 137;
385 pub const MMAP: usize = 197;
386 pub const GETCWD: usize = 277;
387 pub const KQUEUE: usize = 362;
388 pub const KEVENT: usize = 363;
389 pub const KEVENT64: usize = 369;
390 pub const THREAD_SELFID: usize = 372; // macOS 特有的获取 TID 方式
391 pub const OPENAT: usize = 460;
392 pub const RENAMEAT: usize = 464;
393 pub const READLINKAT: usize = 467;
394 pub const FSTATAT: usize = 469;
395 pub const PTRACE: usize = 26;
396}
397
398// =========================================================================
399// 标志位 (Flags) 针对非 macOS 平台
400// =========================================================================
401/// 非 macOS 平台的 open/mmap/socket 等标志位常量。
402///
403/// # Feature Requirement
404///
405/// 需要启用 `"sys-unix"` 特性。
406#[cfg(not(target_os = "macos"))]
407pub mod flags {
408 pub const O_RDONLY: usize = 0;
409 pub const O_WRONLY: usize = 1;
410 pub const O_RDWR: usize = 2;
411 pub const O_CREAT: usize = 0o100;
412 pub const O_NONBLOCK: usize = 0o4000;
413 pub const O_CLOEXEC: usize = 0o2000000;
414 pub const AT_FDCWD: usize = -100_isize as usize;
415
416 pub const PROT_NONE: usize = 0;
417 pub const PROT_READ: usize = 1;
418 pub const PROT_WRITE: usize = 2;
419 pub const PROT_EXEC: usize = 4;
420
421 pub const MAP_SHARED: usize = 0x01;
422 pub const MAP_PRIVATE: usize = 0x02;
423 pub const MAP_ANONYMOUS: usize = 0x20;
424
425 pub const CLOCK_REALTIME: usize = 0;
426 pub const CLOCK_MONOTONIC: usize = 1;
427
428 pub const EPOLL_CTL_ADD: usize = 1;
429 pub const EPOLL_CTL_DEL: usize = 2;
430 pub const EPOLL_CTL_MOD: usize = 3;
431 pub const EPOLLIN: u32 = 0x001;
432 pub const EPOLLOUT: u32 = 0x004;
433 pub const EPOLLET: u32 = 1 << 31;
434
435 pub const AF_INET: usize = 2;
436 pub const AF_INET6: usize = 10;
437 pub const SOCK_STREAM: usize = 1;
438 pub const SOCK_DGRAM: usize = 2;
439
440 pub const SOL_SOCKET: usize = 1;
441 pub const SO_REUSEADDR: usize = 2;
442 pub const SO_KEEPALIVE: usize = 9;
443 pub const MSG_DONTWAIT: usize = 0x40;
444}
445
446// =========================================================================
447// 标志位 (Flags) 针对 macOS 平台
448// =========================================================================
449/// macOS 平台的 open/mmap/socket 等标志位常量。
450///
451/// # Feature Requirement
452///
453/// 需要启用 `"sys-unix"` 特性。
454#[cfg(target_os = "macos")]
455pub mod flags {
456 pub const O_RDONLY: usize = 0x0000;
457 pub const O_WRONLY: usize = 0x0001;
458 pub const O_RDWR: usize = 0x0002;
459 pub const O_NONBLOCK: usize = 0x0004;
460 pub const O_CREAT: usize = 0x0200;
461 pub const O_CLOEXEC: usize = 0x1000000;
462 pub const AT_FDCWD: usize = -2_isize as usize;
463
464 pub const PROT_NONE: usize = 0;
465 pub const PROT_READ: usize = 1;
466 pub const PROT_WRITE: usize = 2;
467 pub const PROT_EXEC: usize = 4;
468
469 pub const MAP_SHARED: usize = 1;
470 pub const MAP_PRIVATE: usize = 2;
471 pub const MAP_ANONYMOUS: usize = 0x1000;
472
473 pub const AF_INET: usize = 2;
474 pub const AF_INET6: usize = 30;
475 pub const SOCK_STREAM: usize = 1;
476 pub const SOCK_DGRAM: usize = 2;
477
478 pub const SOL_SOCKET: usize = 0xffff;
479 pub const SO_REUSEADDR: usize = 0x0004;
480 pub const SO_KEEPALIVE: usize = 0x0008;
481
482 pub const EV_ADD: u16 = 0x0001;
483 pub const EV_DELETE: u16 = 0x0002;
484 pub const EV_CLEAR: u16 = 0x0020;
485 pub const EVFILT_READ: i16 = -1;
486 pub const EVFILT_WRITE: i16 = -2;
487}
488
489/// 非 macOS 平台的 `ptrace` 请求号常量。
490///
491/// # Feature Requirement
492///
493/// 需要启用 `"sys-unix"` 特性。
494#[cfg(not(target_os = "macos"))]
495pub mod ptrace_req {
496 pub const PTRACE_TRACEME: usize = 0;
497 pub const PTRACE_PEEKTEXT: usize = 1;
498 pub const PTRACE_PEEKDATA: usize = 2;
499 pub const PTRACE_PEEKUSER: usize = 3;
500 pub const PTRACE_POKETEXT: usize = 4;
501 pub const PTRACE_POKEDATA: usize = 5;
502 pub const PTRACE_POKEUSER: usize = 6;
503 pub const PTRACE_CONT: usize = 7;
504 pub const PTRACE_KILL: usize = 8;
505 pub const PTRACE_SINGLESTEP: usize = 9;
506 pub const PTRACE_GETREGS: usize = 12;
507 pub const PTRACE_SETREGS: usize = 13;
508 pub const PTRACE_ATTACH: usize = 16;
509 pub const PTRACE_DETACH: usize = 17;
510 pub const PTRACE_SYSCALL: usize = 24;
511 pub const PTRACE_SETOPTIONS: usize = 0x4200;
512 pub const PTRACE_GETEVENTMSG: usize = 0x4201;
513 pub const PTRACE_GETSIGINFO: usize = 0x4202;
514 pub const PTRACE_SETSIGINFO: usize = 0x4203;
515 pub const PTRACE_INTERRUPT: usize = 0x4207;
516 pub const PTRACE_O_TRACESYSGOOD: usize = 1;
517 pub const PTRACE_O_TRACEFORK: usize = 1 << 1;
518 pub const PTRACE_O_TRACECLONE: usize = 1 << 3;
519 pub const PTRACE_O_TRACEEXEC: usize = 1 << 4;
520 pub const PTRACE_O_TRACEEXIT: usize = 1 << 6;
521}
522
523/// macOS 平台的 `ptrace` 请求号常量。
524///
525/// # Feature Requirement
526///
527/// 需要启用 `"sys-unix"` 特性。
528#[cfg(target_os = "macos")]
529pub mod ptrace_req {
530 pub const PT_TRACE_ME: usize = 0;
531 pub const PT_READ_I: usize = 1;
532 pub const PT_READ_D: usize = 2;
533 pub const PT_WRITE_I: usize = 4;
534 pub const PT_WRITE_D: usize = 5;
535 pub const PT_CONTINUE: usize = 7;
536 pub const PT_KILL: usize = 8;
537 pub const PT_STEP: usize = 9;
538 pub const PT_ATTACH: usize = 10;
539 pub const PT_DETACH: usize = 11;
540 pub const PT_SIGEXC: usize = 12;
541 pub const PT_THUPDATE: usize = 13;
542 pub const PT_ATTACHEXC: usize = 14;
543 pub const PT_DENY_ATTACH: usize = 31;
544}
545
546/// 裸系统调用封装的统一返回类型。
547///
548/// # Feature Requirement
549///
550/// 需要启用 `"sys-unix"` 特性。
551///
552/// # Errors
553///
554/// - 内核返回 `-4095..0` 范围内的负值时返回 [`SysErr::Ret`],其余情况见各调用方的 `# Errors` 说明。
555pub type SysResult<T = usize> = Result<T, SysErr>;
556
557/// 裸系统调用封装的错误类型。
558///
559/// # Feature Requirement
560///
561/// 需要启用 `"sys-unix"` 特性。
562#[derive(Debug, Clone)]
563pub enum SysErr {
564 /// 操作系统返回的错误码 (errno)
565 Ret(isize),
566 /// 参数错误
567 // Arg(String),
568 Arg(ErrorMessage),
569}
570/// 定容 64 字节的错误消息,以 UTF-8 存储,超长截断。
571///
572/// # Feature Requirement
573///
574/// 需要启用 `"sys-unix"` 特性。
575///
576/// # Examples
577///
578/// ```rust
579/// use core::str::FromStr;
580/// use lib_unknown::sys::unix::syscall::ErrorMessage;
581///
582/// let msg: ErrorMessage = "bad fd".parse().unwrap();
583/// assert_eq!(msg.as_str(), "bad fd");
584/// ```
585#[derive(Debug, Clone, Copy)]
586pub struct ErrorMessage {
587 buf: [u8; 64],
588 len: u8,
589}
590impl ErrorMessage {
591 /// 以 `&str` 形式查看消息内容。
592 ///
593 /// # Feature Requirement
594 ///
595 /// 需要启用 `"sys-unix"` 特性。
596 ///
597 /// # Examples
598 ///
599 /// ```rust
600 /// use core::str::FromStr;
601 /// use lib_unknown::sys::unix::syscall::ErrorMessage;
602 ///
603 /// let msg: ErrorMessage = "bad fd".parse().unwrap();
604 /// assert_eq!(msg.as_str(), "bad fd");
605 /// ```
606 pub fn as_str(&self) -> &str {
607 // SAFETY: `buf[..len]` 仅由 `FromStr` 经合法 UTF-8 切片写入,`len` 不超过 64,
608 // 因此该切片恒为合法 UTF-8。
609 unsafe { core::str::from_utf8_unchecked(&self.buf[..self.len as usize]) }
610 }
611}
612
613impl core::str::FromStr for ErrorMessage {
614 type Err = core::convert::Infallible;
615
616 fn from_str(s: &str) -> Result<Self, Self::Err> {
617 let mut result = Self {
618 buf: [0; 64],
619 len: 0,
620 };
621 let bytes = s.as_bytes();
622 let len = bytes.len().min(64);
623 result.buf[..len].copy_from_slice(&bytes[..len]);
624 result.len = len as u8;
625 Ok(result)
626 }
627}
628
629impl Display for SysErr {
630 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
631 match self {
632 SysErr::Ret(errno) => write!(f, "OS System Call Error (errno: {})", errno),
633 SysErr::Arg(msg) => write!(f, "Invalid Argument: {}", msg.as_str()),
634 }
635 }
636}
637
638impl Error for SysErr {}
639
640#[inline(always)]
641fn as_sys_result(ret: isize) -> SysResult {
642 if (-4095..0).contains(&ret) {
643 // Linux 标准 errno 范围
644 Err(SysErr::Ret(-ret))
645 } else {
646 Ok(ret as usize)
647 }
648}
649
650/// 退出当前进程,不返回。
651///
652/// # Feature Requirement
653///
654/// 需要启用 `"sys-unix"` 特性。
655///
656/// # Examples
657///
658/// ```rust,no_run
659/// use lib_unknown::sys::unix::syscall::sys_exit;
660///
661/// sys_exit(0);
662/// ```
663#[inline(always)]
664pub fn sys_exit(status: usize) -> ! {
665 // SAFETY: `EXIT` 为合法调用号,`status` 为按值传递的退出码,无指针参数。
666 unsafe {
667 syscall1(constants::EXIT, status);
668 }
669 ::core::unreachable!("exit syscall should not return")
670}
671
672/// 获取当前进程 ID。
673///
674/// # Feature Requirement
675///
676/// 需要启用 `"sys-unix"` 特性。
677///
678/// # Examples
679///
680/// ```rust
681/// use lib_unknown::sys::unix::syscall::sys_getpid;
682///
683/// let pid = sys_getpid();
684/// assert!(pid > 0);
685/// ```
686#[inline(always)]
687pub fn sys_getpid() -> usize {
688 // SAFETY: `GETPID` 为合法调用号,无参数,不触碰用户内存。
689 unsafe { syscall0(constants::GETPID) as usize }
690}
691
692/// 获取当前线程 ID(macOS 下为 `THREAD_SELFID`)。
693///
694/// # Feature Requirement
695///
696/// 需要启用 `"sys-unix"` 特性。
697///
698/// # Examples
699///
700/// ```rust
701/// use lib_unknown::sys::unix::syscall::sys_gettid;
702///
703/// let tid = sys_gettid();
704/// assert!(tid > 0);
705/// ```
706#[inline(always)]
707pub fn sys_gettid() -> usize {
708 #[cfg(target_os = "macos")]
709 // SAFETY: `THREAD_SELFID` 为合法调用号,无参数,不触碰用户内存。
710 unsafe {
711 syscall0(constants::THREAD_SELFID) as usize
712 }
713 #[cfg(not(target_os = "macos"))]
714 // SAFETY: `GETTID` 为合法调用号,无参数,不触碰用户内存。
715 unsafe {
716 syscall0(constants::GETTID) as usize
717 }
718}
719
720/// 从文件描述符读取至多 `buf.len()` 字节。
721///
722/// # Feature Requirement
723///
724/// 需要启用 `"sys-unix"` 特性。
725///
726/// # Examples
727///
728/// ```rust,no_run
729/// use lib_unknown::sys::unix::syscall::sys_read;
730///
731/// let mut buf = [0u8; 16];
732/// let _ = sys_read(0, &mut buf);
733/// ```
734///
735/// # Errors
736///
737/// - 当 `fd` 无效或不可读时返回 [`SysErr::Ret`](内核 errno)。
738#[inline(always)]
739pub fn sys_read(fd: usize, buf: &mut [u8]) -> SysResult {
740 // SAFETY: `READ` 为合法调用号;`buf` 在调用期间有效且可写,长度如实传递。
741 unsafe {
742 as_sys_result(syscall3(
743 constants::READ,
744 fd,
745 buf.as_mut_ptr() as usize,
746 buf.len(),
747 ))
748 }
749}
750
751/// 向文件描述符写入 `buf` 的全部内容(单次调用,不保证写完)。
752///
753/// # Feature Requirement
754///
755/// 需要启用 `"sys-unix"` 特性。
756///
757/// # Examples
758///
759/// ```rust,no_run
760/// use lib_unknown::sys::unix::syscall::sys_write;
761///
762/// let _ = sys_write(1, b"hi");
763/// ```
764///
765/// # Errors
766///
767/// - 当 `fd` 无效或不可写时返回 [`SysErr::Ret`](内核 errno)。
768#[inline(always)]
769pub fn sys_write(fd: usize, buf: &[u8]) -> SysResult {
770 // SAFETY: `WRITE` 为合法调用号;`buf` 在调用期间有效且可读,长度如实传递。
771 unsafe {
772 as_sys_result(syscall3(
773 constants::WRITE,
774 fd,
775 buf.as_ptr() as usize,
776 buf.len(),
777 ))
778 }
779}
780
781/// 关闭文件描述符。
782///
783/// # Feature Requirement
784///
785/// 需要启用 `"sys-unix"` 特性。
786///
787/// # Examples
788///
789/// ```rust,no_run
790/// use lib_unknown::sys::unix::syscall::sys_close;
791///
792/// let _ = sys_close(3);
793/// ```
794///
795/// # Errors
796///
797/// - 当 `fd` 不是已打开的描述符时返回 [`SysErr::Ret`](内核 errno)。
798#[inline(always)]
799pub fn sys_close(fd: usize) -> SysResult {
800 // SAFETY: `CLOSE` 为合法调用号,`fd` 按值传递,无指针参数。
801 unsafe { as_sys_result(syscall1(constants::CLOSE, fd)) }
802}
803
804/// 以 `flags`/`mode` 打开 `path` 指向的路径,返回文件描述符。
805///
806/// aarch64/riscv64 上经 `OPENAT + AT_FDCWD` 实现,其余经 `OPEN` 实现。
807///
808/// # Feature Requirement
809///
810/// 需要启用 `"sys-unix"` 特性。
811///
812/// # Examples
813///
814/// ```rust,no_run
815/// use core::ffi::CStr;
816/// use lib_unknown::sys::unix::syscall::{flags, sys_open};
817///
818/// let path = CStr::from_bytes_with_nul(b"/tmp\0").unwrap();
819/// let _ = sys_open(path, flags::O_RDONLY, 0);
820/// ```
821///
822/// # Errors
823///
824/// - 当路径不存在、无权限或 `flags` 非法时返回 [`SysErr::Ret`](内核 errno)。
825#[inline(always)]
826pub fn sys_open(path: &CStr, flags: usize, mode: usize) -> SysResult {
827 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
828 // SAFETY: 调用号与参数顺序符合目标 ABI;`path` 为合法 NUL 结尾 C 字符串,
829 // 在调用期间有效;`AT_FDCWD` 按值传递。
830 unsafe {
831 as_sys_result(syscall4(
832 constants::OPENAT,
833 flags::AT_FDCWD,
834 path.as_ptr() as usize,
835 flags,
836 mode,
837 ))
838 }
839 #[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))]
840 // SAFETY: 调用号与参数顺序符合目标 ABI;`path` 为合法 NUL 结尾 C 字符串,
841 // 在调用期间有效。
842 unsafe {
843 as_sys_result(syscall3(
844 constants::OPEN,
845 path.as_ptr() as usize,
846 flags,
847 mode,
848 ))
849 }
850}
851
852/// 重定位文件描述符的读写偏移。
853///
854/// # Feature Requirement
855///
856/// 需要启用 `"sys-unix"` 特性。
857///
858/// # Examples
859///
860/// ```rust,no_run
861/// use lib_unknown::sys::unix::syscall::sys_lseek;
862///
863/// let _ = sys_lseek(0, 0, 0);
864/// ```
865///
866/// # Errors
867///
868/// - 当 `fd` 不可定位或 `whence` 非法时返回 [`SysErr::Ret`](内核 errno)。
869#[inline(always)]
870pub fn sys_lseek(fd: usize, offset: isize, whence: usize) -> SysResult {
871 // SAFETY: `LSEEK` 为合法调用号,所有参数按值传递,无指针参数。
872 unsafe { as_sys_result(syscall3(constants::LSEEK, fd, offset as usize, whence)) }
873}
874
875/// 建立内存映射,返回映射起始地址。
876///
877/// 32 位 x86 上经 `MMAP2` 实现(`offset` 须按页对齐),其余经 `MMAP` 实现。
878///
879/// # Feature Requirement
880///
881/// 需要启用 `"sys-unix"` 特性。
882///
883/// # Examples
884///
885/// ```rust,no_run
886/// use lib_unknown::sys::unix::syscall::{flags, sys_mmap};
887///
888/// let _ = sys_mmap(
889/// core::ptr::null_mut(),
890/// 4096,
891/// flags::PROT_READ | flags::PROT_WRITE,
892/// flags::MAP_PRIVATE | flags::MAP_ANONYMOUS,
893/// usize::MAX,
894/// 0,
895/// );
896/// ```
897///
898/// # Errors
899///
900/// - 当参数非法(如 `len` 为 0、无权限)时返回 [`SysErr::Ret`](内核 errno)。
901/// - 32 位 x86 上 `offset` 未按 4096 对齐时返回 [`SysErr::Arg`]。
902#[inline(always)]
903pub fn sys_mmap(
904 addr: *mut u8,
905 len: usize,
906 prot: usize,
907 flags: usize,
908 fd: usize,
909 offset: usize,
910) -> SysResult {
911 #[cfg(all(any(target_os = "linux", target_os = "android"), target_arch = "x86"))]
912 {
913 if offset % 4096 != 0 {
914 const MSG: &str = "offset must be a multiple of 4096 on 32-bit x86";
915 let bytes = MSG.as_bytes();
916 let len = bytes.len().min(64);
917 let mut buf = [0u8; 64];
918 buf[..len].copy_from_slice(&bytes[..len]);
919 return Err(SysErr::Arg(ErrorMessage {
920 buf,
921 len: len as u8,
922 }));
923 }
924 // SAFETY: `MMAP2` 为合法调用号;`addr` 可为空(由内核选择地址),其余按值传递。
925 unsafe {
926 as_sys_result(syscall6(
927 constants::MMAP2,
928 addr as usize,
929 len,
930 prot,
931 flags,
932 fd,
933 offset / 4096,
934 ))
935 }
936 }
937 #[cfg(not(all(any(target_os = "linux", target_os = "android"), target_arch = "x86")))]
938 // SAFETY: `MMAP` 为合法调用号;`addr` 可为空(由内核选择地址),其余按值传递。
939 unsafe {
940 as_sys_result(syscall6(
941 constants::MMAP,
942 addr as usize,
943 len,
944 prot,
945 flags,
946 fd,
947 offset,
948 ))
949 }
950}
951
952/// 解除由 [`sys_mmap`] 建立的内存映射。
953///
954/// # Feature Requirement
955///
956/// 需要启用 `"sys-unix"` 特性。
957///
958/// # Examples
959///
960/// ```rust,no_run
961/// use lib_unknown::sys::unix::syscall::sys_munmap;
962///
963/// let _ = sys_munmap(core::ptr::null_mut(), 4096);
964/// ```
965///
966/// # Errors
967///
968/// - 当地址区间未映射时返回 [`SysErr::Ret`](内核 errno)。
969#[inline(always)]
970pub fn sys_munmap(addr: *mut u8, len: usize) -> SysResult {
971 // SAFETY: `MUNMAP` 为合法调用号;`addr`/`len` 应对应既有映射,按值传递。
972 unsafe { as_sys_result(syscall2(constants::MUNMAP, addr as usize, len)) }
973}
974
975/// 修改既有内存映射的保护属性。
976///
977/// # Feature Requirement
978///
979/// 需要启用 `"sys-unix"` 特性。
980///
981/// # Examples
982///
983/// ```rust,no_run
984/// use lib_unknown::sys::unix::syscall::{flags, sys_mprotect};
985///
986/// let _ = sys_mprotect(core::ptr::null_mut(), 4096, flags::PROT_READ);
987/// ```
988///
989/// # Errors
990///
991/// - 当地址区间未映射或 `prot` 非法时返回 [`SysErr::Ret`](内核 errno)。
992#[inline(always)]
993pub fn sys_mprotect(addr: *mut u8, len: usize, prot: usize) -> SysResult {
994 // SAFETY: `MPROTECT` 为合法调用号;`addr`/`len` 应对应既有映射,按值传递。
995 unsafe { as_sys_result(syscall3(constants::MPROTECT, addr as usize, len, prot)) }
996}
997
998/// 创建套接字,返回文件描述符。
999///
1000/// # Feature Requirement
1001///
1002/// 需要启用 `"sys-unix"` 特性。
1003///
1004/// # Examples
1005///
1006/// ```rust,no_run
1007/// use lib_unknown::sys::unix::syscall::{flags, sys_socket};
1008///
1009/// let _ = sys_socket(flags::AF_INET, flags::SOCK_STREAM, 0);
1010/// ```
1011///
1012/// # Errors
1013///
1014/// - 当协议族/类型不支持时返回 [`SysErr::Ret`](内核 errno)。
1015#[inline(always)]
1016pub fn sys_socket(domain: usize, ty: usize, protocol: usize) -> SysResult {
1017 // SAFETY: `SOCKET` 为合法调用号,所有参数按值传递,无指针参数。
1018 unsafe { as_sys_result(syscall3(constants::SOCKET, domain, ty, protocol)) }
1019}
1020
1021/// 将套接字绑定到 `addr` 描述的地址上。
1022///
1023/// `addr` 应为 `sockaddr` 系列结构的原始字节。
1024///
1025/// # Feature Requirement
1026///
1027/// 需要启用 `"sys-unix"` 特性。
1028///
1029/// # Examples
1030///
1031/// ```rust,no_run
1032/// use lib_unknown::sys::unix::syscall::sys_bind;
1033///
1034/// let addr = [0u8; 16];
1035/// let _ = sys_bind(3, &addr);
1036/// ```
1037///
1038/// # Errors
1039///
1040/// - 当 `fd` 非套接字或地址不可用时返回 [`SysErr::Ret`](内核 errno)。
1041#[inline(always)]
1042pub fn sys_bind(fd: usize, addr: &[u8]) -> SysResult {
1043 // SAFETY: `BIND` 为合法调用号;`addr` 在调用期间有效且可读,长度如实传递。
1044 unsafe {
1045 as_sys_result(syscall3(
1046 constants::BIND,
1047 fd,
1048 addr.as_ptr() as usize,
1049 addr.len(),
1050 ))
1051 }
1052}
1053
1054/// 使套接字进入监听状态。
1055///
1056/// # Feature Requirement
1057///
1058/// 需要启用 `"sys-unix"` 特性。
1059///
1060/// # Examples
1061///
1062/// ```rust,no_run
1063/// use lib_unknown::sys::unix::syscall::sys_listen;
1064///
1065/// let _ = sys_listen(3, 16);
1066/// ```
1067///
1068/// # Errors
1069///
1070/// - 当 `fd` 非套接字或未绑定时返回 [`SysErr::Ret`](内核 errno)。
1071#[inline(always)]
1072pub fn sys_listen(fd: usize, backlog: usize) -> SysResult {
1073 // SAFETY: `LISTEN` 为合法调用号,所有参数按值传递,无指针参数。
1074 unsafe { as_sys_result(syscall2(constants::LISTEN, fd, backlog)) }
1075}
1076
1077/// 接受监听套接字上的连接,返回 `(新连接 fd, 对端地址长度)`。
1078///
1079/// 对端地址写入 `addr_buf`,实际长度经内核回写。
1080///
1081/// # Feature Requirement
1082///
1083/// 需要启用 `"sys-unix"` 特性。
1084///
1085/// # Examples
1086///
1087/// ```rust,no_run
1088/// use lib_unknown::sys::unix::syscall::sys_accept;
1089///
1090/// let mut buf = [0u8; 32];
1091/// let _ = sys_accept(3, &mut buf);
1092/// ```
1093///
1094/// # Errors
1095///
1096/// - 当 `fd` 未监听或无待处理连接时返回 [`SysErr::Ret`](内核 errno)。
1097#[inline(always)]
1098pub fn sys_accept(fd: usize, addr_buf: &mut [u8]) -> Result<(usize, usize), SysErr> {
1099 let mut addrlen: u32 = addr_buf.len() as u32;
1100 // SAFETY: `ACCEPT` 为合法调用号;`addr_buf` 在调用期间有效且可写,
1101 // `addrlen` 指向调用栈上的 `u32`,调用期间有效且可读写。
1102 let ret = unsafe {
1103 syscall3(
1104 constants::ACCEPT,
1105 fd,
1106 addr_buf.as_mut_ptr() as usize,
1107 &mut addrlen as *mut u32 as usize,
1108 )
1109 };
1110 let new_fd = as_sys_result(ret)?;
1111 Ok((new_fd, addrlen as usize))
1112}
1113
1114/// 将套接字连接到 `addr` 描述的地址上。
1115///
1116/// # Feature Requirement
1117///
1118/// 需要启用 `"sys-unix"` 特性。
1119///
1120/// # Examples
1121///
1122/// ```rust,no_run
1123/// use lib_unknown::sys::unix::syscall::sys_connect;
1124///
1125/// let addr = [0u8; 16];
1126/// let _ = sys_connect(3, &addr);
1127/// ```
1128///
1129/// # Errors
1130///
1131/// - 当目标不可达或连接被拒绝时返回 [`SysErr::Ret`](内核 errno)。
1132#[inline(always)]
1133pub fn sys_connect(fd: usize, addr: &[u8]) -> SysResult {
1134 // SAFETY: `CONNECT` 为合法调用号;`addr` 在调用期间有效且可读,长度如实传递。
1135 unsafe {
1136 as_sys_result(syscall3(
1137 constants::CONNECT,
1138 fd,
1139 addr.as_ptr() as usize,
1140 addr.len(),
1141 ))
1142 }
1143}
1144
1145/// 派生子进程,父进程返回子进程 PID,子进程返回 0。
1146///
1147/// aarch64/riscv64 上经 `CLONE + SIGCHLD`(栈传 0,Copy-On-Write)实现,
1148/// 其余经 `FORK` 实现。
1149///
1150/// # Feature Requirement
1151///
1152/// 需要启用 `"sys-unix"` 特性。
1153///
1154/// # Examples
1155///
1156/// ```rust,no_run
1157/// use lib_unknown::sys::unix::syscall::sys_fork;
1158///
1159/// let _ = sys_fork();
1160/// ```
1161///
1162/// # Errors
1163///
1164/// - 当进程数达到上限或内存不足时返回 [`SysErr::Ret`](内核 errno)。
1165#[inline(always)]
1166pub fn sys_fork() -> SysResult {
1167 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
1168 // SAFETY: `CLONE` 为合法调用号;仅传标志与空指针(clone 传 0 栈即 fork 语义),
1169 // 不触碰用户内存。
1170 // clone(flags, child_stack, parent_tidptr, tls, child_tidptr)
1171 // stack 传 0 会触发 Copy-On-Write,与传统的 fork 行为一致。
1172 unsafe {
1173 as_sys_result(syscall5(constants::CLONE, flags::SIGCHLD, 0, 0, 0, 0))
1174 }
1175
1176 #[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))]
1177 // SAFETY: `FORK` 为合法调用号,无参数,不触碰用户内存。
1178 unsafe {
1179 as_sys_result(syscall0(constants::FORK))
1180 }
1181}
1182
1183/// 等待子进程状态变化,`status`/`rusage` 可为空指针表示不接收。
1184///
1185/// # Feature Requirement
1186///
1187/// 需要启用 `"sys-unix"` 特性。
1188///
1189/// # Examples
1190///
1191/// ```rust,no_run
1192/// use lib_unknown::sys::unix::syscall::sys_wait4;
1193///
1194/// let _ = sys_wait4(-1, core::ptr::null_mut(), 0, core::ptr::null_mut());
1195/// ```
1196///
1197/// # Errors
1198///
1199/// - 当 `pid` 无效或无子进程时返回 [`SysErr::Ret`](内核 errno)。
1200#[inline(always)]
1201pub fn sys_wait4(pid: isize, status: *mut i32, options: usize, rusage: *mut u8) -> SysResult {
1202 // SAFETY: `WAIT4` 为合法调用号;`status`/`rusage` 为空或指向调用方保证有效的
1203 // 可写内存,调用期间保持有效。
1204 unsafe {
1205 as_sys_result(syscall4(
1206 constants::WAIT4,
1207 pid as usize,
1208 status as usize,
1209 options,
1210 rusage as usize,
1211 ))
1212 }
1213}
1214
1215/// 以 `argv`/`envp` 执行 `path` 指定的程序,成功时不返回。
1216///
1217/// # Feature Requirement
1218///
1219/// 需要启用 `"sys-unix"` 特性。
1220///
1221/// # Examples
1222///
1223/// ```rust,no_run
1224/// use core::ffi::CStr;
1225/// use lib_unknown::sys::unix::syscall::sys_execve;
1226///
1227/// let path = CStr::from_bytes_with_nul(b"/bin/true\0").unwrap();
1228/// let argv: [*const u8; 1] = [path.as_ptr() as *const u8];
1229/// let envp: [*const u8; 0] = [];
1230/// let _ = sys_execve(path, &argv, &envp);
1231/// ```
1232///
1233/// # Errors
1234///
1235/// - 当程序不存在、无执行权限或参数非法时返回 [`SysErr::Ret`](内核 errno)。
1236#[inline(always)]
1237pub fn sys_execve(path: &CStr, argv: &[*const u8], envp: &[*const u8]) -> SysResult {
1238 // SAFETY: `EXECVE` 为合法调用号;`path` 为合法 NUL 结尾字符串,`argv`/`envp`
1239 // 为调用期间有效的指针数组,其元素按目标约定指向合法字符串或为空。
1240 unsafe {
1241 as_sys_result(syscall3(
1242 constants::EXECVE,
1243 path.as_ptr() as usize,
1244 argv.as_ptr() as usize,
1245 envp.as_ptr() as usize,
1246 ))
1247 }
1248}
1249
1250/// 发起 `ptrace` 调试请求,请求号见 [`ptrace_req`]。
1251///
1252/// # Feature Requirement
1253///
1254/// 需要启用 `"sys-unix"` 特性。
1255///
1256/// # Examples
1257///
1258/// ```rust,no_run
1259/// use lib_unknown::sys::unix::syscall::{ptrace_req, sys_ptrace};
1260///
1261/// let _ = sys_ptrace(ptrace_req::PTRACE_TRACEME, 0, 0, 0);
1262/// ```
1263///
1264/// # Errors
1265///
1266/// - 当目标进程不存在、无权限或请求号非法时返回 [`SysErr::Ret`](内核 errno)。
1267#[inline(always)]
1268pub fn sys_ptrace(request: usize, pid: isize, addr: usize, data: usize) -> SysResult {
1269 // SAFETY: `PTRACE` 为合法调用号;`request` 取自 `ptrace_req`,其余参数语义
1270 // 由具体请求号决定,按值传递。
1271 unsafe {
1272 as_sys_result(syscall4(
1273 constants::PTRACE,
1274 request,
1275 pid as usize,
1276 addr,
1277 data,
1278 ))
1279 }
1280}