mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-11 12:35:26 +00:00
This change contains the results of running ./tools/contib/cargo_refactor.py This will break the next uprev, and needs to be synchronizized with the corresponding ebuild changes in https://crrev.com/c/3248925 BUG=b:195126527 TEST=./tools/run_tests Change-Id: Ied15a1841887bb8f59fba65b912b81acf69beb73 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3248129 Tested-by: kokoro <noreply+kokoro@google.com> Commit-Queue: Dennis Kempin <denniskempin@google.com> Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
96 lines
3.3 KiB
Rust
96 lines
3.3 KiB
Rust
// Copyright 2017 The Chromium OS Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
use std::io::Stdin;
|
|
use std::mem::zeroed;
|
|
use std::os::unix::io::RawFd;
|
|
|
|
use libc::{
|
|
isatty, read, tcgetattr, tcsetattr, termios, ECHO, ICANON, ISIG, O_NONBLOCK, STDIN_FILENO,
|
|
TCSANOW,
|
|
};
|
|
|
|
use crate::{add_fd_flags, clear_fd_flags, errno_result, Result};
|
|
|
|
fn modify_mode<F: FnOnce(&mut termios)>(fd: RawFd, f: F) -> Result<()> {
|
|
// Safe because we check the return value of isatty.
|
|
if unsafe { isatty(fd) } != 1 {
|
|
return Ok(());
|
|
}
|
|
|
|
// The following pair are safe because termios gets totally overwritten by tcgetattr and we
|
|
// check the return result.
|
|
let mut termios: termios = unsafe { zeroed() };
|
|
let ret = unsafe { tcgetattr(fd, &mut termios as *mut _) };
|
|
if ret < 0 {
|
|
return errno_result();
|
|
}
|
|
let mut new_termios = termios;
|
|
f(&mut new_termios);
|
|
// Safe because the syscall will only read the extent of termios and we check the return result.
|
|
let ret = unsafe { tcsetattr(fd, TCSANOW, &new_termios as *const _) };
|
|
if ret < 0 {
|
|
return errno_result();
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Safe only when the FD given is valid and reading the fd will have no Rust safety implications.
|
|
unsafe fn read_raw(fd: RawFd, out: &mut [u8]) -> Result<usize> {
|
|
let ret = read(fd, out.as_mut_ptr() as *mut _, out.len());
|
|
if ret < 0 {
|
|
return errno_result();
|
|
}
|
|
|
|
Ok(ret as usize)
|
|
}
|
|
|
|
/// Read raw bytes from stdin.
|
|
///
|
|
/// This will block depending on the underlying mode of stdin. This will ignore the usual lock
|
|
/// around stdin that the stdlib usually uses. If other code is using stdin, it is undefined who
|
|
/// will get the underlying bytes.
|
|
pub fn read_raw_stdin(out: &mut [u8]) -> Result<usize> {
|
|
// Safe because reading from stdin shouldn't have any safety implications.
|
|
unsafe { read_raw(STDIN_FILENO, out) }
|
|
}
|
|
|
|
/// Trait for file descriptors that are TTYs, according to `isatty(3)`.
|
|
///
|
|
/// This is marked unsafe because the implementation must promise that the returned RawFd is a valid
|
|
/// fd and that the lifetime of the returned fd is at least that of the trait object.
|
|
pub unsafe trait Terminal {
|
|
/// Gets the file descriptor of the TTY.
|
|
fn tty_fd(&self) -> RawFd;
|
|
|
|
/// Set this terminal's mode to canonical mode (`ICANON | ECHO | ISIG`).
|
|
fn set_canon_mode(&self) -> Result<()> {
|
|
modify_mode(self.tty_fd(), |t| t.c_lflag |= ICANON | ECHO | ISIG)
|
|
}
|
|
|
|
/// Set this terminal's mode to raw mode (`!(ICANON | ECHO | ISIG)`).
|
|
fn set_raw_mode(&self) -> Result<()> {
|
|
modify_mode(self.tty_fd(), |t| t.c_lflag &= !(ICANON | ECHO | ISIG))
|
|
}
|
|
|
|
/// Sets the non-blocking mode of this terminal's file descriptor.
|
|
///
|
|
/// If `non_block` is `true`, then `read_raw` will not block. If `non_block` is `false`, then
|
|
/// `read_raw` may block if there is nothing to read.
|
|
fn set_non_block(&self, non_block: bool) -> Result<()> {
|
|
if non_block {
|
|
add_fd_flags(self.tty_fd(), O_NONBLOCK)
|
|
} else {
|
|
clear_fd_flags(self.tty_fd(), O_NONBLOCK)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Safe because we return a genuine terminal fd that never changes and shares our lifetime.
|
|
unsafe impl Terminal for Stdin {
|
|
fn tty_fd(&self) -> RawFd {
|
|
STDIN_FILENO
|
|
}
|
|
}
|