1 /* 2 * Copyright 2002-2009, Haiku Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Tyler Dauwalder 7 * Ingo Weinhold, bonefish@users.sf.net 8 */ 9 10 11 /*! 12 \file Node.cpp 13 BNode implementation. 14 */ 15 16 #include <Node.h> 17 18 #include <errno.h> 19 #include <fcntl.h> 20 #include <new> 21 #include <string.h> 22 #include <unistd.h> 23 24 #include <compat/sys/stat.h> 25 26 #include <Directory.h> 27 #include <Entry.h> 28 #include <fs_attr.h> 29 #include <String.h> 30 #include <TypeConstants.h> 31 32 #include <syscalls.h> 33 34 #include "storage_support.h" 35 36 37 // #pragma mark - node_ref 38 39 40 /*! \brief Creates an uninitialized node_ref object. 41 */ 42 node_ref::node_ref() 43 : device((dev_t)-1), 44 node((ino_t)-1) 45 { 46 } 47 48 // copy constructor 49 /*! \brief Creates a copy of the given node_ref object. 50 \param ref the node_ref to be copied 51 */ 52 node_ref::node_ref(const node_ref &ref) 53 : device((dev_t)-1), 54 node((ino_t)-1) 55 { 56 *this = ref; 57 } 58 59 // == 60 /*! \brief Tests whether this node_ref and the supplied one are equal. 61 \param ref the node_ref to be compared with 62 \return \c true, if the objects are equal, \c false otherwise 63 */ 64 bool 65 node_ref::operator==(const node_ref &ref) const 66 { 67 return (device == ref.device && node == ref.node); 68 } 69 70 // != 71 /*! \brief Tests whether this node_ref and the supplied one are not equal. 72 \param ref the node_ref to be compared with 73 \return \c false, if the objects are equal, \c true otherwise 74 */ 75 bool 76 node_ref::operator!=(const node_ref &ref) const 77 { 78 return !(*this == ref); 79 } 80 81 // = 82 /*! \brief Makes this node ref a copy of the supplied one. 83 \param ref the node_ref to be copied 84 \return a reference to this object 85 */ 86 node_ref& 87 node_ref::operator=(const node_ref &ref) 88 { 89 device = ref.device; 90 node = ref.node; 91 return *this; 92 } 93 94 95 // #pragma mark - BNode 96 97 98 /*! \brief Creates an uninitialized BNode object 99 */ 100 BNode::BNode() 101 : fFd(-1), 102 fAttrFd(-1), 103 fCStatus(B_NO_INIT) 104 { 105 } 106 107 108 /*! \brief Creates a BNode object and initializes it to the specified 109 entry_ref. 110 \param ref the entry_ref referring to the entry 111 */ 112 BNode::BNode(const entry_ref *ref) 113 : fFd(-1), 114 fAttrFd(-1), 115 fCStatus(B_NO_INIT) 116 { 117 SetTo(ref); 118 } 119 120 121 /*! \brief Creates a BNode object and initializes it to the specified 122 filesystem entry. 123 \param entry the BEntry representing the entry 124 */ 125 BNode::BNode(const BEntry *entry) 126 : fFd(-1), 127 fAttrFd(-1), 128 fCStatus(B_NO_INIT) 129 { 130 SetTo(entry); 131 } 132 133 134 /*! \brief Creates a BNode object and initializes it to the entry referred 135 to by the specified path. 136 \param path the path referring to the entry 137 */ 138 BNode::BNode(const char *path) 139 : fFd(-1), 140 fAttrFd(-1), 141 fCStatus(B_NO_INIT) 142 { 143 SetTo(path); 144 } 145 146 147 /*! \brief Creates a BNode object and initializes it to the entry referred 148 to by the specified path rooted in the specified directory. 149 \param dir the BDirectory, relative to which the entry's path name is 150 given 151 \param path the entry's path name relative to \a dir 152 */ 153 BNode::BNode(const BDirectory *dir, const char *path) 154 : fFd(-1), 155 fAttrFd(-1), 156 fCStatus(B_NO_INIT) 157 { 158 SetTo(dir, path); 159 } 160 161 162 /*! \brief Creates a copy of the given BNode. 163 \param node the BNode to be copied 164 */ 165 BNode::BNode(const BNode &node) 166 : fFd(-1), 167 fAttrFd(-1), 168 fCStatus(B_NO_INIT) 169 { 170 *this = node; 171 } 172 173 174 /*! \brief Frees all resources associated with the BNode. 175 */ 176 BNode::~BNode() 177 { 178 Unset(); 179 } 180 181 182 /*! \brief Checks whether the object has been properly initialized or not. 183 \return 184 - \c B_OK, if the object has been properly initialized, 185 - an error code, otherwise. 186 */ 187 status_t 188 BNode::InitCheck() const 189 { 190 return fCStatus; 191 } 192 193 194 /*! \fn status_t BNode::GetStat(struct stat *st) const 195 \brief Fills in the given stat structure with \code stat() \endcode 196 information for this object. 197 \param st a pointer to a stat structure to be filled in 198 \return 199 - \c B_OK: Everything went fine. 200 - \c B_BAD_VALUE: \c NULL \a st. 201 - another error code, e.g., if the object wasn't properly initialized 202 */ 203 204 205 /*! \brief Reinitializes the object to the specified entry_ref. 206 \param ref the entry_ref referring to the entry 207 \return 208 - \c B_OK: Everything went fine. 209 - \c B_BAD_VALUE: \c NULL \a ref. 210 - \c B_ENTRY_NOT_FOUND: The entry could not be found. 211 - \c B_BUSY: The entry is locked. 212 */ 213 status_t 214 BNode::SetTo(const entry_ref *ref) 215 { 216 return _SetTo(ref, false); 217 } 218 219 220 /*! \brief Reinitializes the object to the specified filesystem entry. 221 \param entry the BEntry representing the entry 222 \return 223 - \c B_OK: Everything went fine. 224 - \c B_BAD_VALUE: \c NULL \a entry. 225 - \c B_ENTRY_NOT_FOUND: The entry could not be found. 226 - \c B_BUSY: The entry is locked. 227 */ 228 status_t 229 BNode::SetTo(const BEntry *entry) 230 { 231 if (!entry) { 232 Unset(); 233 return (fCStatus = B_BAD_VALUE); 234 } 235 return _SetTo(entry->fDirFd, entry->fName, false); 236 } 237 238 239 /*! \brief Reinitializes the object to the entry referred to by the specified 240 path. 241 \param path the path referring to the entry 242 \return 243 - \c B_OK: Everything went fine. 244 - \c B_BAD_VALUE: \c NULL \a path. 245 - \c B_ENTRY_NOT_FOUND: The entry could not be found. 246 - \c B_BUSY: The entry is locked. 247 */ 248 status_t 249 BNode::SetTo(const char *path) 250 { 251 return _SetTo(-1, path, false); 252 } 253 254 255 /*! \brief Reinitializes the object to the entry referred to by the specified 256 path rooted in the specified directory. 257 \param dir the BDirectory, relative to which the entry's path name is 258 given 259 \param path the entry's path name relative to \a dir 260 \return 261 - \c B_OK: Everything went fine. 262 - \c B_BAD_VALUE: \c NULL \a dir or \a path. 263 - \c B_ENTRY_NOT_FOUND: The entry could not be found. 264 - \c B_BUSY: The entry is locked. 265 */ 266 status_t 267 BNode::SetTo(const BDirectory *dir, const char *path) 268 { 269 if (!dir || !path || BPrivate::Storage::is_absolute_path(path)) { 270 Unset(); 271 return (fCStatus = B_BAD_VALUE); 272 } 273 return _SetTo(dir->fDirFd, path, false); 274 } 275 276 277 /*! \brief Returns the object to an uninitialized state. 278 */ 279 void 280 BNode::Unset() 281 { 282 close_fd(); 283 fCStatus = B_NO_INIT; 284 } 285 286 287 /*! \brief Attains an exclusive lock on the data referred to by this node, so 288 that it may not be modified by any other objects or methods. 289 \return 290 - \c B_OK: Everything went fine. 291 - \c B_FILE_ERROR: The object is not initialized. 292 - \c B_BUSY: The node is already locked. 293 */ 294 status_t 295 BNode::Lock() 296 { 297 if (fCStatus != B_OK) 298 return fCStatus; 299 return _kern_lock_node(fFd); 300 } 301 302 303 /*! \brief Unlocks the node. 304 \return 305 - \c B_OK: Everything went fine. 306 - \c B_FILE_ERROR: The object is not initialized. 307 - \c B_BAD_VALUE: The node is not locked. 308 */ 309 status_t 310 BNode::Unlock() 311 { 312 if (fCStatus != B_OK) 313 return fCStatus; 314 return _kern_unlock_node(fFd); 315 } 316 317 318 /*! \brief Immediately performs any pending disk actions on the node. 319 \return 320 - \c B_OK: Everything went fine. 321 - an error code, if something went wrong. 322 */ 323 status_t 324 BNode::Sync() 325 { 326 return (fCStatus != B_OK) ? B_FILE_ERROR : _kern_fsync(fFd); 327 } 328 329 330 /*! \brief Writes data from a buffer to an attribute. 331 Write the \a len bytes of data from \a buffer to 332 the attribute specified by \a name after erasing any data 333 that existed previously. The type specified by \a type \em is 334 remembered, and may be queried with GetAttrInfo(). The value of 335 \a offset is currently ignored. 336 \param attr the name of the attribute 337 \param type the type of the attribute 338 \param offset the index at which to write the data (currently ignored) 339 \param buffer the buffer containing the data to be written 340 \param len the number of bytes to be written 341 \return 342 - the number of bytes actually written 343 - \c B_BAD_VALUE: \c NULL \a attr or \a buffer 344 - \c B_FILE_ERROR: The object is not initialized or the node it refers to 345 is read only. 346 - \c B_NOT_ALLOWED: The node resides on a read only volume. 347 - \c B_DEVICE_FULL: Insufficient disk space. 348 - \c B_NO_MEMORY: Insufficient memory to complete the operation. 349 */ 350 ssize_t 351 BNode::WriteAttr(const char *attr, type_code type, off_t offset, 352 const void *buffer, size_t len) 353 { 354 if (fCStatus != B_OK) 355 return B_FILE_ERROR; 356 if (!attr || !buffer) 357 return B_BAD_VALUE; 358 359 ssize_t result = fs_write_attr(fFd, attr, type, offset, buffer, len); 360 return result < 0 ? errno : result; 361 } 362 363 364 /*! \brief Reads data from an attribute into a buffer. 365 Reads the data of the attribute given by \a name into 366 the buffer specified by \a buffer with length specified 367 by \a len. \a type and \a offset are currently ignored. 368 \param attr the name of the attribute 369 \param type the type of the attribute (currently ignored) 370 \param offset the index from which to read the data (currently ignored) 371 \param buffer the buffer for the data to be read 372 \param len the number of bytes to be read 373 \return 374 - the number of bytes actually read 375 - \c B_BAD_VALUE: \c NULL \a attr or \a buffer 376 - \c B_FILE_ERROR: The object is not initialized. 377 - \c B_ENTRY_NOT_FOUND: The node has no attribute \a attr. 378 */ 379 ssize_t 380 BNode::ReadAttr(const char *attr, type_code type, off_t offset, 381 void *buffer, size_t len) const 382 { 383 if (fCStatus != B_OK) 384 return B_FILE_ERROR; 385 if (!attr || !buffer) 386 return B_BAD_VALUE; 387 388 ssize_t result = fs_read_attr(fFd, attr, type, offset, buffer, len ); 389 return result == -1 ? errno : result; 390 } 391 392 393 /*! \brief Deletes the attribute given by \a name. 394 \param name the name of the attribute 395 - \c B_OK: Everything went fine. 396 - \c B_BAD_VALUE: \c NULL \a name 397 - \c B_FILE_ERROR: The object is not initialized or the node it refers to 398 is read only. 399 - \c B_ENTRY_NOT_FOUND: The node has no attribute \a name. 400 - \c B_NOT_ALLOWED: The node resides on a read only volume. 401 */ 402 status_t 403 BNode::RemoveAttr(const char *name) 404 { 405 return fCStatus != B_OK ? B_FILE_ERROR : _kern_remove_attr(fFd, name); 406 } 407 408 409 /*! \brief Moves the attribute given by \a oldname to \a newname. 410 If \a newname already exists, the current data is clobbered. 411 \param oldname the name of the attribute to be renamed 412 \param newname the new name for the attribute 413 \return 414 - \c B_OK: Everything went fine. 415 - \c B_BAD_VALUE: \c NULL \a oldname or \a newname 416 - \c B_FILE_ERROR: The object is not initialized or the node it refers to 417 is read only. 418 - \c B_ENTRY_NOT_FOUND: The node has no attribute \a oldname. 419 - \c B_NOT_ALLOWED: The node resides on a read only volume. 420 */ 421 status_t 422 BNode::RenameAttr(const char *oldname, const char *newname) 423 { 424 if (fCStatus != B_OK) 425 return B_FILE_ERROR; 426 427 return _kern_rename_attr(fFd, oldname, fFd, newname); 428 } 429 430 431 /*! \brief Fills in the pre-allocated attr_info struct pointed to by \a info 432 with useful information about the attribute specified by \a name. 433 \param name the name of the attribute 434 \param info the attr_info structure to be filled in 435 \return 436 - \c B_OK: Everything went fine. 437 - \c B_BAD_VALUE: \c NULL \a name 438 - \c B_FILE_ERROR: The object is not initialized. 439 - \c B_ENTRY_NOT_FOUND: The node has no attribute \a name. 440 */ 441 status_t 442 BNode::GetAttrInfo(const char *name, struct attr_info *info) const 443 { 444 if (fCStatus != B_OK) 445 return B_FILE_ERROR; 446 if (!name || !info) 447 return B_BAD_VALUE; 448 449 return fs_stat_attr(fFd, name, info) < 0 ? errno : B_OK ; 450 } 451 452 453 /*! \brief Returns the next attribute in the node's list of attributes. 454 Every BNode maintains a pointer to its list of attributes. 455 GetNextAttrName() retrieves the name of the attribute that the pointer is 456 currently pointing to, and then bumps the pointer to the next attribute. 457 The name is copied into the buffer, which should be at least 458 B_ATTR_NAME_LENGTH characters long. The copied name is NULL-terminated. 459 When you've asked for every name in the list, GetNextAttrName() 460 returns \c B_ENTRY_NOT_FOUND. 461 \param buffer the buffer the name of the next attribute shall be stored in 462 (must be at least \c B_ATTR_NAME_LENGTH bytes long) 463 \return 464 - \c B_OK: Everything went fine. 465 - \c B_BAD_VALUE: \c NULL \a buffer. 466 - \c B_FILE_ERROR: The object is not initialized. 467 - \c B_ENTRY_NOT_FOUND: There are no more attributes, the last attribute 468 name has already been returned. 469 */ 470 status_t 471 BNode::GetNextAttrName(char *buffer) 472 { 473 // We're allowed to assume buffer is at least 474 // B_ATTR_NAME_LENGTH chars long, but NULLs 475 // are not acceptable. 476 if (buffer == NULL) 477 return B_BAD_VALUE; // /new R5 crashed when passed NULL 478 if (InitAttrDir() != B_OK) 479 return B_FILE_ERROR; 480 481 BPrivate::Storage::LongDirEntry entry; 482 ssize_t result = _kern_read_dir(fAttrFd, &entry, sizeof(entry), 1); 483 if (result < 0) 484 return result; 485 if (result == 0) 486 return B_ENTRY_NOT_FOUND; 487 strlcpy(buffer, entry.d_name, B_ATTR_NAME_LENGTH); 488 return B_OK; 489 } 490 491 492 /*! \brief Resets the object's attribute pointer to the first attribute in the 493 list. 494 \return 495 - \c B_OK: Everything went fine. 496 - \c B_FILE_ERROR: Some error occured. 497 */ 498 status_t 499 BNode::RewindAttrs() 500 { 501 if (InitAttrDir() != B_OK) 502 return B_FILE_ERROR; 503 504 return _kern_rewind_dir(fAttrFd); 505 } 506 507 508 /*! Writes the specified string to the specified attribute, clobbering any 509 previous data. 510 \param name the name of the attribute 511 \param data the BString to be written to the attribute 512 - \c B_OK: Everything went fine. 513 - \c B_BAD_VALUE: \c NULL \a name or \a data 514 - \c B_FILE_ERROR: The object is not initialized or the node it refers to 515 is read only. 516 - \c B_NOT_ALLOWED: The node resides on a read only volume. 517 - \c B_DEVICE_FULL: Insufficient disk space. 518 - \c B_NO_MEMORY: Insufficient memory to complete the operation. 519 */ 520 status_t 521 BNode::WriteAttrString(const char *name, const BString *data) 522 { 523 status_t error = (!name || !data) ? B_BAD_VALUE : B_OK; 524 if (error == B_OK) { 525 int32 len = data->Length() + 1; 526 ssize_t sizeWritten = WriteAttr(name, B_STRING_TYPE, 0, data->String(), 527 len); 528 if (sizeWritten != len) 529 error = sizeWritten; 530 } 531 return error; 532 } 533 534 535 /*! \brief Reads the data of the specified attribute into the pre-allocated 536 \a result. 537 \param name the name of the attribute 538 \param result the BString to be set to the value of the attribute 539 \return 540 - \c B_OK: Everything went fine. 541 - \c B_BAD_VALUE: \c NULL \a name or \a result 542 - \c B_FILE_ERROR: The object is not initialized. 543 - \c B_ENTRY_NOT_FOUND: The node has no attribute \a attr. 544 */ 545 status_t 546 BNode::ReadAttrString(const char *name, BString *result) const 547 { 548 if (!name || !result) 549 return B_BAD_VALUE; 550 551 attr_info info; 552 status_t error; 553 554 error = GetAttrInfo(name, &info); 555 if (error != B_OK) 556 return error; 557 558 // Lock the string's buffer so we can meddle with it 559 char *data = result->LockBuffer(info.size + 1); 560 if (!data) 561 return B_NO_MEMORY; 562 563 // Read the attribute 564 ssize_t bytes = ReadAttr(name, B_STRING_TYPE, 0, data, info.size); 565 // Check for failure 566 if (bytes < 0) { 567 error = bytes; 568 bytes = 0; // In this instance, we simply clear the string 569 } else 570 error = B_OK; 571 572 // Null terminate the new string just to be sure (since it *is* 573 // possible to read and write non-NULL-terminated strings) 574 data[bytes] = 0; 575 result->UnlockBuffer(); 576 return error; 577 } 578 579 580 /*! \brief Reinitializes the object as a copy of the \a node. 581 \param node the BNode to be copied 582 \return a reference to this BNode object. 583 */ 584 BNode& 585 BNode::operator=(const BNode &node) 586 { 587 // No need to do any assignment if already equal 588 if (*this == node) 589 return *this; 590 591 // Close down out current state 592 Unset(); 593 // We have to manually dup the node, because R5::BNode::Dup() 594 // is not declared to be const (which IMO is retarded). 595 fFd = _kern_dup(node.fFd); 596 fCStatus = (fFd < 0) ? B_NO_INIT : B_OK ; 597 return *this; 598 } 599 600 601 /*! Tests whether this and the supplied BNode object are equal. 602 Two BNode objects are said to be equal if they're set to the same node, 603 or if they're both \c B_NO_INIT. 604 \param node the BNode to be compared with 605 \return \c true, if the BNode objects are equal, \c false otherwise 606 */ 607 bool 608 BNode::operator==(const BNode &node) const 609 { 610 if (fCStatus == B_NO_INIT && node.InitCheck() == B_NO_INIT) 611 return true; 612 if (fCStatus == B_OK && node.InitCheck() == B_OK) { 613 // compare the node_refs 614 node_ref ref1, ref2; 615 if (GetNodeRef(&ref1) != B_OK) 616 return false; 617 if (node.GetNodeRef(&ref2) != B_OK) 618 return false; 619 return (ref1 == ref2); 620 } 621 return false; 622 } 623 624 625 /*! Tests whether this and the supplied BNode object are not equal. 626 Two BNode objects are said to be equal if they're set to the same node, 627 or if they're both \c B_NO_INIT. 628 \param node the BNode to be compared with 629 \return \c false, if the BNode objects are equal, \c true otherwise 630 */ 631 bool 632 BNode::operator!=(const BNode &node) const 633 { 634 return !(*this == node); 635 } 636 637 638 /*! \brief Returns a POSIX file descriptor to the node this object refers to. 639 Remember to call close() on the file descriptor when you're through with 640 it. 641 \return a valid file descriptor, or -1, if something went wrong. 642 */ 643 int 644 BNode::Dup() 645 { 646 int fd = _kern_dup(fFd); 647 return (fd >= 0 ? fd : -1); // comply with R5 return value 648 } 649 650 651 /*! (currently unused) */ 652 void BNode::_RudeNode1() { } 653 void BNode::_RudeNode2() { } 654 void BNode::_RudeNode3() { } 655 void BNode::_RudeNode4() { } 656 void BNode::_RudeNode5() { } 657 void BNode::_RudeNode6() { } 658 659 660 /*! \brief Sets the node's file descriptor. 661 Used by each implementation (i.e. BNode, BFile, BDirectory, etc.) to set 662 the node's file descriptor. This allows each subclass to use the various 663 file-type specific system calls for opening file descriptors. 664 \param fd the file descriptor this BNode should be set to (may be -1) 665 \return \c B_OK, if everything went fine, an error code otherwise. 666 \note This method calls close_fd() to close previously opened FDs. Thus 667 derived classes should take care to first call set_fd() and set 668 class specific resources freed in their close_fd() version 669 thereafter. 670 */ 671 status_t 672 BNode::set_fd(int fd) 673 { 674 if (fFd != -1) 675 close_fd(); 676 fFd = fd; 677 return B_OK; 678 } 679 680 681 /*! \brief Closes the node's file descriptor(s). 682 To be implemented by subclasses to close the file descriptor using the 683 proper system call for the given file-type. This implementation calls 684 _kern_close(fFd) and also _kern_close(fAttrDir) if necessary. 685 */ 686 void 687 BNode::close_fd() 688 { 689 if (fAttrFd >= 0) { 690 _kern_close(fAttrFd); 691 fAttrFd = -1; 692 } 693 if (fFd >= 0) { 694 _kern_close(fFd); 695 fFd = -1; 696 } 697 } 698 699 700 /*! \brief Sets the BNode's status. 701 To be used by derived classes instead of accessing the BNode's private 702 \c fCStatus member directly. 703 \param newStatus the new value for the status variable. 704 */ 705 void 706 BNode::set_status(status_t newStatus) 707 { 708 fCStatus = newStatus; 709 } 710 711 712 /*! \brief Initializes the BNode's file descriptor to the node referred to 713 by the given FD and path combo. 714 715 \a path must either be \c NULL, an absolute or a relative path. 716 In the first case, \a fd must not be \c NULL; the node it refers to will 717 be opened. If absolute, \a fd is ignored. If relative and \a fd is >= 0, 718 it will be reckoned off the directory identified by \a fd, otherwise off 719 the current working directory. 720 721 The method will first try to open the node with read and write permission. 722 If that fails due to a read-only FS or because the user has no write 723 permission for the node, it will re-try opening the node read-only. 724 725 The \a fCStatus member will be set to the return value of this method. 726 727 \param fd Either a directory FD or a value < 0. In the latter case \a path 728 must be specified. 729 \param path Either \a NULL in which case \a fd must be given, absolute, or 730 relative to the directory specified by \a fd (if given) or to the 731 current working directory. 732 \param traverse If the node identified by \a fd and \a path is a symlink 733 and \a traverse is \c true, the symlink will be resolved recursively. 734 \return \c B_OK, if everything went fine, another error code otherwise. 735 */ 736 status_t 737 BNode::_SetTo(int fd, const char *path, bool traverse) 738 { 739 Unset(); 740 status_t error = (fd >= 0 || path ? B_OK : B_BAD_VALUE); 741 if (error == B_OK) { 742 int traverseFlag = (traverse ? 0 : O_NOTRAVERSE); 743 fFd = _kern_open(fd, path, O_RDWR | O_CLOEXEC | traverseFlag, 0); 744 if (fFd < B_OK && fFd != B_ENTRY_NOT_FOUND) { 745 // opening read-write failed, re-try read-only 746 fFd = _kern_open(fd, path, O_RDONLY | O_CLOEXEC | traverseFlag, 0); 747 } 748 if (fFd < 0) 749 error = fFd; 750 } 751 return fCStatus = error; 752 } 753 754 755 /*! \brief Initializes the BNode's file descriptor to the node referred to 756 by the given entry_ref. 757 758 The method will first try to open the node with read and write permission. 759 If that fails due to a read-only FS or because the user has no write 760 permission for the node, it will re-try opening the node read-only. 761 762 The \a fCStatus member will be set to the return value of this method. 763 764 \param ref An entry_ref identifying the node to be opened. 765 \param traverse If the node identified by \a ref is a symlink 766 and \a traverse is \c true, the symlink will be resolved recursively. 767 \return \c B_OK, if everything went fine, another error code otherwise. 768 */ 769 status_t 770 BNode::_SetTo(const entry_ref *ref, bool traverse) 771 { 772 Unset(); 773 status_t error = (ref ? B_OK : B_BAD_VALUE); 774 if (error == B_OK) { 775 int traverseFlag = (traverse ? 0 : O_NOTRAVERSE); 776 fFd = _kern_open_entry_ref(ref->device, ref->directory, ref->name, 777 O_RDWR | O_CLOEXEC | traverseFlag, 0); 778 if (fFd < B_OK && fFd != B_ENTRY_NOT_FOUND) { 779 // opening read-write failed, re-try read-only 780 fFd = _kern_open_entry_ref(ref->device, ref->directory, ref->name, 781 O_RDONLY | O_CLOEXEC | traverseFlag, 0); 782 } 783 if (fFd < 0) 784 error = fFd; 785 } 786 return fCStatus = error; 787 } 788 789 790 /*! \brief Modifies a certain setting for this node based on \a what and the 791 corresponding value in \a st. 792 Inherited from and called by BStatable. 793 \param st a stat structure containing the value to be set 794 \param what specifies what setting to be modified 795 \return \c B_OK if everything went fine, an error code otherwise. 796 */ 797 status_t 798 BNode::set_stat(struct stat &st, uint32 what) 799 { 800 if (fCStatus != B_OK) 801 return B_FILE_ERROR; 802 803 return _kern_write_stat(fFd, NULL, false, &st, sizeof(struct stat), 804 what); 805 } 806 807 808 /*! \brief Verifies that the BNode has been properly initialized, and then 809 (if necessary) opens the attribute directory on the node's file 810 descriptor, storing it in fAttrDir. 811 \return \c B_OK if everything went fine, an error code otherwise. 812 */ 813 status_t 814 BNode::InitAttrDir() 815 { 816 if (fCStatus == B_OK && fAttrFd < 0) { 817 fAttrFd = _kern_open_attr_dir(fFd, NULL); 818 if (fAttrFd < 0) 819 return fAttrFd; 820 821 // set close on exec flag 822 fcntl(fAttrFd, F_SETFD, FD_CLOEXEC); 823 } 824 return fCStatus; 825 } 826 827 828 status_t 829 BNode::_GetStat(struct stat *st) const 830 { 831 return fCStatus != B_OK 832 ? fCStatus 833 : _kern_read_stat(fFd, NULL, false, st, sizeof(struct stat)); 834 } 835 836 837 status_t 838 BNode::_GetStat(struct stat_beos *st) const 839 { 840 struct stat newStat; 841 status_t error = _GetStat(&newStat); 842 if (error != B_OK) 843 return error; 844 845 convert_to_stat_beos(&newStat, st); 846 return B_OK; 847 } 848 849 850 /*! \var BNode::fFd 851 File descriptor for the given node. 852 */ 853 854 /*! \var BNode::fAttrFd 855 File descriptor for the attribute directory of the node. Initialized lazily. 856 */ 857 858 /*! \var BNode::fCStatus 859 The object's initialization status. 860 */ 861 862 863 // #pragma mark - symbol versions 864 865 866 #ifdef HAIKU_TARGET_PLATFORM_LIBBE_TEST 867 # if __GNUC__ == 2 // gcc 2 868 869 B_DEFINE_SYMBOL_VERSION("_GetStat__C5BNodeP4stat", 870 "GetStat__C5BNodeP4stat@@LIBBE_TEST"); 871 872 # else // gcc 4 873 874 B_DEFINE_SYMBOL_VERSION("_ZNK5BNode8_GetStatEP4stat", 875 "_ZNK5BNode7GetStatEP4stat@@LIBBE_TEST"); 876 877 # endif // gcc 4 878 #else // !HAIKU_TARGET_PLATFORM_LIBBE_TEST 879 # if __GNUC__ == 2 // gcc 2 880 881 // BeOS compatible GetStat() 882 B_DEFINE_SYMBOL_VERSION("_GetStat__C5BNodeP9stat_beos", 883 "GetStat__C5BNodeP4stat@LIBBE_BASE"); 884 885 // Haiku GetStat() 886 B_DEFINE_SYMBOL_VERSION("_GetStat__C5BNodeP4stat", 887 "GetStat__C5BNodeP4stat@@LIBBE_1_ALPHA1"); 888 889 # else // gcc 4 890 891 // BeOS compatible GetStat() 892 B_DEFINE_SYMBOL_VERSION("_ZNK5BNode8_GetStatEP9stat_beos", 893 "_ZNK5BNode7GetStatEP4stat@LIBBE_BASE"); 894 895 // Haiku GetStat() 896 B_DEFINE_SYMBOL_VERSION("_ZNK5BNode8_GetStatEP4stat", 897 "_ZNK5BNode7GetStatEP4stat@@LIBBE_1_ALPHA1"); 898 899 # endif // gcc 4 900 #endif // !HAIKU_TARGET_PLATFORM_LIBBE_TEST 901