/* * Copyright 2001-2009, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ #include "UserlandRequestHandler.h" #include #include #include #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: %" B_PRIu32 "\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: %" B_PRIdDEV ", d_pdev: %" B_PRIdDEV ", " "d_ino: %" B_PRIdINO ", d_pino: %" B_PRIdINO ", " "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); }