Skip to main content

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}