1 //---------------------------------------------------------------------- 2 // This software is part of the OpenBeOS distribution and is covered 3 // by the OpenBeOS license. 4 //---------------------------------------------------------------------- 5 /*! 6 \file Node.cpp 7 BNode implementation. 8 */ 9 10 #include <fs_attr.h> // for struct attr_info 11 #include <new> 12 #include <string.h> 13 #include <unistd.h> 14 15 #include <Node.h> 16 #include <Entry.h> 17 18 #include "kernel_interface.h" 19 #include "storage_support.h" 20 21 //---------------------------------------------------------------------- 22 // node_ref 23 //---------------------------------------------------------------------- 24 25 // constructor 26 /*! \brief Creates an uninitialized node_ref object. 27 */ 28 node_ref::node_ref() 29 : device(-1), 30 node(-1) 31 { 32 } 33 34 // copy constructor 35 /*! \brief Creates a copy of the given node_ref object. 36 \param ref the node_ref to be copied 37 */ 38 node_ref::node_ref(const node_ref &ref) 39 : device(-1), 40 node(-1) 41 { 42 *this = ref; 43 } 44 45 // == 46 /*! \brief Tests whether this node_ref and the supplied one are equal. 47 \param ref the node_ref to be compared with 48 \return \c true, if the objects are equal, \c false otherwise 49 */ 50 bool 51 node_ref::operator==(const node_ref &ref) const 52 { 53 return (device == ref.device && node == ref.node); 54 } 55 56 // != 57 /*! \brief Tests whether this node_ref and the supplied one are not equal. 58 \param ref the node_ref to be compared with 59 \return \c false, if the objects are equal, \c true otherwise 60 */ 61 bool 62 node_ref::operator!=(const node_ref &ref) const 63 { 64 return !(*this == ref); 65 } 66 67 // = 68 /*! \brief Makes this node ref a copy of the supplied one. 69 \param ref the node_ref to be copied 70 \return a reference to this object 71 */ 72 node_ref& 73 node_ref::operator=(const node_ref &ref) 74 { 75 device = ref.device; 76 node = ref.node; 77 return *this; 78 } 79 80 //---------------------------------------------------------------------- 81 // BNode 82 //---------------------------------------------------------------------- 83 84 /*! \brief Creates an uninitialized BNode object 85 */ 86 BNode::BNode() 87 : fFd(BPrivate::Storage::NullFd), 88 fAttrFd(BPrivate::Storage::NullFd), 89 fCStatus(B_NO_INIT) 90 { 91 } 92 93 /*! \brief Creates a BNode object and initializes it to the specified 94 entry_ref. 95 \param ref the entry_ref referring to the entry 96 */ 97 BNode::BNode(const entry_ref *ref) 98 : fFd(BPrivate::Storage::NullFd), 99 fAttrFd(BPrivate::Storage::NullFd), 100 fCStatus(B_NO_INIT) 101 { 102 SetTo(ref); 103 } 104 105 /*! \brief Creates a BNode object and initializes it to the specified 106 filesystem entry. 107 \param entry the BEntry representing the entry 108 */ 109 BNode::BNode(const BEntry *entry) 110 : fFd(BPrivate::Storage::NullFd), 111 fAttrFd(BPrivate::Storage::NullFd), 112 fCStatus(B_NO_INIT) 113 { 114 SetTo(entry); 115 } 116 117 /*! \brief Creates a BNode object and initializes it to the entry referred 118 to by the specified path. 119 \param path the path referring to the entry 120 */ 121 BNode::BNode(const char *path) 122 : fFd(BPrivate::Storage::NullFd), 123 fAttrFd(BPrivate::Storage::NullFd), 124 fCStatus(B_NO_INIT) 125 { 126 SetTo(path); 127 } 128 129 /*! \brief Creates a BNode object and initializes it to the entry referred 130 to by the specified path rooted in the specified directory. 131 \param dir the BDirectory, relative to which the entry's path name is 132 given 133 \param path the entry's path name relative to \a dir 134 */ 135 BNode::BNode(const BDirectory *dir, const char *path) 136 : fFd(BPrivate::Storage::NullFd), 137 fAttrFd(BPrivate::Storage::NullFd), 138 fCStatus(B_NO_INIT) 139 { 140 SetTo(dir, path); 141 } 142 143 /*! \brief Creates a copy of the given BNode. 144 \param node the BNode to be copied 145 */ 146 BNode::BNode(const BNode &node) 147 : fFd(BPrivate::Storage::NullFd), 148 fAttrFd(BPrivate::Storage::NullFd), 149 fCStatus(B_NO_INIT) 150 { 151 *this = node; 152 } 153 154 /*! \brief Frees all resources associated with this BNode. 155 */ 156 BNode::~BNode() 157 { 158 Unset(); 159 } 160 161 /*! \brief Checks whether the object has been properly initialized or not. 162 \return 163 - \c B_OK, if the object has been properly initialized, 164 - an error code, otherwise. 165 */ 166 status_t 167 BNode::InitCheck() const 168 { 169 return fCStatus; 170 } 171 172 /*! \brief Fills in the given stat structure with \code stat() \endcode 173 information for this object. 174 \param st a pointer to a stat structure to be filled in 175 \return 176 - \c B_OK: Everything went fine. 177 - \c B_BAD_VALUE: \c NULL \a st. 178 - another error code, e.g., if the object wasn't properly initialized 179 */ 180 status_t 181 BNode::GetStat(struct stat *st) const 182 { 183 return (fCStatus != B_OK) ? fCStatus : BPrivate::Storage::get_stat(fFd, st) ; 184 } 185 186 /*! \brief Reinitializes the object to the specified entry_ref. 187 \param ref the entry_ref referring to the entry 188 \return 189 - \c B_OK: Everything went fine. 190 - \c B_BAD_VALUE: \c NULL \a ref. 191 - \c B_ENTRY_NOT_FOUND: The entry could not be found. 192 - \c B_BUSY: The entry is locked. 193 \todo Currently implemented using BPrivate::Storage::entry_ref_to_path(). 194 Reimplement! 195 */ 196 status_t 197 BNode::SetTo(const entry_ref *ref) 198 { 199 Unset(); 200 char path[B_PATH_NAME_LENGTH]; 201 status_t error = (ref ? B_OK : B_BAD_VALUE); 202 if (error == B_OK) { 203 error = BPrivate::Storage::entry_ref_to_path(ref, path, 204 B_PATH_NAME_LENGTH); 205 } 206 if (error == B_OK) 207 error = SetTo(path); 208 fCStatus = error; 209 return error; 210 } 211 212 /*! \brief Reinitializes the object to the specified filesystem entry. 213 \param entry the BEntry representing the entry 214 \return 215 - \c B_OK: Everything went fine. 216 - \c B_BAD_VALUE: \c NULL \a entry. 217 - \c B_ENTRY_NOT_FOUND: The entry could not be found. 218 - \c B_BUSY: The entry is locked. 219 \todo Implemented using SetTo(entry_ref*). Check, if necessary to 220 reimplement! 221 */ 222 status_t 223 BNode::SetTo(const BEntry *entry) 224 { 225 Unset(); 226 entry_ref ref; 227 status_t error = (entry ? B_OK : B_BAD_VALUE); 228 if (error == B_OK && entry->InitCheck() != B_OK) 229 error = B_BAD_VALUE; 230 if (error == B_OK) 231 error = entry->GetRef(&ref); 232 if (error == B_OK) 233 error = SetTo(&ref); 234 fCStatus = error; 235 return error; 236 } 237 238 /*! \brief Reinitializes the object to the entry referred to by the specified 239 path. 240 \param path the path referring to the entry 241 \return 242 - \c B_OK: Everything went fine. 243 - \c B_BAD_VALUE: \c NULL \a path. 244 - \c B_ENTRY_NOT_FOUND: The entry could not be found. 245 - \c B_BUSY: The entry is locked. 246 */ 247 status_t 248 BNode::SetTo(const char *path) 249 { 250 Unset(); 251 if (path != NULL) { 252 fCStatus = BPrivate::Storage::open(path, O_RDWR | O_NOTRAVERSE, fFd, 253 true); 254 } 255 return fCStatus; 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 \todo Implemented using SetTo(BEntry*). Check, if necessary to reimplement! 269 */ 270 status_t 271 BNode::SetTo(const BDirectory *dir, const char *path) 272 { 273 Unset(); 274 status_t error = (dir && path ? B_OK : B_BAD_VALUE); 275 if (error == B_OK && BPrivate::Storage::is_absolute_path(path)) 276 error = B_BAD_VALUE; 277 BEntry entry; 278 if (error == B_OK) 279 error = entry.SetTo(dir, path); 280 if (error == B_OK) 281 error = SetTo(&entry); 282 fCStatus = error; 283 return error; 284 } 285 286 /*! \brief Returns the object to an uninitialized state. 287 */ 288 void 289 BNode::Unset() 290 { 291 close_fd(); 292 fCStatus = B_NO_INIT; 293 } 294 295 /*! \brief Attains an exclusive lock on the data referred to by this node, so 296 that it may not be modified by any other objects or methods. 297 \return 298 - \c B_OK: Everything went fine. 299 - \c B_FILE_ERROR: The object is not initialized. 300 - \c B_BUSY: The node is already locked. 301 \todo Currently unimplemented; requires new kernel. 302 */ 303 status_t 304 BNode::Lock() 305 { 306 if (fCStatus != B_OK) 307 return fCStatus; 308 309 // This will have to wait for the new kenel 310 return B_FILE_ERROR; 311 312 // We'll need to keep lock around if the kernel function 313 // doesn't just work on file descriptors 314 // BPrivate::Storage::FileLock lock; 315 // return BPrivate::Storage::lock(fFd, BPrivate::Storage::READ_WRITE, &lock); 316 } 317 318 /*! \brief Unlocks the node. 319 \return 320 - \c B_OK: Everything went fine. 321 - \c B_FILE_ERROR: The object is not initialized. 322 - \c B_BAD_VALUE: The node is not locked. 323 \todo Currently unimplemented; requires new kernel. 324 */ 325 status_t 326 BNode::Unlock() 327 { 328 if (fCStatus != B_OK) 329 return fCStatus; 330 // This will have to wait for the new kenel 331 return B_FILE_ERROR; 332 } 333 334 /*! \brief Immediately performs any pending disk actions on the node. 335 \return 336 - \c B_OK: Everything went fine. 337 - an error code, if something went wrong. 338 */ 339 status_t 340 BNode::Sync() 341 { 342 return (fCStatus != B_OK) ? B_FILE_ERROR : BPrivate::Storage::sync(fFd) ; 343 } 344 345 /*! \brief Writes data from a buffer to an attribute. 346 Write the \a len bytes of data from \a buffer to 347 the attribute specified by \a name after erasing any data 348 that existed previously. The type specified by \a type \em is 349 remembered, and may be queried with GetAttrInfo(). The value of 350 \a offset is currently ignored. 351 \param attr the name of the attribute 352 \param type the type of the attribute 353 \param offset the index at which to write the data (currently ignored) 354 \param buffer the buffer containing the data to be written 355 \param len the number of bytes to be written 356 \return 357 - the number of bytes actually written 358 - \c B_BAD_VALUE: \c NULL \a attr or \a buffer 359 - \c B_FILE_ERROR: The object is not initialized or the node it refers to 360 is read only. 361 - \c B_NOT_ALLOWED: The node resides on a read only volume. 362 - \c B_DEVICE_FULL: Insufficient disk space. 363 - \c B_NO_MEMORY: Insufficient memory to complete the operation. 364 */ 365 ssize_t 366 BNode::WriteAttr(const char *attr, type_code type, off_t offset, 367 const void *buffer, size_t len) 368 { 369 if (fCStatus != B_OK) 370 return B_FILE_ERROR; 371 else { 372 ssize_t result = BPrivate::Storage::write_attr(fFd, attr, type, offset, 373 buffer, len); 374 return result; 375 } 376 } 377 378 /*! \brief Reads data from an attribute into a buffer. 379 Reads the data of the attribute given by \a name into 380 the buffer specified by \a buffer with length specified 381 by \a len. \a type and \a offset are currently ignored. 382 \param attr the name of the attribute 383 \param type the type of the attribute (currently ignored) 384 \param offset the index from which to read the data (currently ignored) 385 \param buffer the buffer for the data to be read 386 \param len the number of bytes to be read 387 \return 388 - the number of bytes actually read 389 - \c B_BAD_VALUE: \c NULL \a attr or \a buffer 390 - \c B_FILE_ERROR: The object is not initialized. 391 - \c B_ENTRY_NOT_FOUND: The node has no attribute \a attr. 392 */ 393 ssize_t 394 BNode::ReadAttr(const char *attr, type_code type, off_t offset, 395 void *buffer, size_t len) const 396 { 397 if (fCStatus != B_OK) 398 return B_FILE_ERROR; 399 else { 400 ssize_t result = BPrivate::Storage::read_attr(fFd, attr, type, offset, buffer, 401 len); 402 return result; 403 } 404 } 405 406 /*! \brief Deletes the attribute given by \a name. 407 \param name the name of the attribute 408 - \c B_OK: Everything went fine. 409 - \c B_BAD_VALUE: \c NULL \a name 410 - \c B_FILE_ERROR: The object is not initialized or the node it refers to 411 is read only. 412 - \c B_ENTRY_NOT_FOUND: The node has no attribute \a name. 413 - \c B_NOT_ALLOWED: The node resides on a read only volume. 414 */ 415 status_t 416 BNode::RemoveAttr(const char *name) 417 { 418 return (fCStatus != B_OK) ? B_FILE_ERROR 419 : BPrivate::Storage::remove_attr(fFd, name); 420 } 421 422 /*! \brief Moves the attribute given by \a oldname to \a newname. 423 If \a newname already exists, the current data is clobbered. 424 \param oldname the name of the attribute to be renamed 425 \param newname the new name for the attribute 426 \return 427 - \c B_OK: Everything went fine. 428 - \c B_BAD_VALUE: \c NULL \a oldname or \a newname 429 - \c B_FILE_ERROR: The object is not initialized or the node it refers to 430 is read only. 431 - \c B_ENTRY_NOT_FOUND: The node has no attribute \a oldname. 432 - \c B_NOT_ALLOWED: The node resides on a read only volume. 433 */ 434 status_t 435 BNode::RenameAttr(const char *oldname, const char *newname) 436 { 437 if (fCStatus != B_OK) 438 return B_FILE_ERROR; 439 return BPrivate::Storage::rename_attr(fFd, oldname, newname); 440 } 441 442 443 /*! \brief Fills in the pre-allocated attr_info struct pointed to by \a info 444 with useful information about the attribute specified by \a name. 445 \param name the name of the attribute 446 \param info the attr_info structure to be filled in 447 \return 448 - \c B_OK: Everything went fine. 449 - \c B_BAD_VALUE: \c NULL \a name 450 - \c B_FILE_ERROR: The object is not initialized. 451 - \c B_ENTRY_NOT_FOUND: The node has no attribute \a name. 452 */ 453 status_t 454 BNode::GetAttrInfo(const char *name, struct attr_info *info) const 455 { 456 return (fCStatus != B_OK) ? B_FILE_ERROR 457 : BPrivate::Storage::stat_attr(fFd, name, info); 458 } 459 460 /*! \brief Returns the next attribute in the node's list of attributes. 461 Every BNode maintains a pointer to its list of attributes. 462 GetNextAttrName() retrieves the name of the attribute that the pointer is 463 currently pointing to, and then bumps the pointer to the next attribute. 464 The name is copied into the buffer, which should be at least 465 B_ATTR_NAME_LENGTH characters long. The copied name is NULL-terminated. 466 When you've asked for every name in the list, GetNextAttrName() 467 returns \c B_ENTRY_NOT_FOUND. 468 \param buffer the buffer the name of the next attribute shall be stored in 469 (must be at least \c B_ATTR_NAME_LENGTH bytes long) 470 \return 471 - \c B_OK: Everything went fine. 472 - \c B_BAD_VALUE: \c NULL \a buffer. 473 - \c B_FILE_ERROR: The object is not initialized. 474 - \c B_ENTRY_NOT_FOUND: There are no more attributes, the last attribute 475 name has already been returned. 476 */ 477 status_t 478 BNode::GetNextAttrName(char *buffer) 479 { 480 // We're allowed to assume buffer is at least 481 // B_ATTR_NAME_LENGTH chars long, but NULLs 482 // are not acceptable. 483 if (buffer == NULL) 484 return B_BAD_VALUE; // /new R5 crashed when passed NULL 485 if (InitAttrDir() != B_OK) 486 return B_FILE_ERROR; 487 488 BPrivate::Storage::LongDirEntry entry; 489 status_t error = BPrivate::Storage::read_attr_dir(fAttrFd, entry); 490 if (error == B_OK) { 491 strncpy(buffer, entry.d_name, B_ATTR_NAME_LENGTH); 492 return B_OK; 493 } 494 return error; 495 } 496 497 /*! \brief Resets the object's attribute pointer to the first attribute in the 498 list. 499 \return 500 - \c B_OK: Everything went fine. 501 - \c B_FILE_ERROR: Some error occured. 502 */ 503 status_t 504 BNode::RewindAttrs() 505 { 506 if (InitAttrDir() != B_OK) 507 return B_FILE_ERROR; 508 BPrivate::Storage::rewind_attr_dir(fAttrFd); 509 return B_OK; 510 } 511 512 /*! Writes the specified string to the specified attribute, clobbering any 513 previous data. 514 \param name the name of the attribute 515 \param data the BString to be written to the attribute 516 - \c B_OK: Everything went fine. 517 - \c B_BAD_VALUE: \c NULL \a name or \a data 518 - \c B_FILE_ERROR: The object is not initialized or the node it refers to 519 is read only. 520 - \c B_NOT_ALLOWED: The node resides on a read only volume. 521 - \c B_DEVICE_FULL: Insufficient disk space. 522 - \c B_NO_MEMORY: Insufficient memory to complete the operation. 523 */ 524 status_t 525 BNode::WriteAttrString(const char *name, const BString *data) 526 { 527 status_t error = (!name || !data) ? B_BAD_VALUE : B_OK; 528 if (error == B_OK) { 529 int32 len = data->Length(); 530 ssize_t sizeWritten = WriteAttr(name, B_STRING_TYPE, 0, data->String(), 531 len); 532 if (sizeWritten != len) 533 error = sizeWritten; 534 } 535 return error; 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 // Lock the string's buffer so we can meddle with it 561 char *data = result->LockBuffer(info.size+1); 562 if (!data) 563 return B_NO_MEMORY; 564 // Read the attribute 565 ssize_t bytes = ReadAttr(name, B_STRING_TYPE, 0, data, info.size); 566 // Check for failure 567 if (bytes < 0) { 568 error = bytes; 569 bytes = 0; // In this instance, we simply clear the string 570 } else 571 error = B_OK; 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 /*! \brief Reinitializes the object as a copy of the \a node. 580 \param node the BNode to be copied 581 \return a reference to this BNode object. 582 */ 583 BNode& 584 BNode::operator=(const BNode &node) 585 { 586 // No need to do any assignment if already equal 587 if (*this == node) 588 return *this; 589 // Close down out current state 590 Unset(); 591 // We have to manually dup the node, because R5::BNode::Dup() 592 // is not declared to be const (which IMO is retarded). 593 fFd = BPrivate::Storage::dup(node.fFd); 594 fCStatus = (fFd == BPrivate::Storage::NullFd) ? B_NO_INIT : B_OK ; 595 return *this; 596 } 597 598 /*! Tests whether this and the supplied BNode object are equal. 599 Two BNode objects are said to be equal if they're set to the same node, 600 or if they're both \c B_NO_INIT. 601 \param node the BNode to be compared with 602 \return \c true, if the BNode objects are equal, \c false otherwise 603 */ 604 bool 605 BNode::operator==(const BNode &node) const 606 { 607 if (fCStatus == B_NO_INIT && node.InitCheck() == B_NO_INIT) 608 return true; 609 if (fCStatus == B_OK && node.InitCheck() == B_OK) { 610 // Check if they're identical 611 BPrivate::Storage::Stat s1, s2; 612 if (GetStat(&s1) != B_OK) 613 return false; 614 if (node.GetStat(&s2) != B_OK) 615 return false; 616 return (s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino); 617 } 618 return false; 619 } 620 621 /*! Tests whether this and the supplied BNode object are not equal. 622 Two BNode objects are said to be equal if they're set to the same node, 623 or if they're both \c B_NO_INIT. 624 \param node the BNode to be compared with 625 \return \c false, if the BNode objects are equal, \c true otherwise 626 */ 627 bool 628 BNode::operator!=(const BNode &node) const 629 { 630 return !(*this == node); 631 } 632 633 /*! \brief Returns a POSIX file descriptor to the node this object refers to. 634 Remember to call close() on the file descriptor when you're through with 635 it. 636 \return a valid file descriptor, or -1, if something went wrong. 637 */ 638 int 639 BNode::Dup() 640 { 641 return BPrivate::Storage::dup(fFd); 642 } 643 644 645 /*! (currently unused) */ 646 void BNode::_RudeNode1() { } 647 void BNode::_RudeNode2() { } 648 void BNode::_RudeNode3() { } 649 void BNode::_RudeNode4() { } 650 void BNode::_RudeNode5() { } 651 void BNode::_RudeNode6() { } 652 653 /*! \brief Sets the node's file descriptor. 654 Used by each implementation (i.e. BNode, BFile, BDirectory, etc.) to set 655 the node's file descriptor. This allows each subclass to use the various 656 file-type specific system calls for opening file descriptors. 657 \param fd the file descriptor this BNode should be set to (may be -1) 658 \return \c B_OK, if everything went fine, an error code otherwise. 659 \note This method calls close_fd() to close previously opened FDs. Thus 660 derived classes should take care to first call set_fd() and set 661 class specific resources freed in their close_fd() version 662 thereafter. 663 */ 664 status_t 665 BNode::set_fd(BPrivate::Storage::FileDescriptor fd) 666 { 667 if (fFd != -1) 668 close_fd(); 669 fFd = fd; 670 return B_OK; 671 } 672 673 /*! \brief Closes the node's file descriptor(s). 674 To be implemented by subclasses to close the file descriptor using the 675 proper system call for the given file-type. This implementation calls 676 BPrivate::Storage::close(fFd) and also BPrivate::Storage::close_attr_dir(fAttrDir) 677 if necessary. 678 */ 679 void 680 BNode::close_fd() 681 { 682 if (fAttrFd != BPrivate::Storage::NullFd) 683 { 684 BPrivate::Storage::close_attr_dir(fAttrFd); 685 fAttrFd = BPrivate::Storage::NullFd; 686 } 687 if (fFd != BPrivate::Storage::NullFd) { 688 close(fFd); 689 fFd = BPrivate::Storage::NullFd; 690 } 691 } 692 693 // set_status 694 /*! \brief Sets the BNode's status. 695 To be used by derived classes instead of accessing the BNode's private 696 \c fCStatus member directly. 697 \param newStatus the new value for the status variable. 698 */ 699 void 700 BNode::set_status(status_t newStatus) 701 { 702 fCStatus = newStatus; 703 } 704 705 /*! \brief Modifies a certain setting for this node based on \a what and the 706 corresponding value in \a st. 707 Inherited from and called by BStatable. 708 \param st a stat structure containing the value to be set 709 \param what specifies what setting to be modified 710 \return \c B_OK if everything went fine, an error code otherwise. 711 */ 712 status_t 713 BNode::set_stat(struct stat &st, uint32 what) 714 { 715 if (fCStatus != B_OK) 716 return B_FILE_ERROR; 717 return BPrivate::Storage::set_stat(fFd, st, what); 718 } 719 720 /*! \brief Verifies that the BNode has been properly initialized, and then 721 (if necessary) opens the attribute directory on the node's file 722 descriptor, storing it in fAttrDir. 723 \return \c B_OK if everything went fine, an error code otherwise. 724 */ 725 status_t 726 BNode::InitAttrDir() 727 { 728 if (fCStatus == B_OK && fAttrFd == BPrivate::Storage::NullFd) 729 return BPrivate::Storage::open_attr_dir(fFd, fAttrFd); 730 return fCStatus; 731 } 732 733 /*! \var BNode::fFd 734 File descriptor for the given node. 735 */ 736 737 /*! \var BNode::fAttrFd 738 This appears to be passed to the attribute directory functions 739 like a BPrivate::Storage::Dir would be, but it's actually a file descriptor. 740 Best I can figure, the R5 syscall for reading attributes must've 741 just taken a file descriptor. Depending on what our kernel ends up 742 providing, this may or may not be replaced with an Dir* 743 */ 744 745 /*! \var BNode::fCStatus 746 The object's initialization status. 747 */ 748 749 750 751