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
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 23 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -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

Expand Down
8 changes: 5 additions & 3 deletions examples/get_size.rs
Expand Up @@ -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())
);
}

Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Expand Up @@ -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
//!
Expand Down
26 changes: 10 additions & 16 deletions src/unix.rs
@@ -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;

Expand Down

0 comments on commit 2d5c1a3

Please sign in to comment.