xref: /haiku/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.cpp (revision 1e60bdeab63fa7a57bc9a55b032052e95a18bd2c)
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
27 UserlandRequestHandler::UserlandRequestHandler(FileSystem* fileSystem)
28 	: RequestHandler(),
29 	  fFileSystem(fileSystem),
30 	  fExpectReply(false),
31 	  fExpectedReply(0)
32 {
33 }
34 
35 // constructor
36 UserlandRequestHandler::UserlandRequestHandler(FileSystem* fileSystem,
37 	uint32 expectedReply)
38 	: RequestHandler(),
39 	  fFileSystem(fileSystem),
40 	  fExpectReply(true),
41 	  fExpectedReply(expectedReply)
42 {
43 }
44 
45 // destructor
46 UserlandRequestHandler::~UserlandRequestHandler()
47 {
48 }
49 
50 // HandleRequest
51 status_t
52 UserlandRequestHandler::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: %lu\n",
221 request->GetType()));
222 	return B_BAD_DATA;
223 }
224 
225 
226 // #pragma mark - FS
227 
228 
229 // _HandleRequest
230 status_t
231 UserlandRequestHandler::_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
291 status_t
292 UserlandRequestHandler::_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
315 status_t
316 UserlandRequestHandler::_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
340 status_t
341 UserlandRequestHandler::_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
367 status_t
368 UserlandRequestHandler::_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
397 status_t
398 UserlandRequestHandler::_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
428 status_t
429 UserlandRequestHandler::_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
467 status_t
468 UserlandRequestHandler::_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
504 status_t
505 UserlandRequestHandler::_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
532 status_t
533 UserlandRequestHandler::_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 
563 status_t
564 UserlandRequestHandler::_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 
593 status_t
594 UserlandRequestHandler::_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
623 status_t
624 UserlandRequestHandler::_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
664 status_t
665 UserlandRequestHandler::_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
698 status_t
699 UserlandRequestHandler::_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
754 status_t
755 UserlandRequestHandler::_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
783 status_t
784 UserlandRequestHandler::_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
812 status_t
813 UserlandRequestHandler::_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
841 status_t
842 UserlandRequestHandler::_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
869 status_t
870 UserlandRequestHandler::_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
910 status_t
911 UserlandRequestHandler::_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
940 status_t
941 UserlandRequestHandler::_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
969 status_t
970 UserlandRequestHandler::_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
998 status_t
999 UserlandRequestHandler::_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
1028 status_t
1029 UserlandRequestHandler::_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
1056 status_t
1057 UserlandRequestHandler::_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
1086 status_t
1087 UserlandRequestHandler::_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
1118 status_t
1119 UserlandRequestHandler::_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
1152 status_t
1153 UserlandRequestHandler::_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
1182 status_t
1183 UserlandRequestHandler::_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
1210 status_t
1211 UserlandRequestHandler::_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
1238 status_t
1239 UserlandRequestHandler::_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
1282 status_t
1283 UserlandRequestHandler::_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
1318 status_t
1319 UserlandRequestHandler::_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
1347 status_t
1348 UserlandRequestHandler::_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
1376 status_t
1377 UserlandRequestHandler::_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
1406 status_t
1407 UserlandRequestHandler::_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
1434 status_t
1435 UserlandRequestHandler::_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
1462 status_t
1463 UserlandRequestHandler::_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: %ld, d_pdev: %ld, d_ino: %Ld, d_pino: %Ld, "
1501 		"d_reclen: %hu, d_name: %.32s\n",
1502 		entry->d_dev, entry->d_pdev, entry->d_ino, entry->d_pino,
1503 		entry->d_reclen, entry->d_name));
1504 }
1505 )
1506 
1507 	// reconstruct the reply, in case it has been overwritten
1508 	reply = new(reply) ReadDirReply;
1509 
1510 	// send the reply
1511 	reply->error = result;
1512 	reply->count = countRead;
1513 	return _SendReply(allocator, (result == B_OK));
1514 }
1515 
1516 // _HandleRequest
1517 status_t
1518 UserlandRequestHandler::_HandleRequest(RewindDirRequest* request)
1519 {
1520 	// check and execute the request
1521 	status_t result = B_OK;
1522 	Volume* volume = (Volume*)request->volume;
1523 	if (!volume)
1524 		result = B_BAD_VALUE;
1525 
1526 	if (result == B_OK) {
1527 		RequestThreadContext context(volume, request);
1528 		result = volume->RewindDir(request->node, request->dirCookie);
1529 	}
1530 
1531 	// prepare the reply
1532 	RequestAllocator allocator(fPort->GetPort());
1533 	RewindDirReply* reply;
1534 	status_t error = AllocateRequest(allocator, &reply);
1535 	if (error != B_OK)
1536 		RETURN_ERROR(error);
1537 
1538 	reply->error = result;
1539 
1540 	// send the reply
1541 	return _SendReply(allocator, false);
1542 }
1543 
1544 
1545 // #pragma mark - attribute directories
1546 
1547 
1548 // _HandleRequest
1549 status_t
1550 UserlandRequestHandler::_HandleRequest(OpenAttrDirRequest* request)
1551 {
1552 	// check and execute the request
1553 	status_t result = B_OK;
1554 	Volume* volume = (Volume*)request->volume;
1555 	if (!volume)
1556 		result = B_BAD_VALUE;
1557 
1558 	void* attrDirCookie;
1559 	if (result == B_OK) {
1560 		RequestThreadContext context(volume, request);
1561 		result = volume->OpenAttrDir(request->node, &attrDirCookie);
1562 	}
1563 
1564 	// prepare the reply
1565 	RequestAllocator allocator(fPort->GetPort());
1566 	OpenAttrDirReply* reply;
1567 	status_t error = AllocateRequest(allocator, &reply);
1568 	if (error != B_OK)
1569 		RETURN_ERROR(error);
1570 
1571 	reply->error = result;
1572 	reply->attrDirCookie = attrDirCookie;
1573 
1574 	// send the reply
1575 	return _SendReply(allocator, false);
1576 }
1577 
1578 // _HandleRequest
1579 status_t
1580 UserlandRequestHandler::_HandleRequest(CloseAttrDirRequest* request)
1581 {
1582 	// check and execute the request
1583 	status_t result = B_OK;
1584 	Volume* volume = (Volume*)request->volume;
1585 	if (!volume)
1586 		result = B_BAD_VALUE;
1587 
1588 	if (result == B_OK) {
1589 		RequestThreadContext context(volume, request);
1590 		result = volume->CloseAttrDir(request->node, request->attrDirCookie);
1591 	}
1592 
1593 	// prepare the reply
1594 	RequestAllocator allocator(fPort->GetPort());
1595 	CloseAttrDirReply* reply;
1596 	status_t error = AllocateRequest(allocator, &reply);
1597 	if (error != B_OK)
1598 		RETURN_ERROR(error);
1599 
1600 	reply->error = result;
1601 
1602 	// send the reply
1603 	return _SendReply(allocator, false);
1604 }
1605 
1606 // _HandleRequest
1607 status_t
1608 UserlandRequestHandler::_HandleRequest(FreeAttrDirCookieRequest* request)
1609 {
1610 	// check and execute the request
1611 	status_t result = B_OK;
1612 	Volume* volume = (Volume*)request->volume;
1613 	if (!volume)
1614 		result = B_BAD_VALUE;
1615 
1616 	if (result == B_OK) {
1617 		RequestThreadContext context(volume, request);
1618 		result = volume->FreeAttrDirCookie(request->node,
1619 			request->attrDirCookie);
1620 	}
1621 
1622 	// prepare the reply
1623 	RequestAllocator allocator(fPort->GetPort());
1624 	FreeAttrDirCookieReply* reply;
1625 	status_t error = AllocateRequest(allocator, &reply);
1626 	if (error != B_OK)
1627 		RETURN_ERROR(error);
1628 
1629 	reply->error = result;
1630 
1631 	// send the reply
1632 	return _SendReply(allocator, false);
1633 }
1634 
1635 // _HandleRequest
1636 status_t
1637 UserlandRequestHandler::_HandleRequest(ReadAttrDirRequest* request)
1638 {
1639 	// check and execute the request
1640 	status_t result = B_OK;
1641 	Volume* volume = (Volume*)request->volume;
1642 	if (!volume)
1643 		result = B_BAD_VALUE;
1644 
1645 	void* node = request->node;
1646 	void* attrDirCookie = request->attrDirCookie;
1647 	size_t bufferSize = request->bufferSize;
1648 	uint32 count = request->count;
1649 
1650 	// allocate the reply
1651 	RequestAllocator allocator(fPort->GetPort());
1652 	ReadAttrDirReply* reply;
1653 	status_t error = AllocateRequest(allocator, &reply);
1654 	if (error != B_OK)
1655 		RETURN_ERROR(error);
1656 
1657 	void* buffer;
1658 	if (result == B_OK) {
1659 		result = allocator.AllocateAddress(reply->buffer, bufferSize, 1,
1660 			&buffer, true);
1661 	}
1662 
1663 	// execute the request
1664 	uint32 countRead;
1665 	if (result == B_OK) {
1666 		RequestThreadContext context(volume, request);
1667 		result = volume->ReadAttrDir(node, attrDirCookie, buffer, bufferSize,
1668 			count, &countRead);
1669 	}
1670 
1671 	// reconstruct the reply, in case it has been overwritten
1672 	reply = new(reply) ReadAttrDirReply;
1673 
1674 	// send the reply
1675 	reply->error = result;
1676 	reply->count = countRead;
1677 	return _SendReply(allocator, (result == B_OK));
1678 }
1679 
1680 // _HandleRequest
1681 status_t
1682 UserlandRequestHandler::_HandleRequest(RewindAttrDirRequest* request)
1683 {
1684 	// check and execute the request
1685 	status_t result = B_OK;
1686 	Volume* volume = (Volume*)request->volume;
1687 	if (!volume)
1688 		result = B_BAD_VALUE;
1689 
1690 	if (result == B_OK) {
1691 		RequestThreadContext context(volume, request);
1692 		result = volume->RewindAttrDir(request->node, request->attrDirCookie);
1693 	}
1694 
1695 	// prepare the reply
1696 	RequestAllocator allocator(fPort->GetPort());
1697 	RewindAttrDirReply* reply;
1698 	status_t error = AllocateRequest(allocator, &reply);
1699 	if (error != B_OK)
1700 		RETURN_ERROR(error);
1701 
1702 	reply->error = result;
1703 
1704 	// send the reply
1705 	return _SendReply(allocator, false);
1706 }
1707 
1708 
1709 // #pragma mark - attributes
1710 
1711 
1712 // _HandleRequest
1713 status_t
1714 UserlandRequestHandler::_HandleRequest(CreateAttrRequest* request)
1715 {
1716 	// check and execute the request
1717 	status_t result = B_OK;
1718 	Volume* volume = (Volume*)request->volume;
1719 	if (!volume)
1720 		result = B_BAD_VALUE;
1721 
1722 	void* attrCookie;
1723 	if (result == B_OK) {
1724 		RequestThreadContext context(volume, request);
1725 		result = volume->CreateAttr(request->node,
1726 			(const char*)request->name.GetData(), request->type,
1727 			request->openMode, &attrCookie);
1728 	}
1729 
1730 	// prepare the reply
1731 	RequestAllocator allocator(fPort->GetPort());
1732 	CreateAttrReply* reply;
1733 	status_t error = AllocateRequest(allocator, &reply);
1734 	if (error != B_OK)
1735 		RETURN_ERROR(error);
1736 
1737 	reply->error = result;
1738 	reply->attrCookie = attrCookie;
1739 
1740 	// send the reply
1741 	return _SendReply(allocator, false);
1742 }
1743 
1744 // _HandleRequest
1745 status_t
1746 UserlandRequestHandler::_HandleRequest(OpenAttrRequest* request)
1747 {
1748 	// check and execute the request
1749 	status_t result = B_OK;
1750 	Volume* volume = (Volume*)request->volume;
1751 	if (!volume)
1752 		result = B_BAD_VALUE;
1753 
1754 	void* attrCookie;
1755 	if (result == B_OK) {
1756 		RequestThreadContext context(volume, request);
1757 		result = volume->OpenAttr(request->node,
1758 			(const char*)request->name.GetData(), request->openMode,
1759 			&attrCookie);
1760 	}
1761 
1762 	// prepare the reply
1763 	RequestAllocator allocator(fPort->GetPort());
1764 	OpenAttrReply* reply;
1765 	status_t error = AllocateRequest(allocator, &reply);
1766 	if (error != B_OK)
1767 		RETURN_ERROR(error);
1768 
1769 	reply->error = result;
1770 	reply->attrCookie = attrCookie;
1771 
1772 	// send the reply
1773 	return _SendReply(allocator, false);
1774 }
1775 
1776 // _HandleRequest
1777 status_t
1778 UserlandRequestHandler::_HandleRequest(CloseAttrRequest* request)
1779 {
1780 	// check and execute the request
1781 	status_t result = B_OK;
1782 	Volume* volume = (Volume*)request->volume;
1783 	if (!volume)
1784 		result = B_BAD_VALUE;
1785 
1786 	if (result == B_OK) {
1787 		RequestThreadContext context(volume, request);
1788 		result = volume->CloseAttr(request->node, request->attrCookie);
1789 	}
1790 
1791 	// prepare the reply
1792 	RequestAllocator allocator(fPort->GetPort());
1793 	CloseAttrReply* reply;
1794 	status_t error = AllocateRequest(allocator, &reply);
1795 	if (error != B_OK)
1796 		RETURN_ERROR(error);
1797 
1798 	reply->error = result;
1799 
1800 	// send the reply
1801 	return _SendReply(allocator, false);
1802 }
1803 
1804 // _HandleRequest
1805 status_t
1806 UserlandRequestHandler::_HandleRequest(FreeAttrCookieRequest* request)
1807 {
1808 	// check and execute the request
1809 	status_t result = B_OK;
1810 	Volume* volume = (Volume*)request->volume;
1811 	if (!volume)
1812 		result = B_BAD_VALUE;
1813 
1814 	if (result == B_OK) {
1815 		RequestThreadContext context(volume, request);
1816 		result = volume->FreeAttrCookie(request->node, request->attrCookie);
1817 	}
1818 
1819 	// prepare the reply
1820 	RequestAllocator allocator(fPort->GetPort());
1821 	FreeAttrCookieReply* reply;
1822 	status_t error = AllocateRequest(allocator, &reply);
1823 	if (error != B_OK)
1824 		RETURN_ERROR(error);
1825 
1826 	reply->error = result;
1827 
1828 	// send the reply
1829 	return _SendReply(allocator, false);
1830 }
1831 
1832 // _HandleRequest
1833 status_t
1834 UserlandRequestHandler::_HandleRequest(ReadAttrRequest* request)
1835 {
1836 	// check and execute the request
1837 	status_t result = B_OK;
1838 	Volume* volume = (Volume*)request->volume;
1839 	if (!volume)
1840 		result = B_BAD_VALUE;
1841 
1842 	void* node = request->node;
1843 	void* attrCookie = request->attrCookie;
1844 	off_t pos = request->pos;
1845 	size_t size = request->size;
1846 
1847 	// allocate the reply
1848 	RequestAllocator allocator(fPort->GetPort());
1849 	ReadAttrReply* reply;
1850 	status_t error = AllocateRequest(allocator, &reply);
1851 	if (error != B_OK)
1852 		RETURN_ERROR(error);
1853 
1854 	void* buffer;
1855 	if (result == B_OK) {
1856 		result = allocator.AllocateAddress(reply->buffer, size, 1, &buffer,
1857 			true);
1858 	}
1859 
1860 	// execute the request
1861 	size_t bytesRead;
1862 	if (result == B_OK) {
1863 		RequestThreadContext context(volume, request);
1864 		result = volume->ReadAttr(node, attrCookie, pos, buffer, size,
1865 			&bytesRead);
1866 	}
1867 
1868 	// reconstruct the reply, in case it has been overwritten
1869 	reply = new(reply) ReadAttrReply;
1870 
1871 	// send the reply
1872 	reply->error = result;
1873 	reply->bytesRead = bytesRead;
1874 	return _SendReply(allocator, (result == B_OK));
1875 }
1876 
1877 // _HandleRequest
1878 status_t
1879 UserlandRequestHandler::_HandleRequest(WriteAttrRequest* request)
1880 {
1881 	// check and execute the request
1882 	status_t result = B_OK;
1883 	Volume* volume = (Volume*)request->volume;
1884 	if (!volume)
1885 		result = B_BAD_VALUE;
1886 
1887 	size_t bytesWritten;
1888 	if (result == B_OK) {
1889 		RequestThreadContext context(volume, request);
1890 		result = volume->WriteAttr(request->node, request->attrCookie,
1891 			request->pos, request->buffer.GetData(), request->buffer.GetSize(),
1892 			&bytesWritten);
1893 	}
1894 
1895 	// prepare the reply
1896 	RequestAllocator allocator(fPort->GetPort());
1897 	WriteAttrReply* reply;
1898 	status_t error = AllocateRequest(allocator, &reply);
1899 	if (error != B_OK)
1900 		RETURN_ERROR(error);
1901 
1902 	reply->error = result;
1903 	reply->bytesWritten = bytesWritten;
1904 
1905 	// send the reply
1906 	return _SendReply(allocator, false);
1907 }
1908 
1909 // _HandleRequest
1910 status_t
1911 UserlandRequestHandler::_HandleRequest(ReadAttrStatRequest* request)
1912 {
1913 	// check and execute the request
1914 	status_t result = B_OK;
1915 	Volume* volume = (Volume*)request->volume;
1916 	if (!volume)
1917 		result = B_BAD_VALUE;
1918 
1919 	struct stat st;
1920 	if (result == B_OK) {
1921 		RequestThreadContext context(volume, request);
1922 		result = volume->ReadAttrStat(request->node, request->attrCookie,
1923 			&st);
1924 	}
1925 
1926 	// prepare the reply
1927 	RequestAllocator allocator(fPort->GetPort());
1928 	ReadAttrStatReply* reply;
1929 	status_t error = AllocateRequest(allocator, &reply);
1930 	if (error != B_OK)
1931 		RETURN_ERROR(error);
1932 
1933 	reply->error = result;
1934 	reply->st = st;
1935 
1936 	// send the reply
1937 	return _SendReply(allocator, false);
1938 }
1939 
1940 // _HandleRequest
1941 status_t
1942 UserlandRequestHandler::_HandleRequest(WriteAttrStatRequest* request)
1943 {
1944 	// check and execute the request
1945 	status_t result = B_OK;
1946 	Volume* volume = (Volume*)request->volume;
1947 	if (!volume)
1948 		result = B_BAD_VALUE;
1949 
1950 	if (result == B_OK) {
1951 		RequestThreadContext context(volume, request);
1952 		result = volume->WriteAttrStat(request->node, request->attrCookie,
1953 			&request->st, request->mask);
1954 	}
1955 
1956 	// prepare the reply
1957 	RequestAllocator allocator(fPort->GetPort());
1958 	WriteAttrStatReply* reply;
1959 	status_t error = AllocateRequest(allocator, &reply);
1960 	if (error != B_OK)
1961 		RETURN_ERROR(error);
1962 
1963 	reply->error = result;
1964 
1965 	// send the reply
1966 	return _SendReply(allocator, false);
1967 }
1968 
1969 // _HandleRequest
1970 status_t
1971 UserlandRequestHandler::_HandleRequest(RenameAttrRequest* request)
1972 {
1973 	// check and execute the request
1974 	status_t result = B_OK;
1975 	Volume* volume = (Volume*)request->volume;
1976 	if (!volume)
1977 		result = B_BAD_VALUE;
1978 
1979 	if (result == B_OK) {
1980 		RequestThreadContext context(volume, request);
1981 		result = volume->RenameAttr(
1982 			request->oldNode, (const char*)request->oldName.GetData(),
1983 			request->newNode, (const char*)request->newName.GetData());
1984 	}
1985 
1986 	// prepare the reply
1987 	RequestAllocator allocator(fPort->GetPort());
1988 	RenameAttrReply* reply;
1989 	status_t error = AllocateRequest(allocator, &reply);
1990 	if (error != B_OK)
1991 		RETURN_ERROR(error);
1992 
1993 	reply->error = result;
1994 
1995 	// send the reply
1996 	return _SendReply(allocator, false);
1997 }
1998 
1999 // _HandleRequest
2000 status_t
2001 UserlandRequestHandler::_HandleRequest(RemoveAttrRequest* request)
2002 {
2003 	// check and execute the request
2004 	status_t result = B_OK;
2005 	Volume* volume = (Volume*)request->volume;
2006 	if (!volume)
2007 		result = B_BAD_VALUE;
2008 
2009 	if (result == B_OK) {
2010 		RequestThreadContext context(volume, request);
2011 		result = volume->RemoveAttr(request->node,
2012 			(const char*)request->name.GetData());
2013 	}
2014 
2015 	// prepare the reply
2016 	RequestAllocator allocator(fPort->GetPort());
2017 	RemoveAttrReply* reply;
2018 	status_t error = AllocateRequest(allocator, &reply);
2019 	if (error != B_OK)
2020 		RETURN_ERROR(error);
2021 
2022 	reply->error = result;
2023 
2024 	// send the reply
2025 	return _SendReply(allocator, false);
2026 }
2027 
2028 
2029 // #pragma mark - indices
2030 
2031 
2032 // _HandleRequest
2033 status_t
2034 UserlandRequestHandler::_HandleRequest(OpenIndexDirRequest* request)
2035 {
2036 	// check and execute the request
2037 	status_t result = B_OK;
2038 	Volume* volume = (Volume*)request->volume;
2039 	if (!volume)
2040 		result = B_BAD_VALUE;
2041 
2042 	void* indexDirCookie;
2043 	if (result == B_OK) {
2044 		RequestThreadContext context(volume, request);
2045 		result = volume->OpenIndexDir(&indexDirCookie);
2046 	}
2047 
2048 	// prepare the reply
2049 	RequestAllocator allocator(fPort->GetPort());
2050 	OpenIndexDirReply* reply;
2051 	status_t error = AllocateRequest(allocator, &reply);
2052 	if (error != B_OK)
2053 		RETURN_ERROR(error);
2054 
2055 	reply->error = result;
2056 	reply->indexDirCookie = indexDirCookie;
2057 
2058 	// send the reply
2059 	return _SendReply(allocator, false);
2060 }
2061 
2062 // _HandleRequest
2063 status_t
2064 UserlandRequestHandler::_HandleRequest(CloseIndexDirRequest* request)
2065 {
2066 	// check and execute the request
2067 	status_t result = B_OK;
2068 	Volume* volume = (Volume*)request->volume;
2069 	if (!volume)
2070 		result = B_BAD_VALUE;
2071 
2072 	if (result == B_OK) {
2073 		RequestThreadContext context(volume, request);
2074 		result = volume->CloseIndexDir(request->indexDirCookie);
2075 	}
2076 
2077 	// prepare the reply
2078 	RequestAllocator allocator(fPort->GetPort());
2079 	CloseIndexDirReply* reply;
2080 	status_t error = AllocateRequest(allocator, &reply);
2081 	if (error != B_OK)
2082 		RETURN_ERROR(error);
2083 
2084 	reply->error = result;
2085 
2086 	// send the reply
2087 	return _SendReply(allocator, false);
2088 }
2089 
2090 // _HandleRequest
2091 status_t
2092 UserlandRequestHandler::_HandleRequest(FreeIndexDirCookieRequest* request)
2093 {
2094 	// check and execute the request
2095 	status_t result = B_OK;
2096 	Volume* volume = (Volume*)request->volume;
2097 	if (!volume)
2098 		result = B_BAD_VALUE;
2099 
2100 	if (result == B_OK) {
2101 		RequestThreadContext context(volume, request);
2102 		result = volume->FreeIndexDirCookie(request->indexDirCookie);
2103 	}
2104 
2105 	// prepare the reply
2106 	RequestAllocator allocator(fPort->GetPort());
2107 	FreeIndexDirCookieReply* reply;
2108 	status_t error = AllocateRequest(allocator, &reply);
2109 	if (error != B_OK)
2110 		RETURN_ERROR(error);
2111 
2112 	reply->error = result;
2113 
2114 	// send the reply
2115 	return _SendReply(allocator, false);
2116 }
2117 
2118 // _HandleRequest
2119 status_t
2120 UserlandRequestHandler::_HandleRequest(ReadIndexDirRequest* request)
2121 {
2122 	// check and execute the request
2123 	status_t result = B_OK;
2124 	Volume* volume = (Volume*)request->volume;
2125 	if (!volume)
2126 		result = B_BAD_VALUE;
2127 
2128 	void* indexDirCookie = request->indexDirCookie;
2129 	size_t bufferSize = request->bufferSize;
2130 	uint32 count = request->count;
2131 
2132 	// allocate the reply
2133 	RequestAllocator allocator(fPort->GetPort());
2134 	ReadIndexDirReply* reply;
2135 	status_t error = AllocateRequest(allocator, &reply);
2136 	if (error != B_OK)
2137 		RETURN_ERROR(error);
2138 
2139 	void* buffer;
2140 	if (result == B_OK) {
2141 		result = allocator.AllocateAddress(reply->buffer, bufferSize, 1,
2142 			&buffer, true);
2143 	}
2144 
2145 	// execute the request
2146 	uint32 countRead;
2147 	if (result == B_OK) {
2148 		RequestThreadContext context(volume, request);
2149 		result = volume->ReadIndexDir(indexDirCookie, buffer, bufferSize,
2150 			count, &countRead);
2151 	}
2152 
2153 	// reconstruct the reply, in case it has been overwritten
2154 	reply = new(reply) ReadIndexDirReply;
2155 
2156 	// send the reply
2157 	reply->error = result;
2158 	reply->count = countRead;
2159 	return _SendReply(allocator, (result == B_OK));
2160 }
2161 
2162 // _HandleRequest
2163 status_t
2164 UserlandRequestHandler::_HandleRequest(RewindIndexDirRequest* request)
2165 {
2166 	// check and execute the request
2167 	status_t result = B_OK;
2168 	Volume* volume = (Volume*)request->volume;
2169 	if (!volume)
2170 		result = B_BAD_VALUE;
2171 
2172 	if (result == B_OK) {
2173 		RequestThreadContext context(volume, request);
2174 		result = volume->RewindIndexDir(request->indexDirCookie);
2175 	}
2176 
2177 	// prepare the reply
2178 	RequestAllocator allocator(fPort->GetPort());
2179 	RewindIndexDirReply* reply;
2180 	status_t error = AllocateRequest(allocator, &reply);
2181 	if (error != B_OK)
2182 		RETURN_ERROR(error);
2183 
2184 	reply->error = result;
2185 
2186 	// send the reply
2187 	return _SendReply(allocator, false);
2188 }
2189 
2190 // _HandleRequest
2191 status_t
2192 UserlandRequestHandler::_HandleRequest(CreateIndexRequest* request)
2193 {
2194 	// check and execute the request
2195 	status_t result = B_OK;
2196 	Volume* volume = (Volume*)request->volume;
2197 	if (!volume)
2198 		result = B_BAD_VALUE;
2199 
2200 	if (result == B_OK) {
2201 		RequestThreadContext context(volume, request);
2202 		result = volume->CreateIndex((const char*)request->name.GetData(),
2203 			request->type, request->flags);
2204 	}
2205 
2206 	// prepare the reply
2207 	RequestAllocator allocator(fPort->GetPort());
2208 	CreateIndexReply* reply;
2209 	status_t error = AllocateRequest(allocator, &reply);
2210 	if (error != B_OK)
2211 		RETURN_ERROR(error);
2212 
2213 	reply->error = result;
2214 
2215 	// send the reply
2216 	return _SendReply(allocator, false);
2217 }
2218 
2219 // _HandleRequest
2220 status_t
2221 UserlandRequestHandler::_HandleRequest(RemoveIndexRequest* request)
2222 {
2223 	// check and execute the request
2224 	status_t result = B_OK;
2225 	Volume* volume = (Volume*)request->volume;
2226 	if (!volume)
2227 		result = B_BAD_VALUE;
2228 
2229 	if (result == B_OK) {
2230 		RequestThreadContext context(volume, request);
2231 		result = volume->RemoveIndex((const char*)request->name.GetData());
2232 	}
2233 
2234 	// prepare the reply
2235 	RequestAllocator allocator(fPort->GetPort());
2236 	RemoveIndexReply* reply;
2237 	status_t error = AllocateRequest(allocator, &reply);
2238 	if (error != B_OK)
2239 		RETURN_ERROR(error);
2240 
2241 	reply->error = result;
2242 
2243 	// send the reply
2244 	return _SendReply(allocator, false);
2245 }
2246 
2247 // _HandleRequest
2248 status_t
2249 UserlandRequestHandler::_HandleRequest(ReadIndexStatRequest* request)
2250 {
2251 	// check and execute the request
2252 	status_t result = B_OK;
2253 	Volume* volume = (Volume*)request->volume;
2254 	if (!volume)
2255 		result = B_BAD_VALUE;
2256 
2257 	struct stat st;
2258 	if (result == B_OK) {
2259 		RequestThreadContext context(volume, request);
2260 		result = volume->ReadIndexStat((const char*)request->name.GetData(),
2261 			&st);
2262 	}
2263 
2264 	// prepare the reply
2265 	RequestAllocator allocator(fPort->GetPort());
2266 	ReadIndexStatReply* reply;
2267 	status_t error = AllocateRequest(allocator, &reply);
2268 	if (error != B_OK)
2269 		RETURN_ERROR(error);
2270 
2271 	reply->error = result;
2272 	reply->st = st;
2273 
2274 	// send the reply
2275 	return _SendReply(allocator, false);
2276 }
2277 
2278 
2279 // #pragma mark - queries
2280 
2281 
2282 // _HandleRequest
2283 status_t
2284 UserlandRequestHandler::_HandleRequest(OpenQueryRequest* request)
2285 {
2286 	// check and execute the request
2287 	status_t result = B_OK;
2288 	Volume* volume = (Volume*)request->volume;
2289 	if (!volume)
2290 		result = B_BAD_VALUE;
2291 
2292 	void* queryCookie;
2293 	if (result == B_OK) {
2294 		RequestThreadContext context(volume, request);
2295 		result = volume->OpenQuery((const char*)request->queryString.GetData(),
2296 			request->flags, request->port, request->token, &queryCookie);
2297 	}
2298 
2299 	// prepare the reply
2300 	RequestAllocator allocator(fPort->GetPort());
2301 	OpenQueryReply* reply;
2302 	status_t error = AllocateRequest(allocator, &reply);
2303 	if (error != B_OK)
2304 		RETURN_ERROR(error);
2305 
2306 	reply->error = result;
2307 	reply->queryCookie = queryCookie;
2308 
2309 	// send the reply
2310 	return _SendReply(allocator, false);
2311 }
2312 
2313 // _HandleRequest
2314 status_t
2315 UserlandRequestHandler::_HandleRequest(CloseQueryRequest* request)
2316 {
2317 	// check and execute the request
2318 	status_t result = B_OK;
2319 	Volume* volume = (Volume*)request->volume;
2320 	if (!volume)
2321 		result = B_BAD_VALUE;
2322 
2323 	if (result == B_OK) {
2324 		RequestThreadContext context(volume, request);
2325 		result = volume->CloseQuery(request->queryCookie);
2326 	}
2327 
2328 	// prepare the reply
2329 	RequestAllocator allocator(fPort->GetPort());
2330 	CloseQueryReply* reply;
2331 	status_t error = AllocateRequest(allocator, &reply);
2332 	if (error != B_OK)
2333 		RETURN_ERROR(error);
2334 
2335 	reply->error = result;
2336 
2337 	// send the reply
2338 	return _SendReply(allocator, false);
2339 }
2340 
2341 // _HandleRequest
2342 status_t
2343 UserlandRequestHandler::_HandleRequest(FreeQueryCookieRequest* request)
2344 {
2345 	// check and execute the request
2346 	status_t result = B_OK;
2347 	Volume* volume = (Volume*)request->volume;
2348 	if (!volume)
2349 		result = B_BAD_VALUE;
2350 
2351 	if (result == B_OK) {
2352 		RequestThreadContext context(volume, request);
2353 		result = volume->FreeQueryCookie(request->queryCookie);
2354 	}
2355 
2356 	// prepare the reply
2357 	RequestAllocator allocator(fPort->GetPort());
2358 	FreeQueryCookieReply* reply;
2359 	status_t error = AllocateRequest(allocator, &reply);
2360 	if (error != B_OK)
2361 		RETURN_ERROR(error);
2362 
2363 	reply->error = result;
2364 
2365 	// send the reply
2366 	return _SendReply(allocator, false);
2367 }
2368 
2369 // _HandleRequest
2370 status_t
2371 UserlandRequestHandler::_HandleRequest(ReadQueryRequest* request)
2372 {
2373 	// check and execute the request
2374 	status_t result = B_OK;
2375 	Volume* volume = (Volume*)request->volume;
2376 	if (!volume)
2377 		result = B_BAD_VALUE;
2378 
2379 	void* queryCookie = request->queryCookie;
2380 	size_t bufferSize = request->bufferSize;
2381 	uint32 count = request->count;
2382 
2383 	// allocate the reply
2384 	RequestAllocator allocator(fPort->GetPort());
2385 	ReadQueryReply* reply;
2386 	status_t error = AllocateRequest(allocator, &reply);
2387 	if (error != B_OK)
2388 		RETURN_ERROR(error);
2389 
2390 	void* buffer;
2391 	if (result == B_OK) {
2392 		result = allocator.AllocateAddress(reply->buffer, bufferSize, 1,
2393 			&buffer, true);
2394 	}
2395 
2396 	// execute the request
2397 	uint32 countRead;
2398 	if (result == B_OK) {
2399 		RequestThreadContext context(volume, request);
2400 		result = volume->ReadQuery(queryCookie, buffer, bufferSize,
2401 			count, &countRead);
2402 	}
2403 
2404 	// reconstruct the reply, in case it has been overwritten
2405 	reply = new(reply) ReadQueryReply;
2406 
2407 	// send the reply
2408 	reply->error = result;
2409 	reply->count = countRead;
2410 	return _SendReply(allocator, (result == B_OK));
2411 }
2412 
2413 // _HandleRequest
2414 status_t
2415 UserlandRequestHandler::_HandleRequest(RewindQueryRequest* request)
2416 {
2417 	// check and execute the request
2418 	status_t result = B_OK;
2419 	Volume* volume = (Volume*)request->volume;
2420 	if (!volume)
2421 		result = B_BAD_VALUE;
2422 
2423 	if (result == B_OK) {
2424 		RequestThreadContext context(volume, request);
2425 		result = volume->RewindQuery(request->queryCookie);
2426 	}
2427 
2428 	// prepare the reply
2429 	RequestAllocator allocator(fPort->GetPort());
2430 	RewindQueryReply* reply;
2431 	status_t error = AllocateRequest(allocator, &reply);
2432 	if (error != B_OK)
2433 		RETURN_ERROR(error);
2434 
2435 	reply->error = result;
2436 
2437 	// send the reply
2438 	return _SendReply(allocator, false);
2439 }
2440 
2441 
2442 // #pragma mark - node monitoring
2443 
2444 
2445 // _HandleRequest
2446 status_t
2447 UserlandRequestHandler::_HandleRequest(NodeMonitoringEventRequest* request)
2448 {
2449 	// check and execute the request
2450 	KMessage event;
2451 	event.SetTo(request->event.GetData(), request->event.GetSize());
2452 	((NotificationListener*)request->listener)->EventOccurred(
2453 		*(NotificationService*)NULL, &event);
2454 
2455 	// prepare the reply
2456 	RequestAllocator allocator(fPort->GetPort());
2457 	NodeMonitoringEventReply* reply;
2458 	status_t error = AllocateRequest(allocator, &reply);
2459 	if (error != B_OK)
2460 		RETURN_ERROR(error);
2461 
2462 	reply->error = B_OK;
2463 
2464 	// send the reply
2465 	return _SendReply(allocator, false);
2466 }
2467 
2468 
2469 // #pragma mark - other
2470 
2471 
2472 // _SendReply
2473 status_t
2474 UserlandRequestHandler::_SendReply(RequestAllocator& allocator,
2475 	bool expectsReceipt)
2476 {
2477 	if (expectsReceipt) {
2478 		SingleReplyRequestHandler handler(RECEIPT_ACK_REPLY);
2479 		return fPort->SendRequest(&allocator, &handler);
2480 	} else
2481 		return fPort->SendRequest(&allocator);
2482 }
2483 
2484