Skip to content

Commit

Permalink
posix_fallocate
Browse files Browse the repository at this point in the history
  • Loading branch information
dingxiangfei2009 committed Aug 20, 2019
1 parent 414cc86 commit bbd498d
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 0 deletions.
13 changes: 13 additions & 0 deletions src/fcntl.rs
Expand Up @@ -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<libc::c_int> {
let res = unsafe { libc::posix_fallocate(fd, offset, len) };
Errno::result(res)
}
53 changes: 53 additions & 0 deletions test/test_fcntl.rs
Expand Up @@ -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),
}
}
}

0 comments on commit bbd498d

Please sign in to comment.