1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 03:27:44 +00:00

Adapt to API changes in nix

This commit is contained in:
Daniel Hofstetter 2025-05-22 16:41:12 +02:00
parent fd4c315fa3
commit 73e447224c
9 changed files with 44 additions and 44 deletions

View file

@ -10,7 +10,7 @@ use std::io::{self, BufWriter, IsTerminal, Read, Write};
#[cfg(unix)] #[cfg(unix)]
use std::net::Shutdown; use std::net::Shutdown;
#[cfg(unix)] #[cfg(unix)]
use std::os::fd::{AsFd, AsRawFd}; use std::os::fd::AsFd;
#[cfg(unix)] #[cfg(unix)]
use std::os::unix::fs::FileTypeExt; use std::os::unix::fs::FileTypeExt;
#[cfg(unix)] #[cfg(unix)]
@ -372,7 +372,7 @@ fn cat_handle<R: FdReadable>(
#[cfg(unix)] #[cfg(unix)]
fn is_appending() -> bool { fn is_appending() -> bool {
let stdout = io::stdout(); let stdout = io::stdout();
let Ok(flags) = fcntl(stdout.as_raw_fd(), FcntlArg::F_GETFL) else { let Ok(flags) = fcntl(stdout.as_fd(), FcntlArg::F_GETFL) else {
return false; return false;
}; };
// TODO Replace `1 << 10` with `nix::fcntl::Oflag::O_APPEND`. // TODO Replace `1 << 10` with `nix::fcntl::Oflag::O_APPEND`.

View file

@ -5,10 +5,7 @@
use super::{CatResult, FdReadable, InputHandle}; use super::{CatResult, FdReadable, InputHandle};
use nix::unistd; use nix::unistd;
use std::os::{ use std::os::{fd::AsFd, unix::io::AsRawFd};
fd::AsFd,
unix::io::{AsRawFd, RawFd},
};
use uucore::pipes::{pipe, splice, splice_exact}; use uucore::pipes::{pipe, splice, splice_exact};
@ -41,7 +38,7 @@ pub(super) fn write_fast_using_splice<R: FdReadable, S: AsRawFd + AsFd>(
// we can recover by copying the data that we have from the // we can recover by copying the data that we have from the
// intermediate pipe to stdout using normal read/write. Then // intermediate pipe to stdout using normal read/write. Then
// we tell the caller to fall back. // we tell the caller to fall back.
copy_exact(pipe_rd.as_raw_fd(), write_fd, n)?; copy_exact(&pipe_rd, write_fd, n)?;
return Ok(true); return Ok(true);
} }
} }
@ -55,7 +52,7 @@ pub(super) fn write_fast_using_splice<R: FdReadable, S: AsRawFd + AsFd>(
/// Move exactly `num_bytes` bytes from `read_fd` to `write_fd`. /// Move exactly `num_bytes` bytes from `read_fd` to `write_fd`.
/// ///
/// Panics if not enough bytes can be read. /// Panics if not enough bytes can be read.
fn copy_exact(read_fd: RawFd, write_fd: &impl AsFd, num_bytes: usize) -> nix::Result<()> { fn copy_exact(read_fd: &impl AsFd, write_fd: &impl AsFd, num_bytes: usize) -> nix::Result<()> {
let mut left = num_bytes; let mut left = num_bytes;
let mut buf = [0; BUF_SIZE]; let mut buf = [0; BUF_SIZE];
while left > 0 { while left > 0 {

View file

@ -31,6 +31,8 @@ use std::ffi::OsString;
use std::fs::{File, OpenOptions}; use std::fs::{File, OpenOptions};
use std::io::{self, Read, Seek, SeekFrom, Stdout, Write}; use std::io::{self, Read, Seek, SeekFrom, Stdout, Write};
#[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
use std::os::fd::AsFd;
#[cfg(any(target_os = "linux", target_os = "android"))]
use std::os::unix::fs::OpenOptionsExt; use std::os::unix::fs::OpenOptionsExt;
#[cfg(unix)] #[cfg(unix)]
use std::os::unix::{ use std::os::unix::{
@ -279,7 +281,7 @@ impl Source {
match self { match self {
Self::File(f) => { Self::File(f) => {
let advice = PosixFadviseAdvice::POSIX_FADV_DONTNEED; let advice = PosixFadviseAdvice::POSIX_FADV_DONTNEED;
posix_fadvise(f.as_raw_fd(), offset, len, advice) posix_fadvise(f.as_fd(), offset, len, advice)
} }
_ => Err(Errno::ESPIPE), // "Illegal seek" _ => Err(Errno::ESPIPE), // "Illegal seek"
} }
@ -649,7 +651,7 @@ impl Dest {
match self { match self {
Self::File(f, _) => { Self::File(f, _) => {
let advice = PosixFadviseAdvice::POSIX_FADV_DONTNEED; let advice = PosixFadviseAdvice::POSIX_FADV_DONTNEED;
posix_fadvise(f.as_raw_fd(), offset, len, advice) posix_fadvise(f.as_fd(), offset, len, advice)
} }
_ => Err(Errno::ESPIPE), // "Illegal seek" _ => Err(Errno::ESPIPE), // "Illegal seek"
} }
@ -784,7 +786,7 @@ impl<'a> Output<'a> {
#[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
if let Some(libc_flags) = make_linux_oflags(&settings.oflags) { if let Some(libc_flags) = make_linux_oflags(&settings.oflags) {
nix::fcntl::fcntl( nix::fcntl::fcntl(
fx.as_raw().as_raw_fd(), fx.as_raw().as_fd(),
F_SETFL(OFlag::from_bits_retain(libc_flags)), F_SETFL(OFlag::from_bits_retain(libc_flags)),
)?; )?;
} }

View file

@ -390,12 +390,12 @@ pub fn ensure_stdout_not_broken() -> Result<bool> {
poll::{PollFd, PollFlags, PollTimeout}, poll::{PollFd, PollFlags, PollTimeout},
sys::stat::{SFlag, fstat}, sys::stat::{SFlag, fstat},
}; };
use std::os::fd::{AsFd, AsRawFd}; use std::os::fd::AsFd;
let out = stdout(); let out = stdout();
// First, check that stdout is a fifo and return true if it's not the case // First, check that stdout is a fifo and return true if it's not the case
let stat = fstat(out.as_raw_fd())?; let stat = fstat(out.as_fd())?;
if !SFlag::from_bits_truncate(stat.st_mode).contains(SFlag::S_IFIFO) { if !SFlag::from_bits_truncate(stat.st_mode).contains(SFlag::S_IFIFO) {
return Ok(true); return Ok(true);
} }

View file

@ -18,7 +18,7 @@ use libc::{_SC_PAGESIZE, S_IFREG, sysconf};
use nix::sys::stat; use nix::sys::stat;
#[cfg(unix)] #[cfg(unix)]
use std::io::{Seek, SeekFrom}; use std::io::{Seek, SeekFrom};
#[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(unix)]
use std::os::fd::{AsFd, AsRawFd}; use std::os::fd::{AsFd, AsRawFd};
#[cfg(windows)] #[cfg(windows)]
use std::os::windows::fs::MetadataExt; use std::os::windows::fs::MetadataExt;
@ -48,9 +48,7 @@ fn count_bytes_using_splice(fd: &impl AsFd) -> Result<usize, usize> {
.write(true) .write(true)
.open("/dev/null") .open("/dev/null")
.map_err(|_| 0_usize)?; .map_err(|_| 0_usize)?;
let null_rdev = stat::fstat(null_file.as_raw_fd()) let null_rdev = stat::fstat(null_file.as_fd()).map_err(|_| 0_usize)?.st_rdev as libc::dev_t;
.map_err(|_| 0_usize)?
.st_rdev as libc::dev_t;
if (libc::major(null_rdev), libc::minor(null_rdev)) != (1, 3) { if (libc::major(null_rdev), libc::minor(null_rdev)) != (1, 3) {
// This is not a proper /dev/null, writing to it is probably bad // This is not a proper /dev/null, writing to it is probably bad
// Bit of an edge case, but it has been known to happen // Bit of an edge case, but it has been known to happen
@ -92,7 +90,7 @@ pub(crate) fn count_bytes_fast<T: WordCountable>(handle: &mut T) -> (usize, Opti
#[cfg(unix)] #[cfg(unix)]
{ {
let fd = handle.as_raw_fd(); let fd = handle.as_fd();
if let Ok(stat) = stat::fstat(fd) { if let Ok(stat) = stat::fstat(fd) {
// If the file is regular, then the `st_size` should hold // If the file is regular, then the `st_size` should hold
// the file's size in bytes. // the file's size in bytes.
@ -132,7 +130,10 @@ pub(crate) fn count_bytes_fast<T: WordCountable>(handle: &mut T) -> (usize, Opti
// However, the raw file descriptor in this situation would be equal to `0` // However, the raw file descriptor in this situation would be equal to `0`
// for STDIN in both invocations. // for STDIN in both invocations.
// Therefore we cannot rely of `st_size` here and should fall back on full read. // Therefore we cannot rely of `st_size` here and should fall back on full read.
if fd > 0 && (stat.st_mode as libc::mode_t & S_IFREG) != 0 && stat.st_size > 0 { if fd.as_raw_fd() > 0
&& (stat.st_mode as libc::mode_t & S_IFREG) != 0
&& stat.st_size > 0
{
let sys_page_size = unsafe { sysconf(_SC_PAGESIZE) as usize }; let sys_page_size = unsafe { sysconf(_SC_PAGESIZE) as usize };
if stat.st_size as usize % sys_page_size > 0 { if stat.st_size as usize % sys_page_size > 0 {
// regular file or file from /proc, /sys and similar pseudo-filesystems // regular file or file from /proc, /sys and similar pseudo-filesystems

View file

@ -37,9 +37,6 @@ mod tests {
}, },
}; };
#[cfg(any(target_os = "linux", target_os = "android"))]
use std::os::fd::AsRawFd;
use std::io::{Read, Write}; use std::io::{Read, Write};
#[cfg(unix)] #[cfg(unix)]
@ -62,7 +59,7 @@ mod tests {
let n = pipe_write.write(data).unwrap(); let n = pipe_write.write(data).unwrap();
assert_eq!(n, data.len()); assert_eq!(n, data.len());
let mut buf = [0; 1024]; let mut buf = [0; 1024];
let n = copy_exact(pipe_read.as_raw_fd(), &pipe_write, data.len()).unwrap(); let n = copy_exact(&pipe_read, &pipe_write, data.len()).unwrap();
let n2 = pipe_read.read(&mut buf).unwrap(); let n2 = pipe_read.read(&mut buf).unwrap();
assert_eq!(n, n2); assert_eq!(n, n2);
assert_eq!(&buf[..n], data); assert_eq!(&buf[..n], data);

View file

@ -13,7 +13,7 @@ use crate::{
/// Buffer-based copying utilities for unix (excluding Linux). /// Buffer-based copying utilities for unix (excluding Linux).
use std::{ use std::{
io::{Read, Write}, io::{Read, Write},
os::fd::{AsFd, AsRawFd, RawFd}, os::fd::{AsFd, AsRawFd},
}; };
use super::common::Error; use super::common::Error;
@ -105,7 +105,7 @@ where
// we can recover by copying the data that we have from the // we can recover by copying the data that we have from the
// intermediate pipe to stdout using normal read/write. Then // intermediate pipe to stdout using normal read/write. Then
// we tell the caller to fall back. // we tell the caller to fall back.
copy_exact(pipe_rd.as_raw_fd(), dest, n)?; copy_exact(&pipe_rd, dest, n)?;
return Ok((bytes, true)); return Ok((bytes, true));
} }
@ -122,7 +122,7 @@ where
/// and `write` calls. /// and `write` calls.
#[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
pub(crate) fn copy_exact( pub(crate) fn copy_exact(
read_fd: RawFd, read_fd: &impl AsFd,
write_fd: &impl AsFd, write_fd: &impl AsFd,
num_bytes: usize, num_bytes: usize,
) -> std::io::Result<usize> { ) -> std::io::Result<usize> {

View file

@ -25,7 +25,9 @@ use std::hash::Hash;
use std::io::Stdin; use std::io::Stdin;
use std::io::{Error, ErrorKind, Result as IOResult}; use std::io::{Error, ErrorKind, Result as IOResult};
#[cfg(unix)] #[cfg(unix)]
use std::os::unix::{fs::MetadataExt, io::AsRawFd}; use std::os::fd::AsFd;
#[cfg(unix)]
use std::os::unix::fs::MetadataExt;
use std::path::{Component, MAIN_SEPARATOR, Path, PathBuf}; use std::path::{Component, MAIN_SEPARATOR, Path, PathBuf};
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
use winapi_util::AsHandleRef; use winapi_util::AsHandleRef;
@ -50,8 +52,8 @@ pub struct FileInformation(
impl FileInformation { impl FileInformation {
/// Get information from a currently open file /// Get information from a currently open file
#[cfg(unix)] #[cfg(unix)]
pub fn from_file(file: &impl AsRawFd) -> IOResult<Self> { pub fn from_file(file: &impl AsFd) -> IOResult<Self> {
let stat = nix::sys::stat::fstat(file.as_raw_fd())?; let stat = nix::sys::stat::fstat(file)?;
Ok(Self(stat)) Ok(Self(stat))
} }
@ -717,7 +719,7 @@ pub fn is_stdin_directory(stdin: &Stdin) -> bool {
#[cfg(unix)] #[cfg(unix)]
{ {
use nix::sys::stat::fstat; use nix::sys::stat::fstat;
let mode = fstat(stdin.as_raw_fd()).unwrap().st_mode as mode_t; let mode = fstat(stdin.as_fd()).unwrap().st_mode as mode_t;
has!(mode, S_IFDIR) has!(mode, S_IFDIR)
} }

View file

@ -19,8 +19,6 @@ use std::collections::HashMap;
use std::ffi::OsStr; use std::ffi::OsStr;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
use std::os::unix::ffi::OsStrExt; use std::os::unix::ffi::OsStrExt;
#[cfg(all(unix, feature = "chmod"))]
use std::os::unix::io::IntoRawFd;
use std::path::Path; use std::path::Path;
#[cfg(not(windows))] #[cfg(not(windows))]
use std::path::PathBuf; use std::path::PathBuf;
@ -544,50 +542,53 @@ fn test_ls_io_errors() {
#[cfg(unix)] #[cfg(unix)]
{ {
use std::os::fd::AsRawFd;
at.touch("some-dir4/bad-fd.txt"); at.touch("some-dir4/bad-fd.txt");
let fd1 = at.open("some-dir4/bad-fd.txt").into_raw_fd(); let fd1 = at.open("some-dir4/bad-fd.txt");
let fd2 = dup(dbg!(fd1)).unwrap(); let fd2 = dup(dbg!(&fd1)).unwrap();
close(fd1).unwrap(); close(fd1).unwrap();
// on the mac and in certain Linux containers bad fds are typed as dirs, // on the mac and in certain Linux containers bad fds are typed as dirs,
// however sometimes bad fds are typed as links and directory entry on links won't fail // however sometimes bad fds are typed as links and directory entry on links won't fail
if PathBuf::from(format!("/dev/fd/{fd2}")).is_dir() { if PathBuf::from(format!("/dev/fd/{}", fd2.as_raw_fd())).is_dir() {
scene scene
.ucmd() .ucmd()
.arg("-alR") .arg("-alR")
.arg(format!("/dev/fd/{fd2}")) .arg(format!("/dev/fd/{}", fd2.as_raw_fd()))
.fails() .fails()
.stderr_contains(format!( .stderr_contains(format!(
"cannot open directory '/dev/fd/{fd2}': Bad file descriptor" "cannot open directory '/dev/fd/{}': Bad file descriptor",
fd2.as_raw_fd()
)) ))
.stdout_does_not_contain(format!("{fd2}:\n")); .stdout_does_not_contain(format!("{}:\n", fd2.as_raw_fd()));
scene scene
.ucmd() .ucmd()
.arg("-RiL") .arg("-RiL")
.arg(format!("/dev/fd/{fd2}")) .arg(format!("/dev/fd/{}", fd2.as_raw_fd()))
.fails() .fails()
.stderr_contains(format!("cannot open directory '/dev/fd/{fd2}': Bad file descriptor")) .stderr_contains(format!("cannot open directory '/dev/fd/{}': Bad file descriptor", fd2.as_raw_fd()))
// don't double print bad fd errors // don't double print bad fd errors
.stderr_does_not_contain(format!("ls: cannot open directory '/dev/fd/{fd2}': Bad file descriptor\nls: cannot open directory '/dev/fd/{fd2}': Bad file descriptor")); .stderr_does_not_contain(format!("ls: cannot open directory '/dev/fd/{0}': Bad file descriptor\nls: cannot open directory '/dev/fd/{0}': Bad file descriptor", fd2.as_raw_fd()));
} else { } else {
scene scene
.ucmd() .ucmd()
.arg("-alR") .arg("-alR")
.arg(format!("/dev/fd/{fd2}")) .arg(format!("/dev/fd/{}", fd2.as_raw_fd()))
.succeeds(); .succeeds();
scene scene
.ucmd() .ucmd()
.arg("-RiL") .arg("-RiL")
.arg(format!("/dev/fd/{fd2}")) .arg(format!("/dev/fd/{}", fd2.as_raw_fd()))
.succeeds(); .succeeds();
} }
scene scene
.ucmd() .ucmd()
.arg("-alL") .arg("-alL")
.arg(format!("/dev/fd/{fd2}")) .arg(format!("/dev/fd/{}", fd2.as_raw_fd()))
.succeeds(); .succeeds();
let _ = close(fd2); let _ = close(fd2);