use bytes::{Buf, Bytes};
use super::mount::{Mount41, decode_string_from_bytes};
use super::state::{AccessMode, StateId};
use crate::error::{NfsError, Result};
impl Mount41 {
pub(crate) async fn access(&self, fh: Bytes, mode: u32) -> Result<u32> {
let resp = self
.compound("access", |b| b.putfh(&fh).access(mode))
.await?;
resp.op_ok(1)?; let access_op = resp.op_ok(2)?;
let mut data = access_op.data.clone();
if data.remaining() < 8 {
return Err(NfsError::Xdr("ACCESS result too short".to_string()));
}
let _supported = data.get_u32();
let access = data.get_u32();
Ok(access)
}
pub(crate) async fn access_path(&self, path: &str, mode: u32) -> Result<u32> {
let obj = self.lookup_path(path).await?;
self.access(obj.fh, mode).await
}
pub(crate) async fn read(&self, fh: Bytes, offset: u64, count: u32) -> Result<Bytes> {
if count == 0 {
return Ok(Bytes::new());
}
if let Some(result) = self.pnfs_read(&fh, offset, count).await {
return result;
}
self.mds_read(&fh, offset, count).await
}
async fn mds_read(&self, fh: &Bytes, offset: u64, count: u32) -> Result<Bytes> {
let sid = self
.state
.has_open(fh, AccessMode::Read)
.await
.unwrap_or_else(StateId::anonymous);
let stateid = sid.raw;
let resp = self
.compound_data("read", count as usize, |b| {
b.require_generation(sid.generation)
.putfh(fh)
.read(&stateid, offset, count)
})
.await?;
resp.op_ok(1)?; let read_op = resp.op_ok(2)?;
let mut data = read_op.data.clone();
if data.remaining() < 4 {
return Err(NfsError::Xdr("READ result too short".to_string()));
}
let eof = data.get_u32() != 0;
if data.remaining() < 4 {
return Err(NfsError::Xdr("READ data length missing".to_string()));
}
let data_len = data.get_u32() as usize;
if data.remaining() < data_len {
return Err(NfsError::Xdr("READ data truncated".to_string()));
}
crate::mount::read_reply(data.slice(..data_len), eof)
}
pub(crate) async fn read_path(&self, path: &str, offset: u64, count: u32) -> Result<Bytes> {
let obj = self.lookup_path(path).await?;
self.read(obj.fh, offset, count).await
}
pub(crate) async fn readlink(&self, fh: Bytes) -> Result<String> {
let resp = self
.compound("readlink", |b| b.putfh(&fh).readlink())
.await?;
resp.op_ok(1)?; let readlink_op = resp.op_ok(2)?;
let mut data = readlink_op.data.clone();
decode_string_from_bytes(&mut data)
}
pub(crate) async fn readlink_path(&self, path: &str) -> Result<String> {
let obj = self.lookup_path(path).await?;
self.readlink(obj.fh).await
}
}