1use crate::errno::Errno;
2use libc::{self, c_char, c_int, c_uint, size_t, ssize_t};
3use std::ffi::OsString;
4#[cfg(not(target_os = "redox"))]
5use std::os::raw;
6use std::os::unix::ffi::OsStringExt;
7use std::os::unix::io::RawFd;
8
9#[cfg(feature = "fs")]
10use crate::{sys::stat::Mode, NixPath, Result};
11#[cfg(any(target_os = "android", target_os = "linux"))]
12use std::ptr; #[cfg(any(
15 target_os = "linux",
16 target_os = "android",
17 target_os = "emscripten",
18 target_os = "fuchsia",
19 target_os = "wasi",
20 target_env = "uclibc",
21 target_os = "freebsd"
22))]
23#[cfg(feature = "fs")]
24pub use self::posix_fadvise::{posix_fadvise, PosixFadviseAdvice};
25
26#[cfg(not(target_os = "redox"))]
27#[cfg(any(feature = "fs", feature = "process"))]
28libc_bitflags! {
29 #[cfg_attr(docsrs, doc(cfg(any(feature = "fs", feature = "process"))))]
30 pub struct AtFlags: c_int {
31 AT_REMOVEDIR;
32 AT_SYMLINK_FOLLOW;
33 AT_SYMLINK_NOFOLLOW;
34 #[cfg(any(target_os = "android", target_os = "linux"))]
35 AT_NO_AUTOMOUNT;
36 #[cfg(any(target_os = "android", target_os = "linux"))]
37 AT_EMPTY_PATH;
38 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
39 AT_EACCESS;
40 }
41}
42
43#[cfg(any(feature = "fs", feature = "term"))]
44libc_bitflags!(
45 #[cfg_attr(docsrs, doc(cfg(any(feature = "fs", feature = "term"))))]
47 pub struct OFlag: c_int {
48 O_ACCMODE;
50 #[cfg(target_os = "netbsd")]
52 #[cfg_attr(docsrs, doc(cfg(all())))]
53 O_ALT_IO;
54 O_APPEND;
56 #[cfg(not(any(target_os = "illumos", target_os = "solaris", target_os = "haiku")))]
58 #[cfg_attr(docsrs, doc(cfg(all())))]
59 O_ASYNC;
60 O_CLOEXEC;
64 O_CREAT;
66 #[cfg(any(target_os = "android",
68 target_os = "dragonfly",
69 target_os = "freebsd",
70 target_os = "linux",
71 target_os = "netbsd"))]
72 #[cfg_attr(docsrs, doc(cfg(all())))]
73 O_DIRECT;
74 #[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
76 #[cfg_attr(docsrs, doc(cfg(all())))]
77 O_DIRECTORY;
78 #[cfg(any(target_os = "android",
80 target_os = "ios",
81 target_os = "linux",
82 target_os = "macos",
83 target_os = "netbsd",
84 target_os = "openbsd"))]
85 #[cfg_attr(docsrs, doc(cfg(all())))]
86 O_DSYNC;
87 O_EXCL;
89 #[cfg(target_os = "freebsd")]
91 #[cfg_attr(docsrs, doc(cfg(all())))]
92 O_EXEC;
93 #[cfg(any(target_os = "dragonfly",
95 target_os = "freebsd",
96 target_os = "ios",
97 target_os = "macos",
98 target_os = "netbsd",
99 target_os = "openbsd",
100 target_os = "redox"))]
101 #[cfg_attr(docsrs, doc(cfg(all())))]
102 O_EXLOCK;
103 #[cfg(any(target_os = "dragonfly",
105 target_os = "freebsd",
106 target_os = "ios",
107 all(target_os = "linux", not(target_env = "musl")),
108 target_os = "macos",
109 target_os = "netbsd",
110 target_os = "openbsd",
111 target_os = "redox"))]
112 #[cfg_attr(docsrs, doc(cfg(all())))]
113 O_FSYNC;
114 #[cfg(any(target_os = "android", target_os = "linux"))]
116 #[cfg_attr(docsrs, doc(cfg(all())))]
117 O_LARGEFILE;
118 #[cfg(any(target_os = "android", target_os = "linux"))]
120 #[cfg_attr(docsrs, doc(cfg(all())))]
121 O_NOATIME;
122 #[cfg(not(target_os = "redox"))]
124 #[cfg_attr(docsrs, doc(cfg(all())))]
125 O_NOCTTY;
126 #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
128 #[cfg_attr(docsrs, doc(cfg(all())))]
129 O_NDELAY;
130 O_NOFOLLOW;
132 O_NONBLOCK;
134 #[cfg(target_os = "netbsd")]
136 #[cfg_attr(docsrs, doc(cfg(all())))]
137 O_NOSIGPIPE;
138 #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
142 #[cfg_attr(docsrs, doc(cfg(all())))]
143 O_PATH;
144 O_RDONLY;
148 O_RDWR;
152 #[cfg(any(target_os = "linux", target_os = "netbsd", target_os = "openbsd"))]
154 #[cfg_attr(docsrs, doc(cfg(all())))]
155 O_RSYNC;
156 #[cfg(target_os = "netbsd")]
158 #[cfg_attr(docsrs, doc(cfg(all())))]
159 O_SEARCH;
160 #[cfg(any(target_os = "dragonfly",
162 target_os = "freebsd",
163 target_os = "ios",
164 target_os = "macos",
165 target_os = "netbsd",
166 target_os = "openbsd",
167 target_os = "redox"))]
168 #[cfg_attr(docsrs, doc(cfg(all())))]
169 O_SHLOCK;
170 #[cfg(not(target_os = "redox"))]
172 #[cfg_attr(docsrs, doc(cfg(all())))]
173 O_SYNC;
174 #[cfg(any(target_os = "android", target_os = "linux"))]
176 #[cfg_attr(docsrs, doc(cfg(all())))]
177 O_TMPFILE;
178 O_TRUNC;
180 #[cfg(target_os = "freebsd")]
182 #[cfg_attr(docsrs, doc(cfg(all())))]
183 O_TTY_INIT;
184 O_WRONLY;
188 }
189);
190
191feature! {
192#![feature = "fs"]
193
194#[allow(clippy::useless_conversion)]
196pub fn open<P: ?Sized + NixPath>(path: &P, oflag: OFlag, mode: Mode) -> Result<RawFd> {
197 let fd = path.with_nix_path(|cstr| {
198 unsafe { libc::open(cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint) }
199 })?;
200
201 Errno::result(fd)
202}
203
204#[allow(clippy::useless_conversion)]
206#[cfg(not(target_os = "redox"))]
207pub fn openat<P: ?Sized + NixPath>(
208 dirfd: RawFd,
209 path: &P,
210 oflag: OFlag,
211 mode: Mode,
212) -> Result<RawFd> {
213 let fd = path.with_nix_path(|cstr| {
214 unsafe { libc::openat(dirfd, cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint) }
215 })?;
216 Errno::result(fd)
217}
218
219#[cfg(not(target_os = "redox"))]
220pub fn renameat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
221 old_dirfd: Option<RawFd>,
222 old_path: &P1,
223 new_dirfd: Option<RawFd>,
224 new_path: &P2,
225) -> Result<()> {
226 let res = old_path.with_nix_path(|old_cstr| {
227 new_path.with_nix_path(|new_cstr| unsafe {
228 libc::renameat(
229 at_rawfd(old_dirfd),
230 old_cstr.as_ptr(),
231 at_rawfd(new_dirfd),
232 new_cstr.as_ptr(),
233 )
234 })
235 })??;
236 Errno::result(res).map(drop)
237}
238}
239
240#[cfg(all(target_os = "linux", target_env = "gnu",))]
241#[cfg(feature = "fs")]
242libc_bitflags! {
243 #[cfg_attr(docsrs, doc(cfg(feature = "fs")))]
244 pub struct RenameFlags: u32 {
245 RENAME_EXCHANGE;
246 RENAME_NOREPLACE;
247 RENAME_WHITEOUT;
248 }
249}
250
251feature! {
252#![feature = "fs"]
253#[cfg(all(
254 target_os = "linux",
255 target_env = "gnu",
256))]
257pub fn renameat2<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
258 old_dirfd: Option<RawFd>,
259 old_path: &P1,
260 new_dirfd: Option<RawFd>,
261 new_path: &P2,
262 flags: RenameFlags,
263) -> Result<()> {
264 let res = old_path.with_nix_path(|old_cstr| {
265 new_path.with_nix_path(|new_cstr| unsafe {
266 libc::renameat2(
267 at_rawfd(old_dirfd),
268 old_cstr.as_ptr(),
269 at_rawfd(new_dirfd),
270 new_cstr.as_ptr(),
271 flags.bits(),
272 )
273 })
274 })??;
275 Errno::result(res).map(drop)
276}
277
278fn wrap_readlink_result(mut v: Vec<u8>, len: ssize_t) -> Result<OsString> {
279 unsafe { v.set_len(len as usize) }
280 v.shrink_to_fit();
281 Ok(OsString::from_vec(v.to_vec()))
282}
283
284fn readlink_maybe_at<P: ?Sized + NixPath>(
285 dirfd: Option<RawFd>,
286 path: &P,
287 v: &mut Vec<u8>,
288) -> Result<libc::ssize_t> {
289 path.with_nix_path(|cstr| unsafe {
290 match dirfd {
291 #[cfg(target_os = "redox")]
292 Some(_) => unreachable!(),
293 #[cfg(not(target_os = "redox"))]
294 Some(dirfd) => libc::readlinkat(
295 dirfd,
296 cstr.as_ptr(),
297 v.as_mut_ptr() as *mut c_char,
298 v.capacity() as size_t,
299 ),
300 None => libc::readlink(
301 cstr.as_ptr(),
302 v.as_mut_ptr() as *mut c_char,
303 v.capacity() as size_t,
304 ),
305 }
306 })
307}
308
309fn inner_readlink<P: ?Sized + NixPath>(dirfd: Option<RawFd>, path: &P) -> Result<OsString> {
310 let mut v = Vec::with_capacity(libc::PATH_MAX as usize);
311 let res = readlink_maybe_at(dirfd, path, &mut v)?;
313 let len = Errno::result(res)?;
314 debug_assert!(len >= 0);
315 if (len as usize) < v.capacity() {
316 return wrap_readlink_result(v, res);
317 }
318 let reported_size = match dirfd {
321 #[cfg(target_os = "redox")]
322 Some(_) => unreachable!(),
323 #[cfg(any(target_os = "android", target_os = "linux"))]
324 Some(dirfd) => {
325 let flags = if path.is_empty() { AtFlags::AT_EMPTY_PATH } else { AtFlags::empty() };
326 super::sys::stat::fstatat(dirfd, path, flags | AtFlags::AT_SYMLINK_NOFOLLOW)
327 },
328 #[cfg(not(any(target_os = "android", target_os = "linux", target_os = "redox")))]
329 Some(dirfd) => super::sys::stat::fstatat(dirfd, path, AtFlags::AT_SYMLINK_NOFOLLOW),
330 None => super::sys::stat::lstat(path)
331 }
332 .map(|x| x.st_size)
333 .unwrap_or(0);
334 let mut try_size = if reported_size > 0 {
335 reported_size as usize + 1
338 } else {
339 (libc::PATH_MAX as usize).max(128) << 1
342 };
343 loop {
344 v.reserve_exact(try_size);
345 let res = readlink_maybe_at(dirfd, path, &mut v)?;
346 let len = Errno::result(res)?;
347 debug_assert!(len >= 0);
348 if (len as usize) < v.capacity() {
349 break wrap_readlink_result(v, res);
350 } else {
351 match try_size.checked_shl(1) {
353 Some(next_size) => try_size = next_size,
354 None => break Err(Errno::ENAMETOOLONG),
357 }
358 }
359 }
360}
361
362pub fn readlink<P: ?Sized + NixPath>(path: &P) -> Result<OsString> {
363 inner_readlink(None, path)
364}
365
366#[cfg(not(target_os = "redox"))]
367pub fn readlinkat<P: ?Sized + NixPath>(dirfd: RawFd, path: &P) -> Result<OsString> {
368 inner_readlink(Some(dirfd), path)
369}
370
371#[cfg(not(target_os = "redox"))]
373pub(crate) fn at_rawfd(fd: Option<RawFd>) -> raw::c_int {
374 match fd {
375 None => libc::AT_FDCWD,
376 Some(fd) => fd,
377 }
378}
379}
380
381#[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))]
382#[cfg(feature = "fs")]
383libc_bitflags!(
384 #[cfg_attr(docsrs, doc(cfg(feature = "fs")))]
386 pub struct SealFlag: c_int {
387 F_SEAL_SEAL;
389 F_SEAL_SHRINK;
391 F_SEAL_GROW;
393 F_SEAL_WRITE;
395 }
396);
397
398#[cfg(feature = "fs")]
399libc_bitflags!(
400 #[cfg_attr(docsrs, doc(cfg(feature = "fs")))]
402 pub struct FdFlag: c_int {
403 FD_CLOEXEC;
405 }
406);
407
408feature! {
409#![feature = "fs"]
410
411#[cfg(not(target_os = "redox"))]
412#[derive(Debug, Eq, Hash, PartialEq)]
413#[non_exhaustive]
414pub enum FcntlArg<'a> {
415 F_DUPFD(RawFd),
416 F_DUPFD_CLOEXEC(RawFd),
417 F_GETFD,
418 F_SETFD(FdFlag), F_GETFL,
420 F_SETFL(OFlag), F_SETLK(&'a libc::flock),
422 F_SETLKW(&'a libc::flock),
423 F_GETLK(&'a mut libc::flock),
424 #[cfg(any(target_os = "linux", target_os = "android"))]
425 F_OFD_SETLK(&'a libc::flock),
426 #[cfg(any(target_os = "linux", target_os = "android"))]
427 F_OFD_SETLKW(&'a libc::flock),
428 #[cfg(any(target_os = "linux", target_os = "android"))]
429 F_OFD_GETLK(&'a mut libc::flock),
430 #[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))]
431 F_ADD_SEALS(SealFlag),
432 #[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))]
433 F_GET_SEALS,
434 #[cfg(any(target_os = "macos", target_os = "ios"))]
435 F_FULLFSYNC,
436 #[cfg(any(target_os = "linux", target_os = "android"))]
437 F_GETPIPE_SZ,
438 #[cfg(any(target_os = "linux", target_os = "android"))]
439 F_SETPIPE_SZ(c_int),
440 }
442
443#[cfg(target_os = "redox")]
444#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
445#[non_exhaustive]
446pub enum FcntlArg {
447 F_DUPFD(RawFd),
448 F_DUPFD_CLOEXEC(RawFd),
449 F_GETFD,
450 F_SETFD(FdFlag), F_GETFL,
452 F_SETFL(OFlag), }
454pub use self::FcntlArg::*;
455
456pub fn fcntl(fd: RawFd, arg: FcntlArg) -> Result<c_int> {
458 let res = unsafe {
459 match arg {
460 F_DUPFD(rawfd) => libc::fcntl(fd, libc::F_DUPFD, rawfd),
461 F_DUPFD_CLOEXEC(rawfd) => libc::fcntl(fd, libc::F_DUPFD_CLOEXEC, rawfd),
462 F_GETFD => libc::fcntl(fd, libc::F_GETFD),
463 F_SETFD(flag) => libc::fcntl(fd, libc::F_SETFD, flag.bits()),
464 F_GETFL => libc::fcntl(fd, libc::F_GETFL),
465 F_SETFL(flag) => libc::fcntl(fd, libc::F_SETFL, flag.bits()),
466 #[cfg(not(target_os = "redox"))]
467 F_SETLK(flock) => libc::fcntl(fd, libc::F_SETLK, flock),
468 #[cfg(not(target_os = "redox"))]
469 F_SETLKW(flock) => libc::fcntl(fd, libc::F_SETLKW, flock),
470 #[cfg(not(target_os = "redox"))]
471 F_GETLK(flock) => libc::fcntl(fd, libc::F_GETLK, flock),
472 #[cfg(any(target_os = "android", target_os = "linux"))]
473 F_OFD_SETLK(flock) => libc::fcntl(fd, libc::F_OFD_SETLK, flock),
474 #[cfg(any(target_os = "android", target_os = "linux"))]
475 F_OFD_SETLKW(flock) => libc::fcntl(fd, libc::F_OFD_SETLKW, flock),
476 #[cfg(any(target_os = "android", target_os = "linux"))]
477 F_OFD_GETLK(flock) => libc::fcntl(fd, libc::F_OFD_GETLK, flock),
478 #[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))]
479 F_ADD_SEALS(flag) => libc::fcntl(fd, libc::F_ADD_SEALS, flag.bits()),
480 #[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))]
481 F_GET_SEALS => libc::fcntl(fd, libc::F_GET_SEALS),
482 #[cfg(any(target_os = "macos", target_os = "ios"))]
483 F_FULLFSYNC => libc::fcntl(fd, libc::F_FULLFSYNC),
484 #[cfg(any(target_os = "linux", target_os = "android"))]
485 F_GETPIPE_SZ => libc::fcntl(fd, libc::F_GETPIPE_SZ),
486 #[cfg(any(target_os = "linux", target_os = "android"))]
487 F_SETPIPE_SZ(size) => libc::fcntl(fd, libc::F_SETPIPE_SZ, size),
488 }
489 };
490
491 Errno::result(res)
492}
493
494#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
496#[non_exhaustive]
497pub enum FlockArg {
498 LockShared,
499 LockExclusive,
500 Unlock,
501 LockSharedNonblock,
502 LockExclusiveNonblock,
503 UnlockNonblock,
504}
505
506#[cfg(not(target_os = "redox"))]
507pub fn flock(fd: RawFd, arg: FlockArg) -> Result<()> {
508 use self::FlockArg::*;
509
510 let res = unsafe {
511 match arg {
512 LockShared => libc::flock(fd, libc::LOCK_SH),
513 LockExclusive => libc::flock(fd, libc::LOCK_EX),
514 Unlock => libc::flock(fd, libc::LOCK_UN),
515 LockSharedNonblock => libc::flock(fd, libc::LOCK_SH | libc::LOCK_NB),
516 LockExclusiveNonblock => libc::flock(fd, libc::LOCK_EX | libc::LOCK_NB),
517 UnlockNonblock => libc::flock(fd, libc::LOCK_UN | libc::LOCK_NB),
518 }
519 };
520
521 Errno::result(res).map(drop)
522}
523}
524
525#[cfg(any(target_os = "android", target_os = "linux"))]
526#[cfg(feature = "zerocopy")]
527libc_bitflags! {
528 #[cfg_attr(docsrs, doc(cfg(feature = "zerocopy")))]
530 pub struct SpliceFFlags: c_uint {
531 SPLICE_F_MOVE;
535 SPLICE_F_NONBLOCK;
537 SPLICE_F_MORE;
541 SPLICE_F_GIFT;
545 }
546}
547
548feature! {
549#![feature = "zerocopy"]
550
551#[cfg(any(target_os = "android", target_os = "linux"))]
568pub fn copy_file_range(
569 fd_in: RawFd,
570 off_in: Option<&mut libc::loff_t>,
571 fd_out: RawFd,
572 off_out: Option<&mut libc::loff_t>,
573 len: usize,
574) -> Result<usize> {
575 let off_in = off_in
576 .map(|offset| offset as *mut libc::loff_t)
577 .unwrap_or(ptr::null_mut());
578 let off_out = off_out
579 .map(|offset| offset as *mut libc::loff_t)
580 .unwrap_or(ptr::null_mut());
581
582 let ret = unsafe {
583 libc::syscall(
584 libc::SYS_copy_file_range,
585 fd_in,
586 off_in,
587 fd_out,
588 off_out,
589 len,
590 0,
591 )
592 };
593 Errno::result(ret).map(|r| r as usize)
594}
595
596#[cfg(any(target_os = "linux", target_os = "android"))]
597pub fn splice(
598 fd_in: RawFd,
599 off_in: Option<&mut libc::loff_t>,
600 fd_out: RawFd,
601 off_out: Option<&mut libc::loff_t>,
602 len: usize,
603 flags: SpliceFFlags,
604) -> Result<usize> {
605 let off_in = off_in
606 .map(|offset| offset as *mut libc::loff_t)
607 .unwrap_or(ptr::null_mut());
608 let off_out = off_out
609 .map(|offset| offset as *mut libc::loff_t)
610 .unwrap_or(ptr::null_mut());
611
612 let ret = unsafe { libc::splice(fd_in, off_in, fd_out, off_out, len, flags.bits()) };
613 Errno::result(ret).map(|r| r as usize)
614}
615
616#[cfg(any(target_os = "linux", target_os = "android"))]
617pub fn tee(fd_in: RawFd, fd_out: RawFd, len: usize, flags: SpliceFFlags) -> Result<usize> {
618 let ret = unsafe { libc::tee(fd_in, fd_out, len, flags.bits()) };
619 Errno::result(ret).map(|r| r as usize)
620}
621
622#[cfg(any(target_os = "linux", target_os = "android"))]
623pub fn vmsplice(
624 fd: RawFd,
625 iov: &[std::io::IoSlice<'_>],
626 flags: SpliceFFlags
627 ) -> Result<usize>
628{
629 let ret = unsafe {
630 libc::vmsplice(
631 fd,
632 iov.as_ptr() as *const libc::iovec,
633 iov.len(),
634 flags.bits(),
635 )
636 };
637 Errno::result(ret).map(|r| r as usize)
638}
639}
640
641#[cfg(any(target_os = "linux"))]
642#[cfg(feature = "fs")]
643libc_bitflags!(
644 #[cfg_attr(docsrs, doc(cfg(feature = "fs")))]
646 pub struct FallocateFlags: c_int {
647 FALLOC_FL_KEEP_SIZE;
651 FALLOC_FL_PUNCH_HOLE;
655 FALLOC_FL_COLLAPSE_RANGE;
659 FALLOC_FL_ZERO_RANGE;
663 FALLOC_FL_INSERT_RANGE;
667 FALLOC_FL_UNSHARE_RANGE;
671 }
672);
673
674feature! {
675#![feature = "fs"]
676
677#[cfg(any(target_os = "linux"))]
682#[cfg(feature = "fs")]
683pub fn fallocate(
684 fd: RawFd,
685 mode: FallocateFlags,
686 offset: libc::off_t,
687 len: libc::off_t,
688) -> Result<()> {
689 let res = unsafe { libc::fallocate(fd, mode.bits(), offset, len) };
690 Errno::result(res).map(drop)
691}
692
693#[cfg(any(target_os = "freebsd"))]
696#[derive(Clone, Copy, Debug, Eq, PartialEq)]
697pub struct SpacectlRange(pub libc::off_t, pub libc::off_t);
698
699#[cfg(any(target_os = "freebsd"))]
700impl SpacectlRange {
701 #[inline]
702 pub fn is_empty(&self) -> bool {
703 self.1 == 0
704 }
705
706 #[inline]
707 pub fn len(&self) -> libc::off_t {
708 self.1
709 }
710
711 #[inline]
712 pub fn offset(&self) -> libc::off_t {
713 self.0
714 }
715}
716
717#[cfg_attr(fbsd14, doc = " ```")]
739#[cfg_attr(not(fbsd14), doc = " ```no_run")]
740#[cfg(target_os = "freebsd")]
757pub fn fspacectl(fd: RawFd, range: SpacectlRange) -> Result<SpacectlRange> {
758 let mut rqsr = libc::spacectl_range{r_offset: range.0, r_len: range.1};
759 let res = unsafe { libc::fspacectl(
760 fd,
761 libc::SPACECTL_DEALLOC, &rqsr,
763 0, &mut rqsr
765 )};
766 Errno::result(res).map(|_| SpacectlRange(rqsr.r_offset, rqsr.r_len))
767}
768
769#[cfg_attr(fbsd14, doc = " ```")]
785#[cfg_attr(not(fbsd14), doc = " ```no_run")]
786#[cfg(target_os = "freebsd")]
800pub fn fspacectl_all(fd: RawFd, offset: libc::off_t, len: libc::off_t)
801 -> Result<()>
802{
803 let mut rqsr = libc::spacectl_range{r_offset: offset, r_len: len};
804 while rqsr.r_len > 0 {
805 let res = unsafe { libc::fspacectl(
806 fd,
807 libc::SPACECTL_DEALLOC, &rqsr,
809 0, &mut rqsr
811 )};
812 Errno::result(res)?;
813 }
814 Ok(())
815}
816
817#[cfg(any(
818 target_os = "linux",
819 target_os = "android",
820 target_os = "emscripten",
821 target_os = "fuchsia",
822 target_os = "wasi",
823 target_env = "uclibc",
824 target_os = "freebsd"
825))]
826mod posix_fadvise {
827 use crate::errno::Errno;
828 use std::os::unix::io::RawFd;
829 use crate::Result;
830
831 #[cfg(feature = "fs")]
832 libc_enum! {
833 #[repr(i32)]
834 #[non_exhaustive]
835 #[cfg_attr(docsrs, doc(cfg(feature = "fs")))]
836 pub enum PosixFadviseAdvice {
837 POSIX_FADV_NORMAL,
838 POSIX_FADV_SEQUENTIAL,
839 POSIX_FADV_RANDOM,
840 POSIX_FADV_NOREUSE,
841 POSIX_FADV_WILLNEED,
842 POSIX_FADV_DONTNEED,
843 }
844 }
845
846 feature! {
847 #![feature = "fs"]
848 pub fn posix_fadvise(
849 fd: RawFd,
850 offset: libc::off_t,
851 len: libc::off_t,
852 advice: PosixFadviseAdvice,
853 ) -> Result<()> {
854 let res = unsafe { libc::posix_fadvise(fd, offset, len, advice as libc::c_int) };
855
856 if res == 0 {
857 Ok(())
858 } else {
859 Err(Errno::from_i32(res))
860 }
861 }
862 }
863}
864
865#[cfg(any(
866 target_os = "linux",
867 target_os = "android",
868 target_os = "dragonfly",
869 target_os = "emscripten",
870 target_os = "fuchsia",
871 target_os = "wasi",
872 target_os = "freebsd"
873))]
874pub fn posix_fallocate(fd: RawFd, offset: libc::off_t, len: libc::off_t) -> Result<()> {
875 let res = unsafe { libc::posix_fallocate(fd, offset, len) };
876 match Errno::result(res) {
877 Err(err) => Err(err),
878 Ok(0) => Ok(()),
879 Ok(errno) => Err(Errno::from_i32(errno)),
880 }
881}
882}