1#![cfg(all(target_family = "unix", not(target_os = "vxworks")))]
2
3use core::ffi::{c_int, c_uint};
4
5pub use libc::{
6 LOCK_EX, LOCK_NB, O_CLOEXEC, O_CREAT, O_DIRECTORY, O_EXCL, O_RDONLY, O_RDWR, S_IRGRP, S_IRUSR,
7 S_IWGRP, S_IWUSR, mode_t,
8};
9
10use crate::{
11 AsAtRoot, AsFd, BorrowedFd, OwnedFd,
12 errno::{Errno, errno},
13 path::Path,
14};
15
16pub type RawFd = c_int;
18
19pub type RawDir = *mut libc::DIR;
21
22pub type DirEntry = *mut libc::dirent;
24
25pub type AtRoot<'a> = BorrowedFd<'a>;
27
28impl<T: AsFd> AsAtRoot for T {
29 fn as_root(&self) -> AtRoot<'_> {
30 self.as_fd()
31 }
32}
33
34pub fn open(path: &Path, oflag: c_int, mode: mode_t) -> Result<RawFd, Errno> {
36 let fd = path.with_cstr(&|path| {
37 unsafe { libc::open(path, oflag, c_uint::from(mode)) }
39 });
40 if fd < 0 { Err(errno()) } else { Ok(fd) }
41}
42
43pub fn openat(fd: BorrowedFd<'_>, path: &Path, oflag: c_int, mode: mode_t) -> Result<RawFd, Errno> {
45 let fd = path.with_cstr(&|path| {
46 unsafe { libc::openat(fd.fd, path, oflag, c_uint::from(mode)) }
48 });
49 if fd < 0 { Err(errno()) } else { Ok(fd) }
50}
51
52pub fn close(fd: RawFd) -> Result<(), Errno> {
54 let ret = unsafe { libc::close(fd) };
56 if ret < 0 { Err(errno()) } else { Ok(()) }
57}
58
59pub fn flock(fd: BorrowedFd<'_>, op: c_int) -> Result<(), Errno> {
61 let ret = unsafe { libc::flock(fd.fd, op) };
63 if ret < 0 { Err(errno()) } else { Ok(()) }
64}
65
66pub fn fsync(fd: BorrowedFd<'_>) -> Result<(), Errno> {
68 let ret = unsafe { libc::fsync(fd.fd) };
70 if ret < 0 { Err(errno()) } else { Ok(()) }
71}
72
73pub fn unlinkat(fd: BorrowedFd<'_>, path: &Path, flags: c_int) -> Result<(), Errno> {
75 let ret = path.with_cstr(&|path| {
77 unsafe { libc::unlinkat(fd.fd, path, flags) }
79 });
80 if ret < 0 { Err(errno()) } else { Ok(()) }
81}
82
83pub fn dup(old_fd: BorrowedFd<'_>) -> Result<RawFd, Errno> {
85 let ret = unsafe { libc::dup(old_fd.fd) };
87 if ret < 0 { Err(errno()) } else { Ok(ret) }
88}
89
90pub fn fdopendir(fd: OwnedFd) -> Result<RawDir, Errno> {
92 let dir = unsafe { libc::fdopendir(fd.fd) };
94 if dir.is_null() {
95 Err(errno())
96 } else {
97 core::mem::forget(fd);
100 Ok(dir)
101 }
102}
103
104pub fn readdir(dir: RawDir) -> Result<Option<DirEntry>, Errno> {
106 crate::errno::clear_errno();
109
110 let ret = unsafe { libc::readdir(dir) };
112
113 if ret.is_null() {
115 let errno = errno();
116 if errno.code() == 0 {
117 Ok(None)
118 } else {
119 Err(errno)
120 }
121 } else {
122 Ok(Some(ret))
123 }
124}
125
126pub fn rewinddir(dir: RawDir) {
128 unsafe { libc::rewinddir(dir) };
130}
131
132pub fn closedir(dir: RawDir) -> Result<(), Errno> {
134 let ret = unsafe { libc::closedir(dir) };
136 if ret < 0 { Err(errno()) } else { Ok(()) }
137}