1use crate::{
6 c_str::CStr,
7 error::ResultExt,
8 header::{fcntl::AT_SYMLINK_NOFOLLOW, time::timespec},
9 out::Out,
10 platform::{
11 Pal, Sys,
12 types::{
13 blkcnt_t, blksize_t, c_char, c_int, c_long, dev_t, gid_t, ino_t, mode_t, nlink_t,
14 off_t, uid_t,
15 },
16 },
17};
18
19pub const S_IFMT: mode_t = 0o0_170_000;
21
22pub const S_IFDIR: mode_t = 0o040_000;
24pub const S_IFCHR: mode_t = 0o020_000;
26pub const S_IFBLK: mode_t = 0o060_000;
28pub const S_IFREG: mode_t = 0o100_000;
30pub const S_IFIFO: mode_t = 0o010_000;
32pub const S_IFLNK: mode_t = 0o120_000;
34pub const S_IFSOCK: mode_t = 0o140_000;
36
37pub const S_IRWXU: mode_t = 0o0_700;
39pub const S_IRUSR: mode_t = 0o0_400;
41pub const S_IWUSR: mode_t = 0o0_200;
43pub const S_IXUSR: mode_t = 0o0_100;
45
46pub const S_IREAD: mode_t = S_IRUSR;
48pub const S_IWRITE: mode_t = S_IWUSR;
49pub const S_IEXEC: mode_t = S_IXUSR;
50
51pub const S_IRWXG: mode_t = 0o0_070;
53pub const S_IRGRP: mode_t = 0o0_040;
55pub const S_IWGRP: mode_t = 0o0_020;
57pub const S_IXGRP: mode_t = 0o0_010;
59
60pub const S_IRWXO: mode_t = 0o0_007;
62pub const S_IROTH: mode_t = 0o0_004;
64pub const S_IWOTH: mode_t = 0o0_002;
66pub const S_IXOTH: mode_t = 0o0_001;
68pub const S_ISUID: mode_t = 0o4_000;
70pub const S_ISGID: mode_t = 0o2_000;
72pub const S_ISVTX: mode_t = 0o1_000;
74
75pub const UTIME_NOW: c_long = (1 << 30) - 1;
76pub const UTIME_OMIT: c_long = (1 << 30) - 2;
77
78#[repr(C)]
80#[derive(Default)]
81pub struct stat {
82 pub st_dev: dev_t,
84 pub st_ino: ino_t,
86 pub st_nlink: nlink_t,
88 pub st_mode: mode_t,
90 pub st_uid: uid_t,
92 pub st_gid: gid_t,
94 pub st_rdev: dev_t,
96 pub st_size: off_t,
102 pub st_blksize: blksize_t,
105 pub st_blocks: blkcnt_t,
107
108 pub st_atim: timespec,
110 pub st_mtim: timespec,
112 pub st_ctim: timespec,
114
115 pub _pad: [c_char; 24],
119}
120
121#[unsafe(no_mangle)]
123pub unsafe extern "C" fn chmod(path: *const c_char, mode: mode_t) -> c_int {
124 let path = unsafe { CStr::from_ptr(path) };
125 Sys::chmod(path, mode).map(|()| 0).or_minus_one_errno()
126}
127
128#[unsafe(no_mangle)]
130pub extern "C" fn fchmod(fildes: c_int, mode: mode_t) -> c_int {
131 Sys::fchmod(fildes, mode).map(|()| 0).or_minus_one_errno()
132}
133
134#[unsafe(no_mangle)]
136pub unsafe extern "C" fn fchmodat(
137 dirfd: c_int,
138 path: *const c_char,
139 mode: mode_t,
140 flags: c_int,
141) -> c_int {
142 let path = unsafe { CStr::from_nullable_ptr(path) };
143 Sys::fchmodat(dirfd, path, mode, flags)
144 .map(|()| 0)
145 .or_minus_one_errno()
146}
147
148#[unsafe(no_mangle)]
150pub unsafe extern "C" fn fstat(fildes: c_int, buf: *mut stat) -> c_int {
151 let buf = unsafe { Out::nonnull(buf) };
152 Sys::fstat(fildes, buf).map(|()| 0).or_minus_one_errno()
153}
154
155#[unsafe(no_mangle)]
157pub unsafe extern "C" fn fstatat(
158 fildes: c_int,
159 path: *const c_char,
160 buf: *mut stat,
161 flags: c_int,
162) -> c_int {
163 let path = unsafe { CStr::from_nullable_ptr(path) };
164 let buf = unsafe { Out::nonnull(buf) };
165 Sys::fstatat(fildes, path, buf, flags)
166 .map(|()| 0)
167 .or_minus_one_errno()
168}
169
170#[unsafe(no_mangle)]
171pub unsafe extern "C" fn __fxstat(_ver: c_int, fildes: c_int, buf: *mut stat) -> c_int {
172 unsafe { fstat(fildes, buf) }
173}
174
175#[unsafe(no_mangle)]
177pub unsafe extern "C" fn futimens(fd: c_int, times: *const timespec) -> c_int {
178 unsafe { Sys::futimens(fd, times) }
179 .map(|()| 0)
180 .or_minus_one_errno()
181}
182
183#[unsafe(no_mangle)]
185pub unsafe extern "C" fn lstat(path: *const c_char, buf: *mut stat) -> c_int {
186 let path = unsafe { CStr::from_ptr(path) };
187 let buf = unsafe { Out::nonnull(buf) };
188 Sys::lstat(path, buf).map(|()| 0).or_minus_one_errno()
189}
190
191#[unsafe(no_mangle)]
193pub unsafe extern "C" fn mkdirat(dirfd: c_int, path: *const c_char, mode: mode_t) -> c_int {
194 let path = unsafe { CStr::from_ptr(path) };
195 Sys::mkdirat(dirfd, path, mode)
196 .map(|()| 0)
197 .or_minus_one_errno()
198}
199
200#[unsafe(no_mangle)]
202pub unsafe extern "C" fn mkdir(path: *const c_char, mode: mode_t) -> c_int {
203 let path = unsafe { CStr::from_ptr(path) };
204 Sys::mkdir(path, mode).map(|()| 0).or_minus_one_errno()
205}
206
207#[unsafe(no_mangle)]
209pub unsafe extern "C" fn mkfifoat(dirfd: c_int, path: *const c_char, mode: mode_t) -> c_int {
210 let path = unsafe { CStr::from_ptr(path) };
211 Sys::mkfifoat(dirfd, path, mode)
212 .map(|()| 0)
213 .or_minus_one_errno()
214}
215
216#[unsafe(no_mangle)]
218pub unsafe extern "C" fn mkfifo(path: *const c_char, mode: mode_t) -> c_int {
219 let path = unsafe { CStr::from_ptr(path) };
220 Sys::mkfifo(path, mode).map(|()| 0).or_minus_one_errno()
221}
222
223#[unsafe(no_mangle)]
225pub unsafe extern "C" fn mknod(path: *const c_char, mode: mode_t, dev: dev_t) -> c_int {
226 let path = unsafe { CStr::from_ptr(path) };
227 Sys::mknod(path, mode, dev).map(|()| 0).or_minus_one_errno()
228}
229
230#[unsafe(no_mangle)]
232pub unsafe extern "C" fn mknodat(
233 dirfd: c_int,
234 path: *const c_char,
235 mode: mode_t,
236 dev: dev_t,
237) -> c_int {
238 let path = unsafe { CStr::from_ptr(path) };
239 Sys::mknodat(dirfd, path, mode, dev)
240 .map(|()| 0)
241 .or_minus_one_errno()
242}
243
244#[unsafe(no_mangle)]
246pub unsafe extern "C" fn stat(file: *const c_char, buf: *mut stat) -> c_int {
247 let file = unsafe { CStr::from_ptr(file) };
248 let buf = unsafe { Out::nonnull(buf) };
249 Sys::stat(file, buf).map(|()| 0).or_minus_one_errno()
250}
251
252#[unsafe(no_mangle)]
254pub extern "C" fn umask(mask: mode_t) -> mode_t {
255 Sys::umask(mask)
256}
257
258#[unsafe(no_mangle)]
260pub unsafe extern "C" fn utimensat(
261 fd: c_int,
262 path: *const c_char,
263 times: *const timespec,
264 flag: c_int,
265) -> c_int {
266 let path = unsafe { CStr::from_ptr(path) };
267 match Sys::openat(fd, path, flag & AT_SYMLINK_NOFOLLOW, 0) {
268 Ok(fd) => unsafe {
269 let r = Sys::futimens(fd, times).map(|()| 0).or_minus_one_errno();
270 let _ = Sys::close(fd);
271 r
272 },
273 r => r.or_minus_one_errno(),
274 }
275}