nfs4: Add create_symlink() hook
This commit is contained in:
@@ -383,6 +383,49 @@ Inode::Rename(Inode* from, Inode* to, const char* fromName, const char* toName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Inode::CreateLink(const char* name, const char* path, int mode)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
RPC::Server* serv = fFilesystem->Server();
|
||||||
|
Request request(serv);
|
||||||
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
|
req.PutFH(fHandle);
|
||||||
|
|
||||||
|
AttrValue attr;
|
||||||
|
attr.fAttribute = FATTR4_MODE;
|
||||||
|
attr.fFreePointer = false;
|
||||||
|
attr.fData.fValue32 = mode;
|
||||||
|
req.Create(NF4LNK, name, path, &attr, 1);
|
||||||
|
|
||||||
|
status_t result = request.Send();
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
|
// filehandle has expired
|
||||||
|
if (reply.NFS4Error() == NFS4ERR_FHEXPIRED) {
|
||||||
|
_LookUpFilehandle();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// filesystem has been moved
|
||||||
|
if (reply.NFS4Error() == NFS4ERR_MOVED) {
|
||||||
|
fFilesystem->Migrate(fHandle, serv);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = reply.PutFH();
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
return reply.Create();
|
||||||
|
} while (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Inode::ReadLink(void* buffer, size_t* length)
|
Inode::ReadLink(void* buffer, size_t* length)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,7 +31,11 @@ public:
|
|||||||
inline Filesystem* FileSystem() const;
|
inline Filesystem* FileSystem() const;
|
||||||
|
|
||||||
status_t LookUp(const char* name, ino_t* id);
|
status_t LookUp(const char* name, ino_t* id);
|
||||||
|
|
||||||
|
status_t CreateLink(const char* name, const char* path,
|
||||||
|
int mode);
|
||||||
status_t ReadLink(void* buffer, size_t* length);
|
status_t ReadLink(void* buffer, size_t* length);
|
||||||
|
|
||||||
status_t Link(Inode* dir, const char* name);
|
status_t Link(Inode* dir, const char* name);
|
||||||
status_t Remove(const char* name, FileType type);
|
status_t Remove(const char* name, FileType type);
|
||||||
static status_t Rename(Inode* from, Inode* to,
|
static status_t Rename(Inode* from, Inode* to,
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ enum Procedure {
|
|||||||
enum Opcode {
|
enum Opcode {
|
||||||
OpAccess = 3,
|
OpAccess = 3,
|
||||||
OpClose = 4,
|
OpClose = 4,
|
||||||
|
OpCreate = 6,
|
||||||
OpGetAttr = 9,
|
OpGetAttr = 9,
|
||||||
OpGetFH = 10,
|
OpGetFH = 10,
|
||||||
OpLink = 11,
|
OpLink = 11,
|
||||||
|
|||||||
@@ -122,6 +122,25 @@ ReplyInterpreter::Close()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ReplyInterpreter::Create()
|
||||||
|
{
|
||||||
|
status_t res = _OperationError(OpCreate);
|
||||||
|
if (res != B_OK)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
fReply->Stream().GetBoolean();
|
||||||
|
fReply->Stream().GetUHyper();
|
||||||
|
fReply->Stream().GetUHyper();
|
||||||
|
uint32 count = fReply->Stream().GetUInt();
|
||||||
|
for (uint32 i; i < count; i++)
|
||||||
|
fReply->Stream().GetUInt();
|
||||||
|
|
||||||
|
return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Bit Twiddling Hacks
|
// Bit Twiddling Hacks
|
||||||
// http://graphics.stanford.edu/~seander/bithacks.html
|
// http://graphics.stanford.edu/~seander/bithacks.html
|
||||||
static inline uint32 sCountBits(uint32 v)
|
static inline uint32 sCountBits(uint32 v)
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ public:
|
|||||||
|
|
||||||
status_t Access(uint32* supported, uint32* allowed);
|
status_t Access(uint32* supported, uint32* allowed);
|
||||||
status_t Close();
|
status_t Close();
|
||||||
|
status_t Create();
|
||||||
status_t GetAttr(AttrValue** attrs, uint32* count);
|
status_t GetAttr(AttrValue** attrs, uint32* count);
|
||||||
status_t GetFH(Filehandle* fh);
|
status_t GetFH(Filehandle* fh);
|
||||||
status_t Link();
|
status_t Link();
|
||||||
|
|||||||
@@ -86,6 +86,33 @@ RequestBuilder::Close(uint32 seq, const uint32* id, uint32 stateSeq)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
RequestBuilder::Create(FileType type, const char* name, const char* path,
|
||||||
|
AttrValue* attr, uint32 count)
|
||||||
|
{
|
||||||
|
if (fProcedure != ProcCompound)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
if (fRequest == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
if (path == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
if (name == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
if (type != NF4LNK)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
fRequest->Stream().AddUInt(OpCreate);
|
||||||
|
fRequest->Stream().AddUInt(type);
|
||||||
|
fRequest->Stream().AddString(path);
|
||||||
|
fRequest->Stream().AddString(name);
|
||||||
|
_EncodeAttrs(fRequest->Stream(), attr, count);
|
||||||
|
|
||||||
|
fOpCount++;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
RequestBuilder::GetAttr(Attribute* attrs, uint32 count)
|
RequestBuilder::GetAttr(Attribute* attrs, uint32 count)
|
||||||
{
|
{
|
||||||
@@ -459,22 +486,8 @@ RequestBuilder::Verify(AttrValue* attr, uint32 count)
|
|||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
fRequest->Stream().AddUInt(OpVerify);
|
fRequest->Stream().AddUInt(OpVerify);
|
||||||
|
_EncodeAttrs(fRequest->Stream(), attr, count);
|
||||||
|
|
||||||
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++;
|
fOpCount++;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -511,3 +524,30 @@ RequestBuilder::_AttrBitmap(XDR::WriteStream& stream, Attribute* attrs,
|
|||||||
stream.AddUInt(bitmap[i]);
|
stream.AddUInt(bitmap[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
RequestBuilder::_EncodeAttrs(XDR::WriteStream& stream, AttrValue* attr,
|
||||||
|
uint32 count)
|
||||||
|
{
|
||||||
|
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(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++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < count && attr[i].fAttribute == FATTR4_MODE) {
|
||||||
|
str.AddUInt(attr[i].fData.fValue32);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.AddOpaque(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ public:
|
|||||||
status_t Access();
|
status_t Access();
|
||||||
status_t Close(uint32 seq, const uint32* id,
|
status_t Close(uint32 seq, const uint32* id,
|
||||||
uint32 stateSeq);
|
uint32 stateSeq);
|
||||||
|
status_t Create(FileType type, const char* name,
|
||||||
|
const char* path, AttrValue* attr,
|
||||||
|
uint32 count);
|
||||||
status_t GetAttr(Attribute* attrs, uint32 count);
|
status_t GetAttr(Attribute* attrs, uint32 count);
|
||||||
status_t GetFH();
|
status_t GetFH();
|
||||||
status_t Link(const char* name);
|
status_t Link(const char* name);
|
||||||
@@ -59,6 +62,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
void _InitHeader();
|
void _InitHeader();
|
||||||
|
|
||||||
|
void _EncodeAttrs(XDR::WriteStream& stream,
|
||||||
|
AttrValue* attr, uint32 count);
|
||||||
void _AttrBitmap(XDR::WriteStream& stream,
|
void _AttrBitmap(XDR::WriteStream& stream,
|
||||||
Attribute* attrs, uint32 count);
|
Attribute* attrs, uint32 count);
|
||||||
|
|
||||||
|
|||||||
@@ -212,6 +212,15 @@ nfs4_read_symlink(fs_volume* volume, fs_vnode* link, char* buffer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
nfs4_create_symlink(fs_volume* volume, fs_vnode* dir, const char* name,
|
||||||
|
const char* path, int mode)
|
||||||
|
{
|
||||||
|
Inode* inode = reinterpret_cast<Inode*>(dir->private_node);
|
||||||
|
return inode->CreateLink(name, path, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
nfs4_link(fs_volume* volume, fs_vnode* dir, const char* name, fs_vnode* vnode)
|
nfs4_link(fs_volume* volume, fs_vnode* dir, const char* name, fs_vnode* vnode)
|
||||||
{
|
{
|
||||||
@@ -456,7 +465,7 @@ fs_vnode_ops gNFSv4VnodeOps = {
|
|||||||
NULL, // fsync()
|
NULL, // fsync()
|
||||||
|
|
||||||
nfs4_read_symlink,
|
nfs4_read_symlink,
|
||||||
NULL, // create_symlink()
|
nfs4_create_symlink,
|
||||||
|
|
||||||
nfs4_link,
|
nfs4_link,
|
||||||
nfs4_unlink,
|
nfs4_unlink,
|
||||||
|
|||||||
Reference in New Issue
Block a user