/*
 * Copyright 2001-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
 * Distributed under the terms of the MIT License.
 */
 
#include "UserlandRequestHandler.h"
 
#include <algorithm>
 
#include <util/KMessage.h>
 
#include <Notifications.h>
 
#include "AutoDeleter.h"
#include "Compatibility.h"
#include "Debug.h"
#include "FileSystem.h"
#include "IORequestInfo.h"
#include "RequestPort.h"
#include "Requests.h"
#include "RequestThread.h"
#include "SingleReplyRequestHandler.h"
#include "Volume.h"
 
 
// constructor
UserlandRequestHandler::UserlandRequestHandler(FileSystem* fileSystem)
	: RequestHandler(),
	  fFileSystem(fileSystem),
	  fExpectReply(false),
	  fExpectedReply(0)
{
}
 
// constructor
UserlandRequestHandler::UserlandRequestHandler(FileSystem* fileSystem,
	uint32 expectedReply)
	: RequestHandler(),
	  fFileSystem(fileSystem),
	  fExpectReply(true),
	  fExpectedReply(expectedReply)
{
}
 
// destructor
UserlandRequestHandler::~UserlandRequestHandler()
{
}
 
// HandleRequest
status_t
UserlandRequestHandler::HandleRequest(Request* request)
{
	if (fExpectReply && request->GetType() == fExpectedReply) {
		fDone = true;
		return B_OK;
	}
 
	switch (request->GetType()) {
		// FS
		case MOUNT_VOLUME_REQUEST:
			return _HandleRequest((MountVolumeRequest*)request);
		case UNMOUNT_VOLUME_REQUEST:
			return _HandleRequest((UnmountVolumeRequest*)request);
		case SYNC_VOLUME_REQUEST:
			return _HandleRequest((SyncVolumeRequest*)request);
		case READ_FS_INFO_REQUEST:
			return _HandleRequest((ReadFSInfoRequest*)request);
		case WRITE_FS_INFO_REQUEST:
			return _HandleRequest((WriteFSInfoRequest*)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:
			return _HandleRequest((WriteVNodeRequest*)request);
		case FS_REMOVE_VNODE_REQUEST:
			return _HandleRequest((FSRemoveVNodeRequest*)request);
 
		// asynchronous I/O
		case DO_IO_REQUEST:
			return _HandleRequest((DoIORequest*)request);
		case CANCEL_IO_REQUEST:
			return _HandleRequest((CancelIORequest*)request);
		case ITERATIVE_IO_GET_VECS_REQUEST:
			return _HandleRequest((IterativeIOGetVecsRequest*)request);
		case ITERATIVE_IO_FINISHED_REQUEST:
			return _HandleRequest((IterativeIOFinishedRequest*)request);
 
		// nodes
		case IOCTL_REQUEST:
			return _HandleRequest((IOCtlRequest*)request);
		case SET_FLAGS_REQUEST:
			return _HandleRequest((SetFlagsRequest*)request);
		case SELECT_REQUEST:
			return _HandleRequest((SelectRequest*)request);
		case DESELECT_REQUEST:
			return _HandleRequest((DeselectRequest*)request);
		case FSYNC_REQUEST:
			return _HandleRequest((FSyncRequest*)request);
		case READ_SYMLINK_REQUEST:
			return _HandleRequest((ReadSymlinkRequest*)request);
		case CREATE_SYMLINK_REQUEST:
			return _HandleRequest((CreateSymlinkRequest*)request);
		case LINK_REQUEST:
			return _HandleRequest((LinkRequest*)request);
		case UNLINK_REQUEST:
			return _HandleRequest((UnlinkRequest*)request);
		case RENAME_REQUEST:
			return _HandleRequest((RenameRequest*)request);
		case ACCESS_REQUEST:
			return _HandleRequest((AccessRequest*)request);
		case READ_STAT_REQUEST:
			return _HandleRequest((ReadStatRequest*)request);
		case WRITE_STAT_REQUEST:
			return _HandleRequest((WriteStatRequest*)request);
 
		// files
		case CREATE_REQUEST:
			return _HandleRequest((CreateRequest*)request);
		case OPEN_REQUEST:
			return _HandleRequest((OpenRequest*)request);
		case CLOSE_REQUEST:
			return _HandleRequest((CloseRequest*)request);
		case FREE_COOKIE_REQUEST:
			return _HandleRequest((FreeCookieRequest*)request);
		case READ_REQUEST:
			return _HandleRequest((ReadRequest*)request);
		case WRITE_REQUEST:
			return _HandleRequest((WriteRequest*)request);
 
		// directories
		case CREATE_DIR_REQUEST:
			return _HandleRequest((CreateDirRequest*)request);
		case REMOVE_DIR_REQUEST:
			return _HandleRequest((RemoveDirRequest*)request);
		case OPEN_DIR_REQUEST:
			return _HandleRequest((OpenDirRequest*)request);
		case CLOSE_DIR_REQUEST:
			return _HandleRequest((CloseDirRequest*)request);
		case FREE_DIR_COOKIE_REQUEST:
			return _HandleRequest((FreeDirCookieRequest*)request);
		case READ_DIR_REQUEST:
			return _HandleRequest((ReadDirRequest*)request);
		case REWIND_DIR_REQUEST:
			return _HandleRequest((RewindDirRequest*)request);
 
		// attribute directories
		case OPEN_ATTR_DIR_REQUEST:
			return _HandleRequest((OpenAttrDirRequest*)request);
		case CLOSE_ATTR_DIR_REQUEST:
			return _HandleRequest((CloseAttrDirRequest*)request);
		case FREE_ATTR_DIR_COOKIE_REQUEST:
			return _HandleRequest((FreeAttrDirCookieRequest*)request);
		case READ_ATTR_DIR_REQUEST:
			return _HandleRequest((ReadAttrDirRequest*)request);
		case REWIND_ATTR_DIR_REQUEST:
			return _HandleRequest((RewindAttrDirRequest*)request);
 
		// attributes
		case CREATE_ATTR_REQUEST:
			return _HandleRequest((CreateAttrRequest*)request);
		case OPEN_ATTR_REQUEST:
			return _HandleRequest((OpenAttrRequest*)request);
		case CLOSE_ATTR_REQUEST:
			return _HandleRequest((CloseAttrRequest*)request);
		case FREE_ATTR_COOKIE_REQUEST:
			return _HandleRequest((FreeAttrCookieRequest*)request);
		case READ_ATTR_REQUEST:
			return _HandleRequest((ReadAttrRequest*)request);
		case WRITE_ATTR_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:
			return _HandleRequest((RemoveAttrRequest*)request);
 
		// indices
		case OPEN_INDEX_DIR_REQUEST:
			return _HandleRequest((OpenIndexDirRequest*)request);
		case CLOSE_INDEX_DIR_REQUEST:
			return _HandleRequest((CloseIndexDirRequest*)request);
		case FREE_INDEX_DIR_COOKIE_REQUEST:
			return _HandleRequest((FreeIndexDirCookieRequest*)request);
		case READ_INDEX_DIR_REQUEST:
			return _HandleRequest((ReadIndexDirRequest*)request);
		case REWIND_INDEX_DIR_REQUEST:
			return _HandleRequest((RewindIndexDirRequest*)request);
		case CREATE_INDEX_REQUEST:
			return _HandleRequest((CreateIndexRequest*)request);
		case REMOVE_INDEX_REQUEST:
			return _HandleRequest((RemoveIndexRequest*)request);
		case READ_INDEX_STAT_REQUEST:
			return _HandleRequest((ReadIndexStatRequest*)request);
 
		// queries
		case OPEN_QUERY_REQUEST:
			return _HandleRequest((OpenQueryRequest*)request);
		case CLOSE_QUERY_REQUEST:
			return _HandleRequest((CloseQueryRequest*)request);
		case FREE_QUERY_COOKIE_REQUEST:
			return _HandleRequest((FreeQueryCookieRequest*)request);
		case READ_QUERY_REQUEST:
			return _HandleRequest((ReadQueryRequest*)request);
		case REWIND_QUERY_REQUEST:
			return _HandleRequest((RewindQueryRequest*)request);
 
		// node monitoring
		case NODE_MONITORING_EVENT_REQUEST:
			return _HandleRequest((NodeMonitoringEventRequest*)request);
	}
PRINT(("UserlandRequestHandler::HandleRequest(): unexpected request: %lu\n",
request->GetType()));
	return B_BAD_DATA;
}
 
 
// #pragma mark - FS
 
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(MountVolumeRequest* request)
{
	// check and execute the request
	status_t result = B_OK;
 
	// if the device path is relative, make it absolute by appending the
	// provided CWD
	const char* device = (const char*)request->device.GetData();
	char stackDevice[B_PATH_NAME_LENGTH];
	if (result == B_OK) {
		if (device && device[0] != '/') {
			if (const char* cwd = (const char*)request->cwd.GetData()) {
				int32 deviceLen = strlen(device);
				int32 cwdLen = strlen(cwd);
				if (cwdLen + 1 + deviceLen < (int32)sizeof(stackDevice)) {
					strcpy(stackDevice, cwd);
					strcat(stackDevice, "/");
					strcat(stackDevice, device);
					device = stackDevice;
				} else
					result = B_NAME_TOO_LONG;
			} else
				result = B_BAD_VALUE;
		}
	}
 
	// create the volume
	Volume* volume = NULL;
	if (result == B_OK)
		result = fFileSystem->CreateVolume(&volume, request->nsid);
 
	// mount it
	ino_t rootID;
	if (result == B_OK) {
		RequestThreadContext context(volume, request);
		result = volume->Mount(device, request->flags,
			(const char*)request->parameters.GetData(), &rootID);
		if (result != B_OK)
			fFileSystem->DeleteVolume(volume);
	}
	if (result != B_OK)
		volume = NULL;
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	MountVolumeReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
	reply->error = result;
	reply->volume = volume;
	reply->rootID = rootID;
	if (volume != NULL)
		volume->GetCapabilities(reply->capabilities);
 
	// send the reply
	return _SendReply(allocator, false);
}
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(UnmountVolumeRequest* request)
{
	// check and execute the request
	status_t result = B_BAD_VALUE;
	if (Volume* volume = (Volume*)request->volume) {
		RequestThreadContext context(volume, request);
		result = volume->Unmount();
		fFileSystem->DeleteVolume(volume);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	UnmountVolumeReply* 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(SyncVolumeRequest* 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, request);
		result = volume->Sync();
	}
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	SyncVolumeReply* 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(ReadFSInfoRequest* request)
{
	// check and execute the request
	status_t result = B_OK;
	Volume* volume = (Volume*)request->volume;
	if (!volume)
		result = B_BAD_VALUE;
	fs_info info;
	if (result == B_OK) {
		RequestThreadContext context(volume, request);
		result = volume->ReadFSInfo(&info);
	}
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	ReadFSInfoReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
	reply->error = result;
	reply->info = info;
 
	// send the reply
	return _SendReply(allocator, false);
}
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(WriteFSInfoRequest* 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, request);
		result = volume->WriteFSInfo(&request->info, request->mask);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	WriteFSInfoReply* 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 - vnodes
 
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(LookupRequest* request)
{
	// check and execute the request
	status_t result = B_OK;
	Volume* volume = (Volume*)request->volume;
	if (!volume)
		result = B_BAD_VALUE;
 
	ino_t vnid = 0;
	if (result == B_OK) {
		RequestThreadContext context(volume, request);
		result = volume->Lookup(request->node,
			(const char*)request->entryName.GetData(), &vnid);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	LookupReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
 
	reply->vnid = vnid;
	reply->error = result;
 
	// send the reply
	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, request);
		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)
{
	// check and execute the request
	status_t result = B_OK;
	Volume* volume = (Volume*)request->volume;
	if (!volume)
		result = B_BAD_VALUE;
 
	void* node;
	int type;
	uint32 flags;
	FSVNodeCapabilities capabilities;
	if (result == B_OK) {
		RequestThreadContext context(volume, request);
		result = volume->ReadVNode(request->vnid, request->reenter, &node,
			&type, &flags, &capabilities);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	ReadVNodeReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
 
	reply->error = result;
	reply->node = node;
	reply->type = type;
	reply->flags = flags;
	reply->capabilities = capabilities;
 
	// send the reply
	return _SendReply(allocator, false);
}
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(WriteVNodeRequest* 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, request);
		result = volume->WriteVNode(request->node, request->reenter);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	WriteVNodeReply* 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(FSRemoveVNodeRequest* 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, request);
		result = volume->RemoveVNode(request->node, request->reenter);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	FSRemoveVNodeReply* 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 - asynchronous I/O
 
 
status_t
UserlandRequestHandler::_HandleRequest(DoIORequest* 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, request);
		IORequestInfo requestInfo(request->request, request->isWrite,
			request->offset, request->length, request->isVIP);
		result = volume->DoIO(request->node, request->fileCookie, requestInfo);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	DoIOReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
 
	reply->error = result;
 
	// send the reply
	return _SendReply(allocator, false);
}
 
 
status_t
UserlandRequestHandler::_HandleRequest(CancelIORequest* 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, request);
		result = volume->CancelIO(request->node, request->fileCookie,
			request->request);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	CancelIOReply* 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(IterativeIOGetVecsRequest* request)
{
	// check and execute the request
	status_t result = B_OK;
	Volume* volume = (Volume*)request->volume;
	if (!volume)
		result = B_BAD_VALUE;
 
	file_io_vec vecs[IterativeIOGetVecsReply::MAX_VECS];
	size_t vecCount = IterativeIOGetVecsReply::MAX_VECS;
	if (result == B_OK) {
		RequestThreadContext context(volume, request);
		result = volume->IterativeIOGetVecs(request->cookie, request->request,
			request->offset, request->size, vecs, &vecCount);
		if (result == B_OK) {
			vecCount = std::min(vecCount,
				(size_t)IterativeIOGetVecsReply::MAX_VECS);
		}
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	IterativeIOGetVecsReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
 
	reply->error = result;
	if (result == B_OK) {
		memcpy(reply->vecs, vecs, vecCount * sizeof(file_io_vec));
		reply->vecCount = vecCount;
	} else
		reply->vecCount = 0;
 
	// send the reply
	return _SendReply(allocator, false);
}
 
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(IterativeIOFinishedRequest* 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, request);
		result = volume->IterativeIOFinished(request->cookie, request->request,
			request->status, request->partialTransfer,
			request->bytesTransferred);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	IterativeIOFinishedReply* 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 - nodes
 
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(IOCtlRequest* request)
{
	// get the request parameters
	status_t result = B_OK;
	Volume* volume = (Volume*)request->volume;
	if (!volume)
		result = B_BAD_VALUE;
 
	void* buffer = request->bufferParameter;
	size_t len = request->lenParameter;
	bool isBuffer = request->isBuffer;
	int32 bufferSize = 0;
	int32 writeSize = request->writeSize;
	if (isBuffer) {
		buffer = request->buffer.GetData();
		bufferSize = request->buffer.GetSize();
	}
 
	// allocate the reply
	RequestAllocator allocator(fPort->GetPort());
	IOCtlReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
 
	// allocate the writable buffer for the call
	void* writeBuffer = NULL;
	if (result == B_OK && isBuffer && writeSize > 0) {
		if (writeSize < bufferSize)
			writeSize = bufferSize;
		result = allocator.AllocateAddress(reply->buffer, writeSize, 8,
			(void**)&writeBuffer, true);
		if (result == B_OK && bufferSize > 0)
			memcpy(writeBuffer, buffer, bufferSize);
		buffer = writeBuffer;
	}
 
	// execute the request
	status_t ioctlError = B_OK;
	if (result == B_OK) {
		RequestThreadContext context(volume, request);
		ioctlError = volume->IOCtl(request->node, request->fileCookie,
			request->command, buffer, len);
	}
 
	// reconstruct the reply, in case it has been overwritten
	reply = new(reply) IOCtlReply;
 
	// send the reply
	reply->error = result;
	reply->ioctlError = ioctlError;
	return _SendReply(allocator, (result == B_OK && writeBuffer));
}
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(SetFlagsRequest* 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, request);
		result = volume->SetFlags(request->node, request->fileCookie,
			request->flags);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	SetFlagsReply* 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(SelectRequest* 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, request);
		result = volume->Select(request->node, request->fileCookie,
			request->event, request->sync);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	SelectReply* 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(DeselectRequest* 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, request);
		result = volume->Deselect(request->node, request->fileCookie,
			request->event, request->sync);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	DeselectReply* 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(FSyncRequest* 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, request);
		result = volume->FSync(request->node);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	FSyncReply* 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(ReadSymlinkRequest* 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());
	ReadSymlinkReply* 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
	size_t bytesRead;
	if (result == B_OK) {
		RequestThreadContext context(volume, request);
		result = volume->ReadSymlink(node, buffer, bufferSize, &bytesRead);
	}
 
	// reconstruct the reply, in case it has been overwritten
	reply = new(reply) ReadSymlinkReply;
 
	// send the reply
	reply->error = result;
	reply->bytesRead = bytesRead;
	return _SendReply(allocator, (result == B_OK));
}
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(CreateSymlinkRequest* 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, request);
		result = volume->CreateSymlink(request->node,
			(const char*)request->name.GetData(),
			(const char*)request->target.GetData(), request->mode);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	CreateSymlinkReply* 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(LinkRequest* 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, request);
		result = volume->Link(request->node,
			(const char*)request->name.GetData(), request->target);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	LinkReply* 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(UnlinkRequest* 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, request);
		result = volume->Unlink(request->node,
			(const char*)request->name.GetData());
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	UnlinkReply* 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(RenameRequest* 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, request);
		result = volume->Rename(request->oldDir,
			(const char*)request->oldName.GetData(), request->newDir,
			(const char*)request->newName.GetData());
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	RenameReply* 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(AccessRequest* 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, request);
		result = volume->Access(request->node, request->mode);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	AccessReply* 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(ReadStatRequest* request)
{
	// check and execute the request
	status_t result = B_OK;
	Volume* volume = (Volume*)request->volume;
	if (!volume)
		result = B_BAD_VALUE;
 
	struct stat st;
	if (result == B_OK) {
		RequestThreadContext context(volume, request);
		result = volume->ReadStat(request->node, &st);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	ReadStatReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
 
	reply->error = result;
	reply->st = st;
 
	// send the reply
	return _SendReply(allocator, false);
}
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(WriteStatRequest* 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, request);
		result = volume->WriteStat(request->node, &request->st, request->mask);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	WriteStatReply* 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 - files
 
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(CreateRequest* request)
{
	// check and execute the request
	status_t result = B_OK;
	Volume* volume = (Volume*)request->volume;
	if (!volume)
		result = B_BAD_VALUE;
 
	ino_t vnid;
	void* fileCookie;
	if (result == B_OK) {
		RequestThreadContext context(volume, request);
		result = volume->Create(request->node,
			(const char*)request->name.GetData(), request->openMode,
			request->mode, &fileCookie, &vnid);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	CreateReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
 
	reply->error = result;
	reply->vnid = vnid;
	reply->fileCookie = fileCookie;
 
	// send the reply
	return _SendReply(allocator, false);
}
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(OpenRequest* request)
{
	// check and execute the request
	status_t result = B_OK;
	Volume* volume = (Volume*)request->volume;
	if (!volume)
		result = B_BAD_VALUE;
 
	void* fileCookie;
	if (result == B_OK) {
		RequestThreadContext context(volume, request);
		result = volume->Open(request->node, request->openMode, &fileCookie);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	OpenReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
 
	reply->error = result;
	reply->fileCookie = fileCookie;
 
	// send the reply
	return _SendReply(allocator, false);
}
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(CloseRequest* 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, request);
		result = volume->Close(request->node, request->fileCookie);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	CloseReply* 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(FreeCookieRequest* 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, request);
		result = volume->FreeCookie(request->node, request->fileCookie);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	FreeCookieReply* 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(ReadRequest* 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;
	void* fileCookie = request->fileCookie;
	off_t pos = request->pos;
	size_t size = request->size;
 
	// allocate the reply
	RequestAllocator allocator(fPort->GetPort());
	ReadReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
 
	void* buffer;
	if (result == B_OK) {
		result = allocator.AllocateAddress(reply->buffer, size, 1, &buffer,
			true);
	}
 
	// execute the request
	size_t bytesRead;
	if (result == B_OK) {
		RequestThreadContext context(volume, request);
		result = volume->Read(node, fileCookie, pos, buffer, size, &bytesRead);
	}
 
	// reconstruct the reply, in case it has been overwritten
	reply = new(reply) ReadReply;
 
	// send the reply
	reply->error = result;
	reply->bytesRead = bytesRead;
	return _SendReply(allocator, (result == B_OK));
}
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(WriteRequest* request)
{
	// check and execute the request
	status_t result = B_OK;
	Volume* volume = (Volume*)request->volume;
	if (!volume)
		result = B_BAD_VALUE;
 
	size_t bytesWritten;
	if (result == B_OK) {
		RequestThreadContext context(volume, request);
		result = volume->Write(request->node, request->fileCookie,
			request->pos, request->buffer.GetData(), request->buffer.GetSize(),
			&bytesWritten);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	WriteReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
 
	reply->error = result;
	reply->bytesWritten = bytesWritten;
 
	// send the reply
	return _SendReply(allocator, false);
}
 
 
// #pragma mark - directories
 
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(CreateDirRequest* 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, request);
		result = volume->CreateDir(request->node,
			(const char*)request->name.GetData(), request->mode);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	CreateDirReply* 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(RemoveDirRequest* 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, request);
		result = volume->RemoveDir(request->node,
			(const char*)request->name.GetData());
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	RemoveDirReply* 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(OpenDirRequest* request)
{
	// check and execute the request
	status_t result = B_OK;
	Volume* volume = (Volume*)request->volume;
	if (!volume)
		result = B_BAD_VALUE;
 
	void* dirCookie = NULL;
	if (result == B_OK) {
		RequestThreadContext context(volume, request);
		result = volume->OpenDir(request->node, &dirCookie);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	OpenDirReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
 
	reply->error = result;
	reply->dirCookie = dirCookie;
 
	// send the reply
	return _SendReply(allocator, false);
}
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(CloseDirRequest* 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, request);
		result = volume->CloseDir(request->node, request->dirCookie);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	CloseDirReply* 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(FreeDirCookieRequest* 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, request);
		result = volume->FreeDirCookie(request->node, request->dirCookie);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	FreeDirCookieReply* 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(ReadDirRequest* request)
{
	// check the request
	status_t result = B_OK;
	Volume* volume = (Volume*)request->volume;
	if (!volume)
		result = B_BAD_VALUE;
 
	void* node = request->node;
	void* dirCookie = request->dirCookie;
	size_t bufferSize = request->bufferSize;
	uint32 count = request->count;
 
	// allocate the reply
	RequestAllocator allocator(fPort->GetPort());
	ReadDirReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
 
	void* buffer;
	if (result == B_OK) {
		result = allocator.AllocateAddress(reply->buffer, bufferSize, 1,
			&buffer, true);
	}
 
	// execute the request
	uint32 countRead;
	if (result == B_OK) {
		RequestThreadContext context(volume, request);
		result = volume->ReadDir(node, dirCookie, buffer, bufferSize, count,
			&countRead);
	}
 
D(
if (result == B_OK && countRead > 0) {
	dirent* entry = (dirent*)buffer;
	PRINT(("  entry: d_dev: %ld, d_pdev: %ld, d_ino: %Ld, d_pino: %Ld, "
		"d_reclen: %hu, d_name: %.32s\n",
		entry->d_dev, entry->d_pdev, entry->d_ino, entry->d_pino,
		entry->d_reclen, entry->d_name));
}
)
 
	// reconstruct the reply, in case it has been overwritten
	reply = new(reply) ReadDirReply;
 
	// send the reply
	reply->error = result;
	reply->count = countRead;
	return _SendReply(allocator, (result == B_OK));
}
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(RewindDirRequest* 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, request);
		result = volume->RewindDir(request->node, request->dirCookie);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	RewindDirReply* 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 - attribute directories
 
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(OpenAttrDirRequest* request)
{
	// check and execute the request
	status_t result = B_OK;
	Volume* volume = (Volume*)request->volume;
	if (!volume)
		result = B_BAD_VALUE;
 
	void* attrDirCookie;
	if (result == B_OK) {
		RequestThreadContext context(volume, request);
		result = volume->OpenAttrDir(request->node, &attrDirCookie);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	OpenAttrDirReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
 
	reply->error = result;
	reply->attrDirCookie = attrDirCookie;
 
	// send the reply
	return _SendReply(allocator, false);
}
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(CloseAttrDirRequest* 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, request);
		result = volume->CloseAttrDir(request->node, request->attrDirCookie);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	CloseAttrDirReply* 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(FreeAttrDirCookieRequest* 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, request);
		result = volume->FreeAttrDirCookie(request->node,
			request->attrDirCookie);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	FreeAttrDirCookieReply* 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(ReadAttrDirRequest* 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;
	void* attrDirCookie = request->attrDirCookie;
	size_t bufferSize = request->bufferSize;
	uint32 count = request->count;
 
	// allocate the reply
	RequestAllocator allocator(fPort->GetPort());
	ReadAttrDirReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
 
	void* buffer;
	if (result == B_OK) {
		result = allocator.AllocateAddress(reply->buffer, bufferSize, 1,
			&buffer, true);
	}
 
	// execute the request
	uint32 countRead;
	if (result == B_OK) {
		RequestThreadContext context(volume, request);
		result = volume->ReadAttrDir(node, attrDirCookie, buffer, bufferSize,
			count, &countRead);
	}
 
	// reconstruct the reply, in case it has been overwritten
	reply = new(reply) ReadAttrDirReply;
 
	// send the reply
	reply->error = result;
	reply->count = countRead;
	return _SendReply(allocator, (result == B_OK));
}
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(RewindAttrDirRequest* 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, request);
		result = volume->RewindAttrDir(request->node, request->attrDirCookie);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	RewindAttrDirReply* 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 - attributes
 
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(CreateAttrRequest* request)
{
	// check and execute the request
	status_t result = B_OK;
	Volume* volume = (Volume*)request->volume;
	if (!volume)
		result = B_BAD_VALUE;
 
	void* attrCookie;
	if (result == B_OK) {
		RequestThreadContext context(volume, request);
		result = volume->CreateAttr(request->node,
			(const char*)request->name.GetData(), request->type,
			request->openMode, &attrCookie);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	CreateAttrReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
 
	reply->error = result;
	reply->attrCookie = attrCookie;
 
	// send the reply
	return _SendReply(allocator, false);
}
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(OpenAttrRequest* request)
{
	// check and execute the request
	status_t result = B_OK;
	Volume* volume = (Volume*)request->volume;
	if (!volume)
		result = B_BAD_VALUE;
 
	void* attrCookie;
	if (result == B_OK) {
		RequestThreadContext context(volume, request);
		result = volume->OpenAttr(request->node,
			(const char*)request->name.GetData(), request->openMode,
			&attrCookie);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	OpenAttrReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
 
	reply->error = result;
	reply->attrCookie = attrCookie;
 
	// send the reply
	return _SendReply(allocator, false);
}
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(CloseAttrRequest* 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, request);
		result = volume->CloseAttr(request->node, request->attrCookie);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	CloseAttrReply* 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(FreeAttrCookieRequest* 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, request);
		result = volume->FreeAttrCookie(request->node, request->attrCookie);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	FreeAttrCookieReply* 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(ReadAttrRequest* 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;
	void* attrCookie = request->attrCookie;
	off_t pos = request->pos;
	size_t size = request->size;
 
	// allocate the reply
	RequestAllocator allocator(fPort->GetPort());
	ReadAttrReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
 
	void* buffer;
	if (result == B_OK) {
		result = allocator.AllocateAddress(reply->buffer, size, 1, &buffer,
			true);
	}
 
	// execute the request
	size_t bytesRead;
	if (result == B_OK) {
		RequestThreadContext context(volume, request);
		result = volume->ReadAttr(node, attrCookie, pos, buffer, size,
			&bytesRead);
	}
 
	// reconstruct the reply, in case it has been overwritten
	reply = new(reply) ReadAttrReply;
 
	// send the reply
	reply->error = result;
	reply->bytesRead = bytesRead;
	return _SendReply(allocator, (result == B_OK));
}
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(WriteAttrRequest* request)
{
	// check and execute the request
	status_t result = B_OK;
	Volume* volume = (Volume*)request->volume;
	if (!volume)
		result = B_BAD_VALUE;
 
	size_t bytesWritten;
	if (result == B_OK) {
		RequestThreadContext context(volume, request);
		result = volume->WriteAttr(request->node, request->attrCookie,
			request->pos, request->buffer.GetData(), request->buffer.GetSize(),
			&bytesWritten);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	WriteAttrReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
 
	reply->error = result;
	reply->bytesWritten = bytesWritten;
 
	// send the reply
	return _SendReply(allocator, false);
}
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(ReadAttrStatRequest* request)
{
	// check and execute the request
	status_t result = B_OK;
	Volume* volume = (Volume*)request->volume;
	if (!volume)
		result = B_BAD_VALUE;
 
	struct stat st;
	if (result == B_OK) {
		RequestThreadContext context(volume, request);
		result = volume->ReadAttrStat(request->node, request->attrCookie,
			&st);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	ReadAttrStatReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
 
	reply->error = result;
	reply->st = st;
 
	// send the reply
	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, request);
		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)
{
	// 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, request);
		result = volume->RenameAttr(
			request->oldNode, (const char*)request->oldName.GetData(),
			request->newNode, (const char*)request->newName.GetData());
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	RenameAttrReply* 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(RemoveAttrRequest* 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, request);
		result = volume->RemoveAttr(request->node,
			(const char*)request->name.GetData());
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	RemoveAttrReply* 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 - indices
 
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(OpenIndexDirRequest* request)
{
	// check and execute the request
	status_t result = B_OK;
	Volume* volume = (Volume*)request->volume;
	if (!volume)
		result = B_BAD_VALUE;
 
	void* indexDirCookie;
	if (result == B_OK) {
		RequestThreadContext context(volume, request);
		result = volume->OpenIndexDir(&indexDirCookie);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	OpenIndexDirReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
 
	reply->error = result;
	reply->indexDirCookie = indexDirCookie;
 
	// send the reply
	return _SendReply(allocator, false);
}
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(CloseIndexDirRequest* 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, request);
		result = volume->CloseIndexDir(request->indexDirCookie);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	CloseIndexDirReply* 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(FreeIndexDirCookieRequest* 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, request);
		result = volume->FreeIndexDirCookie(request->indexDirCookie);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	FreeIndexDirCookieReply* 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(ReadIndexDirRequest* request)
{
	// check and execute the request
	status_t result = B_OK;
	Volume* volume = (Volume*)request->volume;
	if (!volume)
		result = B_BAD_VALUE;
 
	void* indexDirCookie = request->indexDirCookie;
	size_t bufferSize = request->bufferSize;
	uint32 count = request->count;
 
	// allocate the reply
	RequestAllocator allocator(fPort->GetPort());
	ReadIndexDirReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
 
	void* buffer;
	if (result == B_OK) {
		result = allocator.AllocateAddress(reply->buffer, bufferSize, 1,
			&buffer, true);
	}
 
	// execute the request
	uint32 countRead;
	if (result == B_OK) {
		RequestThreadContext context(volume, request);
		result = volume->ReadIndexDir(indexDirCookie, buffer, bufferSize,
			count, &countRead);
	}
 
	// reconstruct the reply, in case it has been overwritten
	reply = new(reply) ReadIndexDirReply;
 
	// send the reply
	reply->error = result;
	reply->count = countRead;
	return _SendReply(allocator, (result == B_OK));
}
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(RewindIndexDirRequest* 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, request);
		result = volume->RewindIndexDir(request->indexDirCookie);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	RewindIndexDirReply* 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(CreateIndexRequest* 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, request);
		result = volume->CreateIndex((const char*)request->name.GetData(),
			request->type, request->flags);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	CreateIndexReply* 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(RemoveIndexRequest* 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, request);
		result = volume->RemoveIndex((const char*)request->name.GetData());
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	RemoveIndexReply* 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(ReadIndexStatRequest* request)
{
	// check and execute the request
	status_t result = B_OK;
	Volume* volume = (Volume*)request->volume;
	if (!volume)
		result = B_BAD_VALUE;
 
	struct stat st;
	if (result == B_OK) {
		RequestThreadContext context(volume, request);
		result = volume->ReadIndexStat((const char*)request->name.GetData(),
			&st);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	ReadIndexStatReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
 
	reply->error = result;
	reply->st = st;
 
	// send the reply
	return _SendReply(allocator, false);
}
 
 
// #pragma mark - queries
 
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(OpenQueryRequest* request)
{
	// check and execute the request
	status_t result = B_OK;
	Volume* volume = (Volume*)request->volume;
	if (!volume)
		result = B_BAD_VALUE;
 
	void* queryCookie;
	if (result == B_OK) {
		RequestThreadContext context(volume, request);
		result = volume->OpenQuery((const char*)request->queryString.GetData(),
			request->flags, request->port, request->token, &queryCookie);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	OpenQueryReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
 
	reply->error = result;
	reply->queryCookie = queryCookie;
 
	// send the reply
	return _SendReply(allocator, false);
}
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(CloseQueryRequest* 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, request);
		result = volume->CloseQuery(request->queryCookie);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	CloseQueryReply* 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(FreeQueryCookieRequest* 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, request);
		result = volume->FreeQueryCookie(request->queryCookie);
	}
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	FreeQueryCookieReply* 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(ReadQueryRequest* request)
{
	// check and execute the request
	status_t result = B_OK;
	Volume* volume = (Volume*)request->volume;
	if (!volume)
		result = B_BAD_VALUE;
 
	void* queryCookie = request->queryCookie;
	size_t bufferSize = request->bufferSize;
	uint32 count = request->count;
 
	// allocate the reply
	RequestAllocator allocator(fPort->GetPort());
	ReadQueryReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
 
	void* buffer;
	if (result == B_OK) {
		result = allocator.AllocateAddress(reply->buffer, bufferSize, 1,
			&buffer, true);
	}
 
	// execute the request
	uint32 countRead;
	if (result == B_OK) {
		RequestThreadContext context(volume, request);
		result = volume->ReadQuery(queryCookie, buffer, bufferSize,
			count, &countRead);
	}
 
	// reconstruct the reply, in case it has been overwritten
	reply = new(reply) ReadQueryReply;
 
	// send the reply
	reply->error = result;
	reply->count = countRead;
	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, request);
		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 - node monitoring
 
 
// _HandleRequest
status_t
UserlandRequestHandler::_HandleRequest(NodeMonitoringEventRequest* request)
{
	// check and execute the request
	KMessage event;
	event.SetTo(request->event.GetData(), request->event.GetSize());
	((NotificationListener*)request->listener)->EventOccurred(
		*(NotificationService*)NULL, &event);
 
	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	NodeMonitoringEventReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		RETURN_ERROR(error);
 
	reply->error = B_OK;
 
	// send the reply
	return _SendReply(allocator, false);
}
 
 
// #pragma mark - other
 
 
// _SendReply
status_t
UserlandRequestHandler::_SendReply(RequestAllocator& allocator,
	bool expectsReceipt)
{
	if (expectsReceipt) {
		SingleReplyRequestHandler handler(RECEIPT_ACK_REPLY);
		return fPort->SendRequest(&allocator, &handler);
	} else
		return fPort->SendRequest(&allocator);
}
 

V595 The 'writeBuffer' pointer was utilized before it was verified against nullptr. Check lines: 732, 750.

V614 Potentially uninitialized pointer 'fileCookie' used.

V614 Potentially uninitialized pointer 'queryCookie' used.

V614 Potentially uninitialized pointer 'indexDirCookie' used.

V614 Potentially uninitialized pointer 'attrCookie' used.

V614 Potentially uninitialized pointer 'attrCookie' used.

V614 Potentially uninitialized pointer 'attrDirCookie' used.

V614 Potentially uninitialized pointer 'fileCookie' used.

V547 Expression 'result == ((int) 0)' is always true.

V614 Potentially uninitialized pointer 'node' used.