The last missing hooks -- get_vnode_name(), write_attr_stat() and

rewind_query() -- are passed to the userland. get_vnode_name() has an
emulation in userland, in case the client FS doesn't implement it.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20522 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2007-04-03 04:40:54 +00:00
parent 610f8dbb5f
commit ed07b9c7e3
14 changed files with 537 additions and 15 deletions
@@ -43,6 +43,8 @@ enum {
// vnodes
LOOKUP_REQUEST,
LOOKUP_REPLY,
GET_VNODE_NAME_REQUEST,
GET_VNODE_NAME_REPLY,
READ_VNODE_REQUEST,
READ_VNODE_REPLY,
WRITE_VNODE_REQUEST,
@@ -137,6 +139,8 @@ enum {
WRITE_ATTR_REPLY,
READ_ATTR_STAT_REQUEST,
READ_ATTR_STAT_REPLY,
WRITE_ATTR_STAT_REQUEST,
WRITE_ATTR_STAT_REPLY,
RENAME_ATTR_REQUEST,
RENAME_ATTR_REPLY,
REMOVE_ATTR_REQUEST,
@@ -169,6 +173,8 @@ enum {
FREE_QUERY_COOKIE_REPLY,
READ_QUERY_REQUEST,
READ_QUERY_REPLY,
REWIND_QUERY_REQUEST,
REWIND_QUERY_REPLY,
// userland -> kernel requests
// notifications
@@ -428,6 +434,23 @@ public:
int type;
};
// GetVNodeNameRequest
class GetVNodeNameRequest : public NodeRequest {
public:
GetVNodeNameRequest() : NodeRequest(GET_VNODE_NAME_REQUEST) {}
size_t size;
};
// GetVNodeNameReply
class GetVNodeNameReply : public ReplyRequest {
public:
GetVNodeNameReply() : ReplyRequest(GET_VNODE_NAME_REPLY) {}
status_t GetAddressInfos(AddressInfo* infos, int32* count);
Address buffer;
};
// ReadVNodeRequest
class ReadVNodeRequest : public VolumeRequest {
public:
@@ -1085,6 +1108,21 @@ public:
struct stat st;
};
// WriteAttrStatRequest
class WriteAttrStatRequest : public AttributeRequest {
public:
WriteAttrStatRequest() : AttributeRequest(WRITE_ATTR_STAT_REQUEST) {}
struct stat st;
uint32 mask;
};
// WriteAttrStatReply
class WriteAttrStatReply : public ReplyRequest {
public:
WriteAttrStatReply() : ReplyRequest(WRITE_ATTR_STAT_REPLY) {}
};
// RenameAttrRequest
class RenameAttrRequest : public VolumeRequest {
public:
@@ -1308,6 +1346,18 @@ public:
Address buffer;
};
// RewindQueryRequest
class RewindQueryRequest : public QueryRequest {
public:
RewindQueryRequest() : QueryRequest(REWIND_QUERY_REQUEST) {}
};
// RewindQueryReply
class RewindQueryReply : public ReplyRequest {
public:
RewindQueryReply() : ReplyRequest(REWIND_QUERY_REPLY) {}
};
// #pragma mark -
// #pragma mark ----- userland requests -----
@@ -1552,6 +1602,10 @@ do_for_request(Request* request, Task& task)
return task((LookupRequest*)request);
case LOOKUP_REPLY:
return task((LookupReply*)request);
case GET_VNODE_NAME_REQUEST:
return task((GetVNodeNameRequest*)request);
case GET_VNODE_NAME_REPLY:
return task((GetVNodeNameReply*)request);
case READ_VNODE_REQUEST:
return task((ReadVNodeRequest*)request);
case READ_VNODE_REPLY:
@@ -1721,6 +1775,10 @@ do_for_request(Request* request, Task& task)
return task((ReadAttrStatRequest*)request);
case READ_ATTR_STAT_REPLY:
return task((ReadAttrStatReply*)request);
case WRITE_ATTR_STAT_REQUEST:
return task((WriteAttrStatRequest*)request);
case WRITE_ATTR_STAT_REPLY:
return task((WriteAttrStatReply*)request);
case RENAME_ATTR_REQUEST:
return task((RenameAttrRequest*)request);
case RENAME_ATTR_REPLY:
@@ -1779,6 +1837,10 @@ do_for_request(Request* request, Task& task)
return task((ReadQueryRequest*)request);
case READ_QUERY_REPLY:
return task((ReadQueryReply*)request);
case REWIND_QUERY_REQUEST:
return task((RewindQueryRequest*)request);
case REWIND_QUERY_REPLY:
return task((RewindQueryReply*)request);
// userland -> kernel requests
// notifications
@@ -1869,6 +1931,8 @@ using UserlandFSUtil::WriteFSInfoReply;
// vnodes
using UserlandFSUtil::LookupRequest;
using UserlandFSUtil::LookupReply;
using UserlandFSUtil::GetVNodeNameRequest;
using UserlandFSUtil::GetVNodeNameReply;
using UserlandFSUtil::ReadVNodeRequest;
using UserlandFSUtil::ReadVNodeReply;
using UserlandFSUtil::WriteVNodeRequest;
@@ -1956,6 +2020,8 @@ using UserlandFSUtil::WriteAttrRequest;
using UserlandFSUtil::WriteAttrReply;
using UserlandFSUtil::ReadAttrStatRequest;
using UserlandFSUtil::ReadAttrStatReply;
using UserlandFSUtil::WriteAttrStatRequest;
using UserlandFSUtil::WriteAttrStatReply;
using UserlandFSUtil::RenameAttrRequest;
using UserlandFSUtil::RenameAttrReply;
using UserlandFSUtil::RemoveAttrRequest;
@@ -1986,6 +2052,8 @@ using UserlandFSUtil::FreeQueryCookieRequest;
using UserlandFSUtil::FreeQueryCookieReply;
using UserlandFSUtil::ReadQueryRequest;
using UserlandFSUtil::ReadQueryReply;
using UserlandFSUtil::RewindQueryRequest;
using UserlandFSUtil::RewindQueryReply;
// userland -> kernel requests
// notifications
@@ -1,6 +1,9 @@
// Volume.cpp
#include "Volume.h"
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
@@ -16,7 +19,6 @@
#include "RequestPort.h"
#include "Requests.h"
#include "userlandfs_ioctl.h"
#include "Volume.h"
// missing ioctl()s
// TODO: Place somewhere else.
@@ -402,6 +404,55 @@ Volume::Lookup(fs_vnode dir, const char* entryName, vnode_id* vnid, int* type)
return error;
}
// GetVNodeName
status_t
Volume::GetVNodeName(fs_vnode node, char* buffer, size_t bufferSize)
{
// We don't check the capability -- if not implemented by the client FS,
// the functionality is emulated in userland.
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
return B_ERROR;
PortReleaser _(fFileSystem->GetPortPool(), port);
// prepare the request
RequestAllocator allocator(port->GetPort());
GetVNodeNameRequest* request;
status_t error = AllocateRequest(allocator, &request);
if (error != B_OK)
return error;
request->volume = fUserlandVolume;
request->node = node;
request->size = bufferSize;
// send the request
KernelRequestHandler handler(this, GET_VNODE_NAME_REPLY);
GetVNodeNameReply* reply;
error = _SendRequest(port, &allocator, &handler, (Request**)&reply);
if (error != B_OK)
return error;
RequestReleaser requestReleaser(port, reply);
// process the reply
if (reply->error != B_OK)
return reply->error;
char* readBuffer = (char*)reply->buffer.GetData();
size_t nameLen = reply->buffer.GetSize();
nameLen = strnlen(readBuffer, nameLen);
if (nameLen <= 1 || nameLen >= bufferSize)
RETURN_ERROR(B_BAD_DATA);
memcpy(buffer, readBuffer, nameLen);
buffer[nameLen] = '\0';
_SendReceiptAck(port);
return error;
}
// ReadVNode
status_t
Volume::ReadVNode(vnode_id vnid, bool reenter, fs_vnode* node)
@@ -2099,6 +2150,48 @@ Volume::ReadAttrStat(fs_vnode node, fs_cookie cookie, struct stat *st)
return error;
}
// WriteAttrStat
status_t
Volume::WriteAttrStat(fs_vnode node, fs_cookie cookie, const struct stat *st,
int statMask)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_WRITE_ATTR_STAT))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
return B_ERROR;
PortReleaser _(fFileSystem->GetPortPool(), port);
// prepare the request
RequestAllocator allocator(port->GetPort());
WriteAttrStatRequest* request;
status_t error = AllocateRequest(allocator, &request);
if (error != B_OK)
return error;
request->volume = fUserlandVolume;
request->node = node;
request->attrCookie = cookie;
request->st = *st;
request->mask = statMask;
// send the request
KernelRequestHandler handler(this, WRITE_ATTR_STAT_REPLY);
WriteAttrStatReply* reply;
error = _SendRequest(port, &allocator, &handler, (Request**)&reply);
if (error != B_OK)
return error;
RequestReleaser requestReleaser(port, reply);
// process the reply
if (reply->error != B_OK)
return reply->error;
return error;
}
// RenameAttr
status_t
Volume::RenameAttr(fs_vnode oldNode, const char* oldName, fs_vnode newNode,
@@ -2632,6 +2725,44 @@ Volume::ReadQuery(fs_cookie cookie, void* buffer, size_t bufferSize,
return error;
}
// RewindQuery
status_t
Volume::RewindQuery(fs_cookie cookie)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_REWIND_QUERY))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
return B_ERROR;
PortReleaser _(fFileSystem->GetPortPool(), port);
// prepare the request
RequestAllocator allocator(port->GetPort());
RewindQueryRequest* request;
status_t error = AllocateRequest(allocator, &request);
if (error != B_OK)
return error;
request->volume = fUserlandVolume;
request->queryCookie = cookie;
// send the request
KernelRequestHandler handler(this, REWIND_QUERY_REPLY);
RewindQueryReply* reply;
error = _SendRequest(port, &allocator, &handler, (Request**)&reply);
if (error != B_OK)
return error;
RequestReleaser requestReleaser(port, reply);
// process the reply
if (reply->error != B_OK)
return reply->error;
return error;
}
// #pragma mark -
// #pragma mark ----- private implementations -----
@@ -12,15 +12,18 @@ namespace UserlandFSUtil {
class Request;
class RequestAllocator;
class RequestHandler;
class RequestPort;
struct userlandfs_ioctl;
}
using UserlandFSUtil::Request;
using UserlandFSUtil::RequestAllocator;
using UserlandFSUtil::RequestHandler;
using UserlandFSUtil::RequestPort;
using UserlandFSUtil::userlandfs_ioctl;
class FileSystem;
struct userlandfs_ioctl;
class Volume : public Referencable {
public:
@@ -55,6 +58,8 @@ public:
// vnodes
status_t Lookup(fs_vnode dir, const char* entryName,
vnode_id* vnid, int* type);
status_t GetVNodeName(fs_vnode node, char* buffer,
size_t bufferSize);
status_t ReadVNode(vnode_id vnid, bool reenter,
fs_vnode* node);
status_t WriteVNode(fs_vnode node, bool reenter);
@@ -141,6 +146,8 @@ public:
size_t bufferSize, size_t* bytesWritten);
status_t ReadAttrStat(fs_vnode node, fs_cookie cookie,
struct stat *st);
status_t WriteAttrStat(fs_vnode node, fs_cookie cookie,
const struct stat *st, int statMask);
status_t RenameAttr(fs_vnode oldNode,
const char* oldName, fs_vnode newNode,
const char* newName);
@@ -169,6 +176,7 @@ public:
status_t ReadQuery(fs_cookie cookie, void* buffer,
size_t bufferSize, uint32 count,
uint32* countRead);
status_t RewindQuery(fs_cookie cookie);
private:
status_t _Mount(const char* device, uint32 flags,
@@ -176,7 +176,19 @@ userlandfs_lookup(fs_volume fs, fs_vnode dir, const char *entryName,
return error;
}
// TODO: userlandfs_get_vnode_name()
// userlandfs_get_vnode_name
static status_t
userlandfs_get_vnode_name(fs_volume fs, fs_vnode node, char *buffer,
size_t bufferSize)
{
Volume* volume = (Volume*)fs;
PRINT(("userlandfs_get_vnode_name(%p, %p, %p, %lu)\n", fs, node,
buffer, bufferSize));
status_t error = volume->GetVNodeName(node, buffer, bufferSize);
PRINT(("userlandfs_get_vnode_name() done: (%lx, \"%.*s\")\n", error,
(int)bufferSize, (error == B_OK ? buffer : NULL)));
return error;
}
// userlandfs_get_vnode
static status_t
@@ -546,7 +558,7 @@ userlandfs_read_dir(fs_volume fs, fs_vnode node, fs_cookie cookie,
PRINT(("userlandfs_read_dir() done: (%lx, %lu)\n", error, *count));
#if DEBUG
dirent* entry = buffer;
for (uint32 i = 0; i < *count; i++) {
for (uint32 i = 0; error == B_OK && i < *count; i++) {
// R5's kernel vsprintf() doesn't seem to know `%.<number>s', so
// we need to work around.
char name[B_FILE_NAME_LENGTH];
@@ -722,14 +734,25 @@ userlandfs_read_attr_stat(fs_volume fs, fs_vnode node, fs_cookie cookie,
struct stat *st)
{
Volume* volume = (Volume*)fs;
PRINT(("userlandfs_read_attr_stat(%p, %p, %p', %p)\n", fs, node, cookie,
PRINT(("userlandfs_read_attr_stat(%p, %p, %p, %p)\n", fs, node, cookie,
st));
status_t error = volume->ReadAttrStat(node, cookie, st);
PRINT(("userlandfs_read_attr_stat() done: (%lx)\n", error));
return error;
}
// TODO: userlandfs_write_attr_stat
// userlandfs_write_attr_stat
static status_t
userlandfs_write_attr_stat(fs_volume fs, fs_vnode node, fs_cookie cookie,
const struct stat *st, int statMask)
{
Volume* volume = (Volume*)fs;
PRINT(("userlandfs_write_attr_stat(%p, %p, %p, %p, 0x%x)\n", fs, node,
cookie, st, statMask));
status_t error = volume->WriteAttrStat(node, cookie, st, statMask);
PRINT(("userlandfs_write_attr_stat() done: (%lx)\n", error));
return error;
}
// userlandfs_rename_attr
static status_t
@@ -903,7 +926,7 @@ userlandfs_read_query(fs_volume fs, fs_cookie cookie,
count);
PRINT(("userlandfs_read_query() done: (%lx, %ld)\n", error, *count));
#if DEBUG
if (*count > 0) {
if (error == B_OK && *count > 0) {
// R5's kernel vsprintf() doesn't seem to know `%.<number>s', so
// we need to work around.
char name[B_FILE_NAME_LENGTH];
@@ -919,7 +942,16 @@ userlandfs_read_query(fs_volume fs, fs_cookie cookie,
return error;
}
// TODO: userlandfs_rewind_query()
// userlandfs_rewind_query
static status_t
userlandfs_rewind_query(fs_volume fs, fs_cookie cookie)
{
Volume* volume = (Volume*)fs;
PRINT(("userlandfs_rewind_query(%p, %p)\n", fs, cookie));
status_t error = volume->RewindQuery(cookie);
PRINT(("userlandfs_rewind_query() done: (%lx)\n", error));
return error;
}
// userlandfs_initialize
@@ -1017,7 +1049,7 @@ static file_system_module_info sUserlandFSModuleInfo = {
/* vnode operations */
&userlandfs_lookup,
NULL, // &userlandfs_get_vnode_name,
&userlandfs_get_vnode_name,
&userlandfs_get_vnode,
&userlandfs_put_vnode,
&userlandfs_remove_vnode,
@@ -1079,7 +1111,7 @@ static file_system_module_info sUserlandFSModuleInfo = {
&userlandfs_write_attr,
&userlandfs_read_attr_stat,
NULL, // &userlandfs_write_attr_stat,
&userlandfs_write_attr_stat,
&userlandfs_rename_attr,
&userlandfs_remove_attr,
@@ -1099,7 +1131,7 @@ static file_system_module_info sUserlandFSModuleInfo = {
&userlandfs_close_query,
&userlandfs_free_query_cookie,
&userlandfs_read_query,
NULL, // &userlandfs_rewind_query,
&userlandfs_rewind_query
};
module_info *modules[] = {
@@ -53,6 +53,14 @@ MountVolumeRequest::GetAddressInfos(AddressInfo* infos, int32* count)
// return B_OK;
//}
// GetVNodeNameReply
status_t
GetVNodeNameReply::GetAddressInfos(AddressInfo* infos, int32* count)
{
ADD_STRING(buffer);
return B_OK;
}
// CreateRequest
status_t
CreateRequest::GetAddressInfos(AddressInfo* infos, int32* count)
@@ -496,11 +504,13 @@ UserlandFSUtil::is_kernel_request(uint32 type)
return false;
// vnodes
case LOOKUP_REQUEST:
case GET_VNODE_NAME_REQUEST:
case READ_VNODE_REQUEST:
case WRITE_VNODE_REQUEST:
case FS_REMOVE_VNODE_REQUEST:
return true;
case LOOKUP_REPLY:
case GET_VNODE_NAME_REPLY:
case READ_VNODE_REPLY:
case WRITE_VNODE_REPLY:
case FS_REMOVE_VNODE_REPLY:
@@ -587,6 +597,7 @@ UserlandFSUtil::is_kernel_request(uint32 type)
case READ_ATTR_REQUEST:
case WRITE_ATTR_REQUEST:
case READ_ATTR_STAT_REQUEST:
case WRITE_ATTR_STAT_REQUEST:
case RENAME_ATTR_REQUEST:
case REMOVE_ATTR_REQUEST:
return true;
@@ -594,10 +605,10 @@ UserlandFSUtil::is_kernel_request(uint32 type)
case OPEN_ATTR_REPLY:
case CLOSE_ATTR_REPLY:
case FREE_ATTR_COOKIE_REPLY:
case READ_ATTR_REPLY:
case WRITE_ATTR_REPLY:
case READ_ATTR_STAT_REPLY:
case WRITE_ATTR_STAT_REPLY:
case RENAME_ATTR_REPLY:
case REMOVE_ATTR_REPLY:
return false;
@@ -625,11 +636,13 @@ UserlandFSUtil::is_kernel_request(uint32 type)
case CLOSE_QUERY_REQUEST:
case FREE_QUERY_COOKIE_REQUEST:
case READ_QUERY_REQUEST:
case REWIND_QUERY_REQUEST:
return true;
case OPEN_QUERY_REPLY:
case CLOSE_QUERY_REPLY:
case FREE_QUERY_COOKIE_REPLY:
case READ_QUERY_REPLY:
case REWIND_QUERY_REPLY:
return false;
// userland -> kernel requests
@@ -697,11 +710,13 @@ UserlandFSUtil::is_userland_request(uint32 type)
return true;
// vnodes
case LOOKUP_REQUEST:
case GET_VNODE_NAME_REQUEST:
case READ_VNODE_REQUEST:
case WRITE_VNODE_REQUEST:
case FS_REMOVE_VNODE_REQUEST:
return false;
case LOOKUP_REPLY:
case GET_VNODE_NAME_REPLY:
case READ_VNODE_REPLY:
case WRITE_VNODE_REPLY:
case FS_REMOVE_VNODE_REPLY:
@@ -789,6 +804,7 @@ UserlandFSUtil::is_userland_request(uint32 type)
case WRITE_ATTR_REQUEST:
case RENAME_ATTR_REQUEST:
case READ_ATTR_STAT_REQUEST:
case WRITE_ATTR_STAT_REQUEST:
case REMOVE_ATTR_REQUEST:
return false;
case CREATE_ATTR_REPLY:
@@ -798,6 +814,7 @@ UserlandFSUtil::is_userland_request(uint32 type)
case READ_ATTR_REPLY:
case WRITE_ATTR_REPLY:
case READ_ATTR_STAT_REPLY:
case WRITE_ATTR_STAT_REPLY:
case RENAME_ATTR_REPLY:
case REMOVE_ATTR_REPLY:
return true;
@@ -825,11 +842,13 @@ UserlandFSUtil::is_userland_request(uint32 type)
case CLOSE_QUERY_REQUEST:
case FREE_QUERY_COOKIE_REQUEST:
case READ_QUERY_REQUEST:
case REWIND_QUERY_REQUEST:
return false;
case OPEN_QUERY_REPLY:
case CLOSE_QUERY_REPLY:
case FREE_QUERY_COOKIE_REPLY:
case READ_QUERY_REPLY:
case REWIND_QUERY_REPLY:
return true;
// userland -> kernel requests
@@ -1,9 +1,10 @@
// SingleReplyRequestHandler.cpp
#include "SingleReplyRequestHandler.h"
#include "Compatibility.h"
#include "Debug.h"
#include "Request.h"
#include "SingleReplyRequestHandler.h"
// constructor
SingleReplyRequestHandler::SingleReplyRequestHandler()
@@ -157,6 +157,16 @@ BeOSKernelVolume::Lookup(fs_vnode dir, const char* entryName, vnode_id* vnid,
return error;
}
// LookupNoType
status_t
BeOSKernelVolume::LookupNoType(fs_vnode dir, const char* entryName,
vnode_id* vnid)
{
if (!fFSOps->walk)
return B_BAD_VALUE;
return fFSOps->walk(fVolumeCookie, dir, entryName, NULL, vnid);
}
// ReadVNode
status_t
BeOSKernelVolume::ReadVNode(vnode_id vnid, bool reenter, fs_vnode* node)
@@ -27,6 +27,9 @@ public:
// vnodes
virtual status_t Lookup(fs_vnode dir, const char* entryName,
vnode_id* vnid, int* type);
virtual status_t LookupNoType(fs_vnode dir,
const char* entryName, vnode_id* vnid);
// not required
virtual status_t ReadVNode(vnode_id vnid, bool reenter,
fs_vnode* node);
virtual status_t WriteVNode(fs_vnode node, bool reenter);
@@ -126,6 +126,17 @@ HaikuKernelVolume::Lookup(fs_vnode dir, const char* entryName, vnode_id* vnid,
return fFSModule->lookup(fVolumeCookie, dir, entryName, vnid, type);
}
// GetVNodeName
status_t
HaikuKernelVolume::GetVNodeName(fs_vnode node, char* buffer, size_t bufferSize)
{
// If not implemented by the client file system, we invoke our super class
// version, which emulates the functionality.
if (!fFSModule->get_vnode_name)
return Volume::GetVNodeName(node, buffer, bufferSize);
return fFSModule->get_vnode_name(fVolumeCookie, node, buffer, bufferSize);
}
// ReadVNode
status_t
HaikuKernelVolume::ReadVNode(vnode_id vnid, bool reenter, fs_vnode* node)
@@ -563,6 +574,17 @@ HaikuKernelVolume::ReadAttrStat(fs_vnode node, fs_cookie cookie,
return fFSModule->read_attr_stat(fVolumeCookie, node, cookie, st);
}
// WriteAttrStat
status_t
HaikuKernelVolume::WriteAttrStat(fs_vnode node, fs_cookie cookie,
const struct stat* st, int statMask)
{
if (!fFSModule->write_attr_stat)
return B_BAD_VALUE;
return fFSModule->write_attr_stat(fVolumeCookie, node, cookie, st,
statMask);
}
// RenameAttr
status_t
HaikuKernelVolume::RenameAttr(fs_vnode oldNode, const char* oldName,
@@ -710,3 +732,13 @@ HaikuKernelVolume::ReadQuery(fs_cookie cookie, void* buffer, size_t bufferSize,
return fFSModule->read_query(fVolumeCookie, cookie, (struct dirent*)buffer,
bufferSize, countRead);
}
// RewindQuery
status_t
HaikuKernelVolume::RewindQuery(fs_cookie cookie)
{
if (!fFSModule->rewind_query)
return B_BAD_VALUE;
return fFSModule->rewind_query(fVolumeCookie, cookie);
}
@@ -33,6 +33,8 @@ public:
// vnodes
virtual status_t Lookup(fs_vnode dir, const char* entryName,
vnode_id* vnid, int* type);
virtual status_t GetVNodeName(fs_vnode node, char* buffer,
size_t bufferSize);
virtual status_t ReadVNode(vnode_id vnid, bool reenter,
fs_vnode* node);
virtual status_t WriteVNode(fs_vnode node, bool reenter);
@@ -119,6 +121,8 @@ public:
size_t bufferSize, size_t* bytesWritten);
virtual status_t ReadAttrStat(fs_vnode node, fs_cookie cookie,
struct stat *st);
virtual status_t WriteAttrStat(fs_vnode node, fs_cookie cookie,
const struct stat* st, int statMask);
virtual status_t RenameAttr(fs_vnode oldNode,
const char* oldName, fs_vnode newNode,
const char* newName);
@@ -147,6 +151,7 @@ public:
virtual status_t ReadQuery(fs_cookie cookie, void* buffer,
size_t bufferSize, uint32 count,
uint32* countRead);
virtual status_t RewindQuery(fs_cookie cookie);
private:
file_system_module_info* fFSModule;
@@ -60,6 +60,8 @@ UserlandRequestHandler::HandleRequest(Request* request)
// vnodes
case LOOKUP_REQUEST:
return _HandleRequest((LookupRequest*)request);
case GET_VNODE_NAME_REQUEST:
return _HandleRequest((GetVNodeNameRequest*)request);
case READ_VNODE_REQUEST:
return _HandleRequest((ReadVNodeRequest*)request);
case WRITE_VNODE_REQUEST:
@@ -152,6 +154,8 @@ UserlandRequestHandler::HandleRequest(Request* request)
return _HandleRequest((WriteAttrRequest*)request);
case READ_ATTR_STAT_REQUEST:
return _HandleRequest((ReadAttrStatRequest*)request);
case WRITE_ATTR_STAT_REQUEST:
return _HandleRequest((WriteAttrStatRequest*)request);
case RENAME_ATTR_REQUEST:
return _HandleRequest((RenameAttrRequest*)request);
case REMOVE_ATTR_REQUEST:
@@ -184,6 +188,8 @@ UserlandRequestHandler::HandleRequest(Request* request)
return _HandleRequest((FreeQueryCookieRequest*)request);
case READ_QUERY_REQUEST:
return _HandleRequest((ReadQueryRequest*)request);
case REWIND_QUERY_REQUEST:
return _HandleRequest((RewindQueryRequest*)request);
}
PRINT(("UserlandRequestHandler::HandleRequest(): unexpected request: %lu\n",
request->GetType()));
@@ -394,6 +400,45 @@ UserlandRequestHandler::_HandleRequest(LookupRequest* request)
return _SendReply(allocator, false);
}
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(GetVNodeNameRequest* request)
{
// check and execute the request
status_t result = B_OK;
Volume* volume = (Volume*)request->volume;
if (!volume)
result = B_BAD_VALUE;
void* node = request->node;
size_t bufferSize = request->size;
// allocate the reply
RequestAllocator allocator(fPort->GetPort());
GetVNodeNameReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
RETURN_ERROR(error);
char* buffer;
if (result == B_OK) {
result = allocator.AllocateAddress(reply->buffer, bufferSize, 1,
(void**)&buffer, true);
}
// execute the request
if (result == B_OK) {
RequestThreadContext context(volume);
result = volume->GetVNodeName(node, buffer, bufferSize);
}
// reconstruct the reply, in case it has been overwritten
reply = new(reply) GetVNodeNameReply;
// send the reply
reply->error = result;
return _SendReply(allocator, (result == B_OK));
}
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(ReadVNodeRequest* request)
@@ -1729,6 +1774,35 @@ UserlandRequestHandler::_HandleRequest(ReadAttrStatRequest* request)
return _SendReply(allocator, false);
}
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(WriteAttrStatRequest* request)
{
// check and execute the request
status_t result = B_OK;
Volume* volume = (Volume*)request->volume;
if (!volume)
result = B_BAD_VALUE;
if (result == B_OK) {
RequestThreadContext context(volume);
result = volume->WriteAttrStat(request->node, request->attrCookie,
&request->st, request->mask);
}
// prepare the reply
RequestAllocator allocator(fPort->GetPort());
WriteAttrStatReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
RETURN_ERROR(error);
reply->error = result;
// send the reply
return _SendReply(allocator, false);
}
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(RenameAttrRequest* request)
@@ -2173,6 +2247,34 @@ UserlandRequestHandler::_HandleRequest(ReadQueryRequest* request)
return _SendReply(allocator, (result == B_OK));
}
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(RewindQueryRequest* request)
{
// check and execute the request
status_t result = B_OK;
Volume* volume = (Volume*)request->volume;
if (!volume)
result = B_BAD_VALUE;
if (result == B_OK) {
RequestThreadContext context(volume);
result = volume->RewindQuery(request->queryCookie);
}
// prepare the reply
RequestAllocator allocator(fPort->GetPort());
RewindQueryReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
RETURN_ERROR(error);
reply->error = result;
// send the reply
return _SendReply(allocator, false);
}
// #pragma mark - other
@@ -15,6 +15,7 @@ class ReadFSInfoRequest;
class WriteFSInfoRequest;
// vnodes
class LookupRequest;
class GetVNodeNameRequest;
class ReadVNodeRequest;
class WriteVNodeRequest;
class FSRemoveVNodeRequest;
@@ -61,6 +62,7 @@ class FreeAttrCookieRequest;
class ReadAttrRequest;
class WriteAttrRequest;
class ReadAttrStatRequest;
class WriteAttrStatRequest;
class RenameAttrRequest;
class RemoveAttrRequest;
// indices
@@ -77,6 +79,7 @@ class OpenQueryRequest;
class CloseQueryRequest;
class FreeQueryCookieRequest;
class ReadQueryRequest;
class RewindQueryRequest;
class RequestAllocator;
@@ -107,6 +110,7 @@ private:
// vnodes
status_t _HandleRequest(LookupRequest* request);
status_t _HandleRequest(GetVNodeNameRequest* request);
status_t _HandleRequest(ReadVNodeRequest* request);
status_t _HandleRequest(WriteVNodeRequest* request);
status_t _HandleRequest(FSRemoveVNodeRequest* request);
@@ -159,6 +163,7 @@ private:
status_t _HandleRequest(ReadAttrRequest* request);
status_t _HandleRequest(WriteAttrRequest* request);
status_t _HandleRequest(ReadAttrStatRequest* request);
status_t _HandleRequest(WriteAttrStatRequest* request);
status_t _HandleRequest(RenameAttrRequest* request);
status_t _HandleRequest(RemoveAttrRequest* request);
@@ -178,6 +183,7 @@ private:
status_t _HandleRequest(CloseQueryRequest* request);
status_t _HandleRequest(FreeQueryCookieRequest* request);
status_t _HandleRequest(ReadQueryRequest* request);
status_t _HandleRequest(RewindQueryRequest* request);
status_t _SendReply(RequestAllocator& allocator,
bool expectsReceipt);
@@ -2,6 +2,12 @@
#include "Volume.h"
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
#include "kernel_emu.h"
// constructor
Volume::Volume(FileSystem* fileSystem, mount_id id)
: fFileSystem(fileSystem),
@@ -79,6 +85,82 @@ Volume::Lookup(fs_vnode dir, const char* entryName, vnode_id* vnid, int* type)
return B_BAD_VALUE;
}
// LookupNoType
status_t
Volume::LookupNoType(fs_vnode dir, const char* entryName, vnode_id* vnid)
{
int type;
return Lookup(dir, entryName, vnid, &type);
}
// GetVNodeName
status_t
Volume::GetVNodeName(fs_vnode node, char* buffer, size_t bufferSize)
{
// stat the node to get its ID
struct stat st;
status_t error = ReadStat(node, &st);
if (error != B_OK)
return error;
// look up the parent directory
vnode_id parentID;
error = LookupNoType(node, "..", &parentID);
if (error != B_OK)
return error;
// get the parent node handle
fs_vnode parentNode;
error = UserlandFS::KernelEmu::get_vnode(GetID(), parentID, &parentNode);
// Lookup() has already called get_vnode() for us, so we need to put it once
UserlandFS::KernelEmu::put_vnode(GetID(), parentID);
if (error != B_OK)
return error;
// open the parent dir
fs_cookie cookie;
error = OpenDir(parentNode, &cookie);
if (error == B_OK) {
while (true) {
// read an entry
char _entry[sizeof(struct dirent) + B_FILE_NAME_LENGTH];
struct dirent* entry = (struct dirent*)_entry;
uint32 num;
error = ReadDir(parentNode, cookie, entry, sizeof(_entry), 1, &num);
if (error != B_OK)
break;
if (num == 0) {
error = B_ENTRY_NOT_FOUND;
break;
}
// found an entry for our node?
if (st.st_ino == entry->d_ino) {
// yep, copy the entry name
size_t nameLen = strnlen(entry->d_name, B_FILE_NAME_LENGTH);
if (nameLen < bufferSize) {
memcpy(buffer, entry->d_name, nameLen);
buffer[nameLen] = '\0';
} else
error = B_BUFFER_OVERFLOW;
break;
}
}
// close the parent dir
CloseDir(parentNode, cookie);
FreeDirCookie(parentNode, cookie);
}
// put the parent node
UserlandFS::KernelEmu::put_vnode(GetID(), parentID);
return error;
}
// ReadVNode
status_t
Volume::ReadVNode(vnode_id vnid, bool reenter, fs_vnode* node)
@@ -393,13 +475,21 @@ Volume::WriteAttr(fs_vnode node, fs_cookie cookie, off_t pos,
return B_BAD_VALUE;
}
// StatAttr
// ReadAttrStat
status_t
Volume::ReadAttrStat(fs_vnode node, fs_cookie cookie, struct stat *st)
{
return B_BAD_VALUE;
}
// WriteAttrStat
status_t
Volume::WriteAttrStat(fs_vnode node, fs_cookie cookie, const struct stat* st,
int statMask)
{
return B_BAD_VALUE;
}
// RenameAttr
status_t
Volume::RenameAttr(fs_vnode oldNode, const char* oldName, fs_vnode newNode,
@@ -510,3 +600,10 @@ Volume::ReadQuery(fs_cookie cookie, void* buffer, size_t bufferSize,
return B_BAD_VALUE;
}
// RewindQuery
status_t
Volume::RewindQuery(fs_cookie cookie)
{
return B_BAD_VALUE;
}
@@ -30,6 +30,11 @@ public:
// vnodes
virtual status_t Lookup(fs_vnode dir, const char* entryName,
vnode_id* vnid, int* type);
virtual status_t LookupNoType(fs_vnode dir,
const char* entryName, vnode_id* vnid);
// not required
virtual status_t GetVNodeName(fs_vnode node, char* buffer,
size_t bufferSize);
virtual status_t ReadVNode(vnode_id vnid, bool reenter,
fs_vnode* node);
virtual status_t WriteVNode(fs_vnode node, bool reenter);
@@ -115,7 +120,9 @@ public:
off_t pos, const void* buffer,
size_t bufferSize, size_t* bytesWritten);
virtual status_t ReadAttrStat(fs_vnode node, fs_cookie cookie,
struct stat *st);
struct stat* st);
virtual status_t WriteAttrStat(fs_vnode node, fs_cookie cookie,
const struct stat* st, int statMask);
virtual status_t RenameAttr(fs_vnode oldNode,
const char* oldName, fs_vnode newNode,
const char* newName);
@@ -144,6 +151,7 @@ public:
virtual status_t ReadQuery(fs_cookie cookie, void* buffer,
size_t bufferSize, uint32 count,
uint32* countRead);
virtual status_t RewindQuery(fs_cookie cookie);
protected:
FileSystem* fFileSystem;