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