| #![allow(dead_code)] // not used on all platforms |
| |
| use crate::fs; |
| use crate::io::{self, Error, ErrorKind}; |
| use crate::path::Path; |
| use crate::sys_common::ignore_notfound; |
| |
| 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), |
| } |
| } |