xref: /aosp_15_r20/external/crosvm/base/src/sys/unix/fcntl.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2023 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::os::unix::io::RawFd;
6*bb4ee6a4SAndroid Build Coastguard Worker 
7*bb4ee6a4SAndroid Build Coastguard Worker use libc::c_int;
8*bb4ee6a4SAndroid Build Coastguard Worker use libc::fcntl;
9*bb4ee6a4SAndroid Build Coastguard Worker use libc::F_GETFL;
10*bb4ee6a4SAndroid Build Coastguard Worker use libc::F_SETFL;
11*bb4ee6a4SAndroid Build Coastguard Worker 
12*bb4ee6a4SAndroid Build Coastguard Worker use crate::errno::Result;
13*bb4ee6a4SAndroid Build Coastguard Worker use crate::syscall;
14*bb4ee6a4SAndroid Build Coastguard Worker 
15*bb4ee6a4SAndroid Build Coastguard Worker /// Returns the file flags set for the given `RawFD`
16*bb4ee6a4SAndroid Build Coastguard Worker ///
17*bb4ee6a4SAndroid Build Coastguard Worker /// Returns an error if the OS indicates the flags can't be retrieved.
get_fd_flags(fd: RawFd) -> Result<c_int>18*bb4ee6a4SAndroid Build Coastguard Worker fn get_fd_flags(fd: RawFd) -> Result<c_int> {
19*bb4ee6a4SAndroid Build Coastguard Worker     syscall!(
20*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
21*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because no third parameter is expected and we check the return result.
22*bb4ee6a4SAndroid Build Coastguard Worker         unsafe { fcntl(fd, F_GETFL) }
23*bb4ee6a4SAndroid Build Coastguard Worker     )
24*bb4ee6a4SAndroid Build Coastguard Worker }
25*bb4ee6a4SAndroid Build Coastguard Worker 
26*bb4ee6a4SAndroid Build Coastguard Worker /// Sets the file flags set for the given `RawFD`.
27*bb4ee6a4SAndroid Build Coastguard Worker ///
28*bb4ee6a4SAndroid Build Coastguard Worker /// Returns an error if the OS indicates the flags can't be retrieved.
set_fd_flags(fd: RawFd, flags: c_int) -> Result<()>29*bb4ee6a4SAndroid Build Coastguard Worker fn set_fd_flags(fd: RawFd, flags: c_int) -> Result<()> {
30*bb4ee6a4SAndroid Build Coastguard Worker     syscall!(
31*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
32*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because we supply the third parameter and we check the return result.
33*bb4ee6a4SAndroid Build Coastguard Worker         // fcntlt is trusted not to modify the memory of the calling process.
34*bb4ee6a4SAndroid Build Coastguard Worker         unsafe { fcntl(fd, F_SETFL, flags) }
35*bb4ee6a4SAndroid Build Coastguard Worker     )
36*bb4ee6a4SAndroid Build Coastguard Worker     .map(|_| ())
37*bb4ee6a4SAndroid Build Coastguard Worker }
38*bb4ee6a4SAndroid Build Coastguard Worker 
39*bb4ee6a4SAndroid Build Coastguard Worker /// Performs a logical OR of the given flags with the FD's flags, setting the given bits for the
40*bb4ee6a4SAndroid Build Coastguard Worker /// FD.
41*bb4ee6a4SAndroid Build Coastguard Worker ///
42*bb4ee6a4SAndroid Build Coastguard Worker /// Returns an error if the OS indicates the flags can't be retrieved or set.
add_fd_flags(fd: RawFd, set_flags: c_int) -> Result<()>43*bb4ee6a4SAndroid Build Coastguard Worker pub fn add_fd_flags(fd: RawFd, set_flags: c_int) -> Result<()> {
44*bb4ee6a4SAndroid Build Coastguard Worker     let start_flags = get_fd_flags(fd)?;
45*bb4ee6a4SAndroid Build Coastguard Worker     set_fd_flags(fd, start_flags | set_flags)
46*bb4ee6a4SAndroid Build Coastguard Worker }
47*bb4ee6a4SAndroid Build Coastguard Worker 
48*bb4ee6a4SAndroid Build Coastguard Worker /// Clears the given flags in the FD's flags.
49*bb4ee6a4SAndroid Build Coastguard Worker ///
50*bb4ee6a4SAndroid Build Coastguard Worker /// Returns an error if the OS indicates the flags can't be retrieved or set.
clear_fd_flags(fd: RawFd, clear_flags: c_int) -> Result<()>51*bb4ee6a4SAndroid Build Coastguard Worker pub fn clear_fd_flags(fd: RawFd, clear_flags: c_int) -> Result<()> {
52*bb4ee6a4SAndroid Build Coastguard Worker     let start_flags = get_fd_flags(fd)?;
53*bb4ee6a4SAndroid Build Coastguard Worker     set_fd_flags(fd, start_flags & !clear_flags)
54*bb4ee6a4SAndroid Build Coastguard Worker }
55