Skip to content

Commit

Permalink
Migrate from libc to rustix.
Browse files Browse the repository at this point in the history
This migrates terminal_size from using libc directly to using rustix,
which eliminates a few unsafe blocks and manual error handling.

It does also add one new unsafe block, though this is because
`terminal_size_using_fd` is a public safe function that has a `RawFd`
argument. With [I/O safety], which is expected to be [stabilized in Rust 1.63],
there will be new guidance saying be that [such functions should be unsafe].
It's not urgent to make any changes for this right now though.

This also updates the minimum Rust version to 1.48, which is about as
old as the previous minimum Rust version was when it was last updated.

[I/O safety]: https://github.com/rust-lang/rfcs/blob/master/text/3128-io-safety.md
[stabilized in Rust 1.63]: rust-lang/rust#87074
[such functions should be unsafe]: https://doc.rust-lang.org/nightly/std/os/unix/io/index.html
  • Loading branch information
sunfishcode committed Jul 1, 2022
1 parent 0f36d74 commit 2d5c1a3
Showing 5 changed files with 19 additions and 23 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -10,8 +10,8 @@ license = "MIT OR Apache-2.0"
edition = "2018"


[target.'cfg(not(windows))'.dependencies.libc]
version = "0.2"
[target.'cfg(not(windows))'.dependencies]
rustix = { version = "0.35.6", features = ["termios"] }

[target.'cfg(windows)'.dependencies.winapi]
version = "0.3"
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@ if let Some((Width(w), Height(h))) = size {

## Minimum Rust Version

This crate requires a minimum rust version of 1.31.0 (2018-12-06)
This crate requires a minimum rust version of 1.48.0 (2020-11-19)

## License

8 changes: 5 additions & 3 deletions examples/get_size.rs
Original file line number Diff line number Diff line change
@@ -25,17 +25,19 @@ fn run() {

#[cfg(not(windows))]
fn run() {
use std::os::unix::io::AsRawFd;

println!(
"Size from terminal_size_using_fd(stdout): {:?}",
terminal_size::terminal_size_using_fd(libc::STDOUT_FILENO)
terminal_size::terminal_size_using_fd(std::io::stdout().as_raw_fd())
);
println!(
"Size from terminal_size_using_fd(stderr): {:?}",
terminal_size::terminal_size_using_fd(libc::STDERR_FILENO)
terminal_size::terminal_size_using_fd(std::io::stderr().as_raw_fd())
);
println!(
"Size from terminal_size_using_fd(stdin): {:?}",
terminal_size::terminal_size_using_fd(libc::STDIN_FILENO)
terminal_size::terminal_size_using_fd(std::io::stdin().as_raw_fd())
);
}

2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
//!
//! Supports both Linux, MacOS, and Windows.
//!
//! This crate requires a minimum rust version of 1.31.0 (2018-12-06)
//! This crate requires a minimum rust version of 1.48.0 (2020-11-19)
//!
//! # Example
//!
26 changes: 10 additions & 16 deletions src/unix.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,31 @@
use super::{Height, Width};
use std::os::unix::io::RawFd;
use rustix::fd::{BorrowedFd, AsRawFd};

/// Returns the size of the terminal defaulting to STDOUT, if available.
///
/// If STDOUT is not a tty, returns `None`
pub fn terminal_size() -> Option<(Width, Height)> {
terminal_size_using_fd(libc::STDOUT_FILENO)
terminal_size_using_fd(std::io::stdout().as_raw_fd())
}

/// Returns the size of the terminal using the given file descriptor, if available.
///
/// If the given file descriptor is not a tty, returns `None`
pub fn terminal_size_using_fd(fd: RawFd) -> Option<(Width, Height)> {
use libc::ioctl;
use libc::isatty;
use libc::{winsize as WinSize, TIOCGWINSZ};
let is_tty: bool = unsafe { isatty(fd) == 1 };
use rustix::termios::{isatty, tcgetwinsize};

if !is_tty {
return None;
}
// TODO: Once I/O safety is stabilized, the enlosing function here should
// be unsafe due to taking a `RawFd`. We should then move the main
// logic here into a new function which takes a `BorrowedFd` and is safe.
let fd = unsafe { BorrowedFd::borrow_raw(fd) };

let mut winsize = WinSize {
ws_row: 0,
ws_col: 0,
ws_xpixel: 0,
ws_ypixel: 0,
};

if unsafe { ioctl(fd, TIOCGWINSZ.into(), &mut winsize) } == -1 {
if !isatty(fd) {
return None;
}

let winsize = tcgetwinsize(fd).ok()?;

let rows = winsize.ws_row;
let cols = winsize.ws_col;

0 comments on commit 2d5c1a3

Please sign in to comment.