use crate::{
fsemul::pcfs::sata::{
proto::{
SataGetFilePositionPacketBody, SataGetFilePositionResult, SataRequest, SataResponse,
},
server::PcfsServerState,
},
net::{
additions::StreamID,
server::requestable::{Body, State},
},
};
use tracing::debug;
const FS_ERROR: u32 = 0xFFF0_FFE0;
pub async fn handle_get_file_position(
stream: StreamID,
State(state): State<PcfsServerState>,
Body(request): Body<SataRequest<SataGetFilePositionPacketBody>>,
) -> SataResponse<SataGetFilePositionResult> {
let packet = request.body();
SataResponse::new(
state.pid(),
request.header().clone(),
match state
.host_filesystem()
.get_file_position(packet.file_descriptor(), Some(stream.to_raw()))
.await
{
Ok(s) => SataGetFilePositionResult::success(u32::try_from(s).unwrap_or(u32::MAX)),
Err(cause) => {
debug!(
?cause,
packet.fd = packet.file_descriptor(),
packet.typ = "PcfsSrvGetFilePosition",
"Failed to get a file's position!",
);
SataGetFilePositionResult::error(FS_ERROR)
}
},
)
}
#[cfg(test)]
mod unit_tests {
use super::*;
use crate::fsemul::{
filesystem::host::test_helpers::{create_temporary_host_filesystem, join_many},
pcfs::sata::{
proto::{SataCommandInfo, SataPacketHeader, SataReadFilePacketBody, SataRequest},
server::{SataConnectionFlags, read_file::handle_read_file},
},
};
use bytes::Bytes;
use tokio::fs::OpenOptions;
#[tokio::test]
pub async fn simple_close_file_request() {
let (tempdir, fs) = create_temporary_host_filesystem().await;
let base_dir = join_many(tempdir.path(), ["data", "slc", "to-query"]);
tokio::fs::create_dir(&base_dir)
.await
.expect("Failed to create temporary directory for test!");
tokio::fs::write(join_many(&base_dir, ["file.txt"]), vec![0; 16])
.await
.expect("Failed to write test file!");
let mocked_header = SataPacketHeader::new(0);
let mocked_ci = SataCommandInfo::new((0, 0), (0, 0), 0);
let mut open_options = OpenOptions::new();
open_options.read(true).create(false).write(false);
let fd = fs
.open_file(open_options, &join_many(&base_dir, ["file.txt"]), Some(0))
.await
.expect("Failed to open file!");
let state = PcfsServerState::new(true, fs.clone(), 0);
let get_file_position_request = SataGetFilePositionPacketBody::new(fd);
let response: Bytes = handle_get_file_position(
StreamID::from_existing(0),
State(state.clone()),
Body(SataRequest::new(
mocked_header.clone(),
mocked_ci.clone(),
get_file_position_request.clone(),
)),
)
.await
.try_into()
.expect("Failed to serialize get file position response!");
assert_eq!(&response[0x20..0x24], &[0; 4]);
assert_eq!(&response[0x24..], &[0; 4]);
let read_request = SataReadFilePacketBody::new(4, 1, fd, None);
let conn_flags = SataConnectionFlags::new_with_flags(true, true);
conn_flags.set_first_read_size(1000);
conn_flags.set_first_write_size(1000);
_ = handle_read_file(
StreamID::from_existing(0),
conn_flags,
State(fs),
Body(SataRequest::new(
SataPacketHeader::new(0),
SataCommandInfo::new((0, 0), (0, 0), 0),
read_request,
)),
)
.await
.expect("Failed to handle read file!");
let response: Bytes = handle_get_file_position(
StreamID::from_existing(0),
State(state),
Body(SataRequest::new(
mocked_header,
mocked_ci,
get_file_position_request,
)),
)
.await
.try_into()
.expect("Failed to serialize get file position response!");
assert_eq!(&response[0x20..0x24], &[0; 4]);
assert_eq!(&response[0x24..], 4_u32.to_be_bytes());
}
}