use crate::{
errors::CatBridgeError,
fsemul::pcfs::{
errors::PcfsApiError,
sata::{
proto::{SataRequest, SataResponse, SataResultCode, SataWriteFilePacketBody},
server::{PcfsServerState, SataConnectionFlags, wal::WriteAheadLog},
},
},
net::models::Request,
};
use tracing::debug;
const FS_ERROR: u32 = 0xFFF0_FFE0;
pub async fn handle_write_file(
req: Request<PcfsServerState>,
) -> Result<SataResponse<SataResultCode>, CatBridgeError> {
let flags = req
.extensions()
.get::<SataConnectionFlags>()
.cloned()
.ok_or_else(|| PcfsApiError::MissingCriticalExtension("SataConnectionFlags".to_owned()))?;
let opt_wal = req.extensions().get::<WriteAheadLog>();
let state = req.state();
let request = SataRequest::<SataWriteFilePacketBody>::try_from(req.body().clone())?;
let request_header = request.header().clone();
let packet = request.body();
if packet.should_move()
&& let Err(cause) = packet
.move_to_pointer()
.do_move(
state.host_filesystem(),
packet.file_descriptor(),
Some(req.stream_id()),
)
.await
{
debug!(
?cause,
packet.fd = packet.file_descriptor(),
packet.typ = "PcfsSrvWriteFile",
"Failed to seek file!",
);
return Ok(SataResponse::new(
state.pid(),
request_header,
SataResultCode::error(FS_ERROR),
));
}
if flags.ffio_enabled() {
let len_needed = usize::try_from(packet.block_count() * packet.block_size())
.map_err(|_| CatBridgeError::UnsupportedBitsPerCore)?;
let buff = req.unsafe_read_more_bytes_from_stream(len_needed).await?;
if let Some(wal) = opt_wal {
wal.record_oob_file_write_read(req.stream_id(), packet.file_descriptor(), len_needed)
.await;
}
if let Err(cause) = state
.host_filesystem
.write_file(packet.file_descriptor(), buff, Some(req.stream_id()))
.await
{
debug!(
?cause,
packet.fd = packet.file_descriptor(),
packet.typ = "PcfsSrvWriteFile",
"Failed to write file!",
);
return Ok(SataResponse::new(
state.pid(),
request_header,
SataResultCode::error(FS_ERROR),
));
}
Ok(SataResponse::new_force_zero_version(
state.pid(),
request_header,
SataResultCode::error(packet.block_size() * packet.block_count()),
))
} else {
todo!("Implement non-FFIO support.")
}
}