diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index c45b663c6d..f7c837c35b 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -214,13 +214,21 @@ Inode::LookUp(const char* name, ino_t* id) // more than one hard link and we delete the name it stores for filehandle // restoration node will inocorectly become unavailable. status_t -Inode::Remove(const char* name) +Inode::Remove(const char* name, FileType type) { do { RPC::Server* serv = fFilesystem->Server(); Request request(serv); RequestBuilder& req = request.Builder(); + req.PutFH(fHandle); + req.LookUp(name); + AttrValue attr; + attr.fAttribute = FATTR4_TYPE; + attr.fFreePointer = false; + attr.fData.fValue32 = type; + req.Verify(&attr, 1); + req.PutFH(fHandle); req.Remove(name); @@ -242,6 +250,22 @@ Inode::Remove(const char* name) continue; } + result = reply.PutFH(); + if (result != B_OK) + return result; + + result = reply.LookUp(); + if (result != B_OK) + return result; + + result = reply.Verify(); + if (result == NFS4ERR_NOT_SAME && type == NF4REG) + return B_IS_A_DIRECTORY; + if (result == NFS4ERR_NOT_SAME && type == NF4DIR) + return B_NOT_A_DIRECTORY; + if (result != B_OK) + return result; + result = reply.PutFH(); if (result != B_OK) return result; diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.h b/src/add-ons/kernel/file_systems/nfs4/Inode.h index f47182387a..3f1498eecb 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.h @@ -32,7 +32,7 @@ public: status_t LookUp(const char* name, ino_t* id); status_t ReadLink(void* buffer, size_t* length); - status_t Remove(const char* name); + status_t Remove(const char* name, FileType type); static status_t Rename(Inode* from, Inode* to, const char* fromName, const char* toName); status_t Access(int mode); diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h index 7db013f6d2..84d9b934a5 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h @@ -39,7 +39,8 @@ enum Opcode { OpRenew = 30, OpSaveFH = 32, OpSetClientID = 35, - OpSetClientIDConfirm = 36 + OpSetClientIDConfirm = 36, + OpVerify = 37 }; enum Access { diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h index ab295dfa7f..b0b3ba1411 100644 --- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h @@ -84,6 +84,7 @@ public: inline status_t SaveFH(); status_t SetClientID(uint64* clientid, uint64* verifier); inline status_t SetClientIDConfirm(); + inline status_t Verify(); private: void _ParseHeader(); @@ -178,5 +179,12 @@ ReplyInterpreter::SetClientIDConfirm() } +inline status_t +ReplyInterpreter::Verify() +{ + return _OperationError(OpVerify); +} + + #endif // REPLYINTERPRETER_H diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp index c0901baaae..e28bce3916 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp @@ -432,6 +432,37 @@ RequestBuilder::SetClientIDConfirm(uint64 id, uint64 ver) } +status_t +RequestBuilder::Verify(AttrValue* attr, uint32 count) +{ + if (fProcedure != ProcCompound) + return B_BAD_VALUE; + if (fRequest == NULL) + return B_NO_MEMORY; + + fRequest->Stream().AddUInt(OpVerify); + + Attribute* attrs = + reinterpret_cast(malloc(sizeof(Attribute) * count)); + for (uint32 i = 0; i < count; i++) + attrs[i] = static_cast(attr[i].fAttribute); + _AttrBitmap(fRequest->Stream(), attrs, count); + free(attrs); + + uint32 i = 0; + XDR::WriteStream str; + if (i < count && attr[i].fAttribute == FATTR4_TYPE) { + str.AddUInt(attr[i].fData.fValue32); + i++; + } + + fRequest->Stream().AddOpaque(str); + fOpCount++; + + return B_OK; +} + + RPC::Call* RequestBuilder::Request() { diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h index 61c1d19daa..795d6106be 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h +++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h @@ -12,6 +12,7 @@ #include #include "NFS4Defs.h" +#include "ReplyInterpreter.h" #include "RPCCall.h" #include "RPCServer.h" #include "XDR.h" @@ -50,6 +51,7 @@ public: status_t SaveFH(); status_t SetClientID(const RPC::Server* serv); status_t SetClientIDConfirm(uint64 id, uint64 ver); + status_t Verify(AttrValue* attr, uint32 count); RPC::Call* Request(); diff --git a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp index adf6d19eb9..f784dbf740 100644 --- a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp @@ -216,7 +216,7 @@ static status_t nfs4_unlink(fs_volume* volume, fs_vnode* dir, const char* name) { Inode* inode = reinterpret_cast(dir->private_node); - return inode->Remove(name); + return inode->Remove(name, NF4REG); } @@ -321,7 +321,7 @@ static status_t nfs4_remove_dir(fs_volume* volume, fs_vnode* parent, const char* name) { Inode* inode = reinterpret_cast(parent->private_node); - return inode->Remove(name); + return inode->Remove(name, NF4DIR); }