#[cfg(target_os = "linux")]
use std::ffi::CString;
use crate::fs::stat::metadata;
#[cfg(target_os = "linux")]
use crate::op::{MkDirOp, Op, RenameOp, UnlinkOp};
#[cfg(target_os = "linux")]
pub async fn rename(
from: impl AsRef<std::path::Path>,
to: impl AsRef<std::path::Path>,
) -> std::io::Result<()> {
let from = from.as_ref();
let to = to.as_ref();
let driver = crate::executor::current_driver();
if driver.as_ref().is_some_and(|d| d.supports_completion()) {
let from_cstr = CString::new(from.as_os_str().as_encoded_bytes()).map_err(|e| {
std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!("Invalid path: {}", e),
)
})?;
let to_cstr = CString::new(to.as_os_str().as_encoded_bytes()).map_err(|e| {
std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!("Invalid path: {}", e),
)
})?;
let driver = driver.expect("invalid driver state");
let mut op = RenameOp::new(from_cstr, to_cstr);
std::future::poll_fn(|cx| op.poll_completion(cx, driver.as_ref())).await
} else if crate::executor::offload_fs() {
let from = from.to_owned();
let to = to.to_owned();
crate::spawn_blocking(move || std::fs::rename(from, to))
.await
.map_err(|_| crate::fs::file::blocking_pool_io_error())?
} else {
std::fs::rename(from, to)
}
}
#[cfg(not(target_os = "linux"))]
pub async fn rename(
from: impl AsRef<std::path::Path>,
to: impl AsRef<std::path::Path>,
) -> std::io::Result<()> {
if crate::executor::offload_fs() {
let from = from.as_ref().to_owned();
let to = to.as_ref().to_owned();
crate::spawn_blocking(move || std::fs::rename(from, to))
.await
.map_err(|_| crate::fs::file::blocking_pool_io_error())?
} else {
std::fs::rename(from, to)
}
}
#[cfg(target_os = "linux")]
pub async fn remove_dir(path: impl AsRef<std::path::Path>) -> std::io::Result<()> {
let path = path.as_ref();
let driver = crate::executor::current_driver();
if driver.as_ref().is_some_and(|d| d.supports_completion()) {
let path_cstr = CString::new(path.as_os_str().as_encoded_bytes()).map_err(|e| {
std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!("Invalid path: {}", e),
)
})?;
let driver = driver.expect("invalid driver state");
let mut op = UnlinkOp::new(path_cstr, true);
std::future::poll_fn(|cx| op.poll_completion(cx, driver.as_ref())).await
} else if crate::executor::offload_fs() {
let path = path.to_owned();
crate::spawn_blocking(move || std::fs::remove_dir(path))
.await
.map_err(|_| crate::fs::file::blocking_pool_io_error())?
} else {
std::fs::remove_dir(path)
}
}
#[cfg(not(target_os = "linux"))]
pub async fn remove_dir(path: impl AsRef<std::path::Path>) -> std::io::Result<()> {
if crate::executor::offload_fs() {
let path = path.as_ref().to_owned();
crate::spawn_blocking(move || std::fs::remove_dir(path))
.await
.map_err(|_| crate::fs::file::blocking_pool_io_error())?
} else {
std::fs::remove_dir(path)
}
}
#[cfg(target_os = "linux")]
pub async fn remove_file(path: impl AsRef<std::path::Path>) -> std::io::Result<()> {
let path = path.as_ref();
let driver = crate::executor::current_driver();
if driver.as_ref().is_some_and(|d| d.supports_completion()) {
let path_cstr = CString::new(path.as_os_str().as_encoded_bytes()).map_err(|e| {
std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!("Invalid path: {}", e),
)
})?;
let driver = driver.expect("invalid driver state");
let mut op = UnlinkOp::new(path_cstr, false);
std::future::poll_fn(|cx| op.poll_completion(cx, driver.as_ref())).await
} else if crate::executor::offload_fs() {
let path = path.to_owned();
crate::spawn_blocking(move || std::fs::remove_file(path))
.await
.map_err(|_| crate::fs::file::blocking_pool_io_error())?
} else {
std::fs::remove_file(path)
}
}
#[cfg(not(target_os = "linux"))]
pub async fn remove_file(path: impl AsRef<std::path::Path>) -> std::io::Result<()> {
if crate::executor::offload_fs() {
let path = path.as_ref().to_owned();
crate::spawn_blocking(move || std::fs::remove_file(path))
.await
.map_err(|_| crate::fs::file::blocking_pool_io_error())?
} else {
std::fs::remove_file(path)
}
}
#[cfg(target_os = "linux")]
pub async fn create_dir(path: impl AsRef<std::path::Path>) -> std::io::Result<()> {
let path = path.as_ref();
let driver = crate::executor::current_driver();
if driver.as_ref().is_some_and(|d| d.supports_completion()) {
let path_cstr = CString::new(path.as_os_str().as_encoded_bytes()).map_err(|e| {
std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!("Invalid path: {}", e),
)
})?;
let driver = driver.expect("invalid driver state");
let mut op = MkDirOp::new(path_cstr, 0o777);
std::future::poll_fn(|cx| op.poll_completion(cx, driver.as_ref())).await
} else if crate::executor::offload_fs() {
let path = path.to_owned();
crate::spawn_blocking(move || std::fs::create_dir(path))
.await
.map_err(|_| crate::fs::file::blocking_pool_io_error())?
} else {
std::fs::create_dir(path)
}
}
#[cfg(not(target_os = "linux"))]
pub async fn create_dir(path: impl AsRef<std::path::Path>) -> std::io::Result<()> {
if crate::executor::offload_fs() {
let path = path.as_ref().to_owned();
crate::spawn_blocking(move || std::fs::create_dir(path))
.await
.map_err(|_| crate::fs::file::blocking_pool_io_error())?
} else {
std::fs::create_dir(path)
}
}
pub async fn create_dir_all(path: impl AsRef<std::path::Path>) -> std::io::Result<()> {
let path = path.as_ref();
let mut stack = Vec::new();
let mut p = path;
loop {
match create_dir(p).await {
Ok(()) => break,
Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => {
if let Ok(metadata) = metadata(p).await {
if metadata.is_dir() {
break;
}
}
return Err(e);
}
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
stack.push(p);
match p.parent() {
Some(parent) => p = parent,
None => return Err(e),
}
}
Err(e) => return Err(e),
}
}
while let Some(p) = stack.pop() {
match create_dir(p).await {
Ok(()) => continue,
Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => {
if let Ok(metadata) = metadata(p).await {
if metadata.is_dir() {
continue;
}
}
return Err(e);
}
Err(e) => return Err(e),
}
}
Ok(())
}