Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd61c41f

Browse files
committed
fix: detect closed stdin before Rust sanitizes it to /dev/null
1 parentc085cd1 commitd61c41f

File tree

11 files changed

+173
-37
lines changed

11 files changed

+173
-37
lines changed

‎Cargo.lock‎

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎src/uu/dd/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ uucore = { workspace = true, features = [
2626
"parser-size",
2727
"quoting-style",
2828
"fs",
29+
"signals",
2930
] }
3031
thiserror = {workspace =true }
3132
fluent = {workspace =true }

‎src/uu/dd/src/dd.rs‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55

66
// spell-checker:ignore fname, ftype, tname, fpath, specfile, testfile, unspec, ifile, ofile, outfile, fullblock, urand, fileio, atoe, atoibm, behaviour, bmax, bremain, cflags, creat, ctable, ctty, datastructures, doesnt, etoa, fileout, fname, gnudd, iconvflags, iseek, nocache, noctty, noerror, nofollow, nolinks, nonblock, oconvflags, oseek, outfile, parseargs, rlen, rmax, rremain, rsofar, rstat, sigusr, wlen, wstat seekable oconv canonicalized fadvise Fadvise FADV DONTNEED ESPIPE bufferedoutput, SETFL
77

8+
#[cfg(unix)]
9+
uucore::init_stdio_state_capture!();
10+
811
mod blocks;
912
mod bufferedoutput;
1013
mod conversion_tables;
@@ -1485,6 +1488,11 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
14851488
.unwrap_or_default(),
14861489
)?;
14871490

1491+
#[cfg(unix)]
1492+
if uucore::signals::stderr_was_closed() && settings.status !=Some(StatusLevel::None){
1493+
returnErr(USimpleError::new(1,"write error"));
1494+
}
1495+
14881496
let i =match settings.infile{
14891497
#[cfg(unix)]
14901498
Some(ref infile)ifis_fifo(infile) =>Input::new_fifo(Path::new(&infile),&settings)?,

‎src/uu/dd/src/progress.rs‎

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use std::time::Duration;
1818
#[cfg(target_os ="linux")]
1919
use signal_hook::iterator::Handle;
2020
use uucore::{
21-
error::UResult,
21+
error::{UResult, set_exit_code},
2222
format::num_format::{FloatVariant,Formatter},
2323
locale::setup_localization,
2424
translate,
@@ -231,7 +231,9 @@ impl ProgUpdate {
231231
/// See [`ProgUpdate::write_io_lines`] for more information.
232232
pub(crate)fnprint_io_lines(&self){
233233
letmut stderr = std::io::stderr();
234-
self.write_io_lines(&mut stderr).unwrap();
234+
ifself.write_io_lines(&mut stderr).is_err(){
235+
set_exit_code(1);
236+
}
235237
}
236238

237239
/// Re-print the number of bytes written, duration, and throughput.
@@ -240,15 +242,19 @@ impl ProgUpdate {
240242
pub(crate)fnreprint_prog_line(&self){
241243
letmut stderr = std::io::stderr();
242244
let rewrite =true;
243-
self.write_prog_line(&mut stderr, rewrite).unwrap();
245+
ifself.write_prog_line(&mut stderr, rewrite).is_err(){
246+
set_exit_code(1);
247+
}
244248
}
245249

246250
/// Write all summary statistics.
247251
///
248252
/// See [`ProgUpdate::write_transfer_stats`] for more information.
249253
pub(crate)fnprint_transfer_stats(&self,new_line:bool){
250254
letmut stderr = std::io::stderr();
251-
self.write_transfer_stats(&mut stderr, new_line).unwrap();
255+
ifself.write_transfer_stats(&mut stderr, new_line).is_err(){
256+
set_exit_code(1);
257+
}
252258
}
253259

254260
/// Write all the final statistics.

‎src/uu/tac/Cargo.toml‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ memchr = { workspace = true }
2424
memmap2 = {workspace =true }
2525
regex = {workspace =true }
2626
clap = {workspace =true }
27-
uucore = {workspace =true }
27+
libc = {workspace =true }
28+
uucore = {workspace =true,features = ["signals"] }
2829
thiserror = {workspace =true }
2930
fluent = {workspace =true }
3031

‎src/uu/tac/src/tac.rs‎

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
// file that was distributed with this source code.
55

66
// spell-checker:ignore (ToDO) sbytes slen dlen memmem memmap Mmap mmap SIGBUS
7+
#[cfg(unix)]
8+
uucore::init_stdio_state_capture!();
9+
710
mod error;
811

912
use clap::{Arg,ArgAction,Command};
@@ -15,8 +18,7 @@ use std::{
1518
fs::{File, read},
1619
path::Path,
1720
};
18-
use uucore::error::UError;
19-
use uucore::error::UResult;
21+
use uucore::error::{UError,UResult, set_exit_code};
2022
use uucore::{format_usage, show};
2123

2224
usecrate::error::TacError;
@@ -237,6 +239,17 @@ fn tac(filenames: &[OsString], before: bool, regex: bool, separator: &str) -> UR
237239
let buf;
238240

239241
let data:&[u8] =if filename =="-"{
242+
#[cfg(unix)]
243+
if uucore::signals::stdin_was_closed(){
244+
let e:Box<dynUError> =TacError::ReadError(
245+
OsString::from("-"),
246+
std::io::Error::from_raw_os_error(libc::EBADF),
247+
)
248+
.into();
249+
show!(e);
250+
set_exit_code(1);
251+
continue;
252+
}
240253
ifletSome(mmap1) =try_mmap_stdin(){
241254
mmap = mmap1;
242255
&mmap

‎src/uu/tail/Cargo.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ clap = { workspace = true }
2323
libc = {workspace =true }
2424
memchr = {workspace =true }
2525
notify = {workspace =true }
26-
uucore = {workspace =true,features = ["fs","parser-size"] }
26+
uucore = {workspace =true,features = ["fs","parser-size","signals"] }
2727
same-file = {workspace =true }
2828
fluent = {workspace =true }
2929

‎src/uu/tail/src/paths.rs‎

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -229,14 +229,13 @@ pub fn path_is_tailable(path: &Path) -> bool {
229229
}
230230

231231
#[inline]
232+
#[cfg(unix)]
233+
pubfnstdin_is_bad_fd() ->bool{
234+
uucore::signals::stdin_was_closed()
235+
}
236+
237+
#[inline]
238+
#[cfg(not(unix))]
232239
pubfnstdin_is_bad_fd() ->bool{
233-
// FIXME : Rust's stdlib is reopening fds as /dev/null
234-
// see also: https://github.com/uutils/coreutils/issues/2873
235-
// (gnu/tests/tail-2/follow-stdin.sh fails because of this)
236-
//#[cfg(unix)]
237-
{
238-
//platform::stdin_is_bad_fd()
239-
}
240-
//#[cfg(not(unix))]
241240
false
242241
}

‎src/uu/tail/src/tail.rs‎

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,14 @@ use std::fs::File;
3333
use std::io::{self,BufReader,BufWriter,ErrorKind,Read,Seek,SeekFrom,Write, stdin, stdout};
3434
use std::path::{Path,PathBuf};
3535
use uucore::display::Quotable;
36-
use uucore::error::{FromIo,UResult,USimpleError,get_exit_code,set_exit_code};
36+
use uucore::error::{FromIo,UResult,USimpleError, set_exit_code};
3737
use uucore::translate;
3838

3939
use uucore::{show, show_error};
4040

41+
#[cfg(unix)]
42+
uucore::init_stdio_state_capture!();
43+
4144
#[uucore::main]
4245
pubfnuumain(args:impl uucore::Args) ->UResult<()>{
4346
// When we receive a SIGPIPE signal, we want to terminate the process so
@@ -105,10 +108,6 @@ fn uu_tail(settings: &Settings) -> UResult<()> {
105108
}
106109
}
107110

108-
ifget_exit_code() >0 && paths::stdin_is_bad_fd(){
109-
show_error!("{}: {}", text::DASH, translate!("tail-bad-fd"));
110-
}
111-
112111
Ok(())
113112
}
114113

@@ -227,6 +226,17 @@ fn tail_stdin(
227226
}
228227
}
229228

229+
// Check if stdin was closed before Rust reopened it as /dev/null
230+
if paths::stdin_is_bad_fd(){
231+
set_exit_code(1);
232+
show_error!(
233+
"{}",
234+
translate!("tail-error-cannot-fstat","file" => translate!("tail-stdin-header").quote(),"error" => translate!("tail-bad-fd"))
235+
);
236+
show_error!("{}", translate!("tail-no-files-remaining"));
237+
returnOk(());
238+
}
239+
230240
match input.resolve(){
231241
// fifo
232242
Some(path) =>{

‎src/uu/timeout/src/timeout.rs‎

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@
44
// file that was distributed with this source code.
55

66
// spell-checker:ignore (ToDO) tstr sigstr cmdname setpgid sigchld getpid
7+
#[cfg(unix)]
8+
uucore::init_stdio_state_capture!();
9+
710
mod status;
811

912
usecrate::status::ExitStatus;
1013
use clap::{Arg,ArgAction,Command};
1114
use std::io::ErrorKind;
12-
use std::os::unix::process::ExitStatusExt;
15+
use std::os::unix::process::{CommandExt,ExitStatusExt};
1316
use std::process::{self,Child,Stdio};
1417
use std::sync::atomic::{self,AtomicBool};
1518
use std::time::Duration;
@@ -320,23 +323,34 @@ fn timeout(
320323
#[cfg(unix)]
321324
enable_pipe_errors()?;
322325

323-
let process =&mut process::Command::new(&cmd[0])
326+
letmut command = process::Command::new(&cmd[0]);
327+
command
324328
.args(&cmd[1..])
325329
.stdin(Stdio::inherit())
326330
.stdout(Stdio::inherit())
327-
.stderr(Stdio::inherit())
328-
.spawn()
329-
.map_err(|err|{
330-
let status_code =match err.kind(){
331-
ErrorKind::NotFound =>ExitStatus::CommandNotFound.into(),
332-
ErrorKind::PermissionDenied =>ExitStatus::CannotInvoke.into(),
333-
_ =>ExitStatus::CannotInvoke.into(),
334-
};
335-
USimpleError::new(
336-
status_code,
337-
translate!("timeout-error-failed-to-execute-process","error" => err),
338-
)
339-
})?;
331+
.stderr(Stdio::inherit());
332+
333+
// If stdin was closed before Rust reopened it as /dev/null, close it in child
334+
if uucore::signals::stdin_was_closed(){
335+
unsafe{
336+
command.pre_exec(||{
337+
libc::close(libc::STDIN_FILENO);
338+
Ok(())
339+
});
340+
}
341+
}
342+
343+
let process =&mut command.spawn().map_err(|err|{
344+
let status_code =match err.kind(){
345+
ErrorKind::NotFound =>ExitStatus::CommandNotFound.into(),
346+
ErrorKind::PermissionDenied =>ExitStatus::CannotInvoke.into(),
347+
_ =>ExitStatus::CannotInvoke.into(),
348+
};
349+
USimpleError::new(
350+
status_code,
351+
translate!("timeout-error-failed-to-execute-process","error" => err),
352+
)
353+
})?;
340354
unblock_sigchld();
341355
catch_sigterm();
342356
// Wait for the child process for the specified time period.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp