use alloc::string::String;
use alloc::vec::Vec;
use super::error::NfsStatus;
use super::types::{
AccessBits, AttrBitmap, ClientId, DirEntry, FileHandle, FsInfo, FsStat, LockRange, LockType,
NfsAttr, OpenMode, SessionId, SetAttr, ShareAccess, ShareDeny, StateId, Verifier,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u32)]
pub enum Opcode {
Access = 3,
Close = 4,
Commit = 5,
Create = 6,
DelegatePurge = 7,
DelegateReturn = 8,
Getattr = 9,
Getfh = 10,
Link = 11,
Lock = 12,
Lockt = 13,
Locku = 14,
Lookup = 15,
Lookupp = 16,
Nverify = 17,
Open = 18,
Openattr = 19,
OpenConfirm = 20,
OpenDowngrade = 21,
Putfh = 22,
Putpubfh = 23,
Putrootfh = 24,
Read = 25,
Readdir = 26,
Readlink = 27,
Remove = 28,
Rename = 29,
Renew = 30,
Restorefh = 31,
Savefh = 32,
Secinfo = 33,
Setattr = 34,
Setclientid = 35,
SetclientidConfirm = 36,
Verify = 37,
Write = 38,
ReleaseLockowner = 39,
BackchannelCtl = 40,
BindConnToSession = 41,
ExchangeId = 42,
CreateSession = 43,
DestroySession = 44,
FreeStateid = 45,
GetDeviceinfo = 47,
GetDevicelist = 48,
Layoutcommit = 49,
Layoutget = 50,
Layoutreturn = 51,
SecinfoNoName = 52,
Sequence = 53,
SetSsv = 54,
TestStateid = 55,
WantDelegation = 56,
DestroyClientid = 57,
ReclaimComplete = 58,
Illegal = 10044,
}
impl Opcode {
pub fn from_u32(v: u32) -> Option<Self> {
match v {
3 => Some(Self::Access),
4 => Some(Self::Close),
5 => Some(Self::Commit),
6 => Some(Self::Create),
7 => Some(Self::DelegatePurge),
8 => Some(Self::DelegateReturn),
9 => Some(Self::Getattr),
10 => Some(Self::Getfh),
11 => Some(Self::Link),
12 => Some(Self::Lock),
13 => Some(Self::Lockt),
14 => Some(Self::Locku),
15 => Some(Self::Lookup),
16 => Some(Self::Lookupp),
17 => Some(Self::Nverify),
18 => Some(Self::Open),
19 => Some(Self::Openattr),
20 => Some(Self::OpenConfirm),
21 => Some(Self::OpenDowngrade),
22 => Some(Self::Putfh),
23 => Some(Self::Putpubfh),
24 => Some(Self::Putrootfh),
25 => Some(Self::Read),
26 => Some(Self::Readdir),
27 => Some(Self::Readlink),
28 => Some(Self::Remove),
29 => Some(Self::Rename),
30 => Some(Self::Renew),
31 => Some(Self::Restorefh),
32 => Some(Self::Savefh),
33 => Some(Self::Secinfo),
34 => Some(Self::Setattr),
35 => Some(Self::Setclientid),
36 => Some(Self::SetclientidConfirm),
37 => Some(Self::Verify),
38 => Some(Self::Write),
39 => Some(Self::ReleaseLockowner),
40 => Some(Self::BackchannelCtl),
41 => Some(Self::BindConnToSession),
42 => Some(Self::ExchangeId),
43 => Some(Self::CreateSession),
44 => Some(Self::DestroySession),
45 => Some(Self::FreeStateid),
47 => Some(Self::GetDeviceinfo),
48 => Some(Self::GetDevicelist),
49 => Some(Self::Layoutcommit),
50 => Some(Self::Layoutget),
51 => Some(Self::Layoutreturn),
52 => Some(Self::SecinfoNoName),
53 => Some(Self::Sequence),
54 => Some(Self::SetSsv),
55 => Some(Self::TestStateid),
56 => Some(Self::WantDelegation),
57 => Some(Self::DestroyClientid),
58 => Some(Self::ReclaimComplete),
10044 => Some(Self::Illegal),
_ => None,
}
}
pub fn name(&self) -> &'static str {
match self {
Self::Access => "ACCESS",
Self::Close => "CLOSE",
Self::Commit => "COMMIT",
Self::Create => "CREATE",
Self::DelegatePurge => "DELEGPURGE",
Self::DelegateReturn => "DELEGRETURN",
Self::Getattr => "GETATTR",
Self::Getfh => "GETFH",
Self::Link => "LINK",
Self::Lock => "LOCK",
Self::Lockt => "LOCKT",
Self::Locku => "LOCKU",
Self::Lookup => "LOOKUP",
Self::Lookupp => "LOOKUPP",
Self::Nverify => "NVERIFY",
Self::Open => "OPEN",
Self::Openattr => "OPENATTR",
Self::OpenConfirm => "OPEN_CONFIRM",
Self::OpenDowngrade => "OPEN_DOWNGRADE",
Self::Putfh => "PUTFH",
Self::Putpubfh => "PUTPUBFH",
Self::Putrootfh => "PUTROOTFH",
Self::Read => "READ",
Self::Readdir => "READDIR",
Self::Readlink => "READLINK",
Self::Remove => "REMOVE",
Self::Rename => "RENAME",
Self::Renew => "RENEW",
Self::Restorefh => "RESTOREFH",
Self::Savefh => "SAVEFH",
Self::Secinfo => "SECINFO",
Self::Setattr => "SETATTR",
Self::Setclientid => "SETCLIENTID",
Self::SetclientidConfirm => "SETCLIENTID_CONFIRM",
Self::Verify => "VERIFY",
Self::Write => "WRITE",
Self::ReleaseLockowner => "RELEASE_LOCKOWNER",
Self::BackchannelCtl => "BACKCHANNEL_CTL",
Self::BindConnToSession => "BIND_CONN_TO_SESSION",
Self::ExchangeId => "EXCHANGE_ID",
Self::CreateSession => "CREATE_SESSION",
Self::DestroySession => "DESTROY_SESSION",
Self::FreeStateid => "FREE_STATEID",
Self::GetDeviceinfo => "GETDEVICEINFO",
Self::GetDevicelist => "GETDEVICELIST",
Self::Layoutcommit => "LAYOUTCOMMIT",
Self::Layoutget => "LAYOUTGET",
Self::Layoutreturn => "LAYOUTRETURN",
Self::SecinfoNoName => "SECINFO_NO_NAME",
Self::Sequence => "SEQUENCE",
Self::SetSsv => "SET_SSV",
Self::TestStateid => "TEST_STATEID",
Self::WantDelegation => "WANT_DELEGATION",
Self::DestroyClientid => "DESTROY_CLIENTID",
Self::ReclaimComplete => "RECLAIM_COMPLETE",
Self::Illegal => "ILLEGAL",
}
}
}
#[derive(Debug, Clone)]
pub struct PutfhArgs {
pub fh: FileHandle,
}
#[derive(Debug, Clone)]
pub struct LookupArgs {
pub name: String,
}
#[derive(Debug, Clone)]
pub struct GetattrArgs {
pub attr_request: AttrBitmap,
}
#[derive(Debug, Clone)]
pub struct AccessArgs {
pub access: AccessBits,
}
#[derive(Debug, Clone)]
pub struct ReadArgs {
pub stateid: StateId,
pub offset: u64,
pub count: u32,
}
#[derive(Debug, Clone)]
pub struct WriteArgs {
pub stateid: StateId,
pub offset: u64,
pub stable: StableHow,
pub data: Vec<u8>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u32)]
pub enum StableHow {
Unstable = 0,
DataSync = 1,
FileSync = 2,
}
#[derive(Debug, Clone)]
pub struct OpenArgs {
pub seqid: u32,
pub share_access: ShareAccess,
pub share_deny: ShareDeny,
pub owner: StateOwner,
pub open_type: OpenType,
pub name: Option<String>,
}
#[derive(Debug, Clone)]
pub enum OpenType {
NoCreate,
Create {
mode: OpenMode,
attrs: SetAttr,
verifier: Option<Verifier>,
},
}
#[derive(Debug, Clone)]
pub struct StateOwner {
pub clientid: ClientId,
pub owner: Vec<u8>,
}
#[derive(Debug, Clone)]
pub struct CloseArgs {
pub seqid: u32,
pub stateid: StateId,
}
#[derive(Debug, Clone)]
pub struct ReaddirArgs {
pub cookie: u64,
pub cookieverf: Verifier,
pub dircount: u32,
pub maxcount: u32,
pub attr_request: AttrBitmap,
}
#[derive(Debug, Clone)]
pub struct CreateArgs {
pub obj_type: CreateType,
pub name: String,
pub attrs: SetAttr,
}
#[derive(Debug, Clone)]
pub enum CreateType {
Regular,
Directory,
Symlink(String),
Block {
major: u32,
minor: u32,
},
Char {
major: u32,
minor: u32,
},
Socket,
Fifo,
}
#[derive(Debug, Clone)]
pub struct RemoveArgs {
pub target: String,
}
#[derive(Debug, Clone)]
pub struct RenameArgs {
pub oldname: String,
pub newname: String,
}
#[derive(Debug, Clone)]
pub struct LinkArgs {
pub newname: String,
}
#[derive(Debug, Clone)]
pub struct SetattrArgs {
pub stateid: StateId,
pub attrs: SetAttr,
}
#[derive(Debug, Clone)]
pub struct LockArgs {
pub locktype: LockType,
pub reclaim: bool,
pub offset: u64,
pub length: u64,
pub locker: Locker,
}
#[derive(Debug, Clone)]
pub enum Locker {
New {
open_seqid: u32,
open_stateid: StateId,
lock_seqid: u32,
lock_owner: StateOwner,
},
Existing {
lock_stateid: StateId,
lock_seqid: u32,
},
}
#[derive(Debug, Clone)]
pub struct LocktArgs {
pub locktype: LockType,
pub offset: u64,
pub length: u64,
pub owner: StateOwner,
}
#[derive(Debug, Clone)]
pub struct LockuArgs {
pub locktype: LockType,
pub seqid: u32,
pub lock_stateid: StateId,
pub offset: u64,
pub length: u64,
}
#[derive(Debug, Clone)]
pub struct CommitArgs {
pub offset: u64,
pub count: u32,
}
#[derive(Debug, Clone)]
pub struct SetclientidArgs {
pub verifier: Verifier,
pub id: Vec<u8>,
pub callback_program: u32,
pub callback_netid: String,
pub callback_addr: String,
pub callback_ident: u32,
}
#[derive(Debug, Clone)]
pub struct SetclientidConfirmArgs {
pub clientid: ClientId,
pub verifier: Verifier,
}
#[derive(Debug, Clone)]
pub struct RenewArgs {
pub clientid: ClientId,
}
#[derive(Debug, Clone)]
pub struct ExchangeIdArgs {
pub client_owner: ClientOwner4,
pub flags: u32,
pub state_protect: StateProtect4A,
pub impl_id: Vec<NfsImplId4>,
}
#[derive(Debug, Clone)]
pub struct ClientOwner4 {
pub verifier: Verifier,
pub ownerid: Vec<u8>,
}
#[derive(Debug, Clone)]
pub enum StateProtect4A {
None,
MachCred { ops: Vec<u32> },
Ssv {
ssv_ops: Vec<u32>,
hash_algs: Vec<u32>,
encrypt_algs: Vec<u32>,
},
}
#[derive(Debug, Clone)]
pub struct NfsImplId4 {
pub domain: String,
pub name: String,
pub date: u64,
}
#[derive(Debug, Clone)]
pub struct CreateSessionArgs {
pub clientid: ClientId,
pub seqid: u32,
pub flags: u32,
pub fore_chan_attrs: ChannelAttrs4,
pub back_chan_attrs: ChannelAttrs4,
pub cb_program: u32,
pub sec_parms: Vec<CallbackSecParms4>,
}
#[derive(Debug, Clone)]
pub struct ChannelAttrs4 {
pub header_pad_size: u32,
pub max_req_size: u32,
pub max_resp_size: u32,
pub max_resp_size_cached: u32,
pub max_ops: u32,
pub max_reqs: u32,
pub rdma_ird: Vec<u32>,
}
#[derive(Debug, Clone)]
pub struct CallbackSecParms4 {
pub flavor: u32,
pub auth_sys: Option<AuthSys>,
}
#[derive(Debug, Clone)]
pub struct AuthSys {
pub stamp: u32,
pub machinename: String,
pub uid: u32,
pub gid: u32,
pub gids: Vec<u32>,
}
#[derive(Debug, Clone)]
pub struct SequenceArgs {
pub sessionid: SessionId,
pub sequenceid: u32,
pub slotid: u32,
pub highest_slotid: u32,
pub cachethis: bool,
}
#[derive(Debug, Clone)]
pub struct DestroySessionArgs {
pub sessionid: SessionId,
}
#[derive(Debug, Clone)]
pub struct ReclaimCompleteArgs {
pub one_fs: bool,
}
#[derive(Debug, Clone)]
pub struct GetfhResult {
pub fh: FileHandle,
}
#[derive(Debug, Clone)]
pub struct GetattrResult {
pub attrs: NfsAttr,
pub attrmask: AttrBitmap,
}
#[derive(Debug, Clone)]
pub struct AccessResult {
pub supported: AccessBits,
pub access: AccessBits,
}
#[derive(Debug, Clone)]
pub struct ReadResult {
pub eof: bool,
pub data: Vec<u8>,
}
#[derive(Debug, Clone)]
pub struct WriteResult {
pub count: u32,
pub committed: StableHow,
pub verifier: Verifier,
}
#[derive(Debug, Clone)]
pub struct OpenResult {
pub stateid: StateId,
pub cinfo: ChangeInfo,
pub rflags: u32,
pub attrset: AttrBitmap,
pub delegation: Delegation,
}
#[derive(Debug, Clone, Copy)]
pub struct ChangeInfo {
pub atomic: bool,
pub before: u64,
pub after: u64,
}
#[derive(Debug, Clone)]
pub enum Delegation {
None,
Read {
stateid: StateId,
recall: bool,
permissions: u32,
},
Write {
stateid: StateId,
recall: bool,
space_limit: Option<u64>,
permissions: u32,
},
}
#[derive(Debug, Clone)]
pub struct CloseResult {
pub stateid: StateId,
}
#[derive(Debug, Clone)]
pub struct ReaddirResult {
pub cookieverf: Verifier,
pub entries: Vec<DirEntry>,
pub eof: bool,
}
#[derive(Debug, Clone, Copy)]
pub struct LookupResult;
#[derive(Debug, Clone)]
pub struct CreateResult {
pub cinfo: ChangeInfo,
pub attrset: AttrBitmap,
}
#[derive(Debug, Clone)]
pub struct RemoveResult {
pub cinfo: ChangeInfo,
}
#[derive(Debug, Clone)]
pub struct RenameResult {
pub source_cinfo: ChangeInfo,
pub target_cinfo: ChangeInfo,
}
#[derive(Debug, Clone)]
pub struct LinkResult {
pub cinfo: ChangeInfo,
}
#[derive(Debug, Clone)]
pub struct SetattrResult {
pub attrsset: AttrBitmap,
}
#[derive(Debug, Clone)]
pub struct ReadlinkResult {
pub link: String,
}
#[derive(Debug, Clone)]
pub struct LockResult {
pub lock_stateid: StateId,
}
#[derive(Debug, Clone)]
pub struct LockDenied {
pub offset: u64,
pub length: u64,
pub locktype: LockType,
pub owner: StateOwner,
}
#[derive(Debug, Clone)]
pub struct LockuResult {
pub lock_stateid: StateId,
}
#[derive(Debug, Clone)]
pub struct CommitResult {
pub verifier: Verifier,
}
#[derive(Debug, Clone)]
pub struct SetclientidResult {
pub clientid: ClientId,
pub verifier: Verifier,
}
#[derive(Debug, Clone)]
pub struct ExchangeIdResult {
pub clientid: ClientId,
pub sequenceid: u32,
pub flags: u32,
pub state_protect: StateProtect4R,
pub server_owner: ServerOwner4,
pub server_scope: Vec<u8>,
pub impl_id: Vec<NfsImplId4>,
}
#[derive(Debug, Clone)]
pub enum StateProtect4R {
None,
MachCred { ops: Vec<u32> },
Ssv { ssv_info: SsvInfo },
}
#[derive(Debug, Clone)]
pub struct SsvInfo {
pub hash_alg: u32,
pub encrypt_alg: u32,
pub ssv_len: u32,
pub window: u32,
pub handles: Vec<Vec<u8>>,
}
#[derive(Debug, Clone)]
pub struct ServerOwner4 {
pub minor_id: u64,
pub major_id: Vec<u8>,
}
#[derive(Debug, Clone)]
pub struct CreateSessionResult {
pub sessionid: SessionId,
pub sequenceid: u32,
pub flags: u32,
pub fore_chan_attrs: ChannelAttrs4,
pub back_chan_attrs: ChannelAttrs4,
}
#[derive(Debug, Clone)]
pub struct SequenceResult {
pub sessionid: SessionId,
pub sequenceid: u32,
pub slotid: u32,
pub highest_slotid: u32,
pub target_highest_slotid: u32,
pub status_flags: u32,
}
#[derive(Debug, Clone)]
pub struct CompoundRequest {
pub tag: String,
pub minorversion: u32,
pub operations: Vec<Operation>,
}
#[derive(Debug, Clone)]
pub struct CompoundResponse {
pub status: NfsStatus,
pub tag: String,
pub results: Vec<OperationResult>,
}
#[derive(Debug, Clone)]
pub enum Operation {
Access(AccessArgs),
Close(CloseArgs),
Commit(CommitArgs),
Create(CreateArgs),
Getattr(GetattrArgs),
Getfh,
Link(LinkArgs),
Lock(LockArgs),
Lockt(LocktArgs),
Locku(LockuArgs),
Lookup(LookupArgs),
Lookupp,
Open(OpenArgs),
Putfh(PutfhArgs),
Putpubfh,
Putrootfh,
Read(ReadArgs),
Readdir(ReaddirArgs),
Readlink,
Remove(RemoveArgs),
Rename(RenameArgs),
Renew(RenewArgs),
Restorefh,
Savefh,
Setattr(SetattrArgs),
Setclientid(SetclientidArgs),
SetclientidConfirm(SetclientidConfirmArgs),
Write(WriteArgs),
ExchangeId(ExchangeIdArgs),
CreateSession(CreateSessionArgs),
DestroySession(DestroySessionArgs),
Sequence(SequenceArgs),
ReclaimComplete(ReclaimCompleteArgs),
}
impl Operation {
pub fn opcode(&self) -> Opcode {
match self {
Self::Access(_) => Opcode::Access,
Self::Close(_) => Opcode::Close,
Self::Commit(_) => Opcode::Commit,
Self::Create(_) => Opcode::Create,
Self::Getattr(_) => Opcode::Getattr,
Self::Getfh => Opcode::Getfh,
Self::Link(_) => Opcode::Link,
Self::Lock(_) => Opcode::Lock,
Self::Lockt(_) => Opcode::Lockt,
Self::Locku(_) => Opcode::Locku,
Self::Lookup(_) => Opcode::Lookup,
Self::Lookupp => Opcode::Lookupp,
Self::Open(_) => Opcode::Open,
Self::Putfh(_) => Opcode::Putfh,
Self::Putpubfh => Opcode::Putpubfh,
Self::Putrootfh => Opcode::Putrootfh,
Self::Read(_) => Opcode::Read,
Self::Readdir(_) => Opcode::Readdir,
Self::Readlink => Opcode::Readlink,
Self::Remove(_) => Opcode::Remove,
Self::Rename(_) => Opcode::Rename,
Self::Renew(_) => Opcode::Renew,
Self::Restorefh => Opcode::Restorefh,
Self::Savefh => Opcode::Savefh,
Self::Setattr(_) => Opcode::Setattr,
Self::Setclientid(_) => Opcode::Setclientid,
Self::SetclientidConfirm(_) => Opcode::SetclientidConfirm,
Self::Write(_) => Opcode::Write,
Self::ExchangeId(_) => Opcode::ExchangeId,
Self::CreateSession(_) => Opcode::CreateSession,
Self::DestroySession(_) => Opcode::DestroySession,
Self::Sequence(_) => Opcode::Sequence,
Self::ReclaimComplete(_) => Opcode::ReclaimComplete,
}
}
}
#[derive(Debug, Clone)]
pub enum OperationResult {
Access(Result<AccessResult, NfsStatus>),
Close(Result<CloseResult, NfsStatus>),
Commit(Result<CommitResult, NfsStatus>),
Create(Result<CreateResult, NfsStatus>),
Getattr(Result<GetattrResult, NfsStatus>),
Getfh(Result<GetfhResult, NfsStatus>),
Link(Result<LinkResult, NfsStatus>),
Lock(Result<LockResult, NfsStatus>),
Lockt(Result<(), LockDenied>),
Locku(Result<LockuResult, NfsStatus>),
Lookup(Result<LookupResult, NfsStatus>),
Lookupp(Result<LookupResult, NfsStatus>),
Open(Result<OpenResult, NfsStatus>),
Putfh(Result<(), NfsStatus>),
Putpubfh(Result<(), NfsStatus>),
Putrootfh(Result<(), NfsStatus>),
Read(Result<ReadResult, NfsStatus>),
Readdir(Result<ReaddirResult, NfsStatus>),
Readlink(Result<ReadlinkResult, NfsStatus>),
Remove(Result<RemoveResult, NfsStatus>),
Rename(Result<RenameResult, NfsStatus>),
Renew(Result<(), NfsStatus>),
Restorefh(Result<(), NfsStatus>),
Savefh(Result<(), NfsStatus>),
Setattr(Result<SetattrResult, NfsStatus>),
Setclientid(Result<SetclientidResult, NfsStatus>),
SetclientidConfirm(Result<(), NfsStatus>),
Write(Result<WriteResult, NfsStatus>),
ExchangeId(Result<ExchangeIdResult, NfsStatus>),
CreateSession(Result<CreateSessionResult, NfsStatus>),
DestroySession(Result<(), NfsStatus>),
Sequence(Result<SequenceResult, NfsStatus>),
ReclaimComplete(Result<(), NfsStatus>),
}
impl OperationResult {
pub fn status(&self) -> NfsStatus {
match self {
Self::Access(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::Close(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::Commit(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::Create(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::Getattr(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::Getfh(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::Link(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::Lock(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::Lockt(r) => {
if r.is_ok() {
NfsStatus::Ok
} else {
NfsStatus::Denied
}
}
Self::Locku(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::Lookup(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::Lookupp(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::Open(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::Putfh(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::Putpubfh(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::Putrootfh(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::Read(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::Readdir(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::Readlink(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::Remove(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::Rename(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::Renew(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::Restorefh(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::Savefh(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::Setattr(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::Setclientid(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::SetclientidConfirm(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::Write(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::ExchangeId(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::CreateSession(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::DestroySession(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::Sequence(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
Self::ReclaimComplete(r) => r.as_ref().map(|_| NfsStatus::Ok).unwrap_or_else(|e| *e),
}
}
pub fn is_ok(&self) -> bool {
self.status() == NfsStatus::Ok
}
}
#[cfg(test)]
mod tests {
use super::*;
use alloc::vec;
#[test]
fn test_opcode_from_u32() {
assert_eq!(Opcode::from_u32(3), Some(Opcode::Access));
assert_eq!(Opcode::from_u32(25), Some(Opcode::Read));
assert_eq!(Opcode::from_u32(38), Some(Opcode::Write));
assert_eq!(Opcode::from_u32(9999), None);
}
#[test]
fn test_opcode_name() {
assert_eq!(Opcode::Access.name(), "ACCESS");
assert_eq!(Opcode::Read.name(), "READ");
assert_eq!(Opcode::Write.name(), "WRITE");
}
#[test]
fn test_stable_how() {
assert_eq!(StableHow::Unstable as u32, 0);
assert_eq!(StableHow::DataSync as u32, 1);
assert_eq!(StableHow::FileSync as u32, 2);
}
#[test]
fn test_change_info() {
let cinfo = ChangeInfo {
atomic: true,
before: 100,
after: 101,
};
assert!(cinfo.atomic);
assert_eq!(cinfo.before, 100);
assert_eq!(cinfo.after, 101);
}
#[test]
fn test_operation_opcode() {
let op = Operation::Lookup(LookupArgs {
name: "test".into(),
});
assert_eq!(op.opcode(), Opcode::Lookup);
let op2 = Operation::Getfh;
assert_eq!(op2.opcode(), Opcode::Getfh);
}
#[test]
fn test_operation_result_status() {
let ok_result = OperationResult::Lookup(Ok(LookupResult));
assert_eq!(ok_result.status(), NfsStatus::Ok);
assert!(ok_result.is_ok());
let err_result = OperationResult::Lookup(Err(NfsStatus::Noent));
assert_eq!(err_result.status(), NfsStatus::Noent);
assert!(!err_result.is_ok());
}
#[test]
fn test_compound_request() {
let req = CompoundRequest {
tag: "test".into(),
minorversion: 1,
operations: vec![
Operation::Putrootfh,
Operation::Lookup(LookupArgs { name: "dir".into() }),
Operation::Getfh,
],
};
assert_eq!(req.operations.len(), 3);
assert_eq!(req.minorversion, 1);
}
#[test]
fn test_state_owner() {
let owner = StateOwner {
clientid: ClientId::new(12345),
owner: b"user@host".to_vec(),
};
assert_eq!(owner.clientid.id, 12345);
}
#[test]
fn test_delegation_none() {
let deleg = Delegation::None;
assert!(matches!(deleg, Delegation::None));
}
#[test]
fn test_locker_new() {
let locker = Locker::New {
open_seqid: 1,
open_stateid: StateId::anonymous(),
lock_seqid: 1,
lock_owner: StateOwner {
clientid: ClientId::new(1),
owner: vec![],
},
};
assert!(matches!(locker, Locker::New { .. }));
}
#[test]
fn test_create_type() {
let dir = CreateType::Directory;
assert!(matches!(dir, CreateType::Directory));
let symlink = CreateType::Symlink("/target".into());
assert!(matches!(symlink, CreateType::Symlink(_)));
}
}