| //! Unix-specific extensions to primitives in the `std::fs` module. |
| |
| #![stable(feature = "rust1", since = "1.0.0")] |
| |
| use super::platform::fs::MetadataExt as _; |
| use crate::fs::{self, OpenOptions, Permissions}; |
| use crate::io; |
| use crate::path::Path; |
| use crate::sys; |
| use crate::sys_common::{AsInner, AsInnerMut, FromInner}; |
| // Used for `File::read` on intra-doc links |
| use crate::ffi::OsStr; |
| use crate::sealed::Sealed; |
| #[allow(unused_imports)] |
| use io::{Read, Write}; |
| |
| /// Unix-specific extensions to [`fs::File`]. |
| #[stable(feature = "file_offset", since = "1.15.0")] |
| pub trait FileExt { |
| /// Reads a number of bytes starting from a given offset. |
| /// |
| /// Returns the number of bytes read. |
| /// |
| /// The offset is relative to the start of the file and thus independent |
| /// from the current cursor. |
| /// |
| /// The current file cursor is not affected by this function. |
| /// |
| /// Note that similar to [`File::read`], it is not an error to return with a |
| /// short read. |
| /// |
| /// [`File::read`]: fs::File::read |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::io; |
| /// use std::fs::File; |
| /// use std::os::unix::prelude::FileExt; |
| /// |
| /// fn main() -> io::Result<()> { |
| /// let mut buf = [0u8; 8]; |
| /// let file = File::open("foo.txt")?; |
| /// |
| /// // We now read 8 bytes from the offset 10. |
| /// let num_bytes_read = file.read_at(&mut buf, 10)?; |
| /// println!("read {} bytes: {:?}", num_bytes_read, buf); |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[stable(feature = "file_offset", since = "1.15.0")] |
| fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>; |
| |
| /// Reads the exact number of byte required to fill `buf` from the given offset. |
| /// |
| /// The offset is relative to the start of the file and thus independent |
| /// from the current cursor. |
| /// |
| /// The current file cursor is not affected by this function. |
| /// |
| /// Similar to [`io::Read::read_exact`] but uses [`read_at`] instead of `read`. |
| /// |
| /// [`read_at`]: FileExt::read_at |
| /// |
| /// # Errors |
| /// |
| /// If this function encounters an error of the kind |
| /// [`io::ErrorKind::Interrupted`] then the error is ignored and the operation |
| /// will continue. |
| /// |
| /// If this function encounters an "end of file" before completely filling |
| /// the buffer, it returns an error of the kind [`io::ErrorKind::UnexpectedEof`]. |
| /// The contents of `buf` are unspecified in this case. |
| /// |
| /// If any other read error is encountered then this function immediately |
| /// returns. The contents of `buf` are unspecified in this case. |
| /// |
| /// If this function returns an error, it is unspecified how many bytes it |
| /// has read, but it will never read more than would be necessary to |
| /// completely fill the buffer. |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::io; |
| /// use std::fs::File; |
| /// use std::os::unix::prelude::FileExt; |
| /// |
| /// fn main() -> io::Result<()> { |
| /// let mut buf = [0u8; 8]; |
| /// let file = File::open("foo.txt")?; |
| /// |
| /// // We now read exactly 8 bytes from the offset 10. |
| /// file.read_exact_at(&mut buf, 10)?; |
| /// println!("read {} bytes: {:?}", buf.len(), buf); |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[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::Error::new_const(io::ErrorKind::UnexpectedEof, &"failed to fill whole buffer")) |
| } else { |
| Ok(()) |
| } |
| } |
| |
| /// Writes a number of bytes starting from a given offset. |
| /// |
| /// Returns the number of bytes written. |
| /// |
| /// The offset is relative to the start of the file and thus independent |
| /// from the current cursor. |
| /// |
| /// The current file cursor is not affected by this function. |
| /// |
| /// When writing beyond the end of the file, the file is appropriately |
| /// extended and the intermediate bytes are initialized with the value 0. |
| /// |
| /// Note that similar to [`File::write`], it is not an error to return a |
| /// short write. |
| /// |
| /// [`File::write`]: fs::File::write |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::fs::File; |
| /// use std::io; |
| /// use std::os::unix::prelude::FileExt; |
| /// |
| /// fn main() -> io::Result<()> { |
| /// let file = File::open("foo.txt")?; |
| /// |
| /// // We now write at the offset 10. |
| /// file.write_at(b"sushi", 10)?; |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[stable(feature = "file_offset", since = "1.15.0")] |
| fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>; |
| |
| /// Attempts to write an entire buffer starting from a given offset. |
| /// |
| /// The offset is relative to the start of the file and thus independent |
| /// from the current cursor. |
| /// |
| /// The current file cursor is not affected by this function. |
| /// |
| /// This method will continuously call [`write_at`] until there is no more data |
| /// to be written or an error of non-[`io::ErrorKind::Interrupted`] kind is |
| /// returned. This method will not return until the entire buffer has been |
| /// successfully written or such an error occurs. The first error that is |
| /// not of [`io::ErrorKind::Interrupted`] kind generated from this method will be |
| /// returned. |
| /// |
| /// # Errors |
| /// |
| /// This function will return the first error of |
| /// non-[`io::ErrorKind::Interrupted`] kind that [`write_at`] returns. |
| /// |
| /// [`write_at`]: FileExt::write_at |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::fs::File; |
| /// use std::io; |
| /// use std::os::unix::prelude::FileExt; |
| /// |
| /// fn main() -> io::Result<()> { |
| /// let file = File::open("foo.txt")?; |
| /// |
| /// // We now write at the offset 10. |
| /// file.write_all_at(b"sushi", 10)?; |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[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::Error::new_const( |
| 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 write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> { |
| self.as_inner().write_at(buf, offset) |
| } |
| } |
| |
| /// Unix-specific extensions to [`fs::Permissions`]. |
| #[stable(feature = "fs_ext", since = "1.1.0")] |
| pub trait PermissionsExt { |
| /// Returns the underlying raw `st_mode` bits that contain the standard |
| /// Unix permissions for this file. |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::fs::File; |
| /// use std::os::unix::fs::PermissionsExt; |
| /// |
| /// fn main() -> std::io::Result<()> { |
| /// let f = File::create("foo.txt")?; |
| /// let metadata = f.metadata()?; |
| /// let permissions = metadata.permissions(); |
| /// |
| /// println!("permissions: {:o}", permissions.mode()); |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[stable(feature = "fs_ext", since = "1.1.0")] |
| fn mode(&self) -> u32; |
| |
| /// Sets the underlying raw bits for this set of permissions. |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::fs::File; |
| /// use std::os::unix::fs::PermissionsExt; |
| /// |
| /// fn main() -> std::io::Result<()> { |
| /// let f = File::create("foo.txt")?; |
| /// let metadata = f.metadata()?; |
| /// let mut permissions = metadata.permissions(); |
| /// |
| /// permissions.set_mode(0o644); // Read/write for owner and read for others. |
| /// assert_eq!(permissions.mode(), 0o644); |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[stable(feature = "fs_ext", since = "1.1.0")] |
| fn set_mode(&mut self, mode: u32); |
| |
| /// Creates a new instance of `Permissions` from the given set of Unix |
| /// permission bits. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// use std::fs::Permissions; |
| /// use std::os::unix::fs::PermissionsExt; |
| /// |
| /// // Read/write for owner and read for others. |
| /// let permissions = Permissions::from_mode(0o644); |
| /// assert_eq!(permissions.mode(), 0o644); |
| /// ``` |
| #[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)) |
| } |
| } |
| |
| /// Unix-specific extensions to [`fs::OpenOptions`]. |
| #[stable(feature = "fs_ext", since = "1.1.0")] |
| pub trait OpenOptionsExt { |
| /// Sets the mode bits that a new file will be created with. |
| /// |
| /// If a new file is created as part of an `OpenOptions::open` call then this |
| /// specified `mode` will be used as the permission bits for the new file. |
| /// If no `mode` is set, the default of `0o666` will be used. |
| /// The operating system masks out bits with the system's `umask`, to produce |
| /// the final permissions. |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::fs::OpenOptions; |
| /// use std::os::unix::fs::OpenOptionsExt; |
| /// |
| /// # fn main() { |
| /// let mut options = OpenOptions::new(); |
| /// options.mode(0o644); // Give read/write for owner and read for others. |
| /// let file = options.open("foo.txt"); |
| /// # } |
| /// ``` |
| #[stable(feature = "fs_ext", since = "1.1.0")] |
| fn mode(&mut self, mode: u32) -> &mut Self; |
| |
| /// Pass custom flags to the `flags` argument of `open`. |
| /// |
| /// The bits that define the access mode are masked out with `O_ACCMODE`, to |
| /// ensure they do not interfere with the access mode set by Rusts options. |
| /// |
| /// Custom flags can only set flags, not remove flags set by Rusts options. |
| /// This options overwrites any previously set custom flags. |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// # #![feature(rustc_private)] |
| /// extern crate libc; |
| /// use std::fs::OpenOptions; |
| /// use std::os::unix::fs::OpenOptionsExt; |
| /// |
| /// # fn main() { |
| /// let mut options = OpenOptions::new(); |
| /// options.write(true); |
| /// if cfg!(unix) { |
| /// options.custom_flags(libc::O_NOFOLLOW); |
| /// } |
| /// let file = options.open("foo.txt"); |
| /// # } |
| /// ``` |
| #[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 |
| } |
| } |
| |
| /// Unix-specific extensions to [`fs::Metadata`]. |
| #[stable(feature = "metadata_ext", since = "1.1.0")] |
| pub trait MetadataExt { |
| /// Returns the ID of the device containing the file. |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::io; |
| /// use std::fs; |
| /// use std::os::unix::fs::MetadataExt; |
| /// |
| /// fn main() -> io::Result<()> { |
| /// let meta = fs::metadata("some_file")?; |
| /// let dev_id = meta.dev(); |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[stable(feature = "metadata_ext", since = "1.1.0")] |
| fn dev(&self) -> u64; |
| /// Returns the inode number. |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::fs; |
| /// use std::os::unix::fs::MetadataExt; |
| /// use std::io; |
| /// |
| /// fn main() -> io::Result<()> { |
| /// let meta = fs::metadata("some_file")?; |
| /// let inode = meta.ino(); |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[stable(feature = "metadata_ext", since = "1.1.0")] |
| fn ino(&self) -> u64; |
| /// Returns the rights applied to this file. |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::fs; |
| /// use std::os::unix::fs::MetadataExt; |
| /// use std::io; |
| /// |
| /// fn main() -> io::Result<()> { |
| /// let meta = fs::metadata("some_file")?; |
| /// let mode = meta.mode(); |
| /// let user_has_write_access = mode & 0o200; |
| /// let user_has_read_write_access = mode & 0o600; |
| /// let group_has_read_access = mode & 0o040; |
| /// let others_have_exec_access = mode & 0o001; |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[stable(feature = "metadata_ext", since = "1.1.0")] |
| fn mode(&self) -> u32; |
| /// Returns the number of hard links pointing to this file. |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::fs; |
| /// use std::os::unix::fs::MetadataExt; |
| /// use std::io; |
| /// |
| /// fn main() -> io::Result<()> { |
| /// let meta = fs::metadata("some_file")?; |
| /// let nb_hard_links = meta.nlink(); |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[stable(feature = "metadata_ext", since = "1.1.0")] |
| fn nlink(&self) -> u64; |
| /// Returns the user ID of the owner of this file. |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::fs; |
| /// use std::os::unix::fs::MetadataExt; |
| /// use std::io; |
| /// |
| /// fn main() -> io::Result<()> { |
| /// let meta = fs::metadata("some_file")?; |
| /// let user_id = meta.uid(); |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[stable(feature = "metadata_ext", since = "1.1.0")] |
| fn uid(&self) -> u32; |
| /// Returns the group ID of the owner of this file. |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::fs; |
| /// use std::os::unix::fs::MetadataExt; |
| /// use std::io; |
| /// |
| /// fn main() -> io::Result<()> { |
| /// let meta = fs::metadata("some_file")?; |
| /// let group_id = meta.gid(); |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[stable(feature = "metadata_ext", since = "1.1.0")] |
| fn gid(&self) -> u32; |
| /// Returns the device ID of this file (if it is a special one). |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::fs; |
| /// use std::os::unix::fs::MetadataExt; |
| /// use std::io; |
| /// |
| /// fn main() -> io::Result<()> { |
| /// let meta = fs::metadata("some_file")?; |
| /// let device_id = meta.rdev(); |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[stable(feature = "metadata_ext", since = "1.1.0")] |
| fn rdev(&self) -> u64; |
| /// Returns the total size of this file in bytes. |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::fs; |
| /// use std::os::unix::fs::MetadataExt; |
| /// use std::io; |
| /// |
| /// fn main() -> io::Result<()> { |
| /// let meta = fs::metadata("some_file")?; |
| /// let file_size = meta.size(); |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[stable(feature = "metadata_ext", since = "1.1.0")] |
| fn size(&self) -> u64; |
| /// Returns the last access time of the file, in seconds since Unix Epoch. |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::fs; |
| /// use std::os::unix::fs::MetadataExt; |
| /// use std::io; |
| /// |
| /// fn main() -> io::Result<()> { |
| /// let meta = fs::metadata("some_file")?; |
| /// let last_access_time = meta.atime(); |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[stable(feature = "metadata_ext", since = "1.1.0")] |
| fn atime(&self) -> i64; |
| /// Returns the last access time of the file, in nanoseconds since [`atime`]. |
| /// |
| /// [`atime`]: MetadataExt::atime |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::fs; |
| /// use std::os::unix::fs::MetadataExt; |
| /// use std::io; |
| /// |
| /// fn main() -> io::Result<()> { |
| /// let meta = fs::metadata("some_file")?; |
| /// let nano_last_access_time = meta.atime_nsec(); |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[stable(feature = "metadata_ext", since = "1.1.0")] |
| fn atime_nsec(&self) -> i64; |
| /// Returns the last modification time of the file, in seconds since Unix Epoch. |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::fs; |
| /// use std::os::unix::fs::MetadataExt; |
| /// use std::io; |
| /// |
| /// fn main() -> io::Result<()> { |
| /// let meta = fs::metadata("some_file")?; |
| /// let last_modification_time = meta.mtime(); |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[stable(feature = "metadata_ext", since = "1.1.0")] |
| fn mtime(&self) -> i64; |
| /// Returns the last modification time of the file, in nanoseconds since [`mtime`]. |
| /// |
| /// [`mtime`]: MetadataExt::mtime |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::fs; |
| /// use std::os::unix::fs::MetadataExt; |
| /// use std::io; |
| /// |
| /// fn main() -> io::Result<()> { |
| /// let meta = fs::metadata("some_file")?; |
| /// let nano_last_modification_time = meta.mtime_nsec(); |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[stable(feature = "metadata_ext", since = "1.1.0")] |
| fn mtime_nsec(&self) -> i64; |
| /// Returns the last status change time of the file, in seconds since Unix Epoch. |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::fs; |
| /// use std::os::unix::fs::MetadataExt; |
| /// use std::io; |
| /// |
| /// fn main() -> io::Result<()> { |
| /// let meta = fs::metadata("some_file")?; |
| /// let last_status_change_time = meta.ctime(); |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[stable(feature = "metadata_ext", since = "1.1.0")] |
| fn ctime(&self) -> i64; |
| /// Returns the last status change time of the file, in nanoseconds since [`ctime`]. |
| /// |
| /// [`ctime`]: MetadataExt::ctime |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::fs; |
| /// use std::os::unix::fs::MetadataExt; |
| /// use std::io; |
| /// |
| /// fn main() -> io::Result<()> { |
| /// let meta = fs::metadata("some_file")?; |
| /// let nano_last_status_change_time = meta.ctime_nsec(); |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[stable(feature = "metadata_ext", since = "1.1.0")] |
| fn ctime_nsec(&self) -> i64; |
| /// Returns the block size for filesystem I/O. |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::fs; |
| /// use std::os::unix::fs::MetadataExt; |
| /// use std::io; |
| /// |
| /// fn main() -> io::Result<()> { |
| /// let meta = fs::metadata("some_file")?; |
| /// let block_size = meta.blksize(); |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[stable(feature = "metadata_ext", since = "1.1.0")] |
| fn blksize(&self) -> u64; |
| /// Returns the number of blocks allocated to the file, in 512-byte units. |
| /// |
| /// Please note that this may be smaller than `st_size / 512` when the file has holes. |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::fs; |
| /// use std::os::unix::fs::MetadataExt; |
| /// use std::io; |
| /// |
| /// fn main() -> io::Result<()> { |
| /// let meta = fs::metadata("some_file")?; |
| /// let blocks = meta.blocks(); |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[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() |
| } |
| } |
| |
| /// Unix-specific extensions for [`fs::FileType`]. |
| /// |
| /// Adds support for special Unix file types such as block/character devices, |
| /// pipes, and sockets. |
| #[stable(feature = "file_type_ext", since = "1.5.0")] |
| pub trait FileTypeExt { |
| /// Returns `true` if this file type is a block device. |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::fs; |
| /// use std::os::unix::fs::FileTypeExt; |
| /// use std::io; |
| /// |
| /// fn main() -> io::Result<()> { |
| /// let meta = fs::metadata("block_device_file")?; |
| /// let file_type = meta.file_type(); |
| /// assert!(file_type.is_block_device()); |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[stable(feature = "file_type_ext", since = "1.5.0")] |
| fn is_block_device(&self) -> bool; |
| /// Returns `true` if this file type is a char device. |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::fs; |
| /// use std::os::unix::fs::FileTypeExt; |
| /// use std::io; |
| /// |
| /// fn main() -> io::Result<()> { |
| /// let meta = fs::metadata("char_device_file")?; |
| /// let file_type = meta.file_type(); |
| /// assert!(file_type.is_char_device()); |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[stable(feature = "file_type_ext", since = "1.5.0")] |
| fn is_char_device(&self) -> bool; |
| /// Returns `true` if this file type is a fifo. |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::fs; |
| /// use std::os::unix::fs::FileTypeExt; |
| /// use std::io; |
| /// |
| /// fn main() -> io::Result<()> { |
| /// let meta = fs::metadata("fifo_file")?; |
| /// let file_type = meta.file_type(); |
| /// assert!(file_type.is_fifo()); |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[stable(feature = "file_type_ext", since = "1.5.0")] |
| fn is_fifo(&self) -> bool; |
| /// Returns `true` if this file type is a socket. |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::fs; |
| /// use std::os::unix::fs::FileTypeExt; |
| /// use std::io; |
| /// |
| /// fn main() -> io::Result<()> { |
| /// let meta = fs::metadata("unix.socket")?; |
| /// let file_type = meta.file_type(); |
| /// assert!(file_type.is_socket()); |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[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) |
| } |
| } |
| |
| /// Unix-specific extension methods for [`fs::DirEntry`]. |
| #[stable(feature = "dir_entry_ext", since = "1.1.0")] |
| pub trait DirEntryExt { |
| /// Returns the underlying `d_ino` field in the contained `dirent` |
| /// structure. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// use std::fs; |
| /// use std::os::unix::fs::DirEntryExt; |
| /// |
| /// if let Ok(entries) = fs::read_dir(".") { |
| /// for entry in entries { |
| /// if let Ok(entry) = entry { |
| /// // Here, `entry` is a `DirEntry`. |
| /// println!("{:?}: {}", entry.file_name(), entry.ino()); |
| /// } |
| /// } |
| /// } |
| /// ``` |
| #[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() |
| } |
| } |
| |
| /// Sealed Unix-specific extension methods for [`fs::DirEntry`]. |
| #[unstable(feature = "dir_entry_ext2", issue = "85573")] |
| pub trait DirEntryExt2: Sealed { |
| /// Returns a reference to the underlying `OsStr` of this entry's filename. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// #![feature(dir_entry_ext2)] |
| /// use std::os::unix::fs::DirEntryExt2; |
| /// use std::{fs, io}; |
| /// |
| /// fn main() -> io::Result<()> { |
| /// let mut entries = fs::read_dir(".")?.collect::<Result<Vec<_>, io::Error>>()?; |
| /// entries.sort_unstable_by(|a, b| a.file_name_ref().cmp(b.file_name_ref())); |
| /// |
| /// for p in entries { |
| /// println!("{:?}", p); |
| /// } |
| /// |
| /// Ok(()) |
| /// } |
| /// ``` |
| fn file_name_ref(&self) -> &OsStr; |
| } |
| |
| /// Allows extension traits within `std`. |
| #[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() |
| } |
| } |
| |
| /// Creates a new symbolic link on the filesystem. |
| /// |
| /// The `link` path will be a symbolic link pointing to the `original` path. |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::os::unix::fs; |
| /// |
| /// fn main() -> std::io::Result<()> { |
| /// fs::symlink("a.txt", "b.txt")?; |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[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()) |
| } |
| |
| /// Unix-specific extensions to [`fs::DirBuilder`]. |
| #[stable(feature = "dir_builder", since = "1.6.0")] |
| pub trait DirBuilderExt { |
| /// Sets the mode to create new directories with. This option defaults to |
| /// 0o777. |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::fs::DirBuilder; |
| /// use std::os::unix::fs::DirBuilderExt; |
| /// |
| /// let mut builder = DirBuilder::new(); |
| /// builder.mode(0o755); |
| /// ``` |
| #[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 |
| } |
| } |
| |
| /// Change the root directory of the current process to the specified path. |
| /// |
| /// This typically requires privileges, such as root or a specific capability. |
| /// |
| /// This does not change the current working directory; you should call |
| /// [`std::env::set_current_dir`][`crate::env::set_current_dir`] afterwards. |
| /// |
| /// # Examples |
| /// |
| /// ```no_run |
| /// use std::os::unix::fs; |
| /// |
| /// fn main() -> std::io::Result<()> { |
| /// fs::chroot("/sandbox")?; |
| /// std::env::set_current_dir("/")?; |
| /// // continue working in sandbox |
| /// Ok(()) |
| /// } |
| /// ``` |
| #[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()) |
| } |