1// UserlandRequestHandler.cpp
2
3#include "AutoDeleter.h"
4#include "Compatibility.h"
5#include "Debug.h"
6#include "UserVolume.h"
7#include "RequestPort.h"
8#include "Requests.h"
9#include "RequestThread.h"
10#include "SingleReplyRequestHandler.h"
11#include "UserFileSystem.h"
12#include "UserlandRequestHandler.h"
13
14// constructor
15UserlandRequestHandler::UserlandRequestHandler(UserFileSystem* fileSystem)
16	: RequestHandler(),
17	  fFileSystem(fileSystem),
18	  fExpectReply(false),
19	  fExpectedReply(0)
20{
21}
22
23// constructor
24UserlandRequestHandler::UserlandRequestHandler(UserFileSystem* fileSystem,
25	uint32 expectedReply)
26	: RequestHandler(),
27	  fFileSystem(fileSystem),
28	  fExpectReply(true),
29	  fExpectedReply(expectedReply)
30{
31}
32
33// destructor
34UserlandRequestHandler::~UserlandRequestHandler()
35{
36}
37
38// HandleRequest
39status_t
40UserlandRequestHandler::HandleRequest(Request* request)
41{
42	if (fExpectReply && request->GetType() == fExpectedReply) {
43		fDone = true;
44		return B_OK;
45	}
46	switch (request->GetType()) {
47		// FS
48		case MOUNT_VOLUME_REQUEST:
49			return _HandleRequest((MountVolumeRequest*)request);
50		case UNMOUNT_VOLUME_REQUEST:
51			return _HandleRequest((UnmountVolumeRequest*)request);
52		case SYNC_VOLUME_REQUEST:
53			return _HandleRequest((SyncVolumeRequest*)request);
54		case READ_FS_STAT_REQUEST:
55			return _HandleRequest((ReadFSStatRequest*)request);
56		case WRITE_FS_STAT_REQUEST:
57			return _HandleRequest((WriteFSStatRequest*)request);
58		// vnodes
59		case READ_VNODE_REQUEST:
60			return _HandleRequest((ReadVNodeRequest*)request);
61		case WRITE_VNODE_REQUEST:
62			return _HandleRequest((WriteVNodeRequest*)request);
63		case FS_REMOVE_VNODE_REQUEST:
64			return _HandleRequest((FSRemoveVNodeRequest*)request);
65		// nodes
66		case FSYNC_REQUEST:
67			return _HandleRequest((FSyncRequest*)request);
68		case READ_STAT_REQUEST:
69			return _HandleRequest((ReadStatRequest*)request);
70		case WRITE_STAT_REQUEST:
71			return _HandleRequest((WriteStatRequest*)request);
72		case ACCESS_REQUEST:
73			return _HandleRequest((AccessRequest*)request);
74		// files
75		case CREATE_REQUEST:
76			return _HandleRequest((CreateRequest*)request);
77		case OPEN_REQUEST:
78			return _HandleRequest((OpenRequest*)request);
79		case CLOSE_REQUEST:
80			return _HandleRequest((CloseRequest*)request);
81		case FREE_COOKIE_REQUEST:
82			return _HandleRequest((FreeCookieRequest*)request);
83		case READ_REQUEST:
84			return _HandleRequest((ReadRequest*)request);
85		case WRITE_REQUEST:
86			return _HandleRequest((WriteRequest*)request);
87		case IOCTL_REQUEST:
88			return _HandleRequest((IOCtlRequest*)request);
89		case SET_FLAGS_REQUEST:
90			return _HandleRequest((SetFlagsRequest*)request);
91		case SELECT_REQUEST:
92			return _HandleRequest((SelectRequest*)request);
93		case DESELECT_REQUEST:
94			return _HandleRequest((DeselectRequest*)request);
95		// hard links / symlinks
96		case LINK_REQUEST:
97			return _HandleRequest((LinkRequest*)request);
98		case UNLINK_REQUEST:
99			return _HandleRequest((UnlinkRequest*)request);
100		case SYMLINK_REQUEST:
101			return _HandleRequest((SymlinkRequest*)request);
102		case READ_LINK_REQUEST:
103			return _HandleRequest((ReadLinkRequest*)request);
104		case RENAME_REQUEST:
105			return _HandleRequest((RenameRequest*)request);
106		// directories
107		case MKDIR_REQUEST:
108			return _HandleRequest((MkDirRequest*)request);
109		case RMDIR_REQUEST:
110			return _HandleRequest((RmDirRequest*)request);
111		case OPEN_DIR_REQUEST:
112			return _HandleRequest((OpenDirRequest*)request);
113		case CLOSE_DIR_REQUEST:
114			return _HandleRequest((CloseDirRequest*)request);
115		case FREE_DIR_COOKIE_REQUEST:
116			return _HandleRequest((FreeDirCookieRequest*)request);
117		case READ_DIR_REQUEST:
118			return _HandleRequest((ReadDirRequest*)request);
119		case REWIND_DIR_REQUEST:
120			return _HandleRequest((RewindDirRequest*)request);
121		case WALK_REQUEST:
122			return _HandleRequest((WalkRequest*)request);
123		// attributes
124		case OPEN_ATTR_DIR_REQUEST:
125			return _HandleRequest((OpenAttrDirRequest*)request);
126		case CLOSE_ATTR_DIR_REQUEST:
127			return _HandleRequest((CloseAttrDirRequest*)request);
128		case FREE_ATTR_DIR_COOKIE_REQUEST:
129			return _HandleRequest((FreeAttrDirCookieRequest*)request);
130		case READ_ATTR_DIR_REQUEST:
131			return _HandleRequest((ReadAttrDirRequest*)request);
132		case REWIND_ATTR_DIR_REQUEST:
133			return _HandleRequest((RewindAttrDirRequest*)request);
134		case READ_ATTR_REQUEST:
135			return _HandleRequest((ReadAttrRequest*)request);
136		case WRITE_ATTR_REQUEST:
137			return _HandleRequest((WriteAttrRequest*)request);
138		case REMOVE_ATTR_REQUEST:
139			return _HandleRequest((RemoveAttrRequest*)request);
140		case RENAME_ATTR_REQUEST:
141			return _HandleRequest((RenameAttrRequest*)request);
142		case STAT_ATTR_REQUEST:
143			return _HandleRequest((StatAttrRequest*)request);
144		// indices
145		case OPEN_INDEX_DIR_REQUEST:
146			return _HandleRequest((OpenIndexDirRequest*)request);
147		case CLOSE_INDEX_DIR_REQUEST:
148			return _HandleRequest((CloseIndexDirRequest*)request);
149		case FREE_INDEX_DIR_COOKIE_REQUEST:
150			return _HandleRequest((FreeIndexDirCookieRequest*)request);
151		case READ_INDEX_DIR_REQUEST:
152			return _HandleRequest((ReadIndexDirRequest*)request);
153		case REWIND_INDEX_DIR_REQUEST:
154			return _HandleRequest((RewindIndexDirRequest*)request);
155		case CREATE_INDEX_REQUEST:
156			return _HandleRequest((CreateIndexRequest*)request);
157		case REMOVE_INDEX_REQUEST:
158			return _HandleRequest((RemoveIndexRequest*)request);
159		case RENAME_INDEX_REQUEST:
160			return _HandleRequest((RenameIndexRequest*)request);
161		case STAT_INDEX_REQUEST:
162			return _HandleRequest((StatIndexRequest*)request);
163		// queries
164		case OPEN_QUERY_REQUEST:
165			return _HandleRequest((OpenQueryRequest*)request);
166		case CLOSE_QUERY_REQUEST:
167			return _HandleRequest((CloseQueryRequest*)request);
168		case FREE_QUERY_COOKIE_REQUEST:
169			return _HandleRequest((FreeQueryCookieRequest*)request);
170		case READ_QUERY_REQUEST:
171			return _HandleRequest((ReadQueryRequest*)request);
172	}
173PRINT(("UserlandRequestHandler::HandleRequest(): unexpected request: %lu\n",
174request->GetType()));
175	return B_BAD_DATA;
176}
177
178
179// #pragma mark -
180// #pragma mark ----- FS -----
181
182// _HandleRequest
183status_t
184UserlandRequestHandler::_HandleRequest(MountVolumeRequest* request)
185{
186	// check and execute the request
187	status_t result = B_OK;
188	// if the device path is relative, make it absolute by appending the
189	// provided CWD
190	const char* device = (const char*)request->device.GetData();
191	char stackDevice[B_PATH_NAME_LENGTH];
192	if (result == B_OK) {
193		if (device && device[0] != '/') {
194			if (const char* cwd = (const char*)request->cwd.GetData()) {
195				int32 deviceLen = strlen(device);
196				int32 cwdLen = strlen(cwd);
197				if (cwdLen + 1 + deviceLen < (int32)sizeof(stackDevice)) {
198					strcpy(stackDevice, cwd);
199					strcat(stackDevice, "/");
200					strcat(stackDevice, device);
201					device = stackDevice;
202				} else
203					result = B_NAME_TOO_LONG;
204			} else
205				result = B_BAD_VALUE;
206		}
207	}
208
209	// create the volume
210	UserVolume* volume = NULL;
211	if (result == B_OK)
212		result = fFileSystem->CreateVolume(&volume, request->nsid);
213
214	// mount it
215	vnode_id rootID;
216	if (result == B_OK) {
217		RequestThreadContext context(volume);
218		result = volume->Mount(device, request->flags,
219			(const char*)request->parameters.GetData(),
220			request->parameters.GetSize(), &rootID);
221		if (result != B_OK)
222			fFileSystem->DeleteVolume(volume);
223	}
224	if (result != B_OK)
225		volume = NULL;
226
227	// prepare the reply
228	RequestAllocator allocator(fPort->GetPort());
229	MountVolumeReply* reply;
230	status_t error = AllocateRequest(allocator, &reply);
231	if (error != B_OK)
232		RETURN_ERROR(error);
233	reply->error = result;
234	reply->volume = volume;
235	reply->rootID = rootID;
236
237	// send the reply
238	return _SendReply(allocator, false);
239}
240
241// _HandleRequest
242status_t
243UserlandRequestHandler::_HandleRequest(UnmountVolumeRequest* request)
244{
245	// check and execute the request
246	status_t result = B_OK;
247	UserVolume* volume = (UserVolume*)request->volume;
248	if (!volume)
249		result = B_BAD_VALUE;
250	if (result == B_OK) {
251		RequestThreadContext context(volume);
252		result = volume->Unmount();
253	}
254	// prepare the reply
255	RequestAllocator allocator(fPort->GetPort());
256	UnmountVolumeReply* reply;
257	status_t error = AllocateRequest(allocator, &reply);
258	if (error != B_OK)
259		RETURN_ERROR(error);
260	reply->error = result;
261	// send the reply
262	return _SendReply(allocator, false);
263}
264
265// _HandleRequest
266status_t
267UserlandRequestHandler::_HandleRequest(SyncVolumeRequest* request)
268{
269	// check and execute the request
270	status_t result = B_OK;
271	UserVolume* volume = (UserVolume*)request->volume;
272	if (!volume)
273		result = B_BAD_VALUE;
274	if (result == B_OK) {
275		RequestThreadContext context(volume);
276		result = volume->Sync();
277	}
278	// prepare the reply
279	RequestAllocator allocator(fPort->GetPort());
280	SyncVolumeReply* reply;
281	status_t error = AllocateRequest(allocator, &reply);
282	if (error != B_OK)
283		RETURN_ERROR(error);
284	reply->error = result;
285	// send the reply
286	return _SendReply(allocator, false);
287}
288
289// _HandleRequest
290status_t
291UserlandRequestHandler::_HandleRequest(ReadFSStatRequest* request)
292{
293	// check and execute the request
294	status_t result = B_OK;
295	UserVolume* volume = (UserVolume*)request->volume;
296	if (!volume)
297		result = B_BAD_VALUE;
298	fs_info info;
299	if (result == B_OK) {
300		RequestThreadContext context(volume);
301		result = volume->ReadFSStat(&info);
302	}
303	// prepare the reply
304	RequestAllocator allocator(fPort->GetPort());
305	ReadFSStatReply* reply;
306	status_t error = AllocateRequest(allocator, &reply);
307	if (error != B_OK)
308		RETURN_ERROR(error);
309	reply->error = result;
310	reply->info = info;
311	// send the reply
312	return _SendReply(allocator, false);
313}
314
315// _HandleRequest
316status_t
317UserlandRequestHandler::_HandleRequest(WriteFSStatRequest* request)
318{
319	// check and execute the request
320	status_t result = B_OK;
321	UserVolume* volume = (UserVolume*)request->volume;
322	if (!volume)
323		result = B_BAD_VALUE;
324	if (result == B_OK) {
325		RequestThreadContext context(volume);
326		result = volume->WriteFSStat(&request->info, request->mask);
327	}
328	// prepare the reply
329	RequestAllocator allocator(fPort->GetPort());
330	WriteFSStatReply* reply;
331	status_t error = AllocateRequest(allocator, &reply);
332	if (error != B_OK)
333		RETURN_ERROR(error);
334	reply->error = result;
335	// send the reply
336	return _SendReply(allocator, false);
337}
338
339
340// #pragma mark -
341// #pragma mark ----- vnodes -----
342
343// _HandleRequest
344status_t
345UserlandRequestHandler::_HandleRequest(ReadVNodeRequest* request)
346{
347	// check and execute the request
348	status_t result = B_OK;
349	UserVolume* volume = (UserVolume*)request->volume;
350	if (!volume)
351		result = B_BAD_VALUE;
352	void* node;
353	if (result == B_OK) {
354		RequestThreadContext context(volume);
355		result = volume->ReadVNode(request->vnid, request->reenter, &node);
356	}
357	// prepare the reply
358	RequestAllocator allocator(fPort->GetPort());
359	ReadVNodeReply* reply;
360	status_t error = AllocateRequest(allocator, &reply);
361	if (error != B_OK)
362		RETURN_ERROR(error);
363	reply->error = result;
364	reply->node = node;
365	// send the reply
366	return _SendReply(allocator, false);
367}
368
369// _HandleRequest
370status_t
371UserlandRequestHandler::_HandleRequest(WriteVNodeRequest* request)
372{
373	// check and execute the request
374	status_t result = B_OK;
375	UserVolume* volume = (UserVolume*)request->volume;
376	if (!volume)
377		result = B_BAD_VALUE;
378	if (result == B_OK) {
379		RequestThreadContext context(volume);
380		result = volume->WriteVNode(request->node, request->reenter);
381	}
382	// prepare the reply
383	RequestAllocator allocator(fPort->GetPort());
384	WriteVNodeReply* reply;
385	status_t error = AllocateRequest(allocator, &reply);
386	if (error != B_OK)
387		RETURN_ERROR(error);
388	reply->error = result;
389	// send the reply
390	return _SendReply(allocator, false);
391}
392
393// _HandleRequest
394status_t
395UserlandRequestHandler::_HandleRequest(FSRemoveVNodeRequest* request)
396{
397	// check and execute the request
398	status_t result = B_OK;
399	UserVolume* volume = (UserVolume*)request->volume;
400	if (!volume)
401		result = B_BAD_VALUE;
402	if (result == B_OK) {
403		RequestThreadContext context(volume);
404		result = volume->RemoveVNode(request->node, request->reenter);
405	}
406	// prepare the reply
407	RequestAllocator allocator(fPort->GetPort());
408	FSRemoveVNodeReply* reply;
409	status_t error = AllocateRequest(allocator, &reply);
410	if (error != B_OK)
411		RETURN_ERROR(error);
412	reply->error = result;
413	// send the reply
414	return _SendReply(allocator, false);
415}
416
417
418// #pragma mark -
419// #pragma mark ----- nodes -----
420
421// _HandleRequest
422status_t
423UserlandRequestHandler::_HandleRequest(FSyncRequest* request)
424{
425	// check and execute the request
426	status_t result = B_OK;
427	UserVolume* volume = (UserVolume*)request->volume;
428	if (!volume)
429		result = B_BAD_VALUE;
430	if (result == B_OK) {
431		RequestThreadContext context(volume);
432		result = volume->FSync(request->node);
433	}
434	// prepare the reply
435	RequestAllocator allocator(fPort->GetPort());
436	FSyncReply* reply;
437	status_t error = AllocateRequest(allocator, &reply);
438	if (error != B_OK)
439		RETURN_ERROR(error);
440	reply->error = result;
441	// send the reply
442	return _SendReply(allocator, false);
443}
444
445// _HandleRequest
446status_t
447UserlandRequestHandler::_HandleRequest(ReadStatRequest* request)
448{
449	// check and execute the request
450	status_t result = B_OK;
451	UserVolume* volume = (UserVolume*)request->volume;
452	if (!volume)
453		result = B_BAD_VALUE;
454	struct stat st;
455	if (result == B_OK) {
456		RequestThreadContext context(volume);
457		result = volume->ReadStat(request->node, &st);
458	}
459	// prepare the reply
460	RequestAllocator allocator(fPort->GetPort());
461	ReadStatReply* reply;
462	status_t error = AllocateRequest(allocator, &reply);
463	if (error != B_OK)
464		RETURN_ERROR(error);
465	reply->error = result;
466	reply->st = st;
467	// send the reply
468	return _SendReply(allocator, false);
469}
470
471// _HandleRequest
472status_t
473UserlandRequestHandler::_HandleRequest(WriteStatRequest* request)
474{
475	// check and execute the request
476	status_t result = B_OK;
477	UserVolume* volume = (UserVolume*)request->volume;
478	if (!volume)
479		result = B_BAD_VALUE;
480	if (result == B_OK) {
481		RequestThreadContext context(volume);
482		result = volume->WriteStat(request->node, &request->st, request->mask);
483	}
484	// prepare the reply
485	RequestAllocator allocator(fPort->GetPort());
486	WriteStatReply* reply;
487	status_t error = AllocateRequest(allocator, &reply);
488	if (error != B_OK)
489		RETURN_ERROR(error);
490	reply->error = result;
491	// send the reply
492	return _SendReply(allocator, false);
493}
494
495// _HandleRequest
496status_t
497UserlandRequestHandler::_HandleRequest(AccessRequest* request)
498{
499	// check and execute the request
500	status_t result = B_OK;
501	UserVolume* volume = (UserVolume*)request->volume;
502	if (!volume)
503		result = B_BAD_VALUE;
504	if (result == B_OK) {
505		RequestThreadContext context(volume);
506		result = volume->Access(request->node, request->mode);
507	}
508	// prepare the reply
509	RequestAllocator allocator(fPort->GetPort());
510	AccessReply* reply;
511	status_t error = AllocateRequest(allocator, &reply);
512	if (error != B_OK)
513		RETURN_ERROR(error);
514	reply->error = result;
515	// send the reply
516	return _SendReply(allocator, false);
517}
518
519
520// #pragma mark -
521// #pragma mark ----- files -----
522
523// _HandleRequest
524status_t
525UserlandRequestHandler::_HandleRequest(CreateRequest* request)
526{
527	// check and execute the request
528	status_t result = B_OK;
529	UserVolume* volume = (UserVolume*)request->volume;
530	if (!volume)
531		result = B_BAD_VALUE;
532	vnode_id vnid;
533	void* fileCookie;
534	if (result == B_OK) {
535		RequestThreadContext context(volume);
536		result = volume->Create(request->node,
537			(const char*)request->name.GetData(), request->openMode,
538			request->mode, &vnid, &fileCookie);
539	}
540	// prepare the reply
541	RequestAllocator allocator(fPort->GetPort());
542	CreateReply* reply;
543	status_t error = AllocateRequest(allocator, &reply);
544	if (error != B_OK)
545		RETURN_ERROR(error);
546	reply->error = result;
547	reply->vnid = vnid;
548	reply->fileCookie = fileCookie;
549	// send the reply
550	return _SendReply(allocator, false);
551}
552
553// _HandleRequest
554status_t
555UserlandRequestHandler::_HandleRequest(OpenRequest* request)
556{
557	// check and execute the request
558	status_t result = B_OK;
559	UserVolume* volume = (UserVolume*)request->volume;
560	if (!volume)
561		result = B_BAD_VALUE;
562	void* fileCookie;
563	if (result == B_OK) {
564		RequestThreadContext context(volume);
565		result = volume->Open(request->node, request->openMode, &fileCookie);
566	}
567	// prepare the reply
568	RequestAllocator allocator(fPort->GetPort());
569	OpenReply* reply;
570	status_t error = AllocateRequest(allocator, &reply);
571	if (error != B_OK)
572		RETURN_ERROR(error);
573	reply->error = result;
574	reply->fileCookie = fileCookie;
575	// send the reply
576	return _SendReply(allocator, false);
577}
578
579// _HandleRequest
580status_t
581UserlandRequestHandler::_HandleRequest(CloseRequest* request)
582{
583	// check and execute the request
584	status_t result = B_OK;
585	UserVolume* volume = (UserVolume*)request->volume;
586	if (!volume)
587		result = B_BAD_VALUE;
588	if (result == B_OK) {
589		RequestThreadContext context(volume);
590		result = volume->Close(request->node, request->fileCookie);
591	}
592	// prepare the reply
593	RequestAllocator allocator(fPort->GetPort());
594	CloseReply* reply;
595	status_t error = AllocateRequest(allocator, &reply);
596	if (error != B_OK)
597		RETURN_ERROR(error);
598	reply->error = result;
599	// send the reply
600	return _SendReply(allocator, false);
601}
602
603// _HandleRequest
604status_t
605UserlandRequestHandler::_HandleRequest(FreeCookieRequest* request)
606{
607	// check and execute the request
608	status_t result = B_OK;
609	UserVolume* volume = (UserVolume*)request->volume;
610	if (!volume)
611		result = B_BAD_VALUE;
612	if (result == B_OK) {
613		RequestThreadContext context(volume);
614		result = volume->FreeCookie(request->node, request->fileCookie);
615	}
616	// prepare the reply
617	RequestAllocator allocator(fPort->GetPort());
618	FreeCookieReply* reply;
619	status_t error = AllocateRequest(allocator, &reply);
620	if (error != B_OK)
621		RETURN_ERROR(error);
622	reply->error = result;
623	// send the reply
624	return _SendReply(allocator, false);
625}
626
627// _HandleRequest
628status_t
629UserlandRequestHandler::_HandleRequest(ReadRequest* request)
630{
631	// check and execute the request
632	status_t result = B_OK;
633	UserVolume* volume = (UserVolume*)request->volume;
634	if (!volume)
635		result = B_BAD_VALUE;
636	void* node = request->node;
637	void* fileCookie = request->fileCookie;
638	off_t pos = request->pos;
639	size_t size = request->size;
640	// allocate the reply
641	RequestAllocator allocator(fPort->GetPort());
642	ReadReply* reply;
643	status_t error = AllocateRequest(allocator, &reply);
644	if (error != B_OK)
645		RETURN_ERROR(error);
646	void* buffer;
647	if (result == B_OK) {
648		result = allocator.AllocateAddress(reply->buffer, size, 1, &buffer,
649			true);
650	}
651	// execute the request
652	size_t bytesRead;
653	if (result == B_OK) {
654		RequestThreadContext context(volume);
655		result = volume->Read(node, fileCookie, pos, buffer, size, &bytesRead);
656	}
657	// reconstruct the reply, in case it has been overwritten
658	reply = new(reply) ReadReply;
659	// send the reply
660	reply->error = result;
661	reply->bytesRead = bytesRead;
662	return _SendReply(allocator, (result == B_OK));
663}
664
665// _HandleRequest
666status_t
667UserlandRequestHandler::_HandleRequest(WriteRequest* request)
668{
669	// check and execute the request
670	status_t result = B_OK;
671	UserVolume* volume = (UserVolume*)request->volume;
672	if (!volume)
673		result = B_BAD_VALUE;
674	size_t bytesWritten;
675	if (result == B_OK) {
676		RequestThreadContext context(volume);
677		result = volume->Write(request->node, request->fileCookie,
678			request->pos, request->buffer.GetData(), request->buffer.GetSize(),
679			&bytesWritten);
680	}
681	// prepare the reply
682	RequestAllocator allocator(fPort->GetPort());
683	WriteReply* reply;
684	status_t error = AllocateRequest(allocator, &reply);
685	if (error != B_OK)
686		RETURN_ERROR(error);
687	reply->error = result;
688	reply->bytesWritten = bytesWritten;
689	// send the reply
690	return _SendReply(allocator, false);
691}
692
693// _HandleRequest
694status_t
695UserlandRequestHandler::_HandleRequest(IOCtlRequest* request)
696{
697	// get the request parameters
698	status_t result = B_OK;
699	UserVolume* volume = (UserVolume*)request->volume;
700	if (!volume)
701		result = B_BAD_VALUE;
702	void* buffer = request->bufferParameter;
703	size_t len = request->lenParameter;
704	bool isBuffer = request->isBuffer;
705	int32 bufferSize = 0;
706	int32 writeSize = request->writeSize;
707	if (isBuffer) {
708		buffer = request->buffer.GetData();
709		bufferSize = request->buffer.GetSize();
710	}
711	// allocate the reply
712	RequestAllocator allocator(fPort->GetPort());
713	IOCtlReply* reply;
714	status_t error = AllocateRequest(allocator, &reply);
715	if (error != B_OK)
716		RETURN_ERROR(error);
717	// allocate the writable buffer for the call
718	void* writeBuffer = NULL;
719	if (result == B_OK && isBuffer && writeSize > 0) {
720		if (writeSize < bufferSize)
721			writeSize = bufferSize;
722		result = allocator.AllocateAddress(reply->buffer, writeSize, 8,
723			(void**)&writeBuffer, true);
724		if (result == B_OK && bufferSize > 0)
725			memcpy(writeBuffer, buffer, bufferSize);
726		buffer = writeBuffer;
727	}
728	// execute the request
729	status_t ioctlError = B_OK;
730	if (result == B_OK) {
731		RequestThreadContext context(volume);
732		ioctlError = volume->IOCtl(request->node, request->fileCookie,
733			request->command, buffer, len);
734	}
735	// reconstruct the reply, in case it has been overwritten
736	reply = new(reply) IOCtlReply;
737	// send the reply
738	reply->error = result;
739	reply->ioctlError = ioctlError;
740	return _SendReply(allocator, (result == B_OK && writeBuffer));
741}
742
743// _HandleRequest
744status_t
745UserlandRequestHandler::_HandleRequest(SetFlagsRequest* request)
746{
747	// check and execute the request
748	status_t result = B_OK;
749	UserVolume* volume = (UserVolume*)request->volume;
750	if (!volume)
751		result = B_BAD_VALUE;
752	if (result == B_OK) {
753		RequestThreadContext context(volume);
754		result = volume->SetFlags(request->node, request->fileCookie,
755			request->flags);
756	}
757	// prepare the reply
758	RequestAllocator allocator(fPort->GetPort());
759	SetFlagsReply* reply;
760	status_t error = AllocateRequest(allocator, &reply);
761	if (error != B_OK)
762		RETURN_ERROR(error);
763	reply->error = result;
764	// send the reply
765	return _SendReply(allocator, false);
766}
767
768// _HandleRequest
769status_t
770UserlandRequestHandler::_HandleRequest(SelectRequest* request)
771{
772	// check and execute the request
773	status_t result = B_OK;
774	UserVolume* volume = (UserVolume*)request->volume;
775	if (!volume)
776		result = B_BAD_VALUE;
777	if (result == B_OK) {
778		RequestThreadContext context(volume);
779		result = volume->Select(request->node, request->fileCookie,
780			request->event, request->ref, request->sync);
781	}
782	// prepare the reply
783	RequestAllocator allocator(fPort->GetPort());
784	SelectReply* reply;
785	status_t error = AllocateRequest(allocator, &reply);
786	if (error != B_OK)
787		RETURN_ERROR(error);
788	reply->error = result;
789	// send the reply
790	return _SendReply(allocator, false);
791}
792
793// _HandleRequest
794status_t
795UserlandRequestHandler::_HandleRequest(DeselectRequest* request)
796{
797	// check and execute the request
798	status_t result = B_OK;
799	UserVolume* volume = (UserVolume*)request->volume;
800	if (!volume)
801		result = B_BAD_VALUE;
802	if (result == B_OK) {
803		RequestThreadContext context(volume);
804		result = volume->Deselect(request->node, request->fileCookie,
805			request->event, request->sync);
806	}
807	// prepare the reply
808	RequestAllocator allocator(fPort->GetPort());
809	DeselectReply* reply;
810	status_t error = AllocateRequest(allocator, &reply);
811	if (error != B_OK)
812		RETURN_ERROR(error);
813	reply->error = result;
814	// send the reply
815	return _SendReply(allocator, false);
816}
817
818
819// #pragma mark -
820// #pragma mark ----- hard links / symlinks -----
821
822// _HandleRequest
823status_t
824UserlandRequestHandler::_HandleRequest(LinkRequest* request)
825{
826	// check and execute the request
827	status_t result = B_OK;
828	UserVolume* volume = (UserVolume*)request->volume;
829	if (!volume)
830		result = B_BAD_VALUE;
831	if (result == B_OK) {
832		RequestThreadContext context(volume);
833		result = volume->Link(request->node,
834			(const char*)request->name.GetData(), request->target);
835	}
836	// prepare the reply
837	RequestAllocator allocator(fPort->GetPort());
838	LinkReply* reply;
839	status_t error = AllocateRequest(allocator, &reply);
840	if (error != B_OK)
841		RETURN_ERROR(error);
842	reply->error = result;
843	// send the reply
844	return _SendReply(allocator, false);
845}
846
847// _HandleRequest
848status_t
849UserlandRequestHandler::_HandleRequest(UnlinkRequest* request)
850{
851	// check and execute the request
852	status_t result = B_OK;
853	UserVolume* volume = (UserVolume*)request->volume;
854	if (!volume)
855		result = B_BAD_VALUE;
856	if (result == B_OK) {
857		RequestThreadContext context(volume);
858		result = volume->Unlink(request->node,
859			(const char*)request->name.GetData());
860	}
861	// prepare the reply
862	RequestAllocator allocator(fPort->GetPort());
863	UnlinkReply* reply;
864	status_t error = AllocateRequest(allocator, &reply);
865	if (error != B_OK)
866		RETURN_ERROR(error);
867	reply->error = result;
868	// send the reply
869	return _SendReply(allocator, false);
870}
871
872// _HandleRequest
873status_t
874UserlandRequestHandler::_HandleRequest(SymlinkRequest* request)
875{
876	// check and execute the request
877	status_t result = B_OK;
878	UserVolume* volume = (UserVolume*)request->volume;
879	if (!volume)
880		result = B_BAD_VALUE;
881	if (result == B_OK) {
882		RequestThreadContext context(volume);
883		result = volume->Symlink(request->node,
884			(const char*)request->name.GetData(),
885			(const char*)request->target.GetData());
886	}
887	// prepare the reply
888	RequestAllocator allocator(fPort->GetPort());
889	SymlinkReply* reply;
890	status_t error = AllocateRequest(allocator, &reply);
891	if (error != B_OK)
892		RETURN_ERROR(error);
893	reply->error = result;
894	// send the reply
895	return _SendReply(allocator, false);
896}
897
898// _HandleRequest
899status_t
900UserlandRequestHandler::_HandleRequest(ReadLinkRequest* request)
901{
902	// check and execute the request
903	status_t result = B_OK;
904	UserVolume* volume = (UserVolume*)request->volume;
905	if (!volume)
906		result = B_BAD_VALUE;
907	void* node = request->node;
908	size_t bufferSize = request->size;
909	// allocate the reply
910	RequestAllocator allocator(fPort->GetPort());
911	ReadLinkReply* reply;
912	status_t error = AllocateRequest(allocator, &reply);
913	if (error != B_OK)
914		RETURN_ERROR(error);
915	char* buffer;
916	if (result == B_OK) {
917		result = allocator.AllocateAddress(reply->buffer, bufferSize, 1,
918			(void**)&buffer, true);
919	}
920	// execute the request
921	size_t bytesRead;
922	if (result == B_OK) {
923		RequestThreadContext context(volume);
924		result = volume->ReadLink(node, buffer, bufferSize, &bytesRead);
925	}
926	// reconstruct the reply, in case it has been overwritten
927	reply = new(reply) ReadLinkReply;
928	// send the reply
929	reply->error = result;
930	reply->bytesRead = bytesRead;
931	return _SendReply(allocator, (result == B_OK));
932}
933
934// _HandleRequest
935status_t
936UserlandRequestHandler::_HandleRequest(RenameRequest* request)
937{
938	// check and execute the request
939	status_t result = B_OK;
940	UserVolume* volume = (UserVolume*)request->volume;
941	if (!volume)
942		result = B_BAD_VALUE;
943	if (result == B_OK) {
944		RequestThreadContext context(volume);
945		result = volume->Rename(request->oldDir,
946			(const char*)request->oldName.GetData(), request->newDir,
947			(const char*)request->newName.GetData());
948	}
949	// prepare the reply
950	RequestAllocator allocator(fPort->GetPort());
951	RenameReply* reply;
952	status_t error = AllocateRequest(allocator, &reply);
953	if (error != B_OK)
954		RETURN_ERROR(error);
955	reply->error = result;
956	// send the reply
957	return _SendReply(allocator, false);
958}
959
960
961// #pragma mark -
962// #pragma mark ----- directories -----
963
964// _HandleRequest
965status_t
966UserlandRequestHandler::_HandleRequest(MkDirRequest* request)
967{
968	// check and execute the request
969	status_t result = B_OK;
970	UserVolume* volume = (UserVolume*)request->volume;
971	if (!volume)
972		result = B_BAD_VALUE;
973	if (result == B_OK) {
974		RequestThreadContext context(volume);
975		result = volume->MkDir(request->node,
976			(const char*)request->name.GetData(), request->mode);
977	}
978	// prepare the reply
979	RequestAllocator allocator(fPort->GetPort());
980	MkDirReply* reply;
981	status_t error = AllocateRequest(allocator, &reply);
982	if (error != B_OK)
983		RETURN_ERROR(error);
984	reply->error = result;
985	// send the reply
986	return _SendReply(allocator, false);
987}
988
989// _HandleRequest
990status_t
991UserlandRequestHandler::_HandleRequest(RmDirRequest* request)
992{
993	// check and execute the request
994	status_t result = B_OK;
995	UserVolume* volume = (UserVolume*)request->volume;
996	if (!volume)
997		result = B_BAD_VALUE;
998	if (result == B_OK) {
999		RequestThreadContext context(volume);
1000		result = volume->RmDir(request->node,
1001			(const char*)request->name.GetData());
1002	}
1003	// prepare the reply
1004	RequestAllocator allocator(fPort->GetPort());
1005	RmDirReply* reply;
1006	status_t error = AllocateRequest(allocator, &reply);
1007	if (error != B_OK)
1008		RETURN_ERROR(error);
1009	reply->error = result;
1010	// send the reply
1011	return _SendReply(allocator, false);
1012}
1013
1014// _HandleRequest
1015status_t
1016UserlandRequestHandler::_HandleRequest(OpenDirRequest* request)
1017{
1018	// check and execute the request
1019	status_t result = B_OK;
1020	UserVolume* volume = (UserVolume*)request->volume;
1021	if (!volume)
1022		result = B_BAD_VALUE;
1023	void* dirCookie;
1024	if (result == B_OK) {
1025		RequestThreadContext context(volume);
1026		result = volume->OpenDir(request->node, &dirCookie);
1027	}
1028	// prepare the reply
1029	RequestAllocator allocator(fPort->GetPort());
1030	OpenDirReply* reply;
1031	status_t error = AllocateRequest(allocator, &reply);
1032	if (error != B_OK)
1033		RETURN_ERROR(error);
1034	reply->error = result;
1035	reply->dirCookie = dirCookie;
1036	// send the reply
1037	return _SendReply(allocator, false);
1038}
1039
1040// _HandleRequest
1041status_t
1042UserlandRequestHandler::_HandleRequest(CloseDirRequest* request)
1043{
1044	// check and execute the request
1045	status_t result = B_OK;
1046	UserVolume* volume = (UserVolume*)request->volume;
1047	if (!volume)
1048		result = B_BAD_VALUE;
1049	if (result == B_OK) {
1050		RequestThreadContext context(volume);
1051		result = volume->CloseDir(request->node, request->dirCookie);
1052	}
1053	// prepare the reply
1054	RequestAllocator allocator(fPort->GetPort());
1055	CloseDirReply* reply;
1056	status_t error = AllocateRequest(allocator, &reply);
1057	if (error != B_OK)
1058		RETURN_ERROR(error);
1059	reply->error = result;
1060	// send the reply
1061	return _SendReply(allocator, false);
1062}
1063
1064// _HandleRequest
1065status_t
1066UserlandRequestHandler::_HandleRequest(FreeDirCookieRequest* request)
1067{
1068	// check and execute the request
1069	status_t result = B_OK;
1070	UserVolume* volume = (UserVolume*)request->volume;
1071	if (!volume)
1072		result = B_BAD_VALUE;
1073	if (result == B_OK) {
1074		RequestThreadContext context(volume);
1075		result = volume->FreeDirCookie(request->node, request->dirCookie);
1076	}
1077	// prepare the reply
1078	RequestAllocator allocator(fPort->GetPort());
1079	FreeDirCookieReply* reply;
1080	status_t error = AllocateRequest(allocator, &reply);
1081	if (error != B_OK)
1082		RETURN_ERROR(error);
1083	reply->error = result;
1084	// send the reply
1085	return _SendReply(allocator, false);
1086}
1087
1088// _HandleRequest
1089status_t
1090UserlandRequestHandler::_HandleRequest(ReadDirRequest* request)
1091{
1092	// check the request
1093	status_t result = B_OK;
1094	UserVolume* volume = (UserVolume*)request->volume;
1095	if (!volume)
1096		result = B_BAD_VALUE;
1097	void* node = request->node;
1098	void* dirCookie = request->dirCookie;
1099	size_t bufferSize = request->bufferSize;
1100	int32 count = request->count;
1101	// allocate the reply
1102	RequestAllocator allocator(fPort->GetPort());
1103	ReadDirReply* reply;
1104	status_t error = AllocateRequest(allocator, &reply);
1105	if (error != B_OK)
1106		RETURN_ERROR(error);
1107	void* buffer;
1108	if (result == B_OK) {
1109		result = allocator.AllocateAddress(reply->buffer, bufferSize, 1,
1110			&buffer, true);
1111	}
1112	// execute the request
1113	int32 countRead;
1114	if (result == B_OK) {
1115		RequestThreadContext context(volume);
1116		result = volume->ReadDir(node, dirCookie, buffer, bufferSize, count,
1117			&countRead);
1118	}
1119D(
1120if (result == B_OK && countRead > 0) {
1121	dirent* entry = (dirent*)buffer;
1122	PRINT(("  entry: d_dev: %ld, d_pdev: %ld, d_ino: %Ld, d_pino: %Ld, "
1123		"d_reclen: %hu, d_name: %.32s\n",
1124		entry->d_dev, entry->d_pdev, entry->d_ino, entry->d_pino,
1125		entry->d_reclen, entry->d_name));
1126}
1127)
1128	// reconstruct the reply, in case it has been overwritten
1129	reply = new(reply) ReadDirReply;
1130	// send the reply
1131	reply->error = result;
1132	reply->count = countRead;
1133	return _SendReply(allocator, (result == B_OK));
1134}
1135
1136// _HandleRequest
1137status_t
1138UserlandRequestHandler::_HandleRequest(RewindDirRequest* request)
1139{
1140	// check and execute the request
1141	status_t result = B_OK;
1142	UserVolume* volume = (UserVolume*)request->volume;
1143	if (!volume)
1144		result = B_BAD_VALUE;
1145	if (result == B_OK) {
1146		RequestThreadContext context(volume);
1147		result = volume->RewindDir(request->node, request->dirCookie);
1148	}
1149	// prepare the reply
1150	RequestAllocator allocator(fPort->GetPort());
1151	RewindDirReply* reply;
1152	status_t error = AllocateRequest(allocator, &reply);
1153	if (error != B_OK)
1154		RETURN_ERROR(error);
1155	reply->error = result;
1156	// send the reply
1157	return _SendReply(allocator, false);
1158}
1159
1160// _HandleRequest
1161status_t
1162UserlandRequestHandler::_HandleRequest(WalkRequest* request)
1163{
1164	// check and execute the request
1165	status_t result = B_OK;
1166	UserVolume* volume = (UserVolume*)request->volume;
1167	if (!volume)
1168		result = B_BAD_VALUE;
1169	vnode_id vnid;
1170	char* resolvedPath = NULL;
1171	if (result == B_OK) {
1172		RequestThreadContext context(volume);
1173		result = volume->Walk(request->node,
1174			(const char*)request->entryName.GetData(),
1175			(request->traverseLink ? &resolvedPath : NULL), &vnid);
1176	}
1177	MemoryDeleter _(resolvedPath);
1178	// prepare the reply
1179	RequestAllocator allocator(fPort->GetPort());
1180	WalkReply* reply;
1181	status_t error = AllocateRequest(allocator, &reply);
1182	if (error != B_OK)
1183		RETURN_ERROR(error);
1184	if (result == B_OK && resolvedPath)
1185		result = allocator.AllocateString(reply->resolvedPath, resolvedPath);
1186	reply->vnid = vnid;
1187	reply->error = result;
1188	// send the reply
1189	return _SendReply(allocator, (result == B_OK && resolvedPath));
1190}
1191
1192
1193// #pragma mark -
1194// #pragma mark ----- attributes -----
1195
1196// _HandleRequest
1197status_t
1198UserlandRequestHandler::_HandleRequest(OpenAttrDirRequest* request)
1199{
1200	// check and execute the request
1201	status_t result = B_OK;
1202	UserVolume* volume = (UserVolume*)request->volume;
1203	if (!volume)
1204		result = B_BAD_VALUE;
1205	void* attrDirCookie;
1206	if (result == B_OK) {
1207		RequestThreadContext context(volume);
1208		result = volume->OpenAttrDir(request->node, &attrDirCookie);
1209	}
1210	// prepare the reply
1211	RequestAllocator allocator(fPort->GetPort());
1212	OpenAttrDirReply* reply;
1213	status_t error = AllocateRequest(allocator, &reply);
1214	if (error != B_OK)
1215		RETURN_ERROR(error);
1216	reply->error = result;
1217	reply->attrDirCookie = attrDirCookie;
1218	// send the reply
1219	return _SendReply(allocator, false);
1220}
1221
1222// _HandleRequest
1223status_t
1224UserlandRequestHandler::_HandleRequest(CloseAttrDirRequest* request)
1225{
1226	// check and execute the request
1227	status_t result = B_OK;
1228	UserVolume* volume = (UserVolume*)request->volume;
1229	if (!volume)
1230		result = B_BAD_VALUE;
1231	if (result == B_OK) {
1232		RequestThreadContext context(volume);
1233		result = volume->CloseAttrDir(request->node, request->attrDirCookie);
1234	}
1235	// prepare the reply
1236	RequestAllocator allocator(fPort->GetPort());
1237	CloseAttrDirReply* reply;
1238	status_t error = AllocateRequest(allocator, &reply);
1239	if (error != B_OK)
1240		RETURN_ERROR(error);
1241	reply->error = result;
1242	// send the reply
1243	return _SendReply(allocator, false);
1244}
1245
1246// _HandleRequest
1247status_t
1248UserlandRequestHandler::_HandleRequest(FreeAttrDirCookieRequest* request)
1249{
1250	// check and execute the request
1251	status_t result = B_OK;
1252	UserVolume* volume = (UserVolume*)request->volume;
1253	if (!volume)
1254		result = B_BAD_VALUE;
1255	if (result == B_OK) {
1256		RequestThreadContext context(volume);
1257		result = volume->FreeAttrDirCookie(request->node,
1258			request->attrDirCookie);
1259	}
1260	// prepare the reply
1261	RequestAllocator allocator(fPort->GetPort());
1262	FreeAttrDirCookieReply* reply;
1263	status_t error = AllocateRequest(allocator, &reply);
1264	if (error != B_OK)
1265		RETURN_ERROR(error);
1266	reply->error = result;
1267	// send the reply
1268	return _SendReply(allocator, false);
1269}
1270
1271// _HandleRequest
1272status_t
1273UserlandRequestHandler::_HandleRequest(ReadAttrDirRequest* request)
1274{
1275	// check and execute the request
1276	status_t result = B_OK;
1277	UserVolume* volume = (UserVolume*)request->volume;
1278	if (!volume)
1279		result = B_BAD_VALUE;
1280	void* node = request->node;
1281	void* attrDirCookie = request->attrDirCookie;
1282	size_t bufferSize = request->bufferSize;
1283	int32 count = request->count;
1284	// allocate the reply
1285	RequestAllocator allocator(fPort->GetPort());
1286	ReadAttrDirReply* reply;
1287	status_t error = AllocateRequest(allocator, &reply);
1288	if (error != B_OK)
1289		RETURN_ERROR(error);
1290	void* buffer;
1291	if (result == B_OK) {
1292		result = allocator.AllocateAddress(reply->buffer, bufferSize, 1,
1293			&buffer, true);
1294	}
1295	// execute the request
1296	int32 countRead;
1297	if (result == B_OK) {
1298		RequestThreadContext context(volume);
1299		result = volume->ReadAttrDir(node, attrDirCookie, buffer, bufferSize,
1300			count, &countRead);
1301	}
1302	// reconstruct the reply, in case it has been overwritten
1303	reply = new(reply) ReadAttrDirReply;
1304	// send the reply
1305	reply->error = result;
1306	reply->count = countRead;
1307	return _SendReply(allocator, (result == B_OK));
1308}
1309
1310// _HandleRequest
1311status_t
1312UserlandRequestHandler::_HandleRequest(RewindAttrDirRequest* request)
1313{
1314	// check and execute the request
1315	status_t result = B_OK;
1316	UserVolume* volume = (UserVolume*)request->volume;
1317	if (!volume)
1318		result = B_BAD_VALUE;
1319	if (result == B_OK) {
1320		RequestThreadContext context(volume);
1321		result = volume->RewindAttrDir(request->node, request->attrDirCookie);
1322	}
1323	// prepare the reply
1324	RequestAllocator allocator(fPort->GetPort());
1325	RewindAttrDirReply* reply;
1326	status_t error = AllocateRequest(allocator, &reply);
1327	if (error != B_OK)
1328		RETURN_ERROR(error);
1329	reply->error = result;
1330	// send the reply
1331	return _SendReply(allocator, false);
1332}
1333
1334// _HandleRequest
1335status_t
1336UserlandRequestHandler::_HandleRequest(ReadAttrRequest* request)
1337{
1338	// check and execute the request
1339	status_t result = B_OK;
1340	UserVolume* volume = (UserVolume*)request->volume;
1341	if (!volume)
1342		result = B_BAD_VALUE;
1343	void* node = request->node;
1344	off_t pos = request->pos;
1345	size_t size = request->size;
1346	// allocate the reply
1347	RequestAllocator allocator(fPort->GetPort());
1348	ReadAttrReply* reply;
1349	status_t error = AllocateRequest(allocator, &reply);
1350	if (error != B_OK)
1351		RETURN_ERROR(error);
1352	void* buffer;
1353	if (result == B_OK) {
1354		result = allocator.AllocateAddress(reply->buffer, size, 1, &buffer,
1355			true);
1356	}
1357	// execute the request
1358	size_t bytesRead;
1359	if (result == B_OK) {
1360		RequestThreadContext context(volume);
1361		result = volume->ReadAttr(node, (const char*)request->name.GetData(),
1362			request->type, pos, buffer, size, &bytesRead);
1363	}
1364	// reconstruct the reply, in case it has been overwritten
1365	reply = new(reply) ReadAttrReply;
1366	// send the reply
1367	reply->error = result;
1368	reply->bytesRead = bytesRead;
1369	return _SendReply(allocator, (result == B_OK));
1370}
1371
1372// _HandleRequest
1373status_t
1374UserlandRequestHandler::_HandleRequest(WriteAttrRequest* request)
1375{
1376	// check and execute the request
1377	status_t result = B_OK;
1378	UserVolume* volume = (UserVolume*)request->volume;
1379	if (!volume)
1380		result = B_BAD_VALUE;
1381	size_t bytesWritten;
1382	if (result == B_OK) {
1383		RequestThreadContext context(volume);
1384		result = volume->WriteAttr(request->node,
1385			(const char*)request->name.GetData(), request->type, request->pos,
1386			request->buffer.GetData(), request->buffer.GetSize(),
1387			&bytesWritten);
1388	}
1389	// prepare the reply
1390	RequestAllocator allocator(fPort->GetPort());
1391	WriteAttrReply* reply;
1392	status_t error = AllocateRequest(allocator, &reply);
1393	if (error != B_OK)
1394		RETURN_ERROR(error);
1395	reply->error = result;
1396	reply->bytesWritten = bytesWritten;
1397	// send the reply
1398	return _SendReply(allocator, false);
1399}
1400
1401// _HandleRequest
1402status_t
1403UserlandRequestHandler::_HandleRequest(RemoveAttrRequest* request)
1404{
1405	// check and execute the request
1406	status_t result = B_OK;
1407	UserVolume* volume = (UserVolume*)request->volume;
1408	if (!volume)
1409		result = B_BAD_VALUE;
1410	if (result == B_OK) {
1411		RequestThreadContext context(volume);
1412		result = volume->RemoveAttr(request->node,
1413			(const char*)request->name.GetData());
1414	}
1415	// prepare the reply
1416	RequestAllocator allocator(fPort->GetPort());
1417	RemoveAttrReply* reply;
1418	status_t error = AllocateRequest(allocator, &reply);
1419	if (error != B_OK)
1420		RETURN_ERROR(error);
1421	reply->error = result;
1422	// send the reply
1423	return _SendReply(allocator, false);
1424}
1425
1426// _HandleRequest
1427status_t
1428UserlandRequestHandler::_HandleRequest(RenameAttrRequest* request)
1429{
1430	// check and execute the request
1431	status_t result = B_OK;
1432	UserVolume* volume = (UserVolume*)request->volume;
1433	if (!volume)
1434		result = B_BAD_VALUE;
1435	if (result == B_OK) {
1436		RequestThreadContext context(volume);
1437		result = volume->RenameAttr(request->node,
1438			(const char*)request->oldName.GetData(),
1439			(const char*)request->newName.GetData());
1440	}
1441	// prepare the reply
1442	RequestAllocator allocator(fPort->GetPort());
1443	RenameAttrReply* reply;
1444	status_t error = AllocateRequest(allocator, &reply);
1445	if (error != B_OK)
1446		RETURN_ERROR(error);
1447	reply->error = result;
1448	// send the reply
1449	return _SendReply(allocator, false);
1450}
1451
1452// _HandleRequest
1453status_t
1454UserlandRequestHandler::_HandleRequest(StatAttrRequest* request)
1455{
1456	// check and execute the request
1457	status_t result = B_OK;
1458	UserVolume* volume = (UserVolume*)request->volume;
1459	if (!volume)
1460		result = B_BAD_VALUE;
1461	attr_info info;
1462	if (result == B_OK) {
1463		RequestThreadContext context(volume);
1464		result = volume->StatAttr(request->node,
1465			(const char*)request->name.GetData(), &info);
1466	}
1467	// prepare the reply
1468	RequestAllocator allocator(fPort->GetPort());
1469	StatAttrReply* reply;
1470	status_t error = AllocateRequest(allocator, &reply);
1471	if (error != B_OK)
1472		RETURN_ERROR(error);
1473	reply->error = result;
1474	reply->info = info;
1475	// send the reply
1476	return _SendReply(allocator, false);
1477}
1478
1479
1480// #pragma mark -
1481// #pragma mark ----- indices -----
1482
1483// _HandleRequest
1484status_t
1485UserlandRequestHandler::_HandleRequest(OpenIndexDirRequest* request)
1486{
1487	// check and execute the request
1488	status_t result = B_OK;
1489	UserVolume* volume = (UserVolume*)request->volume;
1490	if (!volume)
1491		result = B_BAD_VALUE;
1492	void* indexDirCookie;
1493	if (result == B_OK) {
1494		RequestThreadContext context(volume);
1495		result = volume->OpenIndexDir(&indexDirCookie);
1496	}
1497	// prepare the reply
1498	RequestAllocator allocator(fPort->GetPort());
1499	OpenIndexDirReply* reply;
1500	status_t error = AllocateRequest(allocator, &reply);
1501	if (error != B_OK)
1502		RETURN_ERROR(error);
1503	reply->error = result;
1504	reply->indexDirCookie = indexDirCookie;
1505	// send the reply
1506	return _SendReply(allocator, false);
1507}
1508
1509// _HandleRequest
1510status_t
1511UserlandRequestHandler::_HandleRequest(CloseIndexDirRequest* request)
1512{
1513	// check and execute the request
1514	status_t result = B_OK;
1515	UserVolume* volume = (UserVolume*)request->volume;
1516	if (!volume)
1517		result = B_BAD_VALUE;
1518	if (result == B_OK) {
1519		RequestThreadContext context(volume);
1520		result = volume->CloseIndexDir(request->indexDirCookie);
1521	}
1522	// prepare the reply
1523	RequestAllocator allocator(fPort->GetPort());
1524	CloseIndexDirReply* reply;
1525	status_t error = AllocateRequest(allocator, &reply);
1526	if (error != B_OK)
1527		RETURN_ERROR(error);
1528	reply->error = result;
1529	// send the reply
1530	return _SendReply(allocator, false);
1531}
1532
1533// _HandleRequest
1534status_t
1535UserlandRequestHandler::_HandleRequest(FreeIndexDirCookieRequest* request)
1536{
1537	// check and execute the request
1538	status_t result = B_OK;
1539	UserVolume* volume = (UserVolume*)request->volume;
1540	if (!volume)
1541		result = B_BAD_VALUE;
1542	if (result == B_OK) {
1543		RequestThreadContext context(volume);
1544		result = volume->FreeIndexDirCookie(request->indexDirCookie);
1545	}
1546	// prepare the reply
1547	RequestAllocator allocator(fPort->GetPort());
1548	FreeIndexDirCookieReply* reply;
1549	status_t error = AllocateRequest(allocator, &reply);
1550	if (error != B_OK)
1551		RETURN_ERROR(error);
1552	reply->error = result;
1553	// send the reply
1554	return _SendReply(allocator, false);
1555}
1556
1557// _HandleRequest
1558status_t
1559UserlandRequestHandler::_HandleRequest(ReadIndexDirRequest* request)
1560{
1561	// check and execute the request
1562	status_t result = B_OK;
1563	UserVolume* volume = (UserVolume*)request->volume;
1564	if (!volume)
1565		result = B_BAD_VALUE;
1566	void* indexDirCookie = request->indexDirCookie;
1567	size_t bufferSize = request->bufferSize;
1568	int32 count = request->count;
1569	// allocate the reply
1570	RequestAllocator allocator(fPort->GetPort());
1571	ReadIndexDirReply* reply;
1572	status_t error = AllocateRequest(allocator, &reply);
1573	if (error != B_OK)
1574		RETURN_ERROR(error);
1575	void* buffer;
1576	if (result == B_OK) {
1577		result = allocator.AllocateAddress(reply->buffer, bufferSize, 1,
1578			&buffer, true);
1579	}
1580	// execute the request
1581	int32 countRead;
1582	if (result == B_OK) {
1583		RequestThreadContext context(volume);
1584		result = volume->ReadIndexDir(indexDirCookie, buffer, bufferSize,
1585			count, &countRead);
1586	}
1587	// reconstruct the reply, in case it has been overwritten
1588	reply = new(reply) ReadIndexDirReply;
1589	// send the reply
1590	reply->error = result;
1591	reply->count = countRead;
1592	return _SendReply(allocator, (result == B_OK));
1593}
1594
1595// _HandleRequest
1596status_t
1597UserlandRequestHandler::_HandleRequest(RewindIndexDirRequest* request)
1598{
1599	// check and execute the request
1600	status_t result = B_OK;
1601	UserVolume* volume = (UserVolume*)request->volume;
1602	if (!volume)
1603		result = B_BAD_VALUE;
1604	if (result == B_OK) {
1605		RequestThreadContext context(volume);
1606		result = volume->RewindIndexDir(request->indexDirCookie);
1607	}
1608	// prepare the reply
1609	RequestAllocator allocator(fPort->GetPort());
1610	RewindIndexDirReply* reply;
1611	status_t error = AllocateRequest(allocator, &reply);
1612	if (error != B_OK)
1613		RETURN_ERROR(error);
1614	reply->error = result;
1615	// send the reply
1616	return _SendReply(allocator, false);
1617}
1618
1619// _HandleRequest
1620status_t
1621UserlandRequestHandler::_HandleRequest(CreateIndexRequest* request)
1622{
1623	// check and execute the request
1624	status_t result = B_OK;
1625	UserVolume* volume = (UserVolume*)request->volume;
1626	if (!volume)
1627		result = B_BAD_VALUE;
1628	if (result == B_OK) {
1629		RequestThreadContext context(volume);
1630		result = volume->CreateIndex((const char*)request->name.GetData(),
1631			request->type, request->flags);
1632	}
1633	// prepare the reply
1634	RequestAllocator allocator(fPort->GetPort());
1635	CreateIndexReply* reply;
1636	status_t error = AllocateRequest(allocator, &reply);
1637	if (error != B_OK)
1638		RETURN_ERROR(error);
1639	reply->error = result;
1640	// send the reply
1641	return _SendReply(allocator, false);
1642}
1643
1644// _HandleRequest
1645status_t
1646UserlandRequestHandler::_HandleRequest(RemoveIndexRequest* request)
1647{
1648	// check and execute the request
1649	status_t result = B_OK;
1650	UserVolume* volume = (UserVolume*)request->volume;
1651	if (!volume)
1652		result = B_BAD_VALUE;
1653	if (result == B_OK) {
1654		RequestThreadContext context(volume);
1655		result = volume->RemoveIndex((const char*)request->name.GetData());
1656	}
1657	// prepare the reply
1658	RequestAllocator allocator(fPort->GetPort());
1659	RemoveIndexReply* reply;
1660	status_t error = AllocateRequest(allocator, &reply);
1661	if (error != B_OK)
1662		RETURN_ERROR(error);
1663	reply->error = result;
1664	// send the reply
1665	return _SendReply(allocator, false);
1666}
1667
1668// _HandleRequest
1669status_t
1670UserlandRequestHandler::_HandleRequest(RenameIndexRequest* request)
1671{
1672	// check and execute the request
1673	status_t result = B_OK;
1674	UserVolume* volume = (UserVolume*)request->volume;
1675	if (!volume)
1676		result = B_BAD_VALUE;
1677	if (result == B_OK) {
1678		RequestThreadContext context(volume);
1679		result = volume->RenameIndex((const char*)request->oldName.GetData(),
1680			(const char*)request->newName.GetData());
1681	}
1682	// prepare the reply
1683	RequestAllocator allocator(fPort->GetPort());
1684	RenameIndexReply* reply;
1685	status_t error = AllocateRequest(allocator, &reply);
1686	if (error != B_OK)
1687		RETURN_ERROR(error);
1688	reply->error = result;
1689	// send the reply
1690	return _SendReply(allocator, false);
1691}
1692
1693// _HandleRequest
1694status_t
1695UserlandRequestHandler::_HandleRequest(StatIndexRequest* request)
1696{
1697	// check and execute the request
1698	status_t result = B_OK;
1699	UserVolume* volume = (UserVolume*)request->volume;
1700	if (!volume)
1701		result = B_BAD_VALUE;
1702	index_info info;
1703	if (result == B_OK) {
1704		RequestThreadContext context(volume);
1705		result = volume->StatIndex((const char*)request->name.GetData(), &info);
1706	}
1707	// prepare the reply
1708	RequestAllocator allocator(fPort->GetPort());
1709	StatIndexReply* reply;
1710	status_t error = AllocateRequest(allocator, &reply);
1711	if (error != B_OK)
1712		RETURN_ERROR(error);
1713	reply->error = result;
1714	reply->info = info;
1715	// send the reply
1716	return _SendReply(allocator, false);
1717}
1718
1719
1720// #pragma mark -
1721// #pragma mark ----- queries -----
1722
1723// _HandleRequest
1724status_t
1725UserlandRequestHandler::_HandleRequest(OpenQueryRequest* request)
1726{
1727	// check and execute the request
1728	status_t result = B_OK;
1729	UserVolume* volume = (UserVolume*)request->volume;
1730	if (!volume)
1731		result = B_BAD_VALUE;
1732	void* queryCookie;
1733	if (result == B_OK) {
1734		RequestThreadContext context(volume);
1735		result = volume->OpenQuery((const char*)request->queryString.GetData(),
1736			request->flags, request->port, request->token, &queryCookie);
1737	}
1738	// prepare the reply
1739	RequestAllocator allocator(fPort->GetPort());
1740	OpenQueryReply* reply;
1741	status_t error = AllocateRequest(allocator, &reply);
1742	if (error != B_OK)
1743		RETURN_ERROR(error);
1744	reply->error = result;
1745	reply->queryCookie = queryCookie;
1746	// send the reply
1747	return _SendReply(allocator, false);
1748}
1749
1750// _HandleRequest
1751status_t
1752UserlandRequestHandler::_HandleRequest(CloseQueryRequest* request)
1753{
1754	// check and execute the request
1755	status_t result = B_OK;
1756	UserVolume* volume = (UserVolume*)request->volume;
1757	if (!volume)
1758		result = B_BAD_VALUE;
1759	if (result == B_OK) {
1760		RequestThreadContext context(volume);
1761		result = volume->CloseQuery(request->queryCookie);
1762	}
1763	// prepare the reply
1764	RequestAllocator allocator(fPort->GetPort());
1765	CloseQueryReply* reply;
1766	status_t error = AllocateRequest(allocator, &reply);
1767	if (error != B_OK)
1768		RETURN_ERROR(error);
1769	reply->error = result;
1770	// send the reply
1771	return _SendReply(allocator, false);
1772}
1773
1774// _HandleRequest
1775status_t
1776UserlandRequestHandler::_HandleRequest(FreeQueryCookieRequest* request)
1777{
1778	// check and execute the request
1779	status_t result = B_OK;
1780	UserVolume* volume = (UserVolume*)request->volume;
1781	if (!volume)
1782		result = B_BAD_VALUE;
1783	if (result == B_OK) {
1784		RequestThreadContext context(volume);
1785		result = volume->FreeQueryCookie(request->queryCookie);
1786	}
1787	// prepare the reply
1788	RequestAllocator allocator(fPort->GetPort());
1789	FreeQueryCookieReply* reply;
1790	status_t error = AllocateRequest(allocator, &reply);
1791	if (error != B_OK)
1792		RETURN_ERROR(error);
1793	reply->error = result;
1794	// send the reply
1795	return _SendReply(allocator, false);
1796}
1797
1798// _HandleRequest
1799status_t
1800UserlandRequestHandler::_HandleRequest(ReadQueryRequest* request)
1801{
1802	// check and execute the request
1803	status_t result = B_OK;
1804	UserVolume* volume = (UserVolume*)request->volume;
1805	if (!volume)
1806		result = B_BAD_VALUE;
1807	void* queryCookie = request->queryCookie;
1808	size_t bufferSize = request->bufferSize;
1809	int32 count = request->count;
1810	// allocate the reply
1811	RequestAllocator allocator(fPort->GetPort());
1812	ReadQueryReply* reply;
1813	status_t error = AllocateRequest(allocator, &reply);
1814	if (error != B_OK)
1815		RETURN_ERROR(error);
1816	void* buffer;
1817	if (result == B_OK) {
1818		result = allocator.AllocateAddress(reply->buffer, bufferSize, 1,
1819			&buffer, true);
1820	}
1821	// execute the request
1822	int32 countRead;
1823	if (result == B_OK) {
1824		RequestThreadContext context(volume);
1825		result = volume->ReadQuery(queryCookie, buffer, bufferSize,
1826			count, &countRead);
1827	}
1828	// reconstruct the reply, in case it has been overwritten
1829	reply = new(reply) ReadQueryReply;
1830	// send the reply
1831	reply->error = result;
1832	reply->count = countRead;
1833	return _SendReply(allocator, (result == B_OK));
1834}
1835
1836
1837// #pragma mark -
1838// #pragma mark ----- other -----
1839
1840// _SendReply
1841status_t
1842UserlandRequestHandler::_SendReply(RequestAllocator& allocator,
1843	bool expectsReceipt)
1844{
1845	if (expectsReceipt) {
1846		SingleReplyRequestHandler handler(RECEIPT_ACK_REPLY);
1847		return fPort->SendRequest(&allocator, &handler);
1848	} else
1849		return fPort->SendRequest(&allocator);
1850}
1851
1852