1 2 #include <BeOSBuildCompatibility.h> 3 4 #include "fs_impl.h" 5 6 #include <dirent.h> 7 #include <errno.h> 8 #include <fcntl.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <unistd.h> 12 #include <utime.h> 13 #include <sys/stat.h> 14 15 #include <map> 16 #include <string> 17 18 #include <fs_attr.h> 19 #include <NodeMonitor.h> // for B_STAT_* flags 20 #include <syscalls.h> 21 22 #include "fs_descriptors.h" 23 #include "NodeRef.h" 24 25 using namespace std; 26 using namespace BPrivate; 27 28 29 static status_t get_path(dev_t device, ino_t node, const char *name, 30 string &path); 31 32 33 // find_dir_entry 34 static status_t 35 find_dir_entry(DIR *dir, const char *path, NodeRef ref, string &name, 36 bool skipDot) 37 { 38 // find the entry 39 bool found = false; 40 while (dirent *entry = readdir(dir)) { 41 if ((!skipDot && strcmp(entry->d_name, ".") == 0) 42 || strcmp(entry->d_name, "..") == 0) { 43 // skip "." and ".." 44 } else /*if (entry->d_ino == ref.node)*/ { 45 // Note: Linux doesn't seem to translate dirent::d_ino of 46 // mount points. Thus we always have to lstat(). 47 // We also need to compare the device, which is generally not 48 // included in the dirent structure. Hence we lstat(). 49 string entryPath(path); 50 entryPath += '/'; 51 entryPath += entry->d_name; 52 struct stat st; 53 if (lstat(entryPath.c_str(), &st) == 0) { 54 if (NodeRef(st) == ref) { 55 name = entry->d_name; 56 found = true; 57 break; 58 } 59 } 60 } 61 } 62 63 if (!found) 64 return B_ENTRY_NOT_FOUND; 65 66 return B_OK; 67 } 68 69 // find_dir_entry 70 static status_t 71 find_dir_entry(const char *path, NodeRef ref, string &name, bool skipDot) 72 { 73 // open dir 74 DIR *dir = opendir(path); 75 if (!dir) 76 return errno; 77 78 status_t error = find_dir_entry(dir, path, ref, name, skipDot); 79 80 // close dir 81 closedir(dir); 82 83 return error; 84 } 85 86 // normalize_dir_path 87 static status_t 88 normalize_dir_path(string path, NodeRef ref, string &normalizedPath) 89 { 90 // get parent path 91 path += "/.."; 92 93 // stat the parent dir 94 struct stat st; 95 if (lstat(path.c_str(), &st) < 0) 96 return errno; 97 98 // root dir? 99 NodeRef parentRef(st); 100 if (parentRef == ref) { 101 normalizedPath = "/"; 102 return 0; 103 } 104 105 // find the entry 106 string name; 107 status_t error = find_dir_entry(path.c_str(), ref, name, true) ; 108 if (error != B_OK) 109 return error; 110 111 // recurse to get the parent dir path, if found 112 error = normalize_dir_path(path, parentRef, normalizedPath); 113 if (error != 0) 114 return error; 115 116 // construct the normalizedPath 117 if (normalizedPath.length() > 1) // don't append "/", if parent is root 118 normalizedPath += '/'; 119 normalizedPath += name; 120 121 return 0; 122 } 123 124 // normalize_dir_path 125 static status_t 126 normalize_dir_path(const char *path, string &normalizedPath) 127 { 128 // stat() the dir 129 struct stat st; 130 if (stat(path, &st) < 0) 131 return errno; 132 133 return normalize_dir_path(path, NodeRef(st), normalizedPath); 134 } 135 136 // normalize_entry_path 137 static status_t 138 normalize_entry_path(const char *path, string &normalizedPath) 139 { 140 const char *dirPath = NULL; 141 const char *leafName = NULL; 142 143 string dirPathString; 144 if (char *lastSlash = strrchr(path, '/')) { 145 // found a slash: decompose into dir path and leaf name 146 leafName = lastSlash + 1; 147 if (leafName[0] == '\0') { 148 // slash is at the end: the whole path is a dir name 149 leafName = NULL; 150 } else { 151 dirPathString = string(path, leafName - path); 152 dirPath = dirPathString.c_str(); 153 } 154 155 } else { 156 // path contains no slash, so it is a path relative to the current dir 157 dirPath = "."; 158 leafName = path; 159 } 160 161 // catch special case: no leaf, or leaf is a directory 162 if (!leafName || strcmp(leafName, ".") == 0 || strcmp(leafName, "..")) 163 return normalize_dir_path(path, normalizedPath); 164 165 // normalize the dir path 166 status_t error = normalize_dir_path(dirPath, normalizedPath); 167 if (error != B_OK) 168 return error; 169 170 // append the leaf name 171 if (normalizedPath.length() > 1) // don't append "/", if parent is root 172 normalizedPath += '/'; 173 normalizedPath += leafName; 174 175 return B_OK; 176 } 177 178 179 // #pragma mark - 180 181 typedef map<NodeRef, string> DirPathMap; 182 static DirPathMap sDirPathMap; 183 184 // get_path 185 static status_t 186 get_path(const NodeRef *ref, const char *name, string &path) 187 { 188 if (!ref && !name) 189 return B_BAD_VALUE; 190 191 // no ref or absolute path 192 if (!ref || (name && name[0] == '/')) { 193 path = name; 194 return B_OK; 195 } 196 197 // get the dir path 198 if (ref) { 199 DirPathMap::iterator it = sDirPathMap.find(*ref); 200 if (it == sDirPathMap.end()) 201 return B_ENTRY_NOT_FOUND; 202 203 path = it->second; 204 205 // stat the path to check, if it is still valid 206 struct stat st; 207 if (lstat(path.c_str(), &st) < 0) { 208 sDirPathMap.erase(it); 209 return errno; 210 } 211 212 // compare the NodeRef 213 if (NodeRef(st) != *ref) { 214 sDirPathMap.erase(it); 215 return B_ENTRY_NOT_FOUND; 216 } 217 218 // still a directory? 219 if (!S_ISDIR(st.st_mode)) { 220 sDirPathMap.erase(it); 221 return B_NOT_A_DIRECTORY; 222 } 223 } 224 225 // if there's a name, append it 226 if (name) { 227 path += '/'; 228 path += name; 229 } 230 231 return B_OK; 232 } 233 234 // get_path 235 status_t 236 BPrivate::get_path(int fd, const char *name, string &path) 237 { 238 // get the node ref for the fd, if any, and the path part is not absolute 239 if (fd >= 0 && !(name && name[0] == '/')) { 240 // get descriptor 241 Descriptor *descriptor = get_descriptor(fd); 242 if (!descriptor) 243 return B_FILE_ERROR; 244 245 // get node ref for the descriptor 246 NodeRef ref; 247 status_t error = descriptor->GetNodeRef(ref); 248 if (error != B_OK) 249 return error; 250 251 return ::get_path(&ref, name, path); 252 253 } else // no descriptor or absolute path 254 return ::get_path((NodeRef*)NULL, name, path); 255 } 256 257 // get_path 258 static status_t 259 get_path(dev_t device, ino_t directory, const char *name, string &path) 260 { 261 NodeRef ref; 262 ref.device = device; 263 ref.node = directory; 264 265 return get_path(&ref, name, path); 266 } 267 268 // add_dir_path 269 static void 270 add_dir_path(const char *path, const NodeRef &ref) 271 { 272 // add the normalized path 273 string normalizedPath; 274 if (normalize_dir_path(path, normalizedPath) == B_OK) 275 sDirPathMap[ref] = normalizedPath; 276 } 277 278 279 // #pragma mark - 280 281 // _kern_entry_ref_to_path 282 status_t 283 _kern_entry_ref_to_path(dev_t device, ino_t node, const char *leaf, 284 char *userPath, size_t pathLength) 285 { 286 // get the path 287 string path; 288 status_t error = get_path(device, node, leaf, path); 289 if (error != B_OK) 290 return error; 291 292 // copy it back to the user buffer 293 if (strlcpy(userPath, path.c_str(), pathLength) >= pathLength) 294 return B_BUFFER_OVERFLOW; 295 296 return B_OK; 297 } 298 299 300 // #pragma mark - 301 302 // _kern_create_dir 303 status_t 304 _kern_create_dir(int fd, const char *path, int perms) 305 { 306 // get a usable path 307 string realPath; 308 status_t error = get_path(fd, path, realPath); 309 if (error != B_OK) 310 return error; 311 312 // mkdir 313 if (mkdir(realPath.c_str(), perms) < 0) 314 return errno; 315 316 return B_OK; 317 } 318 319 // _kern_create_dir_entry_ref 320 status_t 321 _kern_create_dir_entry_ref(dev_t device, ino_t node, const char *name, 322 int perms) 323 { 324 // get a usable path 325 string realPath; 326 status_t error = get_path(device, node, name, realPath); 327 if (error != B_OK) 328 return error; 329 330 // mkdir 331 if (mkdir(realPath.c_str(), perms) < 0) 332 return errno; 333 334 return B_OK; 335 } 336 337 // open_dir 338 static int 339 open_dir(const char *path) 340 { 341 // open the dir 342 DIR *dir = opendir(path); 343 if (!dir) 344 return errno; 345 346 // stat the entry 347 struct stat st; 348 if (stat(path, &st) < 0) { 349 closedir(dir); 350 return errno; 351 } 352 353 if (!S_ISDIR(st.st_mode)) { 354 closedir(dir); 355 return B_NOT_A_DIRECTORY; 356 } 357 358 // cache dir path 359 NodeRef ref(st); 360 add_dir_path(path, ref); 361 362 // create descriptor 363 DirectoryDescriptor *descriptor = new DirectoryDescriptor(dir, ref); 364 return add_descriptor(descriptor); 365 } 366 367 // _kern_open_dir 368 int 369 _kern_open_dir(int fd, const char *path) 370 { 371 // get a usable path 372 string realPath; 373 status_t error = get_path(fd, path, realPath); 374 if (error != B_OK) 375 return error; 376 377 return open_dir(realPath.c_str()); 378 } 379 380 // _kern_open_dir_entry_ref 381 int 382 _kern_open_dir_entry_ref(dev_t device, ino_t node, const char *name) 383 { 384 // get a usable path 385 string realPath; 386 status_t error = get_path(device, node, name, realPath); 387 if (error != B_OK) 388 return error; 389 390 return open_dir(realPath.c_str()); 391 } 392 393 // _kern_open_parent_dir 394 int 395 _kern_open_parent_dir(int fd, char *name, size_t nameLength) 396 { 397 // get a usable path 398 string realPath; 399 status_t error = get_path(fd, name, realPath); 400 if (error != B_OK) 401 return error; 402 403 // stat the entry 404 struct stat st; 405 if (stat(realPath.c_str(), &st) < 0) 406 return errno; 407 408 if (!S_ISDIR(st.st_mode)) 409 return B_NOT_A_DIRECTORY; 410 411 // get the entry name 412 realPath += "/.."; 413 string entryName; 414 error = find_dir_entry(realPath.c_str(), NodeRef(st), 415 entryName, false); 416 if (error != B_OK) 417 return error; 418 419 if (strlcpy(name, entryName.c_str(), nameLength) >= nameLength) 420 return B_BUFFER_OVERFLOW; 421 422 // open the parent directory 423 424 return open_dir(realPath.c_str()); 425 } 426 427 // _kern_read_dir 428 ssize_t 429 _kern_read_dir(int fd, struct dirent *buffer, size_t bufferSize, 430 uint32 maxCount) 431 { 432 if (maxCount <= 0) 433 return B_BAD_VALUE; 434 435 // get the descriptor 436 DirectoryDescriptor *descriptor 437 = dynamic_cast<DirectoryDescriptor*>(get_descriptor(fd)); 438 if (!descriptor) 439 return B_FILE_ERROR; 440 441 // get the next entry 442 dirent *entry; 443 if (dynamic_cast<AttrDirDescriptor*>(descriptor)) 444 entry = fs_read_attr_dir(descriptor->dir); 445 else 446 entry = readdir(descriptor->dir); 447 if (!entry) 448 return errno; 449 450 // copy the entry 451 int entryLen = &entry->d_name[strlen(entry->d_name) + 1] - (char*)entry; 452 if (entryLen > (int)bufferSize) 453 return B_BUFFER_OVERFLOW; 454 455 memcpy(buffer, entry, entryLen); 456 457 return 1; 458 } 459 460 // _kern_rewind_dir 461 status_t 462 _kern_rewind_dir(int fd) 463 { 464 // get the descriptor 465 DirectoryDescriptor *descriptor 466 = dynamic_cast<DirectoryDescriptor*>(get_descriptor(fd)); 467 if (!descriptor) 468 return B_FILE_ERROR; 469 470 // rewind 471 if (dynamic_cast<AttrDirDescriptor*>(descriptor)) 472 fs_rewind_attr_dir(descriptor->dir); 473 else 474 rewinddir(descriptor->dir); 475 476 return B_OK; 477 } 478 479 480 // #pragma mark - 481 482 // open_file 483 static int 484 open_file(const char *path, int openMode, int perms) 485 { 486 // stat the node 487 bool exists = true; 488 struct stat st; 489 if (lstat(path, &st) < 0) { 490 exists = false; 491 if (!(openMode & O_CREAT)) 492 return errno; 493 } 494 495 Descriptor *descriptor; 496 if (exists && S_ISLNK(st.st_mode) && (openMode & O_NOTRAVERSE)) { 497 // a symlink not to be followed: create a special descriptor 498 // normalize path first 499 string normalizedPath; 500 status_t error = normalize_entry_path(path, normalizedPath); 501 if (error != B_OK) 502 return error; 503 504 descriptor = new SymlinkDescriptor(normalizedPath.c_str()); 505 506 } else { 507 // open the file 508 openMode &= ~O_NOTRAVERSE; 509 int newFD = open(path, openMode, perms); 510 if (newFD < 0) 511 return errno; 512 513 descriptor = new FileDescriptor(newFD); 514 } 515 516 // cache path, if this is a directory 517 if (S_ISDIR(st.st_mode)) 518 add_dir_path(path, NodeRef(st)); 519 520 return add_descriptor(descriptor); 521 } 522 523 // _kern_open 524 int 525 _kern_open(int fd, const char *path, int openMode, int perms) 526 { 527 // get a usable path 528 string realPath; 529 status_t error = get_path(fd, path, realPath); 530 if (error != B_OK) 531 return error; 532 533 return open_file(realPath.c_str(), openMode, perms); 534 } 535 536 // _kern_open_entry_ref 537 int 538 _kern_open_entry_ref(dev_t device, ino_t node, const char *name, 539 int openMode, int perms) 540 { 541 // get a usable path 542 string realPath; 543 status_t error = get_path(device, node, name, realPath); 544 if (error != B_OK) 545 return error; 546 547 return open_file(realPath.c_str(), openMode, perms); 548 } 549 550 // _kern_seek 551 off_t 552 _kern_seek(int fd, off_t pos, int seekType) 553 { 554 // get the descriptor 555 FileDescriptor *descriptor 556 = dynamic_cast<FileDescriptor*>(get_descriptor(fd)); 557 if (!descriptor) 558 return B_FILE_ERROR; 559 560 // seek 561 off_t result = lseek(descriptor->fd, pos, seekType); 562 if (result < 0) 563 return errno; 564 565 return result; 566 } 567 568 // _kern_read 569 ssize_t 570 _kern_read(int fd, off_t pos, void *buffer, size_t bufferSize) 571 { 572 // get the descriptor 573 FileDescriptor *descriptor 574 = dynamic_cast<FileDescriptor*>(get_descriptor(fd)); 575 if (!descriptor) 576 return B_FILE_ERROR; 577 578 // seek 579 if (pos != -1) { 580 off_t result = lseek(descriptor->fd, pos, SEEK_SET); 581 if (result < 0) 582 return errno; 583 } 584 585 // read 586 ssize_t bytesRead = read(descriptor->fd, buffer, bufferSize); 587 if (bytesRead < 0) 588 return errno; 589 590 return bytesRead; 591 } 592 593 // _kern_write 594 ssize_t 595 _kern_write(int fd, off_t pos, const void *buffer, size_t bufferSize) 596 { 597 // get the descriptor 598 FileDescriptor *descriptor 599 = dynamic_cast<FileDescriptor*>(get_descriptor(fd)); 600 if (!descriptor) 601 return B_FILE_ERROR; 602 603 // seek 604 if (pos != -1) { 605 off_t result = lseek(descriptor->fd, pos, SEEK_SET); 606 if (result < 0) 607 return errno; 608 } 609 610 // read 611 ssize_t bytesWritten = write(descriptor->fd, buffer, bufferSize); 612 if (bytesWritten < 0) 613 return errno; 614 615 return bytesWritten; 616 } 617 618 // _kern_close 619 status_t 620 _kern_close(int fd) 621 { 622 return delete_descriptor(fd); 623 } 624 625 // _kern_dup 626 int 627 _kern_dup(int fd) 628 { 629 // get the descriptor 630 Descriptor *descriptor = get_descriptor(fd); 631 if (!descriptor) 632 return B_FILE_ERROR; 633 634 // clone it 635 Descriptor *clone; 636 status_t error = descriptor->Dup(clone); 637 if (error != B_OK) 638 return error; 639 640 return add_descriptor(clone); 641 } 642 643 // _kern_fsync 644 status_t 645 _kern_fsync(int fd) 646 { 647 // get the descriptor 648 FileDescriptor *descriptor 649 = dynamic_cast<FileDescriptor*>(get_descriptor(fd)); 650 if (!descriptor) 651 return B_FILE_ERROR; 652 653 // sync 654 if (fsync(descriptor->fd) < 0) 655 return errno; 656 657 return B_OK; 658 } 659 660 // _kern_read_stat 661 status_t 662 _kern_read_stat(int fd, const char *path, bool traverseLink, 663 struct stat *st, size_t statSize) 664 { 665 if (path) { 666 // get a usable path 667 string realPath; 668 status_t error = get_path(fd, path, realPath); 669 if (error != B_OK) 670 return error; 671 672 // stat 673 int result; 674 if (traverseLink) 675 result = stat(realPath.c_str(), st); 676 else 677 result = lstat(realPath.c_str(), st); 678 679 if (result < 0) 680 return errno; 681 } else { 682 Descriptor *descriptor = get_descriptor(fd); 683 if (!descriptor) 684 return B_FILE_ERROR; 685 686 return descriptor->GetStat(traverseLink, st); 687 } 688 689 return B_OK; 690 } 691 692 // _kern_write_stat 693 status_t 694 _kern_write_stat(int fd, const char *path, bool traverseLink, 695 const struct stat *st, size_t statSize, int statMask) 696 { 697 // get a usable path 698 int realFD = -1; 699 string realPath; 700 status_t error; 701 bool isSymlink = false; 702 if (path) { 703 error = get_path(fd, path, realPath); 704 if (error != B_OK) 705 return error; 706 707 // stat it to see, if it is a symlink 708 struct stat tmpStat; 709 if (lstat(realPath.c_str(), &tmpStat) < 0) 710 return errno; 711 712 isSymlink = S_ISLNK(tmpStat.st_mode); 713 714 } else { 715 Descriptor *descriptor = get_descriptor(fd); 716 if (!descriptor) 717 return B_FILE_ERROR; 718 719 if (FileDescriptor *fileFD 720 = dynamic_cast<FileDescriptor*>(descriptor)) { 721 realFD = fileFD->fd; 722 723 } else if (dynamic_cast<DirectoryDescriptor*>(descriptor)) { 724 error = get_path(fd, NULL, realPath); 725 if (error != B_OK) 726 return error; 727 728 } else if (SymlinkDescriptor *linkFD 729 = dynamic_cast<SymlinkDescriptor*>(descriptor)) { 730 realPath = linkFD->path; 731 isSymlink = true; 732 733 } else 734 return B_FILE_ERROR; 735 } 736 737 // We're screwed, if the node to manipulate is a symlink. All the 738 // available functions traverse symlinks. 739 if (isSymlink && !traverseLink) 740 return B_ERROR; 741 742 if (realFD >= 0) { 743 if (statMask & B_STAT_MODE) { 744 if (fchmod(realFD, st->st_mode) < 0) 745 return errno; 746 } 747 748 if (statMask & B_STAT_UID) { 749 if (fchown(realFD, st->st_uid, (gid_t)-1) < 0) 750 return errno; 751 } 752 753 if (statMask & B_STAT_GID) { 754 if (fchown(realFD, (uid_t)-1, st->st_gid) < 0) 755 return errno; 756 } 757 758 if (statMask & B_STAT_SIZE) { 759 if (ftruncate(realFD, st->st_size) < 0) 760 return errno; 761 } 762 763 // The timestamps can only be set via utime(), but that requires a 764 // path we don't have. 765 if (statMask & (B_STAT_ACCESS_TIME | B_STAT_MODIFICATION_TIME 766 | B_STAT_CREATION_TIME | B_STAT_CHANGE_TIME)) { 767 return B_ERROR; 768 } 769 770 return 0; 771 772 } else { 773 if (statMask & B_STAT_MODE) { 774 if (chmod(realPath.c_str(), st->st_mode) < 0) 775 return errno; 776 } 777 778 if (statMask & B_STAT_UID) { 779 if (chown(realPath.c_str(), st->st_uid, (gid_t)-1) < 0) 780 return errno; 781 } 782 783 if (statMask & B_STAT_GID) { 784 if (chown(realPath.c_str(), (uid_t)-1, st->st_gid) < 0) 785 return errno; 786 } 787 788 if (statMask & B_STAT_SIZE) { 789 if (truncate(realPath.c_str(), st->st_size) < 0) 790 return errno; 791 } 792 793 if (statMask & (B_STAT_ACCESS_TIME | B_STAT_MODIFICATION_TIME)) { 794 // Grab the previous mod and access times so we only overwrite 795 // the specified time and not both 796 struct stat oldStat; 797 if (~statMask & (B_STAT_ACCESS_TIME | B_STAT_MODIFICATION_TIME)) { 798 if (stat(realPath.c_str(), &oldStat) < 0) 799 return errno; 800 } 801 802 utimbuf buffer; 803 buffer.actime = (statMask & B_STAT_ACCESS_TIME) ? st->st_atime : oldStat.st_atime; 804 buffer.modtime = (statMask & B_STAT_MODIFICATION_TIME) ? st->st_mtime : oldStat.st_mtime; 805 if (utime(realPath.c_str(), &buffer) < 0) 806 return errno; 807 } 808 809 // not supported 810 if (statMask & (B_STAT_CREATION_TIME | B_STAT_CHANGE_TIME)) 811 return B_ERROR; 812 } 813 814 return B_OK; 815 } 816 817 818 // #pragma mark - 819 820 // _kern_create_symlink 821 status_t 822 _kern_create_symlink(int fd, const char *path, const char *toPath, int mode) 823 { 824 // Note: path must not be NULL, so this will always work. 825 // get a usable path 826 string realPath; 827 status_t error = get_path(fd, path, realPath); 828 if (error != B_OK) 829 return error; 830 831 // symlink 832 if (symlink(toPath, realPath.c_str()) < 0) 833 return errno; 834 835 return B_OK; 836 } 837 838 // _kern_read_link 839 status_t 840 _kern_read_link(int fd, const char *path, char *buffer, size_t *_bufferSize) 841 { 842 // get the descriptor 843 SymlinkDescriptor *descriptor 844 = dynamic_cast<SymlinkDescriptor*>(get_descriptor(fd)); 845 if (!descriptor) 846 return B_FILE_ERROR; 847 848 // readlink 849 ssize_t bytesRead = readlink(descriptor->path.c_str(), buffer, 850 *_bufferSize); 851 if (bytesRead < 0) 852 return errno; 853 854 if (*_bufferSize > 0) { 855 if ((size_t)bytesRead == *_bufferSize) 856 bytesRead--; 857 858 buffer[bytesRead] = '\0'; 859 } 860 861 *_bufferSize = bytesRead; 862 863 return B_OK; 864 } 865 866 // _kern_unlink 867 status_t 868 _kern_unlink(int fd, const char *path) 869 { 870 // get a usable path 871 string realPath; 872 status_t error = get_path(fd, path, realPath); 873 if (error != B_OK) 874 return error; 875 876 // unlink 877 if (unlink(realPath.c_str()) < 0) 878 return errno; 879 880 return B_OK; 881 } 882 883 // _kern_rename 884 status_t 885 _kern_rename(int oldDir, const char *oldPath, int newDir, const char *newPath) 886 { 887 // get usable paths 888 string realOldPath; 889 status_t error = get_path(oldDir, oldPath, realOldPath); 890 if (error != B_OK) 891 return error; 892 893 string realNewPath; 894 error = get_path(newDir, newPath, realNewPath); 895 if (error != B_OK) 896 return error; 897 898 // rename 899 if (rename(realOldPath.c_str(), realNewPath.c_str()) < 0) 900 return errno; 901 902 return B_OK; 903 } 904 905 906 // #pragma mark - 907 908 // _kern_lock_node 909 status_t 910 _kern_lock_node(int fd) 911 { 912 return B_ERROR; 913 } 914 915 // _kern_unlock_node 916 status_t 917 _kern_unlock_node(int fd) 918 { 919 return B_ERROR; 920 } 921 922 923 // #pragma mark - 924 925 // read_pos 926 ssize_t 927 read_pos(int fd, off_t pos, void *buffer, size_t bufferSize) 928 { 929 // seek 930 off_t result = lseek(fd, pos, SEEK_SET); 931 if (result < 0) 932 return errno; 933 934 // read 935 ssize_t bytesRead = read(fd, buffer, bufferSize); 936 if (bytesRead < 0) { 937 errno = bytesRead; 938 return -1; 939 } 940 941 return bytesRead; 942 } 943 944 // write_pos 945 ssize_t 946 write_pos(int fd, off_t pos, const void *buffer, size_t bufferSize) 947 { 948 // seek 949 off_t result = lseek(fd, pos, SEEK_SET); 950 if (result < 0) 951 return errno; 952 953 // read 954 ssize_t bytesWritten = write(fd, buffer, bufferSize); 955 if (bytesWritten < 0) { 956 errno = bytesWritten; 957 return -1; 958 } 959 960 return bytesWritten; 961 } 962 963 // readv_pos 964 ssize_t 965 readv_pos(int fd, off_t pos, const struct iovec *vec, size_t count) 966 { 967 // seek 968 off_t result = lseek(fd, pos, SEEK_SET); 969 if (result < 0) 970 return errno; 971 972 // read 973 ssize_t bytesRead = readv(fd, vec, count); 974 if (bytesRead < 0) { 975 errno = bytesRead; 976 return -1; 977 } 978 979 return bytesRead; 980 } 981 982 // writev_pos 983 ssize_t 984 writev_pos(int fd, off_t pos, const struct iovec *vec, size_t count) 985 { 986 // seek 987 off_t result = lseek(fd, pos, SEEK_SET); 988 if (result < 0) 989 return errno; 990 991 // read 992 ssize_t bytesWritten = writev(fd, vec, count); 993 if (bytesWritten < 0) { 994 errno = bytesWritten; 995 return -1; 996 } 997 998 return bytesWritten; 999 } 1000