diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-09-28 16:10:22 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-09-28 16:10:22 +0000 |
commit | 5abef55ea3a9851cd6e83717112126b5df860cde (patch) | |
tree | 19bef9379e103fe70793a3451477c9e76cb918cb | |
parent | 2b07f8d84a03af7208dc08e0687bbea4653a8395 (diff) | |
parent | 877afa11f557a256c0d04c04f6fed14c8aa6b51d (diff) | |
download | nix-5abef55ea3a9851cd6e83717112126b5df860cde.zip |
Merge #1105
1105: posix_fallocate support r=asomers a=dingxiangfei2009
This PR add [`posix_fallocate`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_fallocate.html), which is available on
- Linux
- FreeBSD
- Android
- Emscripten
- Fuchsia
- WASI
Here is a question: for some reason, `posix_fallocate` returns `EBADF` instead of `EPIPE` if a FIFO file descriptor is passed in on Linux 4.19.64. In the test `EBADF` is used for now, but I would like to know if such behaviour is expected.
Co-authored-by: Ding Xiang Fei <dingxiangfei2009@gmail.com>
-rw-r--r-- | CHANGELOG.md | 3 | ||||
-rw-r--r-- | src/fcntl.rs | 21 | ||||
-rw-r--r-- | test/test_fcntl.rs | 57 |
3 files changed, 81 insertions, 0 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index af2069a0..74ecba0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] - ReleaseDate ### Added +- Added `posix_fallocate`. + ([#1105](https://github.com/nix-rust/nix/pull/1105)) + - Implemented `Default` for `FdSet` ([#1107](https://github.com/nix-rust/nix/pull/1107)) diff --git a/src/fcntl.rs b/src/fcntl.rs index 2cb7f505..7d745b06 100644 --- a/src/fcntl.rs +++ b/src/fcntl.rs @@ -505,3 +505,24 @@ mod posix_fadvise { Errno::result(res) } } + +#[cfg(any( + target_os = "linux", + target_os = "android", + target_os = "emscripten", + target_os = "fuchsia", + any(target_os = "wasi", target_env = "wasi"), + target_os = "freebsd" +))] +pub fn posix_fallocate( + fd: RawFd, + offset: libc::off_t, + len: libc::off_t +) -> Result<()> { + let res = unsafe { libc::posix_fallocate(fd, offset, len) }; + match Errno::result(res) { + Err(err) => Err(err), + Ok(0) => Ok(()), + Ok(errno) => Err(crate::Error::Sys(Errno::from_i32(errno))), + } +} diff --git a/test/test_fcntl.rs b/test/test_fcntl.rs index 1bcf12cb..38a1e7b9 100644 --- a/test/test_fcntl.rs +++ b/test/test_fcntl.rs @@ -231,3 +231,60 @@ mod test_posix_fadvise { assert_eq!(errno, Errno::ESPIPE as i32); } } + +#[cfg(any(target_os = "linux", + target_os = "android", + target_os = "emscripten", + target_os = "fuchsia", + any(target_os = "wasi", target_env = "wasi"), + target_os = "freebsd"))] +mod test_posix_fallocate { + + use tempfile::NamedTempFile; + use std::{io::Read, os::unix::io::{RawFd, AsRawFd}}; + use nix::errno::Errno; + use nix::fcntl::*; + use nix::unistd::pipe; + + #[test] + fn success() { + const LEN: usize = 100; + let mut tmp = NamedTempFile::new().unwrap(); + let fd = tmp.as_raw_fd(); + let res = posix_fallocate(fd, 0, LEN as libc::off_t); + match res { + Ok(_) => { + let mut data = [1u8; LEN]; + assert_eq!(tmp.read(&mut data).expect("read failure"), LEN); + assert_eq!(&data[..], &[0u8; LEN][..]); + } + Err(nix::Error::Sys(Errno::EINVAL)) => { + // POSIX requires posix_fallocate to return EINVAL both for + // invalid arguments (i.e. len < 0) and if the operation is not + // supported by the file system. + // There's no way to tell for sure whether the file system + // supports posix_fallocate, so we must pass the test if it + // returns EINVAL. + } + _ => res.unwrap(), + } + } + + #[test] + fn errno() { + let (rd, _wr) = pipe().unwrap(); + let err = posix_fallocate(rd as RawFd, 0, 100).unwrap_err(); + use nix::Error::Sys; + match err { + Sys(Errno::EINVAL) + | Sys(Errno::ENODEV) + | Sys(Errno::ESPIPE) + | Sys(Errno::EBADF) => (), + errno => + panic!( + "unexpected errno {}", + errno, + ), + } + } +} |