Skip to content

Commit

Permalink
Merge #1105
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
bors[bot] and dingxiangfei2009 committed Sep 28, 2019
2 parents 2b07f8d + 877afa1 commit 5abef55
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 0 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Expand Up @@ -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))

Expand Down
21 changes: 21 additions & 0 deletions src/fcntl.rs
Expand Up @@ -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))),
}
}
57 changes: 57 additions & 0 deletions test/test_fcntl.rs
Expand Up @@ -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,
),
}
}
}

0 comments on commit 5abef55

Please sign in to comment.