Skip to content

Commit dcf57ba

Browse files
posix_fallocate
1 parent 1662466 commit dcf57ba

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
@@ -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

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,68 @@ 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 as &[u8], &[0u8; LEN] as &[u8]);
260+
}
261+
Err(nix::Error::Sys(Errno::EINVAL)) => {
262+
// `posix_fallocate` returned EINVAL.
263+
// According to POSIX.1-2008, its implementation shall
264+
// return `EINVAL` if `len` is 0, `offset` is negative or
265+
// the filesystem does not support this operation.
266+
// According to POSIX.1-2001, its implementation shall
267+
// return `EINVAL` if `len` is negative, `offset` is
268+
// negative or the filesystem does not support this
269+
// operation; and may return `EINVAL` if `len` is 0.
270+
// However, this test is using `offset=0` and non-zero
271+
// `len`.
272+
// Suppose that the host platform is POSIX-compliant,
273+
// then this can only be due to an underlying filesystem on
274+
// `/tmp` that does not support `posix_fallocate`.
275+
// This test is passing by giving it the benefit of doubt.
276+
}
277+
_ => res.unwrap(),
278+
}
279+
}
280+
281+
#[test]
282+
fn errno() {
283+
let (rd, _wr) = pipe().unwrap();
284+
let err = posix_fallocate(rd as RawFd, 0, 100).unwrap_err();
285+
use nix::Error::Sys;
286+
match err {
287+
Sys(Errno::EINVAL)
288+
| Sys(Errno::ENODEV)
289+
| Sys(Errno::ESPIPE)
290+
| Sys(Errno::EBADF) => (),
291+
errno =>
292+
panic!(
293+
"errno does not match posix_fallocate spec, errno={}",
294+
errno,
295+
),
296+
}
297+
}
298+
}

0 commit comments

Comments
 (0)