use std::io::{Read, Write};
use tracing::debug;
use crate::protocol::rpc;
use crate::protocol::xdr::{self, deserialize, nfs3, Serialize};
pub async fn nfsproc3_lookup(
xid: u32,
input: &mut impl Read,
output: &mut impl Write,
context: &rpc::Context,
) -> Result<(), anyhow::Error> {
let dirops = deserialize::<nfs3::diropargs3>(input)?;
debug!("nfsproc3_lookup({:?},{:?}) ", xid, dirops);
let dirid = context.vfs.fh_to_id(&dirops.dir);
if let Err(stat) = dirid {
xdr::rpc::make_success_reply(xid).serialize(output)?;
stat.serialize(output)?;
nfs3::post_op_attr::None.serialize(output)?;
return Ok(());
}
let dirid = dirid.unwrap();
let dir_attr_maybe = context.vfs.getattr(dirid).await;
let dir_attr = dir_attr_maybe.ok();
match context.vfs.check_access(dirid, &context.auth, nfs3::ACCESS3_LOOKUP).await {
Ok(granted) if granted & nfs3::ACCESS3_LOOKUP != 0 => {}
Ok(_) => {
xdr::rpc::make_success_reply(xid).serialize(output)?;
nfs3::nfsstat3::NFS3ERR_ACCES.serialize(output)?;
dir_attr.serialize(output)?;
return Ok(());
}
Err(stat) => {
xdr::rpc::make_success_reply(xid).serialize(output)?;
stat.serialize(output)?;
dir_attr.serialize(output)?;
return Ok(());
}
}
match context.vfs.lookup(dirid, &dirops.name).await {
Ok(fid) => {
let obj_attr = context.vfs.getattr(fid).await.ok();
debug!("nfsproc3_lookup success {:?} --> {:?}", xid, obj_attr);
xdr::rpc::make_success_reply(xid).serialize(output)?;
nfs3::nfsstat3::NFS3_OK.serialize(output)?;
context.vfs.id_to_fh(fid).serialize(output)?;
obj_attr.serialize(output)?;
dir_attr.serialize(output)?;
}
Err(stat) => {
debug!("nfsproc3_lookup error {:?}({:?}) --> {:?}", xid, dirops.name, stat);
xdr::rpc::make_success_reply(xid).serialize(output)?;
stat.serialize(output)?;
dir_attr.serialize(output)?;
}
}
Ok(())
}