nfs4: unlink() and remove_dir() should check node type

This commit is contained in:
Pawel Dziepak
2012-06-29 02:15:03 +02:00
parent 6fb3845b38
commit cf511f2446
7 changed files with 71 additions and 5 deletions
+25 -1
View File
@@ -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;
+1 -1
View File
@@ -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);
@@ -39,7 +39,8 @@ enum Opcode {
OpRenew = 30,
OpSaveFH = 32,
OpSetClientID = 35,
OpSetClientIDConfirm = 36
OpSetClientIDConfirm = 36,
OpVerify = 37
};
enum Access {
@@ -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
@@ -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<Attribute*>(malloc(sizeof(Attribute) * count));
for (uint32 i = 0; i < count; i++)
attrs[i] = static_cast<Attribute>(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()
{
@@ -12,6 +12,7 @@
#include <SupportDefs.h>
#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();
@@ -216,7 +216,7 @@ static status_t
nfs4_unlink(fs_volume* volume, fs_vnode* dir, const char* name)
{
Inode* inode = reinterpret_cast<Inode*>(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<Inode*>(parent->private_node);
return inode->Remove(name);
return inode->Remove(name, NF4DIR);
}