blob: 4ea6b1a9007834a1fa7ee0aa07673a087555af26 [file] [log] [blame]
use super::prelude::*;
use crate::protocol::commands::ext::HostIo;
use crate::arch::Arch;
use crate::target::ext::host_io::{HostIoError, HostIoStat};
impl<T: Target, C: Connection> GdbStubImpl<T, C> {
pub(crate) fn handle_host_io(
&mut self,
res: &mut ResponseWriter<'_, C>,
target: &mut T,
command: HostIo<'_>,
) -> Result<HandlerStatus, Error<T::Error, C::Error>> {
let ops = match target.support_host_io() {
Some(ops) => ops,
None => return Ok(HandlerStatus::Handled),
};
crate::__dead_code_marker!("host_io", "impl");
macro_rules! handle_hostio_result {
( if let Ok($val:pat) = $ret:expr => $callback:block ) => {{
match $ret {
Ok($val) => $callback,
Err(HostIoError::Errno(errno)) => {
res.write_str("F-1,")?;
res.write_num(errno as u32)?;
}
Err(HostIoError::Fatal(e)) => return Err(Error::TargetError(e)),
}
}};
}
let handler_status = match command {
HostIo::vFileOpen(cmd) if ops.support_open().is_some() => {
let ops = ops.support_open().unwrap();
handle_hostio_result! {
if let Ok(fd) = ops.open(cmd.filename, cmd.flags, cmd.mode) => {
res.write_str("F")?;
res.write_num(fd)?;
}
}
HandlerStatus::Handled
}
HostIo::vFileClose(cmd) if ops.support_close().is_some() => {
let ops = ops.support_close().unwrap();
handle_hostio_result! {
if let Ok(()) = ops.close(cmd.fd) => {
res.write_str("F0")?;
}
}
HandlerStatus::Handled
}
HostIo::vFilePread(cmd) if ops.support_pread().is_some() => {
let ops = ops.support_pread().unwrap();
handle_hostio_result! {
if let Ok(ret) = ops.pread(cmd.fd, cmd.count, cmd.offset, cmd.buf) => {
res.write_str("F")?;
res.write_num(ret)?;
res.write_str(";")?;
res.write_binary(cmd.buf.get(..ret).ok_or(Error::PacketBufferOverflow)?)?;
}
};
HandlerStatus::Handled
}
HostIo::vFilePwrite(cmd) if ops.support_pwrite().is_some() => {
let offset = <T::Arch as Arch>::Usize::from_be_bytes(cmd.offset)
.ok_or(Error::TargetMismatch)?;
let ops = ops.support_pwrite().unwrap();
handle_hostio_result! {
if let Ok(ret) = ops.pwrite(cmd.fd, offset, cmd.data) => {
res.write_str("F")?;
res.write_num(ret)?;
}
};
HandlerStatus::Handled
}
HostIo::vFileFstat(cmd) if ops.support_fstat().is_some() => {
let ops = ops.support_fstat().unwrap();
handle_hostio_result! {
if let Ok(stat) = ops.fstat(cmd.fd) => {
let size = core::mem::size_of::<HostIoStat>();
res.write_str("F")?;
res.write_num(size)?;
res.write_str(";")?;
res.write_binary(&stat.st_dev.to_be_bytes())?;
res.write_binary(&stat.st_ino.to_be_bytes())?;
res.write_binary(&(stat.st_mode.bits()).to_be_bytes())?;
res.write_binary(&stat.st_nlink.to_be_bytes())?;
res.write_binary(&stat.st_uid.to_be_bytes())?;
res.write_binary(&stat.st_gid.to_be_bytes())?;
res.write_binary(&stat.st_rdev.to_be_bytes())?;
res.write_binary(&stat.st_size.to_be_bytes())?;
res.write_binary(&stat.st_blksize.to_be_bytes())?;
res.write_binary(&stat.st_blocks.to_be_bytes())?;
res.write_binary(&stat.st_atime.to_be_bytes())?;
res.write_binary(&stat.st_mtime.to_be_bytes())?;
res.write_binary(&stat.st_ctime.to_be_bytes())?;
}
};
HandlerStatus::Handled
}
HostIo::vFileUnlink(cmd) if ops.support_unlink().is_some() => {
let ops = ops.support_unlink().unwrap();
handle_hostio_result! {
if let Ok(()) = ops.unlink(cmd.filename) => {
res.write_str("F0")?;
}
};
HandlerStatus::Handled
}
HostIo::vFileReadlink(cmd) if ops.support_readlink().is_some() => {
let ops = ops.support_readlink().unwrap();
handle_hostio_result! {
if let Ok(ret) = ops.readlink(cmd.filename, cmd.buf) => {
res.write_str("F")?;
res.write_num(ret)?;
res.write_str(";")?;
res.write_binary(cmd.buf.get(..ret).ok_or(Error::PacketBufferOverflow)?)?;
}
};
HandlerStatus::Handled
}
HostIo::vFileSetfs(cmd) if ops.support_setfs().is_some() => {
let ops = ops.support_setfs().unwrap();
handle_hostio_result! {
if let Ok(()) = ops.setfs(cmd.fs) => {
res.write_str("F0")?;
}
};
HandlerStatus::Handled
}
_ => HandlerStatus::Handled,
};
Ok(handler_status)
}
}