1 // kernel_emu.cpp 2 3 #include "kernel_emu.h" 4 5 #include <stdarg.h> 6 #include <stdio.h> 7 #include <stdlib.h> 8 9 #include <algorithm> 10 11 #include "FileSystem.h" 12 #include "RequestPort.h" 13 #include "Requests.h" 14 #include "RequestThread.h" 15 #include "UserlandFSServer.h" 16 #include "UserlandRequestHandler.h" 17 #include "Volume.h" 18 19 20 // Taken from the Haiku Storage Kit (storage_support.cpp) 21 /*! The length of the first component is returned as well as the index at 22 which the next one starts. These values are only valid, if the function 23 returns \c B_OK. 24 \param path the path to be parsed 25 \param length the variable the length of the first component is written 26 into 27 \param nextComponent the variable the index of the next component is 28 written into. \c 0 is returned, if there is no next component. 29 \return \c B_OK, if \a path is not \c NULL, \c B_BAD_VALUE otherwise 30 */ 31 static status_t 32 parse_first_path_component(const char *path, int32& length, 33 int32& nextComponent) 34 { 35 status_t error = (path ? B_OK : B_BAD_VALUE); 36 if (error == B_OK) { 37 int32 i = 0; 38 // find first '/' or end of name 39 for (; path[i] != '/' && path[i] != '\0'; i++); 40 // handle special case "/..." (absolute path) 41 if (i == 0 && path[i] != '\0') 42 i = 1; 43 length = i; 44 // find last '/' or end of name 45 for (; path[i] == '/' && path[i] != '\0'; i++); 46 if (path[i] == '\0') // this covers "" as well 47 nextComponent = 0; 48 else 49 nextComponent = i; 50 } 51 return error; 52 } 53 54 // new_path 55 int 56 UserlandFS::KernelEmu::new_path(const char *path, char **copy) 57 { 58 // check errors and special cases 59 if (!copy) 60 return B_BAD_VALUE; 61 if (!path) { 62 *copy = NULL; 63 return B_OK; 64 } 65 int32 len = strlen(path); 66 if (len < 1) 67 return B_ENTRY_NOT_FOUND; 68 bool appendDot = (path[len - 1] == '/'); 69 if (appendDot) 70 len++; 71 if (len >= B_PATH_NAME_LENGTH) 72 return B_NAME_TOO_LONG; 73 // check the path components 74 const char *remainder = path; 75 int32 length, nextComponent; 76 do { 77 status_t error 78 = parse_first_path_component(remainder, length, nextComponent); 79 if (error != B_OK) 80 return error; 81 if (length >= B_FILE_NAME_LENGTH) 82 error = B_NAME_TOO_LONG; 83 remainder += nextComponent; 84 } while (nextComponent != 0); 85 // clone the path 86 char *copiedPath = (char*)malloc(len + 1); 87 if (!copiedPath) 88 return B_NO_MEMORY; 89 strcpy(copiedPath, path); 90 // append a dot, if desired 91 if (appendDot) { 92 copiedPath[len] = '.'; 93 copiedPath[len] = '\0'; 94 } 95 *copy = copiedPath; 96 return B_OK; 97 } 98 99 // free_path 100 void 101 UserlandFS::KernelEmu::free_path(char *p) 102 { 103 free(p); 104 } 105 106 107 // #pragma mark - 108 109 110 // get_port_and_fs 111 static status_t 112 get_port_and_fs(RequestPort** port, FileSystem** fileSystem) 113 { 114 // get the request thread 115 RequestThread* thread = RequestThread::GetCurrentThread(); 116 if (thread) { 117 *port = thread->GetPort(); 118 *fileSystem = thread->GetFileSystem(); 119 } else { 120 *port = UserlandFSServer::GetNotificationRequestPort(); 121 *fileSystem = UserlandFSServer::GetFileSystem(); 122 if (!*port || !*fileSystem) 123 return B_BAD_VALUE; 124 } 125 return B_OK; 126 } 127 128 // notify_listener 129 status_t 130 UserlandFS::KernelEmu::notify_listener(int32 operation, uint32 details, 131 dev_t device, ino_t oldDirectory, ino_t directory, 132 ino_t node, const char* oldName, const char* name) 133 { 134 // get the request port and the file system 135 RequestPort* port; 136 FileSystem* fileSystem; 137 status_t error = get_port_and_fs(&port, &fileSystem); 138 if (error != B_OK) 139 return error; 140 141 // prepare the request 142 RequestAllocator allocator(port->GetPort()); 143 NotifyListenerRequest* request; 144 error = AllocateRequest(allocator, &request); 145 if (error != B_OK) 146 return error; 147 148 request->operation = operation; 149 request->details = details; 150 request->device = device; 151 request->oldDirectory = oldDirectory; 152 request->directory = directory; 153 request->node = node; 154 error = allocator.AllocateString(request->oldName, oldName); 155 if (error != B_OK) 156 return error; 157 error = allocator.AllocateString(request->name, name); 158 if (error != B_OK) 159 return error; 160 161 // send the request 162 UserlandRequestHandler handler(fileSystem, NOTIFY_LISTENER_REPLY); 163 NotifyListenerReply* reply; 164 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 165 if (error != B_OK) 166 return error; 167 RequestReleaser requestReleaser(port, reply); 168 169 // process the reply 170 if (reply->error != B_OK) 171 return reply->error; 172 return error; 173 } 174 175 // notify_select_event 176 status_t 177 UserlandFS::KernelEmu::notify_select_event(selectsync *sync, uint8 event, 178 bool unspecifiedEvent) 179 { 180 // get the request port and the file system 181 RequestPort* port; 182 FileSystem* fileSystem; 183 status_t error = get_port_and_fs(&port, &fileSystem); 184 if (error != B_OK) 185 return error; 186 187 // prepare the request 188 RequestAllocator allocator(port->GetPort()); 189 NotifySelectEventRequest* request; 190 error = AllocateRequest(allocator, &request); 191 if (error != B_OK) 192 return error; 193 194 request->sync = sync; 195 request->event = event; 196 request->unspecifiedEvent = unspecifiedEvent; 197 198 // send the request 199 UserlandRequestHandler handler(fileSystem, NOTIFY_SELECT_EVENT_REPLY); 200 NotifySelectEventReply* reply; 201 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 202 if (error != B_OK) 203 return error; 204 RequestReleaser requestReleaser(port, reply); 205 206 // process the reply 207 if (reply->error != B_OK) 208 return reply->error; 209 return error; 210 } 211 212 // send_notification 213 status_t 214 UserlandFS::KernelEmu::notify_query(port_id targetPort, int32 token, 215 int32 operation, dev_t device, ino_t directory, const char* name, 216 ino_t node) 217 { 218 // get the request port and the file system 219 RequestPort* port; 220 FileSystem* fileSystem; 221 status_t error = get_port_and_fs(&port, &fileSystem); 222 if (error != B_OK) 223 return error; 224 225 // prepare the request 226 RequestAllocator allocator(port->GetPort()); 227 NotifyQueryRequest* request; 228 error = AllocateRequest(allocator, &request); 229 if (error != B_OK) 230 return error; 231 232 request->port = targetPort; 233 request->token = token; 234 request->operation = operation; 235 request->device = device; 236 request->directory = directory; 237 request->node = node; 238 error = allocator.AllocateString(request->name, name); 239 if (error != B_OK) 240 return error; 241 242 // send the request 243 UserlandRequestHandler handler(fileSystem, NOTIFY_QUERY_REPLY); 244 NotifyQueryReply* reply; 245 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 246 if (error != B_OK) 247 return error; 248 RequestReleaser requestReleaser(port, reply); 249 250 // process the reply 251 if (reply->error != B_OK) 252 return reply->error; 253 return error; 254 } 255 256 257 // #pragma mark - 258 259 260 // get_vnode 261 status_t 262 UserlandFS::KernelEmu::get_vnode(dev_t nsid, ino_t vnid, void** node) 263 { 264 // get the request port and the file system 265 RequestPort* port; 266 FileSystem* fileSystem; 267 status_t error = get_port_and_fs(&port, &fileSystem); 268 if (error != B_OK) 269 return error; 270 271 // prepare the request 272 RequestAllocator allocator(port->GetPort()); 273 GetVNodeRequest* request; 274 error = AllocateRequest(allocator, &request); 275 if (error != B_OK) 276 return error; 277 278 request->nsid = nsid; 279 request->vnid = vnid; 280 281 // send the request 282 UserlandRequestHandler handler(fileSystem, GET_VNODE_REPLY); 283 GetVNodeReply* reply; 284 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 285 if (error != B_OK) 286 return error; 287 RequestReleaser requestReleaser(port, reply); 288 289 // process the reply 290 if (reply->error != B_OK) 291 return reply->error; 292 *node = reply->node; 293 return error; 294 } 295 296 // put_vnode 297 status_t 298 UserlandFS::KernelEmu::put_vnode(dev_t nsid, ino_t vnid) 299 { 300 // get the request port and the file system 301 RequestPort* port; 302 FileSystem* fileSystem; 303 status_t error = get_port_and_fs(&port, &fileSystem); 304 if (error != B_OK) 305 return error; 306 307 // prepare the request 308 RequestAllocator allocator(port->GetPort()); 309 PutVNodeRequest* request; 310 error = AllocateRequest(allocator, &request); 311 if (error != B_OK) 312 return error; 313 314 request->nsid = nsid; 315 request->vnid = vnid; 316 317 // send the request 318 UserlandRequestHandler handler(fileSystem, PUT_VNODE_REPLY); 319 PutVNodeReply* reply; 320 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 321 if (error != B_OK) 322 return error; 323 RequestReleaser requestReleaser(port, reply); 324 325 // process the reply 326 if (reply->error != B_OK) 327 return reply->error; 328 return error; 329 } 330 331 // acquire_vnode 332 status_t 333 UserlandFS::KernelEmu::acquire_vnode(dev_t nsid, ino_t vnid) 334 { 335 // get the request port and the file system 336 RequestPort* port; 337 FileSystem* fileSystem; 338 status_t error = get_port_and_fs(&port, &fileSystem); 339 if (error != B_OK) 340 return error; 341 342 // prepare the request 343 RequestAllocator allocator(port->GetPort()); 344 AcquireVNodeRequest* request; 345 error = AllocateRequest(allocator, &request); 346 if (error != B_OK) 347 return error; 348 349 request->nsid = nsid; 350 request->vnid = vnid; 351 352 // send the request 353 UserlandRequestHandler handler(fileSystem, ACQUIRE_VNODE_REPLY); 354 AcquireVNodeReply* reply; 355 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 356 if (error != B_OK) 357 return error; 358 RequestReleaser requestReleaser(port, reply); 359 360 // process the reply 361 if (reply->error != B_OK) 362 return reply->error; 363 return error; 364 } 365 366 // new_vnode 367 status_t 368 UserlandFS::KernelEmu::new_vnode(dev_t nsid, ino_t vnid, void* data, 369 const FSVNodeCapabilities& capabilities) 370 { 371 // get the request port and the file system 372 RequestPort* port; 373 FileSystem* fileSystem; 374 status_t error = get_port_and_fs(&port, &fileSystem); 375 if (error != B_OK) 376 return error; 377 378 // prepare the request 379 RequestAllocator allocator(port->GetPort()); 380 NewVNodeRequest* request; 381 error = AllocateRequest(allocator, &request); 382 if (error != B_OK) 383 return error; 384 385 request->nsid = nsid; 386 request->vnid = vnid; 387 request->node = data; 388 request->capabilities = capabilities; 389 390 // send the request 391 UserlandRequestHandler handler(fileSystem, NEW_VNODE_REPLY); 392 NewVNodeReply* reply; 393 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 394 if (error != B_OK) 395 return error; 396 RequestReleaser requestReleaser(port, reply); 397 398 // process the reply 399 if (reply->error != B_OK) 400 return reply->error; 401 return error; 402 } 403 404 // publish_vnode 405 status_t 406 UserlandFS::KernelEmu::publish_vnode(dev_t nsid, ino_t vnid, void* data, 407 int type, uint32 flags, const FSVNodeCapabilities& capabilities) 408 { 409 // get the request port and the file system 410 RequestPort* port; 411 FileSystem* fileSystem; 412 status_t error = get_port_and_fs(&port, &fileSystem); 413 if (error != B_OK) 414 return error; 415 416 // prepare the request 417 RequestAllocator allocator(port->GetPort()); 418 PublishVNodeRequest* request; 419 error = AllocateRequest(allocator, &request); 420 if (error != B_OK) 421 return error; 422 423 request->nsid = nsid; 424 request->vnid = vnid; 425 request->node = data; 426 request->type = type; 427 request->flags = flags; 428 request->capabilities = capabilities; 429 430 // send the request 431 UserlandRequestHandler handler(fileSystem, PUBLISH_VNODE_REPLY); 432 PublishVNodeReply* reply; 433 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 434 if (error != B_OK) 435 return error; 436 RequestReleaser requestReleaser(port, reply); 437 438 // process the reply 439 if (reply->error != B_OK) 440 return reply->error; 441 return error; 442 } 443 444 445 // publish_vnode 446 status_t 447 UserlandFS::KernelEmu::publish_vnode(dev_t nsid, ino_t vnid, void* data, 448 const FSVNodeCapabilities& capabilities) 449 { 450 // get the volume 451 Volume* volume = FileSystem::GetInstance()->VolumeWithID(nsid); 452 if (volume == NULL) 453 return B_BAD_VALUE; 454 455 // stat() the node to get its type 456 int type; 457 status_t error = volume->GetVNodeType(data, &type); 458 if (error != B_OK) 459 return error; 460 461 // publish the node 462 return UserlandFS::KernelEmu::publish_vnode(nsid, vnid, data, type, 0, 463 capabilities); 464 } 465 466 467 // remove_vnode 468 status_t 469 UserlandFS::KernelEmu::remove_vnode(dev_t nsid, ino_t vnid) 470 { 471 // get the request port and the file system 472 RequestPort* port; 473 FileSystem* fileSystem; 474 status_t error = get_port_and_fs(&port, &fileSystem); 475 if (error != B_OK) 476 return error; 477 478 // prepare the request 479 RequestAllocator allocator(port->GetPort()); 480 RemoveVNodeRequest* request; 481 error = AllocateRequest(allocator, &request); 482 if (error != B_OK) 483 return error; 484 485 request->nsid = nsid; 486 request->vnid = vnid; 487 488 // send the request 489 UserlandRequestHandler handler(fileSystem, REMOVE_VNODE_REPLY); 490 RemoveVNodeReply* reply; 491 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 492 if (error != B_OK) 493 return error; 494 RequestReleaser requestReleaser(port, reply); 495 496 // process the reply 497 if (reply->error != B_OK) 498 return reply->error; 499 return error; 500 } 501 502 // unremove_vnode 503 status_t 504 UserlandFS::KernelEmu::unremove_vnode(dev_t nsid, ino_t vnid) 505 { 506 // get the request port and the file system 507 RequestPort* port; 508 FileSystem* fileSystem; 509 status_t error = get_port_and_fs(&port, &fileSystem); 510 if (error != B_OK) 511 return error; 512 513 // prepare the request 514 RequestAllocator allocator(port->GetPort()); 515 UnremoveVNodeRequest* request; 516 error = AllocateRequest(allocator, &request); 517 if (error != B_OK) 518 return error; 519 520 request->nsid = nsid; 521 request->vnid = vnid; 522 523 // send the request 524 UserlandRequestHandler handler(fileSystem, UNREMOVE_VNODE_REPLY); 525 UnremoveVNodeReply* reply; 526 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 527 if (error != B_OK) 528 return error; 529 RequestReleaser requestReleaser(port, reply); 530 531 // process the reply 532 if (reply->error != B_OK) 533 return reply->error; 534 return error; 535 } 536 537 // get_vnode_removed 538 status_t 539 UserlandFS::KernelEmu::get_vnode_removed(dev_t nsid, ino_t vnid, 540 bool* removed) 541 { 542 // get the request port and the file system 543 RequestPort* port; 544 FileSystem* fileSystem; 545 status_t error = get_port_and_fs(&port, &fileSystem); 546 if (error != B_OK) 547 return error; 548 549 // prepare the request 550 RequestAllocator allocator(port->GetPort()); 551 GetVNodeRemovedRequest* request; 552 error = AllocateRequest(allocator, &request); 553 if (error != B_OK) 554 return error; 555 556 request->nsid = nsid; 557 request->vnid = vnid; 558 559 // send the request 560 UserlandRequestHandler handler(fileSystem, GET_VNODE_REMOVED_REPLY); 561 GetVNodeRemovedReply* reply; 562 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 563 if (error != B_OK) 564 return error; 565 RequestReleaser requestReleaser(port, reply); 566 567 // process the reply 568 *removed = reply->removed; 569 return reply->error; 570 } 571 572 573 // #pragma mark - file cache 574 575 576 // file_cache_create 577 status_t 578 UserlandFS::KernelEmu::file_cache_create(dev_t mountID, ino_t vnodeID, 579 off_t size) 580 { 581 // get the request port and the file system 582 RequestPort* port; 583 FileSystem* fileSystem; 584 status_t error = get_port_and_fs(&port, &fileSystem); 585 if (error != B_OK) 586 RETURN_ERROR(error); 587 588 // prepare the request 589 RequestAllocator allocator(port->GetPort()); 590 FileCacheCreateRequest* request; 591 error = AllocateRequest(allocator, &request); 592 if (error != B_OK) 593 RETURN_ERROR(error); 594 595 request->nsid = mountID; 596 request->vnid = vnodeID; 597 request->size = size; 598 599 // send the request 600 UserlandRequestHandler handler(fileSystem, FILE_CACHE_CREATE_REPLY); 601 FileCacheCreateReply* reply; 602 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 603 if (error != B_OK) 604 RETURN_ERROR(error); 605 RequestReleaser requestReleaser(port, reply); 606 607 // process the reply 608 RETURN_ERROR(reply->error); 609 } 610 611 612 // file_cache_delete 613 status_t 614 UserlandFS::KernelEmu::file_cache_delete(dev_t mountID, ino_t vnodeID) 615 { 616 // get the request port and the file system 617 RequestPort* port; 618 FileSystem* fileSystem; 619 status_t error = get_port_and_fs(&port, &fileSystem); 620 if (error != B_OK) 621 return error; 622 623 // prepare the request 624 RequestAllocator allocator(port->GetPort()); 625 FileCacheDeleteRequest* request; 626 error = AllocateRequest(allocator, &request); 627 if (error != B_OK) 628 return error; 629 630 request->nsid = mountID; 631 request->vnid = vnodeID; 632 633 // send the request 634 UserlandRequestHandler handler(fileSystem, FILE_CACHE_DELETE_REPLY); 635 FileCacheDeleteReply* reply; 636 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 637 if (error != B_OK) 638 return error; 639 RequestReleaser requestReleaser(port, reply); 640 641 // process the reply 642 return reply->error; 643 } 644 645 646 // file_cache_set_enable 647 status_t 648 UserlandFS::KernelEmu::file_cache_set_enabled(dev_t mountID, ino_t vnodeID, 649 bool enabled) 650 { 651 // get the request port and the file system 652 RequestPort* port; 653 FileSystem* fileSystem; 654 status_t error = get_port_and_fs(&port, &fileSystem); 655 if (error != B_OK) 656 return error; 657 658 // prepare the request 659 RequestAllocator allocator(port->GetPort()); 660 FileCacheSetEnabledRequest* request; 661 error = AllocateRequest(allocator, &request); 662 if (error != B_OK) 663 return error; 664 665 request->nsid = mountID; 666 request->vnid = vnodeID; 667 request->enabled = enabled; 668 669 // send the request 670 UserlandRequestHandler handler(fileSystem, FILE_CACHE_SET_ENABLED_REPLY); 671 FileCacheSetEnabledReply* reply; 672 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 673 if (error != B_OK) 674 return error; 675 RequestReleaser requestReleaser(port, reply); 676 677 // process the reply 678 return reply->error; 679 } 680 681 682 // file_cache_set_size 683 status_t 684 UserlandFS::KernelEmu::file_cache_set_size(dev_t mountID, ino_t vnodeID, 685 off_t size) 686 { 687 // get the request port and the file system 688 RequestPort* port; 689 FileSystem* fileSystem; 690 status_t error = get_port_and_fs(&port, &fileSystem); 691 if (error != B_OK) 692 return error; 693 694 // prepare the request 695 RequestAllocator allocator(port->GetPort()); 696 FileCacheSetSizeRequest* request; 697 error = AllocateRequest(allocator, &request); 698 if (error != B_OK) 699 return error; 700 701 request->nsid = mountID; 702 request->vnid = vnodeID; 703 request->size = size; 704 705 // send the request 706 UserlandRequestHandler handler(fileSystem, FILE_CACHE_SET_SIZE_REPLY); 707 FileCacheSetSizeReply* reply; 708 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 709 if (error != B_OK) 710 return error; 711 RequestReleaser requestReleaser(port, reply); 712 713 // process the reply 714 return reply->error; 715 } 716 717 718 // file_cache_sync 719 status_t 720 UserlandFS::KernelEmu::file_cache_sync(dev_t mountID, ino_t vnodeID) 721 { 722 // get the request port and the file system 723 RequestPort* port; 724 FileSystem* fileSystem; 725 status_t error = get_port_and_fs(&port, &fileSystem); 726 if (error != B_OK) 727 return error; 728 729 // prepare the request 730 RequestAllocator allocator(port->GetPort()); 731 FileCacheSyncRequest* request; 732 error = AllocateRequest(allocator, &request); 733 if (error != B_OK) 734 return error; 735 736 request->nsid = mountID; 737 request->vnid = vnodeID; 738 739 // send the request 740 UserlandRequestHandler handler(fileSystem, FILE_CACHE_SYNC_REPLY); 741 FileCacheSyncReply* reply; 742 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 743 if (error != B_OK) 744 return error; 745 RequestReleaser requestReleaser(port, reply); 746 747 // process the reply 748 return reply->error; 749 } 750 751 752 // file_cache_read 753 status_t 754 UserlandFS::KernelEmu::file_cache_read(dev_t mountID, ino_t vnodeID, 755 void *cookie, off_t offset, void *bufferBase, size_t *_size) 756 { 757 // get the request port and the file system 758 RequestPort* port; 759 FileSystem* fileSystem; 760 status_t error = get_port_and_fs(&port, &fileSystem); 761 if (error != B_OK) 762 return error; 763 764 // prepare the request 765 RequestAllocator allocator(port->GetPort()); 766 FileCacheReadRequest* request; 767 error = AllocateRequest(allocator, &request); 768 if (error != B_OK) 769 return error; 770 771 request->nsid = mountID; 772 request->vnid = vnodeID; 773 request->cookie = cookie; 774 request->pos = offset; 775 request->size = *_size; 776 777 // send the request 778 UserlandRequestHandler handler(fileSystem, FILE_CACHE_READ_REPLY); 779 FileCacheReadReply* reply; 780 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 781 if (error != B_OK) 782 return error; 783 RequestReleaser requestReleaser(port, reply); 784 785 // process the reply 786 if (reply->error != B_OK) 787 return reply->error; 788 789 if (reply->bytesRead > 0) { 790 memcpy(bufferBase, reply->buffer.GetData(), reply->buffer.GetSize()); 791 792 // send receipt-ack 793 RequestAllocator receiptAckAllocator(port->GetPort()); 794 ReceiptAckReply* receiptAck; 795 if (AllocateRequest(receiptAckAllocator, &receiptAck) == B_OK) 796 port->SendRequest(&receiptAckAllocator); 797 } 798 799 *_size = reply->bytesRead; 800 801 return B_OK; 802 } 803 804 805 // file_cache_write 806 status_t 807 UserlandFS::KernelEmu::file_cache_write(dev_t mountID, ino_t vnodeID, 808 void *cookie, off_t offset, const void *buffer, size_t *_size) 809 { 810 // get the request port and the file system 811 RequestPort* port; 812 FileSystem* fileSystem; 813 status_t error = get_port_and_fs(&port, &fileSystem); 814 if (error != B_OK) 815 return error; 816 817 // prepare the request 818 RequestAllocator allocator(port->GetPort()); 819 FileCacheWriteRequest* request; 820 error = AllocateRequest(allocator, &request); 821 if (error != B_OK) 822 return error; 823 824 request->nsid = mountID; 825 request->vnid = vnodeID; 826 request->cookie = cookie; 827 request->pos = offset; 828 829 error = allocator.AllocateData(request->buffer, buffer, *_size, 1, false); 830 if (error != B_OK) 831 return error; 832 833 // send the request 834 UserlandRequestHandler handler(fileSystem, FILE_CACHE_WRITE_REPLY); 835 FileCacheWriteReply* reply; 836 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 837 if (error != B_OK) 838 return error; 839 RequestReleaser requestReleaser(port, reply); 840 841 // process the reply 842 *_size = reply->bytesWritten; 843 return reply->error; 844 } 845 846 847 // #pragma mark - I/O 848 849 850 status_t 851 UserlandFS::KernelEmu::do_iterative_fd_io(dev_t volumeID, int fd, 852 int32 requestID, void* cookie, const file_io_vec* vecs, uint32 vecCount) 853 { 854 // get the request port and the file system 855 RequestPort* port; 856 FileSystem* fileSystem; 857 status_t error = get_port_and_fs(&port, &fileSystem); 858 if (error != B_OK) 859 return error; 860 861 // prepare the request 862 RequestAllocator allocator(port->GetPort()); 863 DoIterativeFDIORequest* request; 864 error = AllocateRequest(allocator, &request); 865 if (error != B_OK) 866 return error; 867 868 request->nsid = volumeID; 869 request->fd = fd; 870 request->request = requestID; 871 request->cookie = cookie; 872 873 if (vecCount > 0) { 874 vecCount = std::min(vecCount, (uint32)DoIterativeFDIORequest::MAX_VECS); 875 memcpy(request->vecs, vecs, sizeof(file_io_vec) * vecCount); 876 } 877 request->vecCount = vecCount; 878 879 // send the request 880 UserlandRequestHandler handler(fileSystem, DO_ITERATIVE_FD_IO_REPLY); 881 DoIterativeFDIOReply* reply; 882 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 883 if (error != B_OK) 884 return error; 885 // TODO: Up to this point we should call the finished hook on error! 886 RequestReleaser requestReleaser(port, reply); 887 888 // process the reply 889 return reply->error; 890 } 891 892 893 status_t 894 UserlandFS::KernelEmu::notify_io_request(dev_t volumeID, int32 requestID, 895 status_t status) 896 { 897 // get the request port and the file system 898 RequestPort* port; 899 FileSystem* fileSystem; 900 status_t error = get_port_and_fs(&port, &fileSystem); 901 if (error != B_OK) 902 return error; 903 904 // prepare the request 905 RequestAllocator allocator(port->GetPort()); 906 NotifyIORequestRequest* request; 907 error = AllocateRequest(allocator, &request); 908 if (error != B_OK) 909 return error; 910 911 request->nsid = volumeID; 912 request->request = requestID; 913 request->status = status; 914 915 // send the request 916 UserlandRequestHandler handler(fileSystem, NOTIFY_IO_REQUEST_REPLY); 917 NotifyIORequestReply* reply; 918 error = port->SendRequest(&allocator, &handler, (Request**)&reply); 919 if (error != B_OK) 920 return error; 921 RequestReleaser requestReleaser(port, reply); 922 923 // process the reply 924 return reply->error; 925 } 926 927 928 // #pragma mark - 929 930 931 // kernel_debugger 932 void 933 UserlandFS::KernelEmu::kernel_debugger(const char *message) 934 { 935 debugger(message); 936 } 937 938 // vdprintf 939 void 940 UserlandFS::KernelEmu::vdprintf(const char *format, va_list args) 941 { 942 vprintf(format, args); 943 } 944 945 // dprintf 946 void 947 UserlandFS::KernelEmu::dprintf(const char *format, ...) 948 { 949 va_list args; 950 va_start(args, format); 951 vdprintf(format, args); 952 va_end(args); 953 } 954 955 void 956 UserlandFS::KernelEmu::dump_block(const char *buffer, int size, 957 const char *prefix) 958 { 959 // TODO: Implement! 960 } 961 962 // parse_expression 963 //ulong 964 //parse_expression(char *str) 965 //{ 966 // return 0; 967 //} 968 969 // add_debugger_command 970 int 971 UserlandFS::KernelEmu::add_debugger_command(char *name, 972 int (*func)(int argc, char **argv), char *help) 973 { 974 return B_OK; 975 } 976 977 // remove_debugger_command 978 int 979 UserlandFS::KernelEmu::remove_debugger_command(char *name, 980 int (*func)(int argc, char **argv)) 981 { 982 return B_OK; 983 } 984 985 // parse_expression 986 uint32 987 UserlandFS::KernelEmu::parse_expression(const char *string) 988 { 989 return 0; 990 } 991 992 993 // kprintf 994 //void 995 //kprintf(const char *format, ...) 996 //{ 997 //} 998 999 // spawn_kernel_thread 1000 thread_id 1001 UserlandFS::KernelEmu::spawn_kernel_thread(thread_entry function, 1002 const char *threadName, long priority, void *arg) 1003 { 1004 return spawn_thread(function, threadName, priority, arg); 1005 } 1006