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