Skip to content

Commit 5abef55

Browse files
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>
2 parents 2b07f8d + 877afa1 commit 5abef55

File tree

3 files changed

+81
-0
lines changed

3 files changed

+81
-0
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
66
## [Unreleased] - ReleaseDate
77
### Added
88

9+
- Added `posix_fallocate`.
10+
([#1105](https://github.com/nix-rust/nix/pull/1105))
11+
912
- Implemented `Default` for `FdSet`
1013
([#1107](https://github.com/nix-rust/nix/pull/1107))
1114

src/fcntl.rs

+21
Original file line numberDiff line numberDiff line change
@@ -505,3 +505,24 @@ mod posix_fadvise {
505505
Errno::result(res)
506506
}
507507
}
508+
509+
#[cfg(any(
510+
target_os = "linux",
511+
target_os = "android",
512+
target_os = "emscripten",
513+
target_os = "fuchsia",
514+
any(target_os = "wasi", target_env = "wasi"),
515+
target_os = "freebsd"
516+
))]
517+
pub fn posix_fallocate(
518+
fd: RawFd,
519+
offset: libc::off_t,
520+
len: libc::off_t
521+
) -> Result<()> {
522+
let res = unsafe { libc::posix_fallocate(fd, offset, len) };
523+
match Errno::result(res) {
524+
Err(err) => Err(err),
525+
Ok(0) => Ok(()),
526+
Ok(errno) => Err(crate::Error::Sys(Errno::from_i32(errno))),
527+
}
528+
}

test/test_fcntl.rs

+57
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,60 @@ mod test_posix_fadvise {
231231
assert_eq!(errno, Errno::ESPIPE as i32);
232232
}
233233
}
234+
235+
#[cfg(any(target_os = "linux",
236+
target_os = "android",
237+
target_os = "emscripten",
238+
target_os = "fuchsia",
239+
any(target_os = "wasi", target_env = "wasi"),
240+
target_os = "freebsd"))]
241+
mod test_posix_fallocate {
242+
243+
use tempfile::NamedTempFile;
244+
use std::{io::Read, os::unix::io::{RawFd, AsRawFd}};
245+
use nix::errno::Errno;
246+
use nix::fcntl::*;
247+
use nix::unistd::pipe;
248+
249+
#[test]
250+
fn success() {
251+
const LEN: usize = 100;
252+
let mut tmp = NamedTempFile::new().unwrap();
253+
let fd = tmp.as_raw_fd();
254+
let res = posix_fallocate(fd, 0, LEN as libc::off_t);
255+
match res {
256+
Ok(_) => {
257+
let mut data = [1u8; LEN];
258+
assert_eq!(tmp.read(&mut data).expect("read failure"), LEN);
259+
assert_eq!(&data[..], &[0u8; LEN][..]);
260+
}
261+
Err(nix::Error::Sys(Errno::EINVAL)) => {
262+
// POSIX requires posix_fallocate to return EINVAL both for
263+
// invalid arguments (i.e. len < 0) and if the operation is not
264+
// supported by the file system.
265+
// There's no way to tell for sure whether the file system
266+
// supports posix_fallocate, so we must pass the test if it
267+
// returns EINVAL.
268+
}
269+
_ => res.unwrap(),
270+
}
271+
}
272+
273+
#[test]
274+
fn errno() {
275+
let (rd, _wr) = pipe().unwrap();
276+
let err = posix_fallocate(rd as RawFd, 0, 100).unwrap_err();
277+
use nix::Error::Sys;
278+
match err {
279+
Sys(Errno::EINVAL)
280+
| Sys(Errno::ENODEV)
281+
| Sys(Errno::ESPIPE)
282+
| Sys(Errno::EBADF) => (),
283+
errno =>
284+
panic!(
285+
"unexpected errno {}",
286+
errno,
287+
),
288+
}
289+
}
290+
}

0 commit comments

Comments
 (0)