use std::io::{Read, Write};
use tracing::debug;
use crate::protocol::rpc;
use crate::protocol::xdr::{self, deserialize, nfs3, Serialize};
pub async fn nfsproc3_access(
xid: u32,
input: &mut impl Read,
output: &mut impl Write,
context: &rpc::Context,
) -> Result<(), anyhow::Error> {
let handle = deserialize::<nfs3::nfs_fh3>(input)?;
let access = deserialize::<u32>(input)?;
debug!("nfsproc3_access({:?},{:?},{:?})", xid, handle, access);
let id = context.vfs.fh_to_id(&handle);
if let Err(stat) = id {
xdr::rpc::make_success_reply(xid).serialize(output)?;
stat.serialize(output)?;
nfs3::post_op_attr::None.serialize(output)?;
return Ok(());
}
let id = id.unwrap();
let obj_attr = match context.vfs.getattr(id).await {
Ok(v) => nfs3::post_op_attr::Some(v),
Err(stat) => {
xdr::rpc::make_success_reply(xid).serialize(output)?;
stat.serialize(output)?;
nfs3::post_op_attr::None.serialize(output)?;
return Ok(());
}
};
if obj_attr.is_none() {
xdr::rpc::make_success_reply(xid).serialize(output)?;
nfs3::nfsstat3::NFS3ERR_NOENT.serialize(output)?;
nfs3::post_op_attr::None.serialize(output)?;
return Ok(());
}
let attr = match obj_attr {
nfs3::post_op_attr::Some(attr) => attr,
None => {
xdr::rpc::make_success_reply(xid).serialize(output)?;
nfs3::nfsstat3::NFS3ERR_SERVERFAULT.serialize(output)?;
nfs3::post_op_attr::None.serialize(output)?;
return Ok(());
}
};
let granted_access = match context.vfs.check_access(id, &context.auth, access).await {
Ok(granted) => granted,
Err(stat) => {
xdr::rpc::make_success_reply(xid).serialize(output)?;
stat.serialize(output)?;
nfs3::post_op_attr::Some(attr).serialize(output)?;
return Ok(());
}
};
debug!(" {:?} ---> {:?}", xid, granted_access);
xdr::rpc::make_success_reply(xid).serialize(output)?;
nfs3::nfsstat3::NFS3_OK.serialize(output)?;
obj_attr.serialize(output)?;
granted_access.serialize(output)?;
Ok(())
}