Skip to content

Commit

Permalink
Clear CLOEXEC flag on FDs for temporary files
Browse files Browse the repository at this point in the history
All `System::open_tmpfile` implementations should consistently return a
file descriptor without the `O_CLOEXEC` flag set. Otherwise, it would
break callers that expect the file descriptor to be visible to the user.

Previously, the 'command exec retains redirection' test was failing
because the file descriptor to the temporary file containing the here-
document content was not visible to the command.
  • Loading branch information
magicant committed Apr 20, 2024
1 parent c5adaee commit 3662079
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 5 deletions.
1 change: 0 additions & 1 deletion yash-cli/tests/scripted_test/command-p.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ cat () { false; }
command cat </dev/null
__IN__

: TODO yash is broken <<\__OUT__
test_oE -e 0 'command exec retains redirection'
command exec 3<<\__END__
here
Expand Down
7 changes: 7 additions & 0 deletions yash-env/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ All notable changes to `yash-env` will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.1.1] - Unreleased

### Fixed

- `RealSystem::open_tmpfile` no longer returns a file descriptor with the
`O_CLOEXEC` flag set.

## [0.1.0] - 2024-04-13

### Added
Expand Down
12 changes: 8 additions & 4 deletions yash-env/src/system/real.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,10 +216,14 @@ impl System for RealSystem {
}

fn open_tmpfile(&mut self, parent_dir: &Path) -> Result<Fd> {
match tempfile::tempfile_in(parent_dir) {
Ok(file) => Ok(Fd(file.into_raw_fd())),
Err(error) => Err(Errno(error.raw_os_error().unwrap_or(0))),
}
let file = tempfile::tempfile_in(parent_dir)
.map_err(|errno| Errno(errno.raw_os_error().unwrap_or(0)))?;
let fd = Fd(file.into_raw_fd());

// Clear the CLOEXEC flag
_ = self.fcntl_setfd(fd, FdFlag::empty());

Ok(fd)
}

fn close(&mut self, fd: Fd) -> Result<()> {
Expand Down

0 comments on commit 3662079

Please sign in to comment.