From bbd498d38f4a90fde87253ab6cfb0b6eda890e93 Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Sun, 11 Aug 2019 15:20:44 +0800 Subject: [PATCH] posix_fallocate --- src/fcntl.rs | 13 ++++++++++++ test/test_fcntl.rs | 53 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/src/fcntl.rs b/src/fcntl.rs index be6ee0f73a..c78cd377fa 100644 --- a/src/fcntl.rs +++ b/src/fcntl.rs @@ -504,3 +504,16 @@ 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_env = "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) }; + Errno::result(res) +} diff --git a/test/test_fcntl.rs b/test/test_fcntl.rs index 6b2bbd679f..7dc7d35696 100644 --- a/test/test_fcntl.rs +++ b/test/test_fcntl.rs @@ -232,3 +232,56 @@ 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_env = "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 test_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).unwrap(); + if res == 0 { + let mut data = [1u8; LEN]; + assert_eq!(tmp.read(&mut data).expect("read failure"), LEN); + assert_eq!(&data as &[u8], &[0u8; LEN] as &[u8]); + } else { + match Errno::from_i32(res) { + Errno::EINVAL => { + eprintln!(r#" +`posix_fallocate` returned EINVAL. +According to POSIX.1-2008, its implementation shall return `EINVAL` if `len` is 0, `offset` is negative or the filesystem does not support this operation. +According to POSIX.1-2001, its implementation shall return `EINVAL` if `len` is negative, `offset` is negative or the filesystem does not support this operation; and may return `EINVAL` if `len` is 0. +However, this test is using `offset=0` and `len={}`. +Suppose that the host platform is POSIX-compliant, then this can only be due to an underlying filesystem on `/tmp` that does not support `posix_fallocate`. + +This test is passing by giving it the benefit of doubt. +"#, LEN as libc::off_t); + } + errno => panic!("unexpected errno={}", errno), + } + } + } + + #[test] + fn test_errno() { + let (rd, _wr) = pipe().unwrap(); + let errno = posix_fallocate(rd as RawFd, 0, 100).unwrap(); + match Errno::from_i32(errno) { + Errno::EINVAL | Errno::ENODEV | Errno::ESPIPE | Errno::EBADF => (), + errno => panic!("errno does not match posix_fallocate spec, errno={}", errno), + } + } +}