From 36d5013fac3d4fd4158d721e2fa24b685c775a07 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Thu, 7 Sep 2023 15:07:20 +0200 Subject: [PATCH] stty: adapt to API change in nix 0.27.x tcgetattr(fd: RawFd) changed to tcgetattr(fd: Fd), with RawFd not implementing AsFd. A similar change was applied to tcsetattr. --- src/uu/stty/src/stty.rs | 56 +++++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/src/uu/stty/src/stty.rs b/src/uu/stty/src/stty.rs index d55870730..669285750 100644 --- a/src/uu/stty/src/stty.rs +++ b/src/uu/stty/src/stty.rs @@ -14,10 +14,12 @@ use nix::sys::termios::{ OutputFlags, SpecialCharacterIndices, Termios, }; use nix::{ioctl_read_bad, ioctl_write_ptr_bad}; -use std::io::{self, stdout}; +use std::fs::File; +use std::io::{self, stdout, Stdout}; use std::ops::ControlFlow; +use std::os::fd::{AsFd, BorrowedFd}; use std::os::unix::fs::OpenOptionsExt; -use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd}; +use std::os::unix::io::{AsRawFd, RawFd}; use uucore::error::{UResult, USimpleError}; use uucore::{format_usage, help_about, help_usage}; @@ -91,10 +93,33 @@ mod options { struct Options<'a> { all: bool, save: bool, - file: RawFd, + file: Device, settings: Option>, } +enum Device { + File(File), + Stdout(Stdout), +} + +impl AsFd for Device { + fn as_fd(&self) -> BorrowedFd<'_> { + match self { + Self::File(f) => f.as_fd(), + Self::Stdout(stdout) => stdout.as_fd(), + } + } +} + +impl AsRawFd for Device { + fn as_raw_fd(&self) -> RawFd { + match self { + Self::File(f) => f.as_raw_fd(), + Self::Stdout(stdout) => stdout.as_raw_fd(), + } + } +} + impl<'a> Options<'a> { fn from(matches: &'a ArgMatches) -> io::Result { Ok(Self { @@ -110,12 +135,13 @@ impl<'a> Options<'a> { // will clean up the FD for us on exit, so it doesn't // matter. The alternative would be to have an enum of // BorrowedFd/OwnedFd to handle both cases. - Some(f) => std::fs::OpenOptions::new() - .read(true) - .custom_flags(O_NONBLOCK) - .open(f)? - .into_raw_fd(), - None => stdout().as_raw_fd(), + Some(f) => Device::File( + std::fs::OpenOptions::new() + .read(true) + .custom_flags(O_NONBLOCK) + .open(f)?, + ), + None => Device::Stdout(stdout()), }, settings: matches .get_many::(options::SETTINGS) @@ -175,7 +201,7 @@ fn stty(opts: &Options) -> UResult<()> { } // TODO: Figure out the right error message for when tcgetattr fails - let mut termios = tcgetattr(opts.file).expect("Could not get terminal attributes"); + let mut termios = tcgetattr(opts.file.as_fd()).expect("Could not get terminal attributes"); if let Some(settings) = &opts.settings { for setting in settings { @@ -187,8 +213,12 @@ fn stty(opts: &Options) -> UResult<()> { } } - tcsetattr(opts.file, nix::sys::termios::SetArg::TCSANOW, &termios) - .expect("Could not write terminal attributes"); + tcsetattr( + opts.file.as_fd(), + nix::sys::termios::SetArg::TCSANOW, + &termios, + ) + .expect("Could not write terminal attributes"); } else { print_settings(&termios, opts).expect("TODO: make proper error here from nix error"); } @@ -228,7 +258,7 @@ fn print_terminal_size(termios: &Termios, opts: &Options) -> nix::Result<()> { if opts.all { let mut size = TermSize::default(); - unsafe { tiocgwinsz(opts.file, &mut size as *mut _)? }; + unsafe { tiocgwinsz(opts.file.as_raw_fd(), &mut size as *mut _)? }; print!("rows {}; columns {}; ", size.rows, size.columns); }