| #![allow(dead_code)] // not used on all platforms | |
| use crate::io::{self, Error, ErrorKind}; | |
| use crate::path::{Path, PathBuf}; | |
| use crate::sys::fs::{File, OpenOptions}; | |
| use crate::sys::helpers::ignore_notfound; | |
| use crate::{fmt, fs}; | |
| pub(crate) const NOT_FILE_ERROR: Error = io::const_error!( | |
| ErrorKind::InvalidInput, | |
| "the source path is neither a regular file nor a symlink to a regular file", | |
| ); | |
| pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { | |
| let mut reader = fs::File::open(from)?; | |
| let metadata = reader.metadata()?; | |
| if !metadata.is_file() { | |
| return Err(NOT_FILE_ERROR); | |
| } | |
| let mut writer = fs::File::create(to)?; | |
| let perm = metadata.permissions(); | |
| let ret = io::copy(&mut reader, &mut writer)?; | |
| writer.set_permissions(perm)?; | |
| Ok(ret) | |
| } | |
| pub fn remove_dir_all(path: &Path) -> io::Result<()> { | |
| let filetype = fs::symlink_metadata(path)?.file_type(); | |
| if filetype.is_symlink() { fs::remove_file(path) } else { remove_dir_all_recursive(path) } | |
| } | |
| fn remove_dir_all_recursive(path: &Path) -> io::Result<()> { | |
| for child in fs::read_dir(path)? { | |
| let result: io::Result<()> = try { | |
| let child = child?; | |
| if child.file_type()?.is_dir() { | |
| remove_dir_all_recursive(&child.path())?; | |
| } else { | |
| fs::remove_file(&child.path())?; | |
| } | |
| }; | |
| // ignore internal NotFound errors to prevent race conditions | |
| if let Err(err) = &result | |
| && err.kind() != io::ErrorKind::NotFound | |
| { | |
| return result; | |
| } | |
| } | |
| ignore_notfound(fs::remove_dir(path)) | |
| } | |
| pub fn exists(path: &Path) -> io::Result<bool> { | |
| match fs::metadata(path) { | |
| Ok(_) => Ok(true), | |
| Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(false), | |
| Err(error) => Err(error), | |
| } | |
| } | |
| pub struct Dir { | |
| path: PathBuf, | |
| } | |
| impl Dir { | |
| pub fn open(path: &Path, _opts: &OpenOptions) -> io::Result<Self> { | |
| path.canonicalize().map(|path| Self { path }) | |
| } | |
| pub fn open_file(&self, path: &Path, opts: &OpenOptions) -> io::Result<File> { | |
| File::open(&self.path.join(path), &opts) | |
| } | |
| } | |
| impl fmt::Debug for Dir { | |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| f.debug_struct("Dir").field("path", &self.path).finish() | |
| } | |
| } |