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