Use nix OFlag for open_cloexec

This commit is contained in:
PolyMeilex
2024-01-21 00:21:49 +01:00
committed by Johannes Altmanninger
parent 6915aeb44c
commit 2512849ece
13 changed files with 70 additions and 54 deletions

View File

@@ -325,7 +325,7 @@ fn test_autoload() {
use crate::common::{charptr2wcstring, wcs2zstring, write_loop};
use crate::fds::wopen_cloexec;
use crate::wutil::sprintf;
use libc::{O_CREAT, O_RDWR};
use nix::fcntl::OFlag;
macro_rules! run {
( $fmt:expr $(, $arg:expr )* $(,)? ) => {
@@ -340,7 +340,7 @@ fn touch_file(path: &wstr) {
let fd = wopen_cloexec(
path,
O_RDWR | O_CREAT,
OFlag::O_RDWR | OFlag::O_CREAT,
Mode::S_IRUSR
| Mode::S_IWUSR
| Mode::S_IRGRP

View File

@@ -8,8 +8,8 @@
wutil::{normalize_path, wperror, wreadlink},
};
use errno::{self, Errno};
use libc::{fchdir, EACCES, ELOOP, ENOENT, ENOTDIR, EPERM, O_RDONLY};
use nix::sys::stat::Mode;
use libc::{fchdir, EACCES, ELOOP, ENOENT, ENOTDIR, EPERM};
use nix::{fcntl::OFlag, sys::stat::Mode};
use std::{os::fd::AsRawFd, sync::Arc};
// The cd builtin. Changes the current directory to the one specified or to $HOME if none is
@@ -87,7 +87,7 @@ pub fn cd(parser: &Parser, streams: &mut IoStreams, args: &mut [&wstr]) -> Optio
errno::set_errno(Errno(0));
let res = wopen_cloexec(&norm_dir, O_RDONLY, Mode::empty())
let res = wopen_cloexec(&norm_dir, OFlag::O_RDONLY, Mode::empty())
.map(AutoCloseFd::new)
.map_err(|err| err as i32);

View File

@@ -7,8 +7,8 @@
parser::Block,
reader::reader_read,
};
use libc::{c_int, O_RDONLY, S_IFMT, S_IFREG};
use nix::sys::stat::Mode;
use libc::{c_int, S_IFMT, S_IFREG};
use nix::{fcntl::OFlag, sys::stat::Mode};
use super::prelude::*;
@@ -51,7 +51,7 @@ pub fn source(parser: &Parser, streams: &mut IoStreams, args: &mut [&wstr]) -> O
func_filename = FilenameRef::new(L!("-").to_owned());
fd = streams.stdin_fd;
} else {
let Ok(raw_fd) = wopen_cloexec(args[optind], O_RDONLY, Mode::empty()) else {
let Ok(raw_fd) = wopen_cloexec(args[optind], OFlag::O_RDONLY, Mode::empty()) else {
let esc = escape(args[optind]);
streams.err.append(wgettext_fmt!(
"%ls: Error encountered while sourcing file '%ls':\n",

View File

@@ -19,8 +19,8 @@
wunlink, FileId, INVALID_FILE_ID,
};
use errno::{errno, Errno};
use libc::{EINTR, LOCK_EX, O_CREAT, O_RDONLY, O_RDWR};
use nix::sys::stat::Mode;
use libc::{EINTR, LOCK_EX};
use nix::{fcntl::OFlag, sys::stat::Mode};
use std::collections::hash_map::Entry;
use std::collections::HashSet;
use std::ffi::CString;
@@ -30,10 +30,10 @@
// Pull in the O_EXLOCK constant if it is defined, otherwise set it to 0.
#[cfg(any(bsd, target_os = "macos"))]
use libc::O_EXLOCK;
const O_EXLOCK: OFlag = OFlag::O_EXLOCK;
#[cfg(not(any(bsd, target_os = "macos")))]
const O_EXLOCK: libc::c_int = 0;
const O_EXLOCK: OFlag = OFlag::empty();
/// Callback data, reflecting a change in universal variables.
pub struct CallbackData {
@@ -389,7 +389,8 @@ fn load_from_path_narrow(&mut self, callbacks: &mut CallbackDataList) -> bool {
return true;
}
let Ok(raw_fd) = open_cloexec(&self.narrow_vars_path, O_RDONLY, Mode::empty()) else {
let Ok(raw_fd) = open_cloexec(&self.narrow_vars_path, OFlag::O_RDONLY, Mode::empty())
else {
return false;
};
@@ -433,9 +434,9 @@ fn open_and_acquire_lock(&mut self) -> Option<OwnedFd> {
// We pass O_RDONLY with O_CREAT; this creates a potentially empty file. We do this so that we
// have something to lock on.
let mut locked_by_open = false;
let mut flags = O_RDWR | O_CREAT;
let mut flags = OFlag::O_RDWR | OFlag::O_CREAT;
if O_EXLOCK != 0 && self.do_flock {
if !O_EXLOCK.is_empty() && self.do_flock {
flags |= O_EXLOCK;
locked_by_open = true;
}
@@ -453,8 +454,8 @@ fn open_and_acquire_lock(&mut self) -> Option<OwnedFd> {
continue; // signaled; try again
}
if O_EXLOCK != 0 {
if (flags & O_EXLOCK) != 0
if !O_EXLOCK.is_empty() {
if flags.intersects(O_EXLOCK)
&& [nix::Error::ENOTSUP, nix::Error::EOPNOTSUPP].contains(&err)
{
// Filesystem probably does not support locking. Give up on locking.

View File

@@ -50,9 +50,10 @@
use crate::wutil::{wgettext, wgettext_fmt};
use errno::{errno, set_errno};
use libc::{
c_char, EACCES, ENOENT, ENOEXEC, ENOTDIR, EPIPE, EXIT_FAILURE, EXIT_SUCCESS, O_NOCTTY,
O_RDONLY, STDERR_FILENO, STDIN_FILENO, STDOUT_FILENO,
c_char, EACCES, ENOENT, ENOEXEC, ENOTDIR, EPIPE, EXIT_FAILURE, EXIT_SUCCESS, STDERR_FILENO,
STDIN_FILENO, STDOUT_FILENO,
};
use nix::fcntl::OFlag;
use nix::sys::stat;
use std::ffi::CStr;
use std::io::{Read, Write};
@@ -367,7 +368,7 @@ pub fn is_thompson_shell_script(path: &CStr) -> bool {
}
let e = errno();
let mut res = false;
let fd = open_cloexec(path, O_RDONLY | O_NOCTTY, stat::Mode::empty());
let fd = open_cloexec(path, OFlag::O_RDONLY | OFlag::O_NOCTTY, stat::Mode::empty());
if let Ok(fd) = fd {
let mut file = unsafe { std::fs::File::from_raw_fd(fd) };
let mut buf = [b'\0'; 256];

View File

@@ -224,15 +224,14 @@ pub fn set_cloexec(fd: RawFd, should_set: bool /* = true */) -> c_int {
/// possible).
pub fn wopen_cloexec(
pathname: &wstr,
flags: i32,
flags: OFlag,
mode: nix::sys::stat::Mode,
) -> nix::Result<RawFd> {
open_cloexec(wcs2zstring(pathname).as_c_str(), flags, mode)
}
/// Narrow versions of wopen_cloexec.
pub fn open_cloexec(path: &CStr, flags: i32, mode: nix::sys::stat::Mode) -> nix::Result<RawFd> {
let flags = unsafe { OFlag::from_bits_unchecked(flags) };
pub fn open_cloexec(path: &CStr, flags: OFlag, mode: nix::sys::stat::Mode) -> nix::Result<RawFd> {
// Port note: the C++ version of this function had a fallback for platforms where
// O_CLOEXEC is not supported, using fcntl. In 2023, this is no longer needed.
let saved_errno = errno();

View File

@@ -31,12 +31,9 @@
};
use bitflags::bitflags;
use libc::{
fchmod, fchown, flock, fstat, ftruncate, lseek, LOCK_EX, LOCK_SH, LOCK_UN, O_APPEND, O_CREAT,
O_RDONLY, O_WRONLY, SEEK_SET,
};
use libc::{fchmod, fchown, flock, fstat, ftruncate, lseek, LOCK_EX, LOCK_SH, LOCK_UN, SEEK_SET};
use lru::LruCache;
use nix::sys::stat::Mode;
use nix::{fcntl::OFlag, sys::stat::Mode};
use rand::Rng;
use crate::{
@@ -481,7 +478,7 @@ fn load_old_if_needed(&mut self) {
let _profiler = TimeProfiler::new("load_old");
if let Some(filename) = history_filename(&self.name, L!("")) {
let Ok(raw_fd) = wopen_cloexec(&filename, O_RDONLY, Mode::empty()) else {
let Ok(raw_fd) = wopen_cloexec(&filename, OFlag::O_RDONLY, Mode::empty()) else {
return;
};
@@ -674,9 +671,12 @@ fn save_internal_via_rewrite(&mut self) {
break;
}
let target_fd_before =
wopen_cloexec(&target_name, O_RDONLY | O_CREAT, HISTORY_FILE_MODE)
.map(|raw_fd| unsafe { OwnedFd::from_raw_fd(raw_fd) });
let target_fd_before = wopen_cloexec(
&target_name,
OFlag::O_RDONLY | OFlag::O_CREAT,
HISTORY_FILE_MODE,
)
.map(|raw_fd| unsafe { OwnedFd::from_raw_fd(raw_fd) });
let orig_file_id = target_fd_before
.as_ref()
@@ -698,7 +698,7 @@ fn save_internal_via_rewrite(&mut self) {
// If the open fails, then proceed; this may be because there is no current history
let mut new_file_id = INVALID_FILE_ID;
let target_fd_after = wopen_cloexec(&target_name, O_RDONLY, Mode::empty())
let target_fd_after = wopen_cloexec(&target_name, OFlag::O_RDONLY, Mode::empty())
.map(|raw_fd| unsafe { OwnedFd::from_raw_fd(raw_fd) });
if let Ok(target_fd_after) = target_fd_after.as_ref() {
@@ -815,7 +815,11 @@ fn save_internal_via_appending(&mut self) -> bool {
// Limit our max tries so we don't do this forever.
let mut history_fd = None;
for _i in 0..MAX_SAVE_TRIES {
let Ok(fd) = wopen_cloexec(&history_path, O_WRONLY | O_APPEND, Mode::empty()) else {
let Ok(fd) = wopen_cloexec(
&history_path,
OFlag::O_WRONLY | OFlag::O_APPEND,
Mode::empty(),
) else {
// can't open, we're hosed
break;
};
@@ -1106,7 +1110,7 @@ fn populate_from_config_path(&mut self) {
old_file.push_utfstr(&self.name);
old_file.push_str("_history");
let Ok(src_fd) = wopen_cloexec(&old_file, O_RDONLY, Mode::empty()) else {
let Ok(src_fd) = wopen_cloexec(&old_file, OFlag::O_RDONLY, Mode::empty()) else {
return;
};
@@ -1116,7 +1120,11 @@ fn populate_from_config_path(&mut self) {
// destination file descriptor, since it destroys the name and the file.
self.clear();
let Ok(dst_fd) = wopen_cloexec(&new_file, O_WRONLY | O_CREAT, HISTORY_FILE_MODE) else {
let Ok(dst_fd) = wopen_cloexec(
&new_file,
OFlag::O_WRONLY | OFlag::O_CREAT,
HISTORY_FILE_MODE,
) else {
FLOG!(history_file, "Error when writing history file");
return;
};

View File

@@ -17,7 +17,8 @@
use crate::wchar::prelude::*;
use crate::wutil::{perror, perror_io, wdirname, wstat, wwrite_to_fd};
use errno::Errno;
use libc::{EAGAIN, EINTR, ENOENT, ENOTDIR, EPIPE, EWOULDBLOCK, O_EXCL, STDOUT_FILENO};
use libc::{EAGAIN, EINTR, ENOENT, ENOTDIR, EPIPE, EWOULDBLOCK, STDOUT_FILENO};
use nix::fcntl::OFlag;
use nix::sys::stat::Mode;
use std::cell::{RefCell, UnsafeCell};
use std::os::fd::RawFd;
@@ -665,7 +666,7 @@ pub fn append_from_specs(&mut self, specs: &RedirectionSpecList, pwd: &wstr) ->
self.push(Arc::new(IoFile::new(spec.fd, file)));
}
Err(err) => {
if (oflags & O_EXCL) != 0 && err == nix::Error::EEXIST {
if oflags.intersects(OFlag::O_EXCL) && err == nix::Error::EEXIST {
FLOGF!(warning, NOCLOB_ERROR, spec.target);
} else {
if should_flog!(warning) {

View File

@@ -33,7 +33,7 @@
use crate::wchar::{wstr, WString, L};
use crate::wutil::{perror, wgettext, wgettext_fmt};
use libc::c_int;
use libc::O_RDONLY;
use nix::fcntl::OFlag;
use nix::sys::stat::Mode;
use once_cell::sync::Lazy;
use printf_compat::sprintf;
@@ -361,7 +361,7 @@ pub fn new(variables: EnvStackRef, is_principal: bool) -> ParserRef {
match open_cloexec(
CStr::from_bytes_with_nul(b".\0").unwrap(),
O_RDONLY,
OFlag::O_RDONLY,
Mode::empty(),
) {
Ok(raw_fd) => {

View File

@@ -17,6 +17,7 @@
IXOFF, IXON, ONLCR, OPOST, O_NONBLOCK, O_RDONLY, SIGINT, SIGTTIN, STDIN_FILENO, STDOUT_FILENO,
S_IFDIR, TCSANOW, VMIN, VQUIT, VSUSP, VTIME, _POSIX_VDISABLE,
};
use nix::fcntl::OFlag;
use nix::sys::stat::Mode;
use once_cell::sync::Lazy;
use std::cell::UnsafeCell;
@@ -4660,7 +4661,7 @@ fn import_history_if_necessary(&mut self) {
var.map_or_else(|| L!("~/.bash_history").to_owned(), |var| var.as_string());
expand_tilde(&mut path, self.vars());
let Ok(raw_fd) = wopen_cloexec(&path, O_RDONLY, Mode::empty()) else {
let Ok(raw_fd) = wopen_cloexec(&path, OFlag::O_RDONLY, Mode::empty()) else {
return;
};

View File

@@ -3,7 +3,7 @@
use crate::io::IoChain;
use crate::wchar::prelude::*;
use crate::wutil::fish_wcstoi;
use libc::{c_int, O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_TRUNC, O_WRONLY};
use nix::fcntl::OFlag;
use std::os::fd::RawFd;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
@@ -33,12 +33,12 @@ pub struct Dup2List {
impl RedirectionMode {
/// The open flags for this redirection mode.
pub fn oflags(self) -> Option<c_int> {
pub fn oflags(self) -> Option<OFlag> {
match self {
RedirectionMode::append => Some(O_CREAT | O_APPEND | O_WRONLY),
RedirectionMode::overwrite => Some(O_CREAT | O_WRONLY | O_TRUNC),
RedirectionMode::noclob => Some(O_CREAT | O_EXCL | O_WRONLY),
RedirectionMode::input => Some(O_RDONLY),
RedirectionMode::append => Some(OFlag::O_CREAT | OFlag::O_APPEND | OFlag::O_WRONLY),
RedirectionMode::overwrite => Some(OFlag::O_CREAT | OFlag::O_WRONLY | OFlag::O_TRUNC),
RedirectionMode::noclob => Some(OFlag::O_CREAT | OFlag::O_EXCL | OFlag::O_WRONLY),
RedirectionMode::input => Some(OFlag::O_RDONLY),
_ => None,
}
}
@@ -83,7 +83,7 @@ pub fn get_target_as_fd(&self) -> Option<RawFd> {
}
/// \return the open flags for this redirection.
pub fn oflags(&self) -> c_int {
pub fn oflags(&self) -> OFlag {
match self.mode.oflags() {
Some(flags) => flags,
None => panic!("Not a file redirection"),

View File

@@ -7,8 +7,7 @@
use crate::tests::string_escape::ESCAPE_TEST_CHAR;
use crate::wchar::prelude::*;
use crate::wcstringutil::{string_prefixes_string, string_prefixes_string_case_insensitive};
use libc::O_RDONLY;
use nix::sys::stat::Mode;
use nix::{fcntl::OFlag, sys::stat::Mode};
use rand::random;
use std::collections::VecDeque;
use std::ffi::CString;
@@ -596,7 +595,12 @@ fn test_history_formats() {
];
let test_history_imported_from_bash = History::with_name(L!("bash_import"));
let file = AutoCloseFd::new(
wopen_cloexec(L!("tests/history_sample_bash"), O_RDONLY, Mode::empty()).unwrap(),
wopen_cloexec(
L!("tests/history_sample_bash"),
OFlag::O_RDONLY,
Mode::empty(),
)
.unwrap(),
);
test_history_imported_from_bash.populate_from_bash(BufReader::new(file));
assert_eq!(test_history_imported_from_bash.get_history(), expected);

View File

@@ -6,7 +6,8 @@
use crate::parse_constants::SOURCE_OFFSET_INVALID;
use crate::redirection::RedirectionMode;
use crate::wchar::prelude::*;
use libc::{c_int, STDIN_FILENO, STDOUT_FILENO};
use libc::{STDIN_FILENO, STDOUT_FILENO};
use nix::fcntl::OFlag;
use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not};
use std::os::fd::RawFd;
@@ -1036,8 +1037,8 @@ fn try_from(buff: &wstr) -> Result<PipeOrRedir, ()> {
impl PipeOrRedir {
/// \return the oflags (as in open(2)) for this redirection.
pub fn oflags(&self) -> c_int {
self.mode.oflags().unwrap_or(-1)
pub fn oflags(&self) -> Option<OFlag> {
self.mode.oflags()
}
// \return if we are "valid". Here "valid" means only that the source fd did not overflow.