Skip to content

Commit cf1f4ae

Browse files
posix_fallocate
1 parent 414cc86 commit cf1f4ae

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

src/fcntl.rs

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

test/test_fcntl.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,3 +232,68 @@ mod test_posix_fadvise {
232232
assert_eq!(errno, Errno::ESPIPE as i32);
233233
}
234234
}
235+
236+
#[cfg(any(target_os = "linux",
237+
target_os = "android",
238+
target_os = "emscripten",
239+
target_os = "fuchsia",
240+
any(target_os = "wasi", target_env = "wasi"),
241+
target_os = "freebsd"))]
242+
mod test_posix_fallocate {
243+
244+
use tempfile::NamedTempFile;
245+
use std::{io::Read, os::unix::io::{RawFd, AsRawFd}};
246+
use nix::errno::Errno;
247+
use nix::fcntl::*;
248+
use nix::unistd::pipe;
249+
250+
#[test]
251+
fn success() {
252+
const LEN: usize = 100;
253+
let mut tmp = NamedTempFile::new().unwrap();
254+
let fd = tmp.as_raw_fd();
255+
let res = posix_fallocate(fd, 0, LEN as libc::off_t);
256+
match res {
257+
Ok(_) => {
258+
let mut data = [1u8; LEN];
259+
assert_eq!(tmp.read(&mut data).expect("read failure"), LEN);
260+
assert_eq!(&data as &[u8], &[0u8; LEN] as &[u8]);
261+
}
262+
Err(nix::Error::Sys(Errno::EINVAL)) => {
263+
// `posix_fallocate` returned EINVAL.
264+
// According to POSIX.1-2008, its implementation shall
265+
// return `EINVAL` if `len` is 0, `offset` is negative or
266+
// the filesystem does not support this operation.
267+
// According to POSIX.1-2001, its implementation shall
268+
// return `EINVAL` if `len` is negative, `offset` is
269+
// negative or the filesystem does not support this
270+
// operation; and may return `EINVAL` if `len` is 0.
271+
// However, this test is using `offset=0` and non-zero
272+
// `len`.
273+
// Suppose that the host platform is POSIX-compliant,
274+
// then this can only be due to an underlying filesystem on
275+
// `/tmp` that does not support `posix_fallocate`.
276+
// This test is passing by giving it the benefit of doubt.
277+
}
278+
_ => res.unwrap(),
279+
}
280+
}
281+
282+
#[test]
283+
fn errno() {
284+
let (rd, _wr) = pipe().unwrap();
285+
let err = posix_fallocate(rd as RawFd, 0, 100).unwrap_err();
286+
use nix::Error::Sys;
287+
match err {
288+
Sys(Errno::EINVAL)
289+
| Sys(Errno::ENODEV)
290+
| Sys(Errno::ESPIPE)
291+
| Sys(Errno::EBADF) => (),
292+
errno =>
293+
panic!(
294+
"errno does not match posix_fallocate spec, errno={}",
295+
errno,
296+
),
297+
}
298+
}
299+
}

0 commit comments

Comments
 (0)