1/*
2 * Copyright 2001-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6#include "UserlandRequestHandler.h"
7
8#include <algorithm>
9
10#include <util/KMessage.h>
11
12#include <Notifications.h>
13
14#include "AutoDeleter.h"
15#include "Compatibility.h"
16#include "Debug.h"
17#include "FileSystem.h"
18#include "IORequestInfo.h"
19#include "RequestPort.h"
20#include "Requests.h"
21#include "RequestThread.h"
22#include "SingleReplyRequestHandler.h"
23#include "Volume.h"
24
25
26// constructor
27UserlandRequestHandler::UserlandRequestHandler(FileSystem* fileSystem)
28	: RequestHandler(),
29	  fFileSystem(fileSystem),
30	  fExpectReply(false),
31	  fExpectedReply(0)
32{
33}
34
35// constructor
36UserlandRequestHandler::UserlandRequestHandler(FileSystem* fileSystem,
37	uint32 expectedReply)
38	: RequestHandler(),
39	  fFileSystem(fileSystem),
40	  fExpectReply(true),
41	  fExpectedReply(expectedReply)
42{
43}
44
45// destructor
46UserlandRequestHandler::~UserlandRequestHandler()
47{
48}
49
50// HandleRequest
51status_t
52UserlandRequestHandler::HandleRequest(Request* request)
53{
54	if (fExpectReply && request->GetType() == fExpectedReply) {
55		fDone = true;
56		return B_OK;
57	}
58
59	switch (request->GetType()) {
60		// FS
61		case MOUNT_VOLUME_REQUEST:
62			return _HandleRequest((MountVolumeRequest*)request);
63		case UNMOUNT_VOLUME_REQUEST:
64			return _HandleRequest((UnmountVolumeRequest*)request);
65		case SYNC_VOLUME_REQUEST:
66			return _HandleRequest((SyncVolumeRequest*)request);
67		case READ_FS_INFO_REQUEST:
68			return _HandleRequest((ReadFSInfoRequest*)request);
69		case WRITE_FS_INFO_REQUEST:
70			return _HandleRequest((WriteFSInfoRequest*)request);
71
72		// vnodes
73		case LOOKUP_REQUEST:
74			return _HandleRequest((LookupRequest*)request);
75		case GET_VNODE_NAME_REQUEST:
76			return _HandleRequest((GetVNodeNameRequest*)request);
77		case READ_VNODE_REQUEST:
78			return _HandleRequest((ReadVNodeRequest*)request);
79		case WRITE_VNODE_REQUEST:
80			return _HandleRequest((WriteVNodeRequest*)request);
81		case FS_REMOVE_VNODE_REQUEST:
82			return _HandleRequest((FSRemoveVNodeRequest*)request);
83
84		// asynchronous I/O
85		case DO_IO_REQUEST:
86			return _HandleRequest((DoIORequest*)request);
87		case CANCEL_IO_REQUEST:
88			return _HandleRequest((CancelIORequest*)request);
89		case ITERATIVE_IO_GET_VECS_REQUEST:
90			return _HandleRequest((IterativeIOGetVecsRequest*)request);
91		case ITERATIVE_IO_FINISHED_REQUEST:
92			return _HandleRequest((IterativeIOFinishedRequest*)request);
93
94		// nodes
95		case IOCTL_REQUEST:
96			return _HandleRequest((IOCtlRequest*)request);
97		case SET_FLAGS_REQUEST:
98			return _HandleRequest((SetFlagsRequest*)request);
99		case SELECT_REQUEST:
100			return _HandleRequest((SelectRequest*)request);
101		case DESELECT_REQUEST:
102			return _HandleRequest((DeselectRequest*)request);
103		case FSYNC_REQUEST:
104			return _HandleRequest((FSyncRequest*)request);
105		case READ_SYMLINK_REQUEST:
106			return _HandleRequest((ReadSymlinkRequest*)request);
107		case CREATE_SYMLINK_REQUEST:
108			return _HandleRequest((CreateSymlinkRequest*)request);
109		case LINK_REQUEST:
110			return _HandleRequest((LinkRequest*)request);
111		case UNLINK_REQUEST:
112			return _HandleRequest((UnlinkRequest*)request);
113		case RENAME_REQUEST:
114			return _HandleRequest((RenameRequest*)request);
115		case ACCESS_REQUEST:
116			return _HandleRequest((AccessRequest*)request);
117		case READ_STAT_REQUEST:
118			return _HandleRequest((ReadStatRequest*)request);
119		case WRITE_STAT_REQUEST:
120			return _HandleRequest((WriteStatRequest*)request);
121
122		// files
123		case CREATE_REQUEST:
124			return _HandleRequest((CreateRequest*)request);
125		case OPEN_REQUEST:
126			return _HandleRequest((OpenRequest*)request);
127		case CLOSE_REQUEST:
128			return _HandleRequest((CloseRequest*)request);
129		case FREE_COOKIE_REQUEST:
130			return _HandleRequest((FreeCookieRequest*)request);
131		case READ_REQUEST:
132			return _HandleRequest((ReadRequest*)request);
133		case WRITE_REQUEST:
134			return _HandleRequest((WriteRequest*)request);
135
136		// directories
137		case CREATE_DIR_REQUEST:
138			return _HandleRequest((CreateDirRequest*)request);
139		case REMOVE_DIR_REQUEST:
140			return _HandleRequest((RemoveDirRequest*)request);
141		case OPEN_DIR_REQUEST:
142			return _HandleRequest((OpenDirRequest*)request);
143		case CLOSE_DIR_REQUEST:
144			return _HandleRequest((CloseDirRequest*)request);
145		case FREE_DIR_COOKIE_REQUEST:
146			return _HandleRequest((FreeDirCookieRequest*)request);
147		case READ_DIR_REQUEST:
148			return _HandleRequest((ReadDirRequest*)request);
149		case REWIND_DIR_REQUEST:
150			return _HandleRequest((RewindDirRequest*)request);
151
152		// attribute directories
153		case OPEN_ATTR_DIR_REQUEST:
154			return _HandleRequest((OpenAttrDirRequest*)request);
155		case CLOSE_ATTR_DIR_REQUEST:
156			return _HandleRequest((CloseAttrDirRequest*)request);
157		case FREE_ATTR_DIR_COOKIE_REQUEST:
158			return _HandleRequest((FreeAttrDirCookieRequest*)request);
159		case READ_ATTR_DIR_REQUEST:
160			return _HandleRequest((ReadAttrDirRequest*)request);
161		case REWIND_ATTR_DIR_REQUEST:
162			return _HandleRequest((RewindAttrDirRequest*)request);
163
164		// attributes
165		case CREATE_ATTR_REQUEST:
166			return _HandleRequest((CreateAttrRequest*)request);
167		case OPEN_ATTR_REQUEST:
168			return _HandleRequest((OpenAttrRequest*)request);
169		case CLOSE_ATTR_REQUEST:
170			return _HandleRequest((CloseAttrRequest*)request);
171		case FREE_ATTR_COOKIE_REQUEST:
172			return _HandleRequest((FreeAttrCookieRequest*)request);
173		case READ_ATTR_REQUEST:
174			return _HandleRequest((ReadAttrRequest*)request);
175		case WRITE_ATTR_REQUEST:
176			return _HandleRequest((WriteAttrRequest*)request);
177		case READ_ATTR_STAT_REQUEST:
178			return _HandleRequest((ReadAttrStatRequest*)request);
179		case WRITE_ATTR_STAT_REQUEST:
180			return _HandleRequest((WriteAttrStatRequest*)request);
181		case RENAME_ATTR_REQUEST:
182			return _HandleRequest((RenameAttrRequest*)request);
183		case REMOVE_ATTR_REQUEST:
184			return _HandleRequest((RemoveAttrRequest*)request);
185
186		// indices
187		case OPEN_INDEX_DIR_REQUEST:
188			return _HandleRequest((OpenIndexDirRequest*)request);
189		case CLOSE_INDEX_DIR_REQUEST:
190			return _HandleRequest((CloseIndexDirRequest*)request);
191		case FREE_INDEX_DIR_COOKIE_REQUEST:
192			return _HandleRequest((FreeIndexDirCookieRequest*)request);
193		case READ_INDEX_DIR_REQUEST:
194			return _HandleRequest((ReadIndexDirRequest*)request);
195		case REWIND_INDEX_DIR_REQUEST:
196			return _HandleRequest((RewindIndexDirRequest*)request);
197		case CREATE_INDEX_REQUEST:
198			return _HandleRequest((CreateIndexRequest*)request);
199		case REMOVE_INDEX_REQUEST:
200			return _HandleRequest((RemoveIndexRequest*)request);
201		case READ_INDEX_STAT_REQUEST:
202			return _HandleRequest((ReadIndexStatRequest*)request);
203
204		// queries
205		case OPEN_QUERY_REQUEST:
206			return _HandleRequest((OpenQueryRequest*)request);
207		case CLOSE_QUERY_REQUEST:
208			return _HandleRequest((CloseQueryRequest*)request);
209		case FREE_QUERY_COOKIE_REQUEST:
210			return _HandleRequest((FreeQueryCookieRequest*)request);
211		case READ_QUERY_REQUEST:
212			return _HandleRequest((ReadQueryRequest*)request);
213		case REWIND_QUERY_REQUEST:
214			return _HandleRequest((RewindQueryRequest*)request);
215
216		// node monitoring
217		case NODE_MONITORING_EVENT_REQUEST:
218			return _HandleRequest((NodeMonitoringEventRequest*)request);
219	}
220	PRINT(("UserlandRequestHandler::HandleRequest(): unexpected request: %"
221		B_PRIu32 "\n", request->GetType()));
222	return B_BAD_DATA;
223}
224
225
226// #pragma mark - FS
227
228
229// _HandleRequest
230status_t
231UserlandRequestHandler::_HandleRequest(MountVolumeRequest* request)
232{
233	// check and execute the request
234	status_t result = B_OK;
235
236	// if the device path is relative, make it absolute by appending the
237	// provided CWD
238	const char* device = (const char*)request->device.GetData();
239	char stackDevice[B_PATH_NAME_LENGTH];
240	if (result == B_OK) {
241		if (device && device[0] != '/') {
242			if (const char* cwd = (const char*)request->cwd.GetData()) {
243				int32 deviceLen = strlen(device);
244				int32 cwdLen = strlen(cwd);
245				if (cwdLen + 1 + deviceLen < (int32)sizeof(stackDevice)) {
246					strcpy(stackDevice, cwd);
247					strcat(stackDevice, "/");
248					strcat(stackDevice, device);
249					device = stackDevice;
250				} else
251					result = B_NAME_TOO_LONG;
252			} else
253				result = B_BAD_VALUE;
254		}
255	}
256
257	// create the volume
258	Volume* volume = NULL;
259	if (result == B_OK)
260		result = fFileSystem->CreateVolume(&volume, request->nsid);
261
262	// mount it
263	ino_t rootID;
264	if (result == B_OK) {
265		RequestThreadContext context(volume, request);
266		result = volume->Mount(device, request->flags,
267			(const char*)request->parameters.GetData(), &rootID);
268		if (result != B_OK)
269			fFileSystem->DeleteVolume(volume);
270	}
271	if (result != B_OK)
272		volume = NULL;
273
274	// prepare the reply
275	RequestAllocator allocator(fPort->GetPort());
276	MountVolumeReply* reply;
277	status_t error = AllocateRequest(allocator, &reply);
278	if (error != B_OK)
279		RETURN_ERROR(error);
280	reply->error = result;
281	reply->volume = volume;
282	reply->rootID = rootID;
283	if (volume != NULL)
284		volume->GetCapabilities(reply->capabilities);
285
286	// send the reply
287	return _SendReply(allocator, false);
288}
289
290// _HandleRequest
291status_t
292UserlandRequestHandler::_HandleRequest(UnmountVolumeRequest* request)
293{
294	// check and execute the request
295	status_t result = B_BAD_VALUE;
296	if (Volume* volume = (Volume*)request->volume) {
297		RequestThreadContext context(volume, request);
298		result = volume->Unmount();
299		fFileSystem->DeleteVolume(volume);
300	}
301
302	// prepare the reply
303	RequestAllocator allocator(fPort->GetPort());
304	UnmountVolumeReply* reply;
305	status_t error = AllocateRequest(allocator, &reply);
306	if (error != B_OK)
307		RETURN_ERROR(error);
308	reply->error = result;
309
310	// send the reply
311	return _SendReply(allocator, false);
312}
313
314// _HandleRequest
315status_t
316UserlandRequestHandler::_HandleRequest(SyncVolumeRequest* request)
317{
318	// check and execute the request
319	status_t result = B_OK;
320	Volume* volume = (Volume*)request->volume;
321	if (!volume)
322		result = B_BAD_VALUE;
323	if (result == B_OK) {
324		RequestThreadContext context(volume, request);
325		result = volume->Sync();
326	}
327	// prepare the reply
328	RequestAllocator allocator(fPort->GetPort());
329	SyncVolumeReply* reply;
330	status_t error = AllocateRequest(allocator, &reply);
331	if (error != B_OK)
332		RETURN_ERROR(error);
333	reply->error = result;
334
335	// send the reply
336	return _SendReply(allocator, false);
337}
338
339// _HandleRequest
340status_t
341UserlandRequestHandler::_HandleRequest(ReadFSInfoRequest* request)
342{
343	// check and execute the request
344	status_t result = B_OK;
345	Volume* volume = (Volume*)request->volume;
346	if (!volume)
347		result = B_BAD_VALUE;
348	fs_info info;
349	if (result == B_OK) {
350		RequestThreadContext context(volume, request);
351		result = volume->ReadFSInfo(&info);
352	}
353	// prepare the reply
354	RequestAllocator allocator(fPort->GetPort());
355	ReadFSInfoReply* reply;
356	status_t error = AllocateRequest(allocator, &reply);
357	if (error != B_OK)
358		RETURN_ERROR(error);
359	reply->error = result;
360	reply->info = info;
361
362	// send the reply
363	return _SendReply(allocator, false);
364}
365
366// _HandleRequest
367status_t
368UserlandRequestHandler::_HandleRequest(WriteFSInfoRequest* request)
369{
370	// check and execute the request
371	status_t result = B_OK;
372	Volume* volume = (Volume*)request->volume;
373	if (!volume)
374		result = B_BAD_VALUE;
375	if (result == B_OK) {
376		RequestThreadContext context(volume, request);
377		result = volume->WriteFSInfo(&request->info, request->mask);
378	}
379
380	// prepare the reply
381	RequestAllocator allocator(fPort->GetPort());
382	WriteFSInfoReply* reply;
383	status_t error = AllocateRequest(allocator, &reply);
384	if (error != B_OK)
385		RETURN_ERROR(error);
386	reply->error = result;
387
388	// send the reply
389	return _SendReply(allocator, false);
390}
391
392
393// #pragma mark - vnodes
394
395
396// _HandleRequest
397status_t
398UserlandRequestHandler::_HandleRequest(LookupRequest* request)
399{
400	// check and execute the request
401	status_t result = B_OK;
402	Volume* volume = (Volume*)request->volume;
403	if (!volume)
404		result = B_BAD_VALUE;
405
406	ino_t vnid = 0;
407	if (result == B_OK) {
408		RequestThreadContext context(volume, request);
409		result = volume->Lookup(request->node,
410			(const char*)request->entryName.GetData(), &vnid);
411	}
412
413	// prepare the reply
414	RequestAllocator allocator(fPort->GetPort());
415	LookupReply* reply;
416	status_t error = AllocateRequest(allocator, &reply);
417	if (error != B_OK)
418		RETURN_ERROR(error);
419
420	reply->vnid = vnid;
421	reply->error = result;
422
423	// send the reply
424	return _SendReply(allocator, false);
425}
426
427// _HandleRequest
428status_t
429UserlandRequestHandler::_HandleRequest(GetVNodeNameRequest* request)
430{
431	// check and execute the request
432	status_t result = B_OK;
433	Volume* volume = (Volume*)request->volume;
434	if (!volume)
435		result = B_BAD_VALUE;
436
437	void* node = request->node;
438	size_t bufferSize = request->size;
439
440	// allocate the reply
441	RequestAllocator allocator(fPort->GetPort());
442	GetVNodeNameReply* reply;
443	status_t error = AllocateRequest(allocator, &reply);
444	if (error != B_OK)
445		RETURN_ERROR(error);
446	char* buffer;
447	if (result == B_OK) {
448		result = allocator.AllocateAddress(reply->buffer, bufferSize, 1,
449			(void**)&buffer, true);
450	}
451
452	// execute the request
453	if (result == B_OK) {
454		RequestThreadContext context(volume, request);
455		result = volume->GetVNodeName(node, buffer, bufferSize);
456	}
457
458	// reconstruct the reply, in case it has been overwritten
459	reply = new(reply) GetVNodeNameReply;
460
461	// send the reply
462	reply->error = result;
463	return _SendReply(allocator, (result == B_OK));
464}
465
466// _HandleRequest
467status_t
468UserlandRequestHandler::_HandleRequest(ReadVNodeRequest* request)
469{
470	// check and execute the request
471	status_t result = B_OK;
472	Volume* volume = (Volume*)request->volume;
473	if (!volume)
474		result = B_BAD_VALUE;
475
476	void* node;
477	int type;
478	uint32 flags;
479	FSVNodeCapabilities capabilities;
480	if (result == B_OK) {
481		RequestThreadContext context(volume, request);
482		result = volume->ReadVNode(request->vnid, request->reenter, &node,
483			&type, &flags, &capabilities);
484	}
485
486	// prepare the reply
487	RequestAllocator allocator(fPort->GetPort());
488	ReadVNodeReply* reply;
489	status_t error = AllocateRequest(allocator, &reply);
490	if (error != B_OK)
491		RETURN_ERROR(error);
492
493	reply->error = result;
494	reply->node = node;
495	reply->type = type;
496	reply->flags = flags;
497	reply->capabilities = capabilities;
498
499	// send the reply
500	return _SendReply(allocator, false);
501}
502
503// _HandleRequest
504status_t
505UserlandRequestHandler::_HandleRequest(WriteVNodeRequest* request)
506{
507	// check and execute the request
508	status_t result = B_OK;
509	Volume* volume = (Volume*)request->volume;
510	if (!volume)
511		result = B_BAD_VALUE;
512
513	if (result == B_OK) {
514		RequestThreadContext context(volume, request);
515		result = volume->WriteVNode(request->node, request->reenter);
516	}
517
518	// prepare the reply
519	RequestAllocator allocator(fPort->GetPort());
520	WriteVNodeReply* reply;
521	status_t error = AllocateRequest(allocator, &reply);
522	if (error != B_OK)
523		RETURN_ERROR(error);
524
525	reply->error = result;
526
527	// send the reply
528	return _SendReply(allocator, false);
529}
530
531// _HandleRequest
532status_t
533UserlandRequestHandler::_HandleRequest(FSRemoveVNodeRequest* request)
534{
535	// check and execute the request
536	status_t result = B_OK;
537	Volume* volume = (Volume*)request->volume;
538	if (!volume)
539		result = B_BAD_VALUE;
540
541	if (result == B_OK) {
542		RequestThreadContext context(volume, request);
543		result = volume->RemoveVNode(request->node, request->reenter);
544	}
545
546	// prepare the reply
547	RequestAllocator allocator(fPort->GetPort());
548	FSRemoveVNodeReply* reply;
549	status_t error = AllocateRequest(allocator, &reply);
550	if (error != B_OK)
551		RETURN_ERROR(error);
552
553	reply->error = result;
554
555	// send the reply
556	return _SendReply(allocator, false);
557}
558
559
560// #pragma mark - asynchronous I/O
561
562
563status_t
564UserlandRequestHandler::_HandleRequest(DoIORequest* request)
565{
566	// check and execute the request
567	status_t result = B_OK;
568	Volume* volume = (Volume*)request->volume;
569	if (!volume)
570		result = B_BAD_VALUE;
571
572	if (result == B_OK) {
573		RequestThreadContext context(volume, request);
574		IORequestInfo requestInfo(request->request, request->isWrite,
575			request->offset, request->length, request->isVIP);
576		result = volume->DoIO(request->node, request->fileCookie, requestInfo);
577	}
578
579	// prepare the reply
580	RequestAllocator allocator(fPort->GetPort());
581	DoIOReply* reply;
582	status_t error = AllocateRequest(allocator, &reply);
583	if (error != B_OK)
584		RETURN_ERROR(error);
585
586	reply->error = result;
587
588	// send the reply
589	return _SendReply(allocator, false);
590}
591
592
593status_t
594UserlandRequestHandler::_HandleRequest(CancelIORequest* request)
595{
596	// check and execute the request
597	status_t result = B_OK;
598	Volume* volume = (Volume*)request->volume;
599	if (!volume)
600		result = B_BAD_VALUE;
601
602	if (result == B_OK) {
603		RequestThreadContext context(volume, request);
604		result = volume->CancelIO(request->node, request->fileCookie,
605			request->request);
606	}
607
608	// prepare the reply
609	RequestAllocator allocator(fPort->GetPort());
610	CancelIOReply* reply;
611	status_t error = AllocateRequest(allocator, &reply);
612	if (error != B_OK)
613		RETURN_ERROR(error);
614
615	reply->error = result;
616
617	// send the reply
618	return _SendReply(allocator, false);
619}
620
621
622// _HandleRequest
623status_t
624UserlandRequestHandler::_HandleRequest(IterativeIOGetVecsRequest* request)
625{
626	// check and execute the request
627	status_t result = B_OK;
628	Volume* volume = (Volume*)request->volume;
629	if (!volume)
630		result = B_BAD_VALUE;
631
632	file_io_vec vecs[IterativeIOGetVecsReply::MAX_VECS];
633	size_t vecCount = IterativeIOGetVecsReply::MAX_VECS;
634	if (result == B_OK) {
635		RequestThreadContext context(volume, request);
636		result = volume->IterativeIOGetVecs(request->cookie, request->request,
637			request->offset, request->size, vecs, &vecCount);
638		if (result == B_OK) {
639			vecCount = std::min(vecCount,
640				(size_t)IterativeIOGetVecsReply::MAX_VECS);
641		}
642	}
643
644	// prepare the reply
645	RequestAllocator allocator(fPort->GetPort());
646	IterativeIOGetVecsReply* reply;
647	status_t error = AllocateRequest(allocator, &reply);
648	if (error != B_OK)
649		RETURN_ERROR(error);
650
651	reply->error = result;
652	if (result == B_OK) {
653		memcpy(reply->vecs, vecs, vecCount * sizeof(file_io_vec));
654		reply->vecCount = vecCount;
655	} else
656		reply->vecCount = 0;
657
658	// send the reply
659	return _SendReply(allocator, false);
660}
661
662
663// _HandleRequest
664status_t
665UserlandRequestHandler::_HandleRequest(IterativeIOFinishedRequest* request)
666{
667	// check and execute the request
668	status_t result = B_OK;
669	Volume* volume = (Volume*)request->volume;
670	if (!volume)
671		result = B_BAD_VALUE;
672
673	if (result == B_OK) {
674		RequestThreadContext context(volume, request);
675		result = volume->IterativeIOFinished(request->cookie, request->request,
676			request->status, request->partialTransfer,
677			request->bytesTransferred);
678	}
679
680	// prepare the reply
681	RequestAllocator allocator(fPort->GetPort());
682	IterativeIOFinishedReply* reply;
683	status_t error = AllocateRequest(allocator, &reply);
684	if (error != B_OK)
685		RETURN_ERROR(error);
686
687	reply->error = result;
688
689	// send the reply
690	return _SendReply(allocator, false);
691}
692
693
694// #pragma mark - nodes
695
696
697// _HandleRequest
698status_t
699UserlandRequestHandler::_HandleRequest(IOCtlRequest* request)
700{
701	// get the request parameters
702	status_t result = B_OK;
703	Volume* volume = (Volume*)request->volume;
704	if (!volume)
705		result = B_BAD_VALUE;
706
707	void* buffer = request->bufferParameter;
708	size_t len = request->lenParameter;
709	bool isBuffer = request->isBuffer;
710	int32 bufferSize = 0;
711	int32 writeSize = request->writeSize;
712	if (isBuffer) {
713		buffer = request->buffer.GetData();
714		bufferSize = request->buffer.GetSize();
715	}
716
717	// allocate the reply
718	RequestAllocator allocator(fPort->GetPort());
719	IOCtlReply* reply;
720	status_t error = AllocateRequest(allocator, &reply);
721	if (error != B_OK)
722		RETURN_ERROR(error);
723
724	// allocate the writable buffer for the call
725	void* writeBuffer = NULL;
726	if (result == B_OK && isBuffer && writeSize > 0) {
727		if (writeSize < bufferSize)
728			writeSize = bufferSize;
729		result = allocator.AllocateAddress(reply->buffer, writeSize, 8,
730			(void**)&writeBuffer, true);
731		if (result == B_OK && bufferSize > 0)
732			memcpy(writeBuffer, buffer, bufferSize);
733		buffer = writeBuffer;
734	}
735
736	// execute the request
737	status_t ioctlError = B_OK;
738	if (result == B_OK) {
739		RequestThreadContext context(volume, request);
740		ioctlError = volume->IOCtl(request->node, request->fileCookie,
741			request->command, buffer, len);
742	}
743
744	// reconstruct the reply, in case it has been overwritten
745	reply = new(reply) IOCtlReply;
746
747	// send the reply
748	reply->error = result;
749	reply->ioctlError = ioctlError;
750	return _SendReply(allocator, (result == B_OK && writeBuffer));
751}
752
753// _HandleRequest
754status_t
755UserlandRequestHandler::_HandleRequest(SetFlagsRequest* request)
756{
757	// check and execute the request
758	status_t result = B_OK;
759	Volume* volume = (Volume*)request->volume;
760	if (!volume)
761		result = B_BAD_VALUE;
762
763	if (result == B_OK) {
764		RequestThreadContext context(volume, request);
765		result = volume->SetFlags(request->node, request->fileCookie,
766			request->flags);
767	}
768
769	// prepare the reply
770	RequestAllocator allocator(fPort->GetPort());
771	SetFlagsReply* reply;
772	status_t error = AllocateRequest(allocator, &reply);
773	if (error != B_OK)
774		RETURN_ERROR(error);
775
776	reply->error = result;
777
778	// send the reply
779	return _SendReply(allocator, false);
780}
781
782// _HandleRequest
783status_t
784UserlandRequestHandler::_HandleRequest(SelectRequest* request)
785{
786	// check and execute the request
787	status_t result = B_OK;
788	Volume* volume = (Volume*)request->volume;
789	if (!volume)
790		result = B_BAD_VALUE;
791
792	if (result == B_OK) {
793		RequestThreadContext context(volume, request);
794		result = volume->Select(request->node, request->fileCookie,
795			request->event, request->sync);
796	}
797
798	// prepare the reply
799	RequestAllocator allocator(fPort->GetPort());
800	SelectReply* reply;
801	status_t error = AllocateRequest(allocator, &reply);
802	if (error != B_OK)
803		RETURN_ERROR(error);
804
805	reply->error = result;
806
807	// send the reply
808	return _SendReply(allocator, false);
809}
810
811// _HandleRequest
812status_t
813UserlandRequestHandler::_HandleRequest(DeselectRequest* request)
814{
815	// check and execute the request
816	status_t result = B_OK;
817	Volume* volume = (Volume*)request->volume;
818	if (!volume)
819		result = B_BAD_VALUE;
820
821	if (result == B_OK) {
822		RequestThreadContext context(volume, request);
823		result = volume->Deselect(request->node, request->fileCookie,
824			request->event, request->sync);
825	}
826
827	// prepare the reply
828	RequestAllocator allocator(fPort->GetPort());
829	DeselectReply* reply;
830	status_t error = AllocateRequest(allocator, &reply);
831	if (error != B_OK)
832		RETURN_ERROR(error);
833
834	reply->error = result;
835
836	// send the reply
837	return _SendReply(allocator, false);
838}
839
840// _HandleRequest
841status_t
842UserlandRequestHandler::_HandleRequest(FSyncRequest* request)
843{
844	// check and execute the request
845	status_t result = B_OK;
846	Volume* volume = (Volume*)request->volume;
847	if (!volume)
848		result = B_BAD_VALUE;
849
850	if (result == B_OK) {
851		RequestThreadContext context(volume, request);
852		result = volume->FSync(request->node);
853	}
854
855	// prepare the reply
856	RequestAllocator allocator(fPort->GetPort());
857	FSyncReply* reply;
858	status_t error = AllocateRequest(allocator, &reply);
859	if (error != B_OK)
860		RETURN_ERROR(error);
861
862	reply->error = result;
863
864	// send the reply
865	return _SendReply(allocator, false);
866}
867
868// _HandleRequest
869status_t
870UserlandRequestHandler::_HandleRequest(ReadSymlinkRequest* request)
871{
872	// check and execute the request
873	status_t result = B_OK;
874	Volume* volume = (Volume*)request->volume;
875	if (!volume)
876		result = B_BAD_VALUE;
877
878	void* node = request->node;
879	size_t bufferSize = request->size;
880
881	// allocate the reply
882	RequestAllocator allocator(fPort->GetPort());
883	ReadSymlinkReply* reply;
884	status_t error = AllocateRequest(allocator, &reply);
885	if (error != B_OK)
886		RETURN_ERROR(error);
887	char* buffer;
888	if (result == B_OK) {
889		result = allocator.AllocateAddress(reply->buffer, bufferSize, 1,
890			(void**)&buffer, true);
891	}
892
893	// execute the request
894	size_t bytesRead;
895	if (result == B_OK) {
896		RequestThreadContext context(volume, request);
897		result = volume->ReadSymlink(node, buffer, bufferSize, &bytesRead);
898	}
899
900	// reconstruct the reply, in case it has been overwritten
901	reply = new(reply) ReadSymlinkReply;
902
903	// send the reply
904	reply->error = result;
905	reply->bytesRead = bytesRead;
906	return _SendReply(allocator, (result == B_OK));
907}
908
909// _HandleRequest
910status_t
911UserlandRequestHandler::_HandleRequest(CreateSymlinkRequest* request)
912{
913	// check and execute the request
914	status_t result = B_OK;
915	Volume* volume = (Volume*)request->volume;
916	if (!volume)
917		result = B_BAD_VALUE;
918
919	if (result == B_OK) {
920		RequestThreadContext context(volume, request);
921		result = volume->CreateSymlink(request->node,
922			(const char*)request->name.GetData(),
923			(const char*)request->target.GetData(), request->mode);
924	}
925
926	// prepare the reply
927	RequestAllocator allocator(fPort->GetPort());
928	CreateSymlinkReply* reply;
929	status_t error = AllocateRequest(allocator, &reply);
930	if (error != B_OK)
931		RETURN_ERROR(error);
932
933	reply->error = result;
934
935	// send the reply
936	return _SendReply(allocator, false);
937}
938
939// _HandleRequest
940status_t
941UserlandRequestHandler::_HandleRequest(LinkRequest* request)
942{
943	// check and execute the request
944	status_t result = B_OK;
945	Volume* volume = (Volume*)request->volume;
946	if (!volume)
947		result = B_BAD_VALUE;
948
949	if (result == B_OK) {
950		RequestThreadContext context(volume, request);
951		result = volume->Link(request->node,
952			(const char*)request->name.GetData(), request->target);
953	}
954
955	// prepare the reply
956	RequestAllocator allocator(fPort->GetPort());
957	LinkReply* reply;
958	status_t error = AllocateRequest(allocator, &reply);
959	if (error != B_OK)
960		RETURN_ERROR(error);
961
962	reply->error = result;
963
964	// send the reply
965	return _SendReply(allocator, false);
966}
967
968// _HandleRequest
969status_t
970UserlandRequestHandler::_HandleRequest(UnlinkRequest* request)
971{
972	// check and execute the request
973	status_t result = B_OK;
974	Volume* volume = (Volume*)request->volume;
975	if (!volume)
976		result = B_BAD_VALUE;
977
978	if (result == B_OK) {
979		RequestThreadContext context(volume, request);
980		result = volume->Unlink(request->node,
981			(const char*)request->name.GetData());
982	}
983
984	// prepare the reply
985	RequestAllocator allocator(fPort->GetPort());
986	UnlinkReply* reply;
987	status_t error = AllocateRequest(allocator, &reply);
988	if (error != B_OK)
989		RETURN_ERROR(error);
990
991	reply->error = result;
992
993	// send the reply
994	return _SendReply(allocator, false);
995}
996
997// _HandleRequest
998status_t
999UserlandRequestHandler::_HandleRequest(RenameRequest* request)
1000{
1001	// check and execute the request
1002	status_t result = B_OK;
1003	Volume* volume = (Volume*)request->volume;
1004	if (!volume)
1005		result = B_BAD_VALUE;
1006
1007	if (result == B_OK) {
1008		RequestThreadContext context(volume, request);
1009		result = volume->Rename(request->oldDir,
1010			(const char*)request->oldName.GetData(), request->newDir,
1011			(const char*)request->newName.GetData());
1012	}
1013
1014	// prepare the reply
1015	RequestAllocator allocator(fPort->GetPort());
1016	RenameReply* reply;
1017	status_t error = AllocateRequest(allocator, &reply);
1018	if (error != B_OK)
1019		RETURN_ERROR(error);
1020
1021	reply->error = result;
1022
1023	// send the reply
1024	return _SendReply(allocator, false);
1025}
1026
1027// _HandleRequest
1028status_t
1029UserlandRequestHandler::_HandleRequest(AccessRequest* request)
1030{
1031	// check and execute the request
1032	status_t result = B_OK;
1033	Volume* volume = (Volume*)request->volume;
1034	if (!volume)
1035		result = B_BAD_VALUE;
1036
1037	if (result == B_OK) {
1038		RequestThreadContext context(volume, request);
1039		result = volume->Access(request->node, request->mode);
1040	}
1041
1042	// prepare the reply
1043	RequestAllocator allocator(fPort->GetPort());
1044	AccessReply* reply;
1045	status_t error = AllocateRequest(allocator, &reply);
1046	if (error != B_OK)
1047		RETURN_ERROR(error);
1048
1049	reply->error = result;
1050
1051	// send the reply
1052	return _SendReply(allocator, false);
1053}
1054
1055// _HandleRequest
1056status_t
1057UserlandRequestHandler::_HandleRequest(ReadStatRequest* request)
1058{
1059	// check and execute the request
1060	status_t result = B_OK;
1061	Volume* volume = (Volume*)request->volume;
1062	if (!volume)
1063		result = B_BAD_VALUE;
1064
1065	struct stat st;
1066	if (result == B_OK) {
1067		RequestThreadContext context(volume, request);
1068		result = volume->ReadStat(request->node, &st);
1069	}
1070
1071	// prepare the reply
1072	RequestAllocator allocator(fPort->GetPort());
1073	ReadStatReply* reply;
1074	status_t error = AllocateRequest(allocator, &reply);
1075	if (error != B_OK)
1076		RETURN_ERROR(error);
1077
1078	reply->error = result;
1079	reply->st = st;
1080
1081	// send the reply
1082	return _SendReply(allocator, false);
1083}
1084
1085// _HandleRequest
1086status_t
1087UserlandRequestHandler::_HandleRequest(WriteStatRequest* request)
1088{
1089	// check and execute the request
1090	status_t result = B_OK;
1091	Volume* volume = (Volume*)request->volume;
1092	if (!volume)
1093		result = B_BAD_VALUE;
1094
1095	if (result == B_OK) {
1096		RequestThreadContext context(volume, request);
1097		result = volume->WriteStat(request->node, &request->st, request->mask);
1098	}
1099
1100	// prepare the reply
1101	RequestAllocator allocator(fPort->GetPort());
1102	WriteStatReply* reply;
1103	status_t error = AllocateRequest(allocator, &reply);
1104	if (error != B_OK)
1105		RETURN_ERROR(error);
1106
1107	reply->error = result;
1108
1109	// send the reply
1110	return _SendReply(allocator, false);
1111}
1112
1113
1114// #pragma mark - files
1115
1116
1117// _HandleRequest
1118status_t
1119UserlandRequestHandler::_HandleRequest(CreateRequest* request)
1120{
1121	// check and execute the request
1122	status_t result = B_OK;
1123	Volume* volume = (Volume*)request->volume;
1124	if (!volume)
1125		result = B_BAD_VALUE;
1126
1127	ino_t vnid;
1128	void* fileCookie;
1129	if (result == B_OK) {
1130		RequestThreadContext context(volume, request);
1131		result = volume->Create(request->node,
1132			(const char*)request->name.GetData(), request->openMode,
1133			request->mode, &fileCookie, &vnid);
1134	}
1135
1136	// prepare the reply
1137	RequestAllocator allocator(fPort->GetPort());
1138	CreateReply* reply;
1139	status_t error = AllocateRequest(allocator, &reply);
1140	if (error != B_OK)
1141		RETURN_ERROR(error);
1142
1143	reply->error = result;
1144	reply->vnid = vnid;
1145	reply->fileCookie = fileCookie;
1146
1147	// send the reply
1148	return _SendReply(allocator, false);
1149}
1150
1151// _HandleRequest
1152status_t
1153UserlandRequestHandler::_HandleRequest(OpenRequest* request)
1154{
1155	// check and execute the request
1156	status_t result = B_OK;
1157	Volume* volume = (Volume*)request->volume;
1158	if (!volume)
1159		result = B_BAD_VALUE;
1160
1161	void* fileCookie;
1162	if (result == B_OK) {
1163		RequestThreadContext context(volume, request);
1164		result = volume->Open(request->node, request->openMode, &fileCookie);
1165	}
1166
1167	// prepare the reply
1168	RequestAllocator allocator(fPort->GetPort());
1169	OpenReply* reply;
1170	status_t error = AllocateRequest(allocator, &reply);
1171	if (error != B_OK)
1172		RETURN_ERROR(error);
1173
1174	reply->error = result;
1175	reply->fileCookie = fileCookie;
1176
1177	// send the reply
1178	return _SendReply(allocator, false);
1179}
1180
1181// _HandleRequest
1182status_t
1183UserlandRequestHandler::_HandleRequest(CloseRequest* request)
1184{
1185	// check and execute the request
1186	status_t result = B_OK;
1187	Volume* volume = (Volume*)request->volume;
1188	if (!volume)
1189		result = B_BAD_VALUE;
1190
1191	if (result == B_OK) {
1192		RequestThreadContext context(volume, request);
1193		result = volume->Close(request->node, request->fileCookie);
1194	}
1195
1196	// prepare the reply
1197	RequestAllocator allocator(fPort->GetPort());
1198	CloseReply* reply;
1199	status_t error = AllocateRequest(allocator, &reply);
1200	if (error != B_OK)
1201		RETURN_ERROR(error);
1202
1203	reply->error = result;
1204
1205	// send the reply
1206	return _SendReply(allocator, false);
1207}
1208
1209// _HandleRequest
1210status_t
1211UserlandRequestHandler::_HandleRequest(FreeCookieRequest* request)
1212{
1213	// check and execute the request
1214	status_t result = B_OK;
1215	Volume* volume = (Volume*)request->volume;
1216	if (!volume)
1217		result = B_BAD_VALUE;
1218
1219	if (result == B_OK) {
1220		RequestThreadContext context(volume, request);
1221		result = volume->FreeCookie(request->node, request->fileCookie);
1222	}
1223
1224	// prepare the reply
1225	RequestAllocator allocator(fPort->GetPort());
1226	FreeCookieReply* reply;
1227	status_t error = AllocateRequest(allocator, &reply);
1228	if (error != B_OK)
1229		RETURN_ERROR(error);
1230
1231	reply->error = result;
1232
1233	// send the reply
1234	return _SendReply(allocator, false);
1235}
1236
1237// _HandleRequest
1238status_t
1239UserlandRequestHandler::_HandleRequest(ReadRequest* request)
1240{
1241	// check and execute the request
1242	status_t result = B_OK;
1243	Volume* volume = (Volume*)request->volume;
1244	if (!volume)
1245		result = B_BAD_VALUE;
1246
1247	void* node = request->node;
1248	void* fileCookie = request->fileCookie;
1249	off_t pos = request->pos;
1250	size_t size = request->size;
1251
1252	// allocate the reply
1253	RequestAllocator allocator(fPort->GetPort());
1254	ReadReply* reply;
1255	status_t error = AllocateRequest(allocator, &reply);
1256	if (error != B_OK)
1257		RETURN_ERROR(error);
1258
1259	void* buffer;
1260	if (result == B_OK) {
1261		result = allocator.AllocateAddress(reply->buffer, size, 1, &buffer,
1262			true);
1263	}
1264
1265	// execute the request
1266	size_t bytesRead;
1267	if (result == B_OK) {
1268		RequestThreadContext context(volume, request);
1269		result = volume->Read(node, fileCookie, pos, buffer, size, &bytesRead);
1270	}
1271
1272	// reconstruct the reply, in case it has been overwritten
1273	reply = new(reply) ReadReply;
1274
1275	// send the reply
1276	reply->error = result;
1277	reply->bytesRead = bytesRead;
1278	return _SendReply(allocator, (result == B_OK));
1279}
1280
1281// _HandleRequest
1282status_t
1283UserlandRequestHandler::_HandleRequest(WriteRequest* request)
1284{
1285	// check and execute the request
1286	status_t result = B_OK;
1287	Volume* volume = (Volume*)request->volume;
1288	if (!volume)
1289		result = B_BAD_VALUE;
1290
1291	size_t bytesWritten;
1292	if (result == B_OK) {
1293		RequestThreadContext context(volume, request);
1294		result = volume->Write(request->node, request->fileCookie,
1295			request->pos, request->buffer.GetData(), request->buffer.GetSize(),
1296			&bytesWritten);
1297	}
1298
1299	// prepare the reply
1300	RequestAllocator allocator(fPort->GetPort());
1301	WriteReply* reply;
1302	status_t error = AllocateRequest(allocator, &reply);
1303	if (error != B_OK)
1304		RETURN_ERROR(error);
1305
1306	reply->error = result;
1307	reply->bytesWritten = bytesWritten;
1308
1309	// send the reply
1310	return _SendReply(allocator, false);
1311}
1312
1313
1314// #pragma mark - directories
1315
1316
1317// _HandleRequest
1318status_t
1319UserlandRequestHandler::_HandleRequest(CreateDirRequest* request)
1320{
1321	// check and execute the request
1322	status_t result = B_OK;
1323	Volume* volume = (Volume*)request->volume;
1324	if (!volume)
1325		result = B_BAD_VALUE;
1326
1327	if (result == B_OK) {
1328		RequestThreadContext context(volume, request);
1329		result = volume->CreateDir(request->node,
1330			(const char*)request->name.GetData(), request->mode);
1331	}
1332
1333	// prepare the reply
1334	RequestAllocator allocator(fPort->GetPort());
1335	CreateDirReply* reply;
1336	status_t error = AllocateRequest(allocator, &reply);
1337	if (error != B_OK)
1338		RETURN_ERROR(error);
1339
1340	reply->error = result;
1341
1342	// send the reply
1343	return _SendReply(allocator, false);
1344}
1345
1346// _HandleRequest
1347status_t
1348UserlandRequestHandler::_HandleRequest(RemoveDirRequest* request)
1349{
1350	// check and execute the request
1351	status_t result = B_OK;
1352	Volume* volume = (Volume*)request->volume;
1353	if (!volume)
1354		result = B_BAD_VALUE;
1355
1356	if (result == B_OK) {
1357		RequestThreadContext context(volume, request);
1358		result = volume->RemoveDir(request->node,
1359			(const char*)request->name.GetData());
1360	}
1361
1362	// prepare the reply
1363	RequestAllocator allocator(fPort->GetPort());
1364	RemoveDirReply* reply;
1365	status_t error = AllocateRequest(allocator, &reply);
1366	if (error != B_OK)
1367		RETURN_ERROR(error);
1368
1369	reply->error = result;
1370
1371	// send the reply
1372	return _SendReply(allocator, false);
1373}
1374
1375// _HandleRequest
1376status_t
1377UserlandRequestHandler::_HandleRequest(OpenDirRequest* request)
1378{
1379	// check and execute the request
1380	status_t result = B_OK;
1381	Volume* volume = (Volume*)request->volume;
1382	if (!volume)
1383		result = B_BAD_VALUE;
1384
1385	void* dirCookie = NULL;
1386	if (result == B_OK) {
1387		RequestThreadContext context(volume, request);
1388		result = volume->OpenDir(request->node, &dirCookie);
1389	}
1390
1391	// prepare the reply
1392	RequestAllocator allocator(fPort->GetPort());
1393	OpenDirReply* reply;
1394	status_t error = AllocateRequest(allocator, &reply);
1395	if (error != B_OK)
1396		RETURN_ERROR(error);
1397
1398	reply->error = result;
1399	reply->dirCookie = dirCookie;
1400
1401	// send the reply
1402	return _SendReply(allocator, false);
1403}
1404
1405// _HandleRequest
1406status_t
1407UserlandRequestHandler::_HandleRequest(CloseDirRequest* request)
1408{
1409	// check and execute the request
1410	status_t result = B_OK;
1411	Volume* volume = (Volume*)request->volume;
1412	if (!volume)
1413		result = B_BAD_VALUE;
1414
1415	if (result == B_OK) {
1416		RequestThreadContext context(volume, request);
1417		result = volume->CloseDir(request->node, request->dirCookie);
1418	}
1419
1420	// prepare the reply
1421	RequestAllocator allocator(fPort->GetPort());
1422	CloseDirReply* reply;
1423	status_t error = AllocateRequest(allocator, &reply);
1424	if (error != B_OK)
1425		RETURN_ERROR(error);
1426
1427	reply->error = result;
1428
1429	// send the reply
1430	return _SendReply(allocator, false);
1431}
1432
1433// _HandleRequest
1434status_t
1435UserlandRequestHandler::_HandleRequest(FreeDirCookieRequest* request)
1436{
1437	// check and execute the request
1438	status_t result = B_OK;
1439	Volume* volume = (Volume*)request->volume;
1440	if (!volume)
1441		result = B_BAD_VALUE;
1442
1443	if (result == B_OK) {
1444		RequestThreadContext context(volume, request);
1445		result = volume->FreeDirCookie(request->node, request->dirCookie);
1446	}
1447
1448	// prepare the reply
1449	RequestAllocator allocator(fPort->GetPort());
1450	FreeDirCookieReply* reply;
1451	status_t error = AllocateRequest(allocator, &reply);
1452	if (error != B_OK)
1453		RETURN_ERROR(error);
1454
1455	reply->error = result;
1456
1457	// send the reply
1458	return _SendReply(allocator, false);
1459}
1460
1461// _HandleRequest
1462status_t
1463UserlandRequestHandler::_HandleRequest(ReadDirRequest* request)
1464{
1465	// check the request
1466	status_t result = B_OK;
1467	Volume* volume = (Volume*)request->volume;
1468	if (!volume)
1469		result = B_BAD_VALUE;
1470
1471	void* node = request->node;
1472	void* dirCookie = request->dirCookie;
1473	size_t bufferSize = request->bufferSize;
1474	uint32 count = request->count;
1475
1476	// allocate the reply
1477	RequestAllocator allocator(fPort->GetPort());
1478	ReadDirReply* reply;
1479	status_t error = AllocateRequest(allocator, &reply);
1480	if (error != B_OK)
1481		RETURN_ERROR(error);
1482
1483	void* buffer;
1484	if (result == B_OK) {
1485		result = allocator.AllocateAddress(reply->buffer, bufferSize, 1,
1486			&buffer, true);
1487	}
1488
1489	// execute the request
1490	uint32 countRead;
1491	if (result == B_OK) {
1492		RequestThreadContext context(volume, request);
1493		result = volume->ReadDir(node, dirCookie, buffer, bufferSize, count,
1494			&countRead);
1495	}
1496
1497	D(
1498		if (result == B_OK && countRead > 0) {
1499			dirent* entry = (dirent*)buffer;
1500			PRINT(("  entry: d_dev: %" B_PRIdDEV ", d_pdev: %" B_PRIdDEV ", "
1501				"d_ino: %" B_PRIdINO ", d_pino: %" B_PRIdINO ", "
1502				"d_reclen: %hu, d_name: %.32s\n",
1503			entry->d_dev, entry->d_pdev,
1504			entry->d_ino, entry->d_pino,
1505			entry->d_reclen, entry->d_name));
1506		}
1507	)
1508
1509	// reconstruct the reply, in case it has been overwritten
1510	reply = new(reply) ReadDirReply;
1511
1512	// send the reply
1513	reply->error = result;
1514	reply->count = countRead;
1515	return _SendReply(allocator, (result == B_OK));
1516}
1517
1518// _HandleRequest
1519status_t
1520UserlandRequestHandler::_HandleRequest(RewindDirRequest* request)
1521{
1522	// check and execute the request
1523	status_t result = B_OK;
1524	Volume* volume = (Volume*)request->volume;
1525	if (!volume)
1526		result = B_BAD_VALUE;
1527
1528	if (result == B_OK) {
1529		RequestThreadContext context(volume, request);
1530		result = volume->RewindDir(request->node, request->dirCookie);
1531	}
1532
1533	// prepare the reply
1534	RequestAllocator allocator(fPort->GetPort());
1535	RewindDirReply* reply;
1536	status_t error = AllocateRequest(allocator, &reply);
1537	if (error != B_OK)
1538		RETURN_ERROR(error);
1539
1540	reply->error = result;
1541
1542	// send the reply
1543	return _SendReply(allocator, false);
1544}
1545
1546
1547// #pragma mark - attribute directories
1548
1549
1550// _HandleRequest
1551status_t
1552UserlandRequestHandler::_HandleRequest(OpenAttrDirRequest* request)
1553{
1554	// check and execute the request
1555	status_t result = B_OK;
1556	Volume* volume = (Volume*)request->volume;
1557	if (!volume)
1558		result = B_BAD_VALUE;
1559
1560	void* attrDirCookie;
1561	if (result == B_OK) {
1562		RequestThreadContext context(volume, request);
1563		result = volume->OpenAttrDir(request->node, &attrDirCookie);
1564	}
1565
1566	// prepare the reply
1567	RequestAllocator allocator(fPort->GetPort());
1568	OpenAttrDirReply* reply;
1569	status_t error = AllocateRequest(allocator, &reply);
1570	if (error != B_OK)
1571		RETURN_ERROR(error);
1572
1573	reply->error = result;
1574	reply->attrDirCookie = attrDirCookie;
1575
1576	// send the reply
1577	return _SendReply(allocator, false);
1578}
1579
1580// _HandleRequest
1581status_t
1582UserlandRequestHandler::_HandleRequest(CloseAttrDirRequest* request)
1583{
1584	// check and execute the request
1585	status_t result = B_OK;
1586	Volume* volume = (Volume*)request->volume;
1587	if (!volume)
1588		result = B_BAD_VALUE;
1589
1590	if (result == B_OK) {
1591		RequestThreadContext context(volume, request);
1592		result = volume->CloseAttrDir(request->node, request->attrDirCookie);
1593	}
1594
1595	// prepare the reply
1596	RequestAllocator allocator(fPort->GetPort());
1597	CloseAttrDirReply* reply;
1598	status_t error = AllocateRequest(allocator, &reply);
1599	if (error != B_OK)
1600		RETURN_ERROR(error);
1601
1602	reply->error = result;
1603
1604	// send the reply
1605	return _SendReply(allocator, false);
1606}
1607
1608// _HandleRequest
1609status_t
1610UserlandRequestHandler::_HandleRequest(FreeAttrDirCookieRequest* request)
1611{
1612	// check and execute the request
1613	status_t result = B_OK;
1614	Volume* volume = (Volume*)request->volume;
1615	if (!volume)
1616		result = B_BAD_VALUE;
1617
1618	if (result == B_OK) {
1619		RequestThreadContext context(volume, request);
1620		result = volume->FreeAttrDirCookie(request->node,
1621			request->attrDirCookie);
1622	}
1623
1624	// prepare the reply
1625	RequestAllocator allocator(fPort->GetPort());
1626	FreeAttrDirCookieReply* reply;
1627	status_t error = AllocateRequest(allocator, &reply);
1628	if (error != B_OK)
1629		RETURN_ERROR(error);
1630
1631	reply->error = result;
1632
1633	// send the reply
1634	return _SendReply(allocator, false);
1635}
1636
1637// _HandleRequest
1638status_t
1639UserlandRequestHandler::_HandleRequest(ReadAttrDirRequest* request)
1640{
1641	// check and execute the request
1642	status_t result = B_OK;
1643	Volume* volume = (Volume*)request->volume;
1644	if (!volume)
1645		result = B_BAD_VALUE;
1646
1647	void* node = request->node;
1648	void* attrDirCookie = request->attrDirCookie;
1649	size_t bufferSize = request->bufferSize;
1650	uint32 count = request->count;
1651
1652	// allocate the reply
1653	RequestAllocator allocator(fPort->GetPort());
1654	ReadAttrDirReply* reply;
1655	status_t error = AllocateRequest(allocator, &reply);
1656	if (error != B_OK)
1657		RETURN_ERROR(error);
1658
1659	void* buffer;
1660	if (result == B_OK) {
1661		result = allocator.AllocateAddress(reply->buffer, bufferSize, 1,
1662			&buffer, true);
1663	}
1664
1665	// execute the request
1666	uint32 countRead;
1667	if (result == B_OK) {
1668		RequestThreadContext context(volume, request);
1669		result = volume->ReadAttrDir(node, attrDirCookie, buffer, bufferSize,
1670			count, &countRead);
1671	}
1672
1673	// reconstruct the reply, in case it has been overwritten
1674	reply = new(reply) ReadAttrDirReply;
1675
1676	// send the reply
1677	reply->error = result;
1678	reply->count = countRead;
1679	return _SendReply(allocator, (result == B_OK));
1680}
1681
1682// _HandleRequest
1683status_t
1684UserlandRequestHandler::_HandleRequest(RewindAttrDirRequest* request)
1685{
1686	// check and execute the request
1687	status_t result = B_OK;
1688	Volume* volume = (Volume*)request->volume;
1689	if (!volume)
1690		result = B_BAD_VALUE;
1691
1692	if (result == B_OK) {
1693		RequestThreadContext context(volume, request);
1694		result = volume->RewindAttrDir(request->node, request->attrDirCookie);
1695	}
1696
1697	// prepare the reply
1698	RequestAllocator allocator(fPort->GetPort());
1699	RewindAttrDirReply* reply;
1700	status_t error = AllocateRequest(allocator, &reply);
1701	if (error != B_OK)
1702		RETURN_ERROR(error);
1703
1704	reply->error = result;
1705
1706	// send the reply
1707	return _SendReply(allocator, false);
1708}
1709
1710
1711// #pragma mark - attributes
1712
1713
1714// _HandleRequest
1715status_t
1716UserlandRequestHandler::_HandleRequest(CreateAttrRequest* request)
1717{
1718	// check and execute the request
1719	status_t result = B_OK;
1720	Volume* volume = (Volume*)request->volume;
1721	if (!volume)
1722		result = B_BAD_VALUE;
1723
1724	void* attrCookie;
1725	if (result == B_OK) {
1726		RequestThreadContext context(volume, request);
1727		result = volume->CreateAttr(request->node,
1728			(const char*)request->name.GetData(), request->type,
1729			request->openMode, &attrCookie);
1730	}
1731
1732	// prepare the reply
1733	RequestAllocator allocator(fPort->GetPort());
1734	CreateAttrReply* reply;
1735	status_t error = AllocateRequest(allocator, &reply);
1736	if (error != B_OK)
1737		RETURN_ERROR(error);
1738
1739	reply->error = result;
1740	reply->attrCookie = attrCookie;
1741
1742	// send the reply
1743	return _SendReply(allocator, false);
1744}
1745
1746// _HandleRequest
1747status_t
1748UserlandRequestHandler::_HandleRequest(OpenAttrRequest* request)
1749{
1750	// check and execute the request
1751	status_t result = B_OK;
1752	Volume* volume = (Volume*)request->volume;
1753	if (!volume)
1754		result = B_BAD_VALUE;
1755
1756	void* attrCookie;
1757	if (result == B_OK) {
1758		RequestThreadContext context(volume, request);
1759		result = volume->OpenAttr(request->node,
1760			(const char*)request->name.GetData(), request->openMode,
1761			&attrCookie);
1762	}
1763
1764	// prepare the reply
1765	RequestAllocator allocator(fPort->GetPort());
1766	OpenAttrReply* reply;
1767	status_t error = AllocateRequest(allocator, &reply);
1768	if (error != B_OK)
1769		RETURN_ERROR(error);
1770
1771	reply->error = result;
1772	reply->attrCookie = attrCookie;
1773
1774	// send the reply
1775	return _SendReply(allocator, false);
1776}
1777
1778// _HandleRequest
1779status_t
1780UserlandRequestHandler::_HandleRequest(CloseAttrRequest* request)
1781{
1782	// check and execute the request
1783	status_t result = B_OK;
1784	Volume* volume = (Volume*)request->volume;
1785	if (!volume)
1786		result = B_BAD_VALUE;
1787
1788	if (result == B_OK) {
1789		RequestThreadContext context(volume, request);
1790		result = volume->CloseAttr(request->node, request->attrCookie);
1791	}
1792
1793	// prepare the reply
1794	RequestAllocator allocator(fPort->GetPort());
1795	CloseAttrReply* reply;
1796	status_t error = AllocateRequest(allocator, &reply);
1797	if (error != B_OK)
1798		RETURN_ERROR(error);
1799
1800	reply->error = result;
1801
1802	// send the reply
1803	return _SendReply(allocator, false);
1804}
1805
1806// _HandleRequest
1807status_t
1808UserlandRequestHandler::_HandleRequest(FreeAttrCookieRequest* request)
1809{
1810	// check and execute the request
1811	status_t result = B_OK;
1812	Volume* volume = (Volume*)request->volume;
1813	if (!volume)
1814		result = B_BAD_VALUE;
1815
1816	if (result == B_OK) {
1817		RequestThreadContext context(volume, request);
1818		result = volume->FreeAttrCookie(request->node, request->attrCookie);
1819	}
1820
1821	// prepare the reply
1822	RequestAllocator allocator(fPort->GetPort());
1823	FreeAttrCookieReply* reply;
1824	status_t error = AllocateRequest(allocator, &reply);
1825	if (error != B_OK)
1826		RETURN_ERROR(error);
1827
1828	reply->error = result;
1829
1830	// send the reply
1831	return _SendReply(allocator, false);
1832}
1833
1834// _HandleRequest
1835status_t
1836UserlandRequestHandler::_HandleRequest(ReadAttrRequest* request)
1837{
1838	// check and execute the request
1839	status_t result = B_OK;
1840	Volume* volume = (Volume*)request->volume;
1841	if (!volume)
1842		result = B_BAD_VALUE;
1843
1844	void* node = request->node;
1845	void* attrCookie = request->attrCookie;
1846	off_t pos = request->pos;
1847	size_t size = request->size;
1848
1849	// allocate the reply
1850	RequestAllocator allocator(fPort->GetPort());
1851	ReadAttrReply* reply;
1852	status_t error = AllocateRequest(allocator, &reply);
1853	if (error != B_OK)
1854		RETURN_ERROR(error);
1855
1856	void* buffer;
1857	if (result == B_OK) {
1858		result = allocator.AllocateAddress(reply->buffer, size, 1, &buffer,
1859			true);
1860	}
1861
1862	// execute the request
1863	size_t bytesRead;
1864	if (result == B_OK) {
1865		RequestThreadContext context(volume, request);
1866		result = volume->ReadAttr(node, attrCookie, pos, buffer, size,
1867			&bytesRead);
1868	}
1869
1870	// reconstruct the reply, in case it has been overwritten
1871	reply = new(reply) ReadAttrReply;
1872
1873	// send the reply
1874	reply->error = result;
1875	reply->bytesRead = bytesRead;
1876	return _SendReply(allocator, (result == B_OK));
1877}
1878
1879// _HandleRequest
1880status_t
1881UserlandRequestHandler::_HandleRequest(WriteAttrRequest* request)
1882{
1883	// check and execute the request
1884	status_t result = B_OK;
1885	Volume* volume = (Volume*)request->volume;
1886	if (!volume)
1887		result = B_BAD_VALUE;
1888
1889	size_t bytesWritten;
1890	if (result == B_OK) {
1891		RequestThreadContext context(volume, request);
1892		result = volume->WriteAttr(request->node, request->attrCookie,
1893			request->pos, request->buffer.GetData(), request->buffer.GetSize(),
1894			&bytesWritten);
1895	}
1896
1897	// prepare the reply
1898	RequestAllocator allocator(fPort->GetPort());
1899	WriteAttrReply* reply;
1900	status_t error = AllocateRequest(allocator, &reply);
1901	if (error != B_OK)
1902		RETURN_ERROR(error);
1903
1904	reply->error = result;
1905	reply->bytesWritten = bytesWritten;
1906
1907	// send the reply
1908	return _SendReply(allocator, false);
1909}
1910
1911// _HandleRequest
1912status_t
1913UserlandRequestHandler::_HandleRequest(ReadAttrStatRequest* request)
1914{
1915	// check and execute the request
1916	status_t result = B_OK;
1917	Volume* volume = (Volume*)request->volume;
1918	if (!volume)
1919		result = B_BAD_VALUE;
1920
1921	struct stat st;
1922	if (result == B_OK) {
1923		RequestThreadContext context(volume, request);
1924		result = volume->ReadAttrStat(request->node, request->attrCookie,
1925			&st);
1926	}
1927
1928	// prepare the reply
1929	RequestAllocator allocator(fPort->GetPort());
1930	ReadAttrStatReply* reply;
1931	status_t error = AllocateRequest(allocator, &reply);
1932	if (error != B_OK)
1933		RETURN_ERROR(error);
1934
1935	reply->error = result;
1936	reply->st = st;
1937
1938	// send the reply
1939	return _SendReply(allocator, false);
1940}
1941
1942// _HandleRequest
1943status_t
1944UserlandRequestHandler::_HandleRequest(WriteAttrStatRequest* request)
1945{
1946	// check and execute the request
1947	status_t result = B_OK;
1948	Volume* volume = (Volume*)request->volume;
1949	if (!volume)
1950		result = B_BAD_VALUE;
1951
1952	if (result == B_OK) {
1953		RequestThreadContext context(volume, request);
1954		result = volume->WriteAttrStat(request->node, request->attrCookie,
1955			&request->st, request->mask);
1956	}
1957
1958	// prepare the reply
1959	RequestAllocator allocator(fPort->GetPort());
1960	WriteAttrStatReply* reply;
1961	status_t error = AllocateRequest(allocator, &reply);
1962	if (error != B_OK)
1963		RETURN_ERROR(error);
1964
1965	reply->error = result;
1966
1967	// send the reply
1968	return _SendReply(allocator, false);
1969}
1970
1971// _HandleRequest
1972status_t
1973UserlandRequestHandler::_HandleRequest(RenameAttrRequest* request)
1974{
1975	// check and execute the request
1976	status_t result = B_OK;
1977	Volume* volume = (Volume*)request->volume;
1978	if (!volume)
1979		result = B_BAD_VALUE;
1980
1981	if (result == B_OK) {
1982		RequestThreadContext context(volume, request);
1983		result = volume->RenameAttr(
1984			request->oldNode, (const char*)request->oldName.GetData(),
1985			request->newNode, (const char*)request->newName.GetData());
1986	}
1987
1988	// prepare the reply
1989	RequestAllocator allocator(fPort->GetPort());
1990	RenameAttrReply* reply;
1991	status_t error = AllocateRequest(allocator, &reply);
1992	if (error != B_OK)
1993		RETURN_ERROR(error);
1994
1995	reply->error = result;
1996
1997	// send the reply
1998	return _SendReply(allocator, false);
1999}
2000
2001// _HandleRequest
2002status_t
2003UserlandRequestHandler::_HandleRequest(RemoveAttrRequest* request)
2004{
2005	// check and execute the request
2006	status_t result = B_OK;
2007	Volume* volume = (Volume*)request->volume;
2008	if (!volume)
2009		result = B_BAD_VALUE;
2010
2011	if (result == B_OK) {
2012		RequestThreadContext context(volume, request);
2013		result = volume->RemoveAttr(request->node,
2014			(const char*)request->name.GetData());
2015	}
2016
2017	// prepare the reply
2018	RequestAllocator allocator(fPort->GetPort());
2019	RemoveAttrReply* reply;
2020	status_t error = AllocateRequest(allocator, &reply);
2021	if (error != B_OK)
2022		RETURN_ERROR(error);
2023
2024	reply->error = result;
2025
2026	// send the reply
2027	return _SendReply(allocator, false);
2028}
2029
2030
2031// #pragma mark - indices
2032
2033
2034// _HandleRequest
2035status_t
2036UserlandRequestHandler::_HandleRequest(OpenIndexDirRequest* request)
2037{
2038	// check and execute the request
2039	status_t result = B_OK;
2040	Volume* volume = (Volume*)request->volume;
2041	if (!volume)
2042		result = B_BAD_VALUE;
2043
2044	void* indexDirCookie;
2045	if (result == B_OK) {
2046		RequestThreadContext context(volume, request);
2047		result = volume->OpenIndexDir(&indexDirCookie);
2048	}
2049
2050	// prepare the reply
2051	RequestAllocator allocator(fPort->GetPort());
2052	OpenIndexDirReply* reply;
2053	status_t error = AllocateRequest(allocator, &reply);
2054	if (error != B_OK)
2055		RETURN_ERROR(error);
2056
2057	reply->error = result;
2058	reply->indexDirCookie = indexDirCookie;
2059
2060	// send the reply
2061	return _SendReply(allocator, false);
2062}
2063
2064// _HandleRequest
2065status_t
2066UserlandRequestHandler::_HandleRequest(CloseIndexDirRequest* request)
2067{
2068	// check and execute the request
2069	status_t result = B_OK;
2070	Volume* volume = (Volume*)request->volume;
2071	if (!volume)
2072		result = B_BAD_VALUE;
2073
2074	if (result == B_OK) {
2075		RequestThreadContext context(volume, request);
2076		result = volume->CloseIndexDir(request->indexDirCookie);
2077	}
2078
2079	// prepare the reply
2080	RequestAllocator allocator(fPort->GetPort());
2081	CloseIndexDirReply* reply;
2082	status_t error = AllocateRequest(allocator, &reply);
2083	if (error != B_OK)
2084		RETURN_ERROR(error);
2085
2086	reply->error = result;
2087
2088	// send the reply
2089	return _SendReply(allocator, false);
2090}
2091
2092// _HandleRequest
2093status_t
2094UserlandRequestHandler::_HandleRequest(FreeIndexDirCookieRequest* request)
2095{
2096	// check and execute the request
2097	status_t result = B_OK;
2098	Volume* volume = (Volume*)request->volume;
2099	if (!volume)
2100		result = B_BAD_VALUE;
2101
2102	if (result == B_OK) {
2103		RequestThreadContext context(volume, request);
2104		result = volume->FreeIndexDirCookie(request->indexDirCookie);
2105	}
2106
2107	// prepare the reply
2108	RequestAllocator allocator(fPort->GetPort());
2109	FreeIndexDirCookieReply* reply;
2110	status_t error = AllocateRequest(allocator, &reply);
2111	if (error != B_OK)
2112		RETURN_ERROR(error);
2113
2114	reply->error = result;
2115
2116	// send the reply
2117	return _SendReply(allocator, false);
2118}
2119
2120// _HandleRequest
2121status_t
2122UserlandRequestHandler::_HandleRequest(ReadIndexDirRequest* request)
2123{
2124	// check and execute the request
2125	status_t result = B_OK;
2126	Volume* volume = (Volume*)request->volume;
2127	if (!volume)
2128		result = B_BAD_VALUE;
2129
2130	void* indexDirCookie = request->indexDirCookie;
2131	size_t bufferSize = request->bufferSize;
2132	uint32 count = request->count;
2133
2134	// allocate the reply
2135	RequestAllocator allocator(fPort->GetPort());
2136	ReadIndexDirReply* reply;
2137	status_t error = AllocateRequest(allocator, &reply);
2138	if (error != B_OK)
2139		RETURN_ERROR(error);
2140
2141	void* buffer;
2142	if (result == B_OK) {
2143		result = allocator.AllocateAddress(reply->buffer, bufferSize, 1,
2144			&buffer, true);
2145	}
2146
2147	// execute the request
2148	uint32 countRead;
2149	if (result == B_OK) {
2150		RequestThreadContext context(volume, request);
2151		result = volume->ReadIndexDir(indexDirCookie, buffer, bufferSize,
2152			count, &countRead);
2153	}
2154
2155	// reconstruct the reply, in case it has been overwritten
2156	reply = new(reply) ReadIndexDirReply;
2157
2158	// send the reply
2159	reply->error = result;
2160	reply->count = countRead;
2161	return _SendReply(allocator, (result == B_OK));
2162}
2163
2164// _HandleRequest
2165status_t
2166UserlandRequestHandler::_HandleRequest(RewindIndexDirRequest* request)
2167{
2168	// check and execute the request
2169	status_t result = B_OK;
2170	Volume* volume = (Volume*)request->volume;
2171	if (!volume)
2172		result = B_BAD_VALUE;
2173
2174	if (result == B_OK) {
2175		RequestThreadContext context(volume, request);
2176		result = volume->RewindIndexDir(request->indexDirCookie);
2177	}
2178
2179	// prepare the reply
2180	RequestAllocator allocator(fPort->GetPort());
2181	RewindIndexDirReply* reply;
2182	status_t error = AllocateRequest(allocator, &reply);
2183	if (error != B_OK)
2184		RETURN_ERROR(error);
2185
2186	reply->error = result;
2187
2188	// send the reply
2189	return _SendReply(allocator, false);
2190}
2191
2192// _HandleRequest
2193status_t
2194UserlandRequestHandler::_HandleRequest(CreateIndexRequest* request)
2195{
2196	// check and execute the request
2197	status_t result = B_OK;
2198	Volume* volume = (Volume*)request->volume;
2199	if (!volume)
2200		result = B_BAD_VALUE;
2201
2202	if (result == B_OK) {
2203		RequestThreadContext context(volume, request);
2204		result = volume->CreateIndex((const char*)request->name.GetData(),
2205			request->type, request->flags);
2206	}
2207
2208	// prepare the reply
2209	RequestAllocator allocator(fPort->GetPort());
2210	CreateIndexReply* reply;
2211	status_t error = AllocateRequest(allocator, &reply);
2212	if (error != B_OK)
2213		RETURN_ERROR(error);
2214
2215	reply->error = result;
2216
2217	// send the reply
2218	return _SendReply(allocator, false);
2219}
2220
2221// _HandleRequest
2222status_t
2223UserlandRequestHandler::_HandleRequest(RemoveIndexRequest* request)
2224{
2225	// check and execute the request
2226	status_t result = B_OK;
2227	Volume* volume = (Volume*)request->volume;
2228	if (!volume)
2229		result = B_BAD_VALUE;
2230
2231	if (result == B_OK) {
2232		RequestThreadContext context(volume, request);
2233		result = volume->RemoveIndex((const char*)request->name.GetData());
2234	}
2235
2236	// prepare the reply
2237	RequestAllocator allocator(fPort->GetPort());
2238	RemoveIndexReply* reply;
2239	status_t error = AllocateRequest(allocator, &reply);
2240	if (error != B_OK)
2241		RETURN_ERROR(error);
2242
2243	reply->error = result;
2244
2245	// send the reply
2246	return _SendReply(allocator, false);
2247}
2248
2249// _HandleRequest
2250status_t
2251UserlandRequestHandler::_HandleRequest(ReadIndexStatRequest* request)
2252{
2253	// check and execute the request
2254	status_t result = B_OK;
2255	Volume* volume = (Volume*)request->volume;
2256	if (!volume)
2257		result = B_BAD_VALUE;
2258
2259	struct stat st;
2260	if (result == B_OK) {
2261		RequestThreadContext context(volume, request);
2262		result = volume->ReadIndexStat((const char*)request->name.GetData(),
2263			&st);
2264	}
2265
2266	// prepare the reply
2267	RequestAllocator allocator(fPort->GetPort());
2268	ReadIndexStatReply* reply;
2269	status_t error = AllocateRequest(allocator, &reply);
2270	if (error != B_OK)
2271		RETURN_ERROR(error);
2272
2273	reply->error = result;
2274	reply->st = st;
2275
2276	// send the reply
2277	return _SendReply(allocator, false);
2278}
2279
2280
2281// #pragma mark - queries
2282
2283
2284// _HandleRequest
2285status_t
2286UserlandRequestHandler::_HandleRequest(OpenQueryRequest* request)
2287{
2288	// check and execute the request
2289	status_t result = B_OK;
2290	Volume* volume = (Volume*)request->volume;
2291	if (!volume)
2292		result = B_BAD_VALUE;
2293
2294	void* queryCookie;
2295	if (result == B_OK) {
2296		RequestThreadContext context(volume, request);
2297		result = volume->OpenQuery((const char*)request->queryString.GetData(),
2298			request->flags, request->port, request->token, &queryCookie);
2299	}
2300
2301	// prepare the reply
2302	RequestAllocator allocator(fPort->GetPort());
2303	OpenQueryReply* reply;
2304	status_t error = AllocateRequest(allocator, &reply);
2305	if (error != B_OK)
2306		RETURN_ERROR(error);
2307
2308	reply->error = result;
2309	reply->queryCookie = queryCookie;
2310
2311	// send the reply
2312	return _SendReply(allocator, false);
2313}
2314
2315// _HandleRequest
2316status_t
2317UserlandRequestHandler::_HandleRequest(CloseQueryRequest* request)
2318{
2319	// check and execute the request
2320	status_t result = B_OK;
2321	Volume* volume = (Volume*)request->volume;
2322	if (!volume)
2323		result = B_BAD_VALUE;
2324
2325	if (result == B_OK) {
2326		RequestThreadContext context(volume, request);
2327		result = volume->CloseQuery(request->queryCookie);
2328	}
2329
2330	// prepare the reply
2331	RequestAllocator allocator(fPort->GetPort());
2332	CloseQueryReply* reply;
2333	status_t error = AllocateRequest(allocator, &reply);
2334	if (error != B_OK)
2335		RETURN_ERROR(error);
2336
2337	reply->error = result;
2338
2339	// send the reply
2340	return _SendReply(allocator, false);
2341}
2342
2343// _HandleRequest
2344status_t
2345UserlandRequestHandler::_HandleRequest(FreeQueryCookieRequest* request)
2346{
2347	// check and execute the request
2348	status_t result = B_OK;
2349	Volume* volume = (Volume*)request->volume;
2350	if (!volume)
2351		result = B_BAD_VALUE;
2352
2353	if (result == B_OK) {
2354		RequestThreadContext context(volume, request);
2355		result = volume->FreeQueryCookie(request->queryCookie);
2356	}
2357
2358	// prepare the reply
2359	RequestAllocator allocator(fPort->GetPort());
2360	FreeQueryCookieReply* reply;
2361	status_t error = AllocateRequest(allocator, &reply);
2362	if (error != B_OK)
2363		RETURN_ERROR(error);
2364
2365	reply->error = result;
2366
2367	// send the reply
2368	return _SendReply(allocator, false);
2369}
2370
2371// _HandleRequest
2372status_t
2373UserlandRequestHandler::_HandleRequest(ReadQueryRequest* request)
2374{
2375	// check and execute the request
2376	status_t result = B_OK;
2377	Volume* volume = (Volume*)request->volume;
2378	if (!volume)
2379		result = B_BAD_VALUE;
2380
2381	void* queryCookie = request->queryCookie;
2382	size_t bufferSize = request->bufferSize;
2383	uint32 count = request->count;
2384
2385	// allocate the reply
2386	RequestAllocator allocator(fPort->GetPort());
2387	ReadQueryReply* reply;
2388	status_t error = AllocateRequest(allocator, &reply);
2389	if (error != B_OK)
2390		RETURN_ERROR(error);
2391
2392	void* buffer;
2393	if (result == B_OK) {
2394		result = allocator.AllocateAddress(reply->buffer, bufferSize, 1,
2395			&buffer, true);
2396	}
2397
2398	// execute the request
2399	uint32 countRead;
2400	if (result == B_OK) {
2401		RequestThreadContext context(volume, request);
2402		result = volume->ReadQuery(queryCookie, buffer, bufferSize,
2403			count, &countRead);
2404	}
2405
2406	// reconstruct the reply, in case it has been overwritten
2407	reply = new(reply) ReadQueryReply;
2408
2409	// send the reply
2410	reply->error = result;
2411	reply->count = countRead;
2412	return _SendReply(allocator, (result == B_OK));
2413}
2414
2415// _HandleRequest
2416status_t
2417UserlandRequestHandler::_HandleRequest(RewindQueryRequest* request)
2418{
2419	// check and execute the request
2420	status_t result = B_OK;
2421	Volume* volume = (Volume*)request->volume;
2422	if (!volume)
2423		result = B_BAD_VALUE;
2424
2425	if (result == B_OK) {
2426		RequestThreadContext context(volume, request);
2427		result = volume->RewindQuery(request->queryCookie);
2428	}
2429
2430	// prepare the reply
2431	RequestAllocator allocator(fPort->GetPort());
2432	RewindQueryReply* reply;
2433	status_t error = AllocateRequest(allocator, &reply);
2434	if (error != B_OK)
2435		RETURN_ERROR(error);
2436
2437	reply->error = result;
2438
2439	// send the reply
2440	return _SendReply(allocator, false);
2441}
2442
2443
2444// #pragma mark - node monitoring
2445
2446
2447// _HandleRequest
2448status_t
2449UserlandRequestHandler::_HandleRequest(NodeMonitoringEventRequest* request)
2450{
2451	// check and execute the request
2452	KMessage event;
2453	event.SetTo(request->event.GetData(), request->event.GetSize());
2454	((NotificationListener*)request->listener)->EventOccurred(
2455		*(NotificationService*)NULL, &event);
2456
2457	// prepare the reply
2458	RequestAllocator allocator(fPort->GetPort());
2459	NodeMonitoringEventReply* reply;
2460	status_t error = AllocateRequest(allocator, &reply);
2461	if (error != B_OK)
2462		RETURN_ERROR(error);
2463
2464	reply->error = B_OK;
2465
2466	// send the reply
2467	return _SendReply(allocator, false);
2468}
2469
2470
2471// #pragma mark - other
2472
2473
2474// _SendReply
2475status_t
2476UserlandRequestHandler::_SendReply(RequestAllocator& allocator,
2477	bool expectsReceipt)
2478{
2479	if (expectsReceipt) {
2480		SingleReplyRequestHandler handler(RECEIPT_ACK_REPLY);
2481		return fPort->SendRequest(&allocator, &handler);
2482	} else
2483		return fPort->SendRequest(&allocator);
2484}
2485
2486