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