Skip to content

Commit 3cf717f

Browse files
committed
Use upstream libc definitions for fcntl FFI
1 parent 28c5b4a commit 3cf717f

File tree

3 files changed

+177
-132
lines changed

3 files changed

+177
-132
lines changed

src/fcntl.rs

Lines changed: 172 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,138 @@ use std::os::unix::io::RawFd;
55
use std::ffi::OsStr;
66
use std::os::unix::ffi::OsStrExt;
77

8-
#[cfg(any(target_os = "linux", target_os = "android"))]
8+
#[cfg(any(target_os = "android", target_os = "linux"))]
99
use sys::uio::IoVec; // For vmsplice
1010

11-
pub use self::consts::*;
12-
13-
// TODO: The remainder of the ffi module should be removed afer work on
14-
// https://github.com/rust-lang/libc/issues/235 is resolved.
15-
#[allow(dead_code)]
16-
mod ffi {
17-
use libc::c_int;
18-
19-
pub const F_ADD_SEALS: c_int = 1033;
20-
pub const F_GET_SEALS: c_int = 1034;
21-
}
22-
2311
libc_bitflags!{
2412
pub struct AtFlags: c_int {
2513
AT_SYMLINK_NOFOLLOW;
26-
#[cfg(any(target_os = "linux", target_os = "android"))]
14+
#[cfg(any(target_os = "android", target_os = "linux"))]
2715
AT_NO_AUTOMOUNT;
28-
#[cfg(any(target_os = "linux", target_os = "android"))]
16+
#[cfg(any(target_os = "android", target_os = "linux"))]
2917
AT_EMPTY_PATH;
3018
}
3119
}
3220

21+
libc_bitflags!(
22+
/// Configuration options for opened files.
23+
pub struct OFlag: c_int {
24+
/// Mask for the access mode of the file.
25+
O_ACCMODE;
26+
/// Use alternate I/O semantics.
27+
#[cfg(target_os = "netbsd")]
28+
O_ALT_IO;
29+
/// Open the file in append-only mode.
30+
O_APPEND;
31+
/// Generate a signal when input or output becomes possible.
32+
O_ASYNC;
33+
/// Closes the file descriptor once an `execve` call is made.
34+
///
35+
/// Also sets the file offset to the beginning of the file.
36+
O_CLOEXEC;
37+
/// Create the file if it does not exist.
38+
O_CREAT;
39+
/// Try to minimize cache effects of the I/O for this file.
40+
#[cfg(any(target_os = "android",
41+
target_os = "dragonfly",
42+
target_os = "freebsd",
43+
target_os = "linux",
44+
target_os = "netbsd"))]
45+
O_DIRECT;
46+
/// If the specified path isn't a directory, fail.
47+
O_DIRECTORY;
48+
/// Implicitly follow each `write()` with an `fdatasync()`.
49+
#[cfg(any(target_os = "android",
50+
target_os = "dragonfly",
51+
target_os = "ios",
52+
target_os = "linux",
53+
target_os = "macos",
54+
target_os = "netbsd",
55+
target_os = "openbsd"))]
56+
O_DSYNC;
57+
/// Error out if a file was not created.
58+
O_EXCL;
59+
/// Open for execute only.
60+
#[cfg(target_os = "freebsd")]
61+
O_EXEC;
62+
/// Open with an exclusive file lock.
63+
#[cfg(any(target_os = "dragonfly",
64+
target_os = "freebsd",
65+
target_os = "ios",
66+
target_os = "macos",
67+
target_os = "netbsd",
68+
target_os = "openbsd"))]
69+
O_EXLOCK;
70+
/// Same as `O_SYNC`.
71+
#[cfg(any(target_os = "dragonfly",
72+
target_os = "freebsd",
73+
target_os = "ios",
74+
all(target_os = "linux", not(target_env = "musl")),
75+
target_os = "macos",
76+
target_os = "netbsd",
77+
target_os = "openbsd"))]
78+
O_FSYNC;
79+
/// Allow files whose sizes can't be represented in an `off_t` to be opened.
80+
#[cfg(any(target_os = "android", target_os = "linux"))]
81+
O_LARGEFILE;
82+
/// Do not update the file last access time during `read(2)`s.
83+
#[cfg(any(target_os = "android", target_os = "linux"))]
84+
O_NOATIME;
85+
/// Don't attach the device as the process' controlling terminal.
86+
O_NOCTTY;
87+
/// Same as `O_NONBLOCK`.
88+
O_NDELAY;
89+
/// `open()` will fail if the given path is a symbolic link.
90+
O_NOFOLLOW;
91+
/// When possible, open the file in nonblocking mode.
92+
O_NONBLOCK;
93+
/// Don't deliver `SIGPIPE`.
94+
#[cfg(target_os = "netbsd")]
95+
O_NOSIGPIPE;
96+
/// Obtain a file descriptor for low-level access.
97+
///
98+
/// The file itself is not opened and other file operations will fail.
99+
#[cfg(any(target_os = "android", target_os = "linux"))]
100+
O_PATH;
101+
/// Only allow reading.
102+
///
103+
/// This should not be combined with `O_WRONLY` or `O_RDWR`.
104+
O_RDONLY;
105+
/// Allow both reading and writing.
106+
///
107+
/// This should not be combined with `O_WRONLY` or `O_RDWR`.
108+
O_RDWR;
109+
/// Similar to `O_DSYNC` but applies to `read`s instead.
110+
#[cfg(any(target_os = "linux", target_os = "netbsd", target_os = "openbsd"))]
111+
O_RSYNC;
112+
/// Skip search permission checks.
113+
#[cfg(target_os = "netbsd")]
114+
O_SEARCH;
115+
/// Open with a shared file lock.
116+
#[cfg(any(target_os = "dragonfly",
117+
target_os = "freebsd",
118+
target_os = "ios",
119+
target_os = "macos",
120+
target_os = "netbsd",
121+
target_os = "openbsd"))]
122+
O_SHLOCK;
123+
/// Implicitly follow each `write()` with an `fsync()`.
124+
O_SYNC;
125+
/// Create an unnamed temporary file.
126+
#[cfg(any(target_os = "android", target_os = "linux"))]
127+
O_TMPFILE;
128+
/// Truncate an existing regular file to 0 length if it allows writing.
129+
O_TRUNC;
130+
/// Restore default TTY attributes.
131+
#[cfg(target_os = "freebsd")]
132+
O_TTY_INIT;
133+
/// Only allow writing.
134+
///
135+
/// This should not be combined with `O_RDONLY` or `O_RDWR`.
136+
O_WRONLY;
137+
}
138+
);
139+
33140
pub fn open<P: ?Sized + NixPath>(path: &P, oflag: OFlag, mode: Mode) -> Result<RawFd> {
34141
let fd = try!(path.with_nix_path(|cstr| {
35142
unsafe { libc::open(cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint) }
@@ -76,6 +183,29 @@ pub fn readlinkat<'a, P: ?Sized + NixPath>(dirfd: RawFd, path: &P, buffer: &'a m
76183
wrap_readlink_result(buffer, res)
77184
}
78185

186+
#[cfg(any(target_os = "android", target_os = "linux"))]
187+
libc_bitflags!(
188+
/// Additional flags for file sealing, which allows for limiting operations on a file.
189+
pub struct SealFlag: c_int {
190+
/// Prevents further calls to `fcntl()` with `F_ADD_SEALS`.
191+
F_SEAL_SEAL;
192+
/// The file cannot be reduced in size.
193+
F_SEAL_SHRINK;
194+
/// The size of the file cannot be increased.
195+
F_SEAL_GROW;
196+
/// The file contents cannot be modified.
197+
F_SEAL_WRITE;
198+
}
199+
);
200+
201+
libc_bitflags!(
202+
/// Additional configuration flags for `fcntl`'s `F_SETFD`.
203+
pub struct FdFlag: c_int {
204+
/// The file descriptor will automatically be closed during a successful `execve(2)`.
205+
FD_CLOEXEC;
206+
}
207+
);
208+
79209
pub enum FcntlArg<'a> {
80210
F_DUPFD(RawFd),
81211
F_DUPFD_CLOEXEC(RawFd),
@@ -92,9 +222,9 @@ pub enum FcntlArg<'a> {
92222
F_OFD_SETLKW(&'a libc::flock),
93223
#[cfg(any(target_os = "linux", target_os = "android"))]
94224
F_OFD_GETLK(&'a mut libc::flock),
95-
#[cfg(target_os = "linux")]
225+
#[cfg(any(target_os = "android", target_os = "linux"))]
96226
F_ADD_SEALS(SealFlag),
97-
#[cfg(target_os = "linux")]
227+
#[cfg(any(target_os = "android", target_os = "linux"))]
98228
F_GET_SEALS,
99229
#[cfg(any(target_os = "macos", target_os = "ios"))]
100230
F_FULLFSYNC,
@@ -120,10 +250,10 @@ pub fn fcntl(fd: RawFd, arg: FcntlArg) -> Result<c_int> {
120250
F_SETLK(flock) => libc::fcntl(fd, libc::F_SETLK, flock),
121251
F_SETLKW(flock) => libc::fcntl(fd, libc::F_SETLKW, flock),
122252
F_GETLK(flock) => libc::fcntl(fd, libc::F_GETLK, flock),
123-
#[cfg(target_os = "linux")]
124-
F_ADD_SEALS(flag) => libc::fcntl(fd, ffi::F_ADD_SEALS, flag.bits()),
125-
#[cfg(target_os = "linux")]
126-
F_GET_SEALS => libc::fcntl(fd, ffi::F_GET_SEALS),
253+
#[cfg(any(target_os = "android", target_os = "linux"))]
254+
F_ADD_SEALS(flag) => libc::fcntl(fd, libc::F_ADD_SEALS, flag.bits()),
255+
#[cfg(any(target_os = "android", target_os = "linux"))]
256+
F_GET_SEALS => libc::fcntl(fd, libc::F_GET_SEALS),
127257
#[cfg(any(target_os = "macos", target_os = "ios"))]
128258
F_FULLFSYNC => libc::fcntl(fd, libc::F_FULLFSYNC),
129259
#[cfg(any(target_os = "linux", target_os = "android"))]
@@ -164,6 +294,27 @@ pub fn flock(fd: RawFd, arg: FlockArg) -> Result<()> {
164294
Errno::result(res).map(drop)
165295
}
166296

297+
#[cfg(any(target_os = "android", target_os = "linux"))]
298+
libc_bitflags! {
299+
/// Additional flags to `splice` and friends.
300+
pub struct SpliceFFlags: c_uint {
301+
/// Request that pages be moved instead of copied.
302+
///
303+
/// Not applicable to `vmsplice`.
304+
SPLICE_F_MOVE;
305+
/// Do not block on I/O.
306+
SPLICE_F_NONBLOCK;
307+
/// Hint that more data will be coming in a subsequent splice.
308+
///
309+
/// Not applicable to `vmsplice`.
310+
SPLICE_F_MORE;
311+
/// Gift the user pages to the kernel.
312+
///
313+
/// Not applicable to `splice`.
314+
SPLICE_F_GIFT;
315+
}
316+
}
317+
167318
#[cfg(any(target_os = "linux", target_os = "android"))]
168319
pub fn splice(fd_in: RawFd, off_in: Option<&mut libc::loff_t>,
169320
fd_out: RawFd, off_out: Option<&mut libc::loff_t>,
@@ -190,111 +341,3 @@ pub fn vmsplice(fd: RawFd, iov: &[IoVec<&[u8]>], flags: SpliceFFlags) -> Result<
190341
Errno::result(ret).map(|r| r as usize)
191342
}
192343

193-
#[cfg(any(target_os = "linux", target_os = "android"))]
194-
mod consts {
195-
use libc::{self, c_int, c_uint};
196-
197-
libc_bitflags! {
198-
pub struct SpliceFFlags: c_uint {
199-
SPLICE_F_MOVE;
200-
SPLICE_F_NONBLOCK;
201-
SPLICE_F_MORE;
202-
SPLICE_F_GIFT;
203-
}
204-
}
205-
206-
bitflags!(
207-
pub struct OFlag: c_int {
208-
const O_ACCMODE = libc::O_ACCMODE;
209-
const O_RDONLY = libc::O_RDONLY;
210-
const O_WRONLY = libc::O_WRONLY;
211-
const O_RDWR = libc::O_RDWR;
212-
const O_CREAT = libc::O_CREAT;
213-
const O_EXCL = libc::O_EXCL;
214-
const O_NOCTTY = libc::O_NOCTTY;
215-
const O_TRUNC = libc::O_TRUNC;
216-
const O_APPEND = libc::O_APPEND;
217-
const O_NONBLOCK = libc::O_NONBLOCK;
218-
const O_DSYNC = libc::O_DSYNC;
219-
const O_DIRECT = libc::O_DIRECT;
220-
const O_LARGEFILE = 0o00100000;
221-
const O_DIRECTORY = libc::O_DIRECTORY;
222-
const O_NOFOLLOW = libc::O_NOFOLLOW;
223-
const O_NOATIME = 0o01000000;
224-
const O_CLOEXEC = libc::O_CLOEXEC;
225-
const O_SYNC = libc::O_SYNC;
226-
const O_PATH = 0o10000000;
227-
const O_TMPFILE = libc::O_TMPFILE;
228-
const O_NDELAY = libc::O_NDELAY;
229-
}
230-
);
231-
232-
libc_bitflags!(
233-
pub struct FdFlag: c_int {
234-
FD_CLOEXEC;
235-
}
236-
);
237-
238-
bitflags!(
239-
pub struct SealFlag: c_int {
240-
const F_SEAL_SEAL = 1;
241-
const F_SEAL_SHRINK = 2;
242-
const F_SEAL_GROW = 4;
243-
const F_SEAL_WRITE = 8;
244-
}
245-
);
246-
247-
}
248-
249-
#[cfg(any(target_os = "netbsd", target_os = "dragonfly", target_os = "openbsd",
250-
target_os = "freebsd", target_os = "macos", target_os = "ios"))]
251-
mod consts {
252-
use libc::{self,c_int};
253-
254-
libc_bitflags!(
255-
pub struct OFlag: c_int {
256-
O_ACCMODE;
257-
O_RDONLY;
258-
O_WRONLY;
259-
O_RDWR;
260-
O_NONBLOCK;
261-
O_APPEND;
262-
O_SHLOCK;
263-
O_EXLOCK;
264-
O_ASYNC;
265-
O_SYNC;
266-
O_NOFOLLOW;
267-
O_CREAT;
268-
O_TRUNC;
269-
O_EXCL;
270-
O_NOCTTY;
271-
O_DIRECTORY;
272-
O_CLOEXEC;
273-
O_FSYNC;
274-
O_NDELAY;
275-
#[cfg(any(target_os = "netbsd", target_os = "openbsd", target_os = "macos",
276-
target_os = "ios"))]
277-
O_DSYNC;
278-
#[cfg(any(target_os = "netbsd", target_os = "dragonfly", target_os = "freebsd"))]
279-
O_DIRECT;
280-
#[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
281-
O_RSYNC;
282-
#[cfg(target_os = "freebsd")]
283-
O_EXEC;
284-
#[cfg(target_os = "freebsd")]
285-
O_TTY_INIT;
286-
#[cfg(target_os = "netbsd")]
287-
O_ALT_IO;
288-
#[cfg(target_os = "netbsd")]
289-
O_NOSIGPIPE;
290-
#[cfg(target_os = "netbsd")]
291-
O_SEARCH;
292-
}
293-
);
294-
295-
libc_bitflags!(
296-
pub struct FdFlag: c_int {
297-
FD_CLOEXEC;
298-
}
299-
);
300-
}

src/unistd.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use errno;
44
use {Errno, Error, Result, NixPath};
5-
use fcntl::{fcntl, OFlag, O_CLOEXEC, FD_CLOEXEC};
5+
use fcntl::{fcntl, OFlag};
66
use fcntl::FcntlArg::F_SETFD;
77
use libc::{self, c_char, c_void, c_int, c_long, c_uint, size_t, pid_t, off_t,
88
uid_t, gid_t, mode_t};
@@ -355,6 +355,8 @@ pub fn dup3(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
355355

356356
#[inline]
357357
fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
358+
use fcntl::{FD_CLOEXEC, O_CLOEXEC};
359+
358360
if oldfd == newfd {
359361
return Err(Error::Sys(Errno::EINVAL));
360362
}
@@ -857,7 +859,7 @@ pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> {
857859
target_os = "android",
858860
target_os = "emscripten")))]
859861
fn pipe2_setflags(fd1: RawFd, fd2: RawFd, flags: OFlag) -> Result<()> {
860-
use fcntl::O_NONBLOCK;
862+
use fcntl::{FD_CLOEXEC, O_CLOEXEC, O_NONBLOCK};
861863
use fcntl::FcntlArg::F_SETFL;
862864

863865
let mut res = Ok(0);

test/sys/test_termios.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ fn test_local_flags() {
116116

117117
// Set the master is in nonblocking mode or reading will never return.
118118
let flags = fcntl::fcntl(pty.master, fcntl::F_GETFL).unwrap();
119-
let new_flags = fcntl::OFlag::from_bits(flags).unwrap() | fcntl::O_NONBLOCK;
119+
let new_flags = fcntl::OFlag::from_bits_truncate(flags) | fcntl::O_NONBLOCK;
120120
fcntl::fcntl(pty.master, fcntl::F_SETFL(new_flags)).unwrap();
121121

122122
// Write into the master

0 commit comments

Comments
 (0)