#![stable(feature = "rust1", since = "1.0.0")]
use super::platform::fs::MetadataExt as _;
use crate::fs::{self, OpenOptions, Permissions};
use crate::io;
use crate::os::unix::io::{AsFd, AsRawFd};
use crate::path::Path;
use crate::sys;
use crate::sys_common::{AsInner, AsInnerMut, FromInner};
use crate::ffi::OsStr;
use crate::sealed::Sealed;
#[allow(unused_imports)]
use io::{Read, Write};
#[cfg(test)]
mod tests;
#[stable(feature = "file_offset", since = "1.15.0")]
pub trait FileExt {
#[stable(feature = "file_offset", since = "1.15.0")]
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
#[unstable(feature = "unix_file_vectored_at", issue = "89517")]
fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
io::default_read_vectored(|b| self.read_at(b, offset), bufs)
}
#[stable(feature = "rw_exact_all_at", since = "1.33.0")]
fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> {
while !buf.is_empty() {
match self.read_at(buf, offset) {
Ok(0) => break,
Ok(n) => {
let tmp = buf;
buf = &mut tmp[n..];
offset += n as u64;
}
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
if !buf.is_empty() {
Err(io::const_io_error!(io::ErrorKind::UnexpectedEof, "failed to fill whole buffer",))
} else {
Ok(())
}
}
#[stable(feature = "file_offset", since = "1.15.0")]
fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
#[unstable(feature = "unix_file_vectored_at", issue = "89517")]
fn write_vectored_at(&self, bufs: &[io::IoSlice<'_>], offset: u64) -> io::Result<usize> {
io::default_write_vectored(|b| self.write_at(b, offset), bufs)
}
#[stable(feature = "rw_exact_all_at", since = "1.33.0")]
fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> {
while !buf.is_empty() {
match self.write_at(buf, offset) {
Ok(0) => {
return Err(io::const_io_error!(
io::ErrorKind::WriteZero,
"failed to write whole buffer",
));
}
Ok(n) => {
buf = &buf[n..];
offset += n as u64
}
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
Ok(())
}
}
#[stable(feature = "file_offset", since = "1.15.0")]
impl FileExt for fs::File {
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
self.as_inner().read_at(buf, offset)
}
fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
self.as_inner().read_vectored_at(bufs, offset)
}
fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
self.as_inner().write_at(buf, offset)
}
fn write_vectored_at(&self, bufs: &[io::IoSlice<'_>], offset: u64) -> io::Result<usize> {
self.as_inner().write_vectored_at(bufs, offset)
}
}
#[stable(feature = "fs_ext", since = "1.1.0")]
pub trait PermissionsExt {
#[stable(feature = "fs_ext", since = "1.1.0")]
fn mode(&self) -> u32;
#[stable(feature = "fs_ext", since = "1.1.0")]
fn set_mode(&mut self, mode: u32);
#[stable(feature = "fs_ext", since = "1.1.0")]
fn from_mode(mode: u32) -> Self;
}
#[stable(feature = "fs_ext", since = "1.1.0")]
impl PermissionsExt for Permissions {
fn mode(&self) -> u32 {
self.as_inner().mode()
}
fn set_mode(&mut self, mode: u32) {
*self = Permissions::from_inner(FromInner::from_inner(mode));
}
fn from_mode(mode: u32) -> Permissions {
Permissions::from_inner(FromInner::from_inner(mode))
}
}
#[stable(feature = "fs_ext", since = "1.1.0")]
pub trait OpenOptionsExt {
#[stable(feature = "fs_ext", since = "1.1.0")]
fn mode(&mut self, mode: u32) -> &mut Self;
#[stable(feature = "open_options_ext", since = "1.10.0")]
fn custom_flags(&mut self, flags: i32) -> &mut Self;
}
#[stable(feature = "fs_ext", since = "1.1.0")]
impl OpenOptionsExt for OpenOptions {
fn mode(&mut self, mode: u32) -> &mut OpenOptions {
self.as_inner_mut().mode(mode);
self
}
fn custom_flags(&mut self, flags: i32) -> &mut OpenOptions {
self.as_inner_mut().custom_flags(flags);
self
}
}
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn dev(&self) -> u64;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn ino(&self) -> u64;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn mode(&self) -> u32;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn nlink(&self) -> u64;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn uid(&self) -> u32;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn gid(&self) -> u32;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn rdev(&self) -> u64;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn size(&self) -> u64;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn atime(&self) -> i64;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn atime_nsec(&self) -> i64;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn mtime(&self) -> i64;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn mtime_nsec(&self) -> i64;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn ctime(&self) -> i64;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn ctime_nsec(&self) -> i64;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn blksize(&self) -> u64;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn blocks(&self) -> u64;
#[cfg(target_os = "vxworks")]
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn attrib(&self) -> u8;
}
#[stable(feature = "metadata_ext", since = "1.1.0")]
impl MetadataExt for fs::Metadata {
fn dev(&self) -> u64 {
self.st_dev()
}
fn ino(&self) -> u64 {
self.st_ino()
}
fn mode(&self) -> u32 {
self.st_mode()
}
fn nlink(&self) -> u64 {
self.st_nlink()
}
fn uid(&self) -> u32 {
self.st_uid()
}
fn gid(&self) -> u32 {
self.st_gid()
}
fn rdev(&self) -> u64 {
self.st_rdev()
}
fn size(&self) -> u64 {
self.st_size()
}
fn atime(&self) -> i64 {
self.st_atime()
}
fn atime_nsec(&self) -> i64 {
self.st_atime_nsec()
}
fn mtime(&self) -> i64 {
self.st_mtime()
}
fn mtime_nsec(&self) -> i64 {
self.st_mtime_nsec()
}
fn ctime(&self) -> i64 {
self.st_ctime()
}
fn ctime_nsec(&self) -> i64 {
self.st_ctime_nsec()
}
fn blksize(&self) -> u64 {
self.st_blksize()
}
fn blocks(&self) -> u64 {
self.st_blocks()
}
#[cfg(target_os = "vxworks")]
fn attrib(&self) -> u8 {
self.st_attrib()
}
}
#[stable(feature = "file_type_ext", since = "1.5.0")]
pub trait FileTypeExt {
#[stable(feature = "file_type_ext", since = "1.5.0")]
fn is_block_device(&self) -> bool;
#[stable(feature = "file_type_ext", since = "1.5.0")]
fn is_char_device(&self) -> bool;
#[stable(feature = "file_type_ext", since = "1.5.0")]
fn is_fifo(&self) -> bool;
#[stable(feature = "file_type_ext", since = "1.5.0")]
fn is_socket(&self) -> bool;
}
#[stable(feature = "file_type_ext", since = "1.5.0")]
impl FileTypeExt for fs::FileType {
fn is_block_device(&self) -> bool {
self.as_inner().is(libc::S_IFBLK)
}
fn is_char_device(&self) -> bool {
self.as_inner().is(libc::S_IFCHR)
}
fn is_fifo(&self) -> bool {
self.as_inner().is(libc::S_IFIFO)
}
fn is_socket(&self) -> bool {
self.as_inner().is(libc::S_IFSOCK)
}
}
#[stable(feature = "dir_entry_ext", since = "1.1.0")]
pub trait DirEntryExt {
#[stable(feature = "dir_entry_ext", since = "1.1.0")]
fn ino(&self) -> u64;
}
#[stable(feature = "dir_entry_ext", since = "1.1.0")]
impl DirEntryExt for fs::DirEntry {
fn ino(&self) -> u64 {
self.as_inner().ino()
}
}
#[unstable(feature = "dir_entry_ext2", issue = "85573")]
pub trait DirEntryExt2: Sealed {
fn file_name_ref(&self) -> &OsStr;
}
#[unstable(feature = "sealed", issue = "none")]
impl Sealed for fs::DirEntry {}
#[unstable(feature = "dir_entry_ext2", issue = "85573")]
impl DirEntryExt2 for fs::DirEntry {
fn file_name_ref(&self) -> &OsStr {
self.as_inner().file_name_os_str()
}
}
#[stable(feature = "symlink", since = "1.1.0")]
pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
sys::fs::symlink(original.as_ref(), link.as_ref())
}
#[stable(feature = "dir_builder", since = "1.6.0")]
pub trait DirBuilderExt {
#[stable(feature = "dir_builder", since = "1.6.0")]
fn mode(&mut self, mode: u32) -> &mut Self;
}
#[stable(feature = "dir_builder", since = "1.6.0")]
impl DirBuilderExt for fs::DirBuilder {
fn mode(&mut self, mode: u32) -> &mut fs::DirBuilder {
self.as_inner_mut().set_mode(mode);
self
}
}
#[unstable(feature = "unix_chown", issue = "88989")]
pub fn chown<P: AsRef<Path>>(dir: P, uid: Option<u32>, gid: Option<u32>) -> io::Result<()> {
sys::fs::chown(dir.as_ref(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX))
}
#[unstable(feature = "unix_chown", issue = "88989")]
pub fn fchown<F: AsFd>(fd: F, uid: Option<u32>, gid: Option<u32>) -> io::Result<()> {
sys::fs::fchown(fd.as_fd().as_raw_fd(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX))
}
#[unstable(feature = "unix_chown", issue = "88989")]
pub fn lchown<P: AsRef<Path>>(dir: P, uid: Option<u32>, gid: Option<u32>) -> io::Result<()> {
sys::fs::lchown(dir.as_ref(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX))
}
#[stable(feature = "unix_chroot", since = "1.56.0")]
#[cfg(not(any(target_os = "fuchsia", target_os = "vxworks")))]
pub fn chroot<P: AsRef<Path>>(dir: P) -> io::Result<()> {
sys::fs::chroot(dir.as_ref())
}