The Storage Kit: BEntry

Derived from: BStatable

Declared in: be/StorageKit/Entry.h

Library: libbe.so


Overview

The BEntry class defines objects that represent named "entries" in a directory. A BEntry object can represent a file, directory, or symbolic link; the construction and use of the object doesn't depend on which of these three is being represented:

All the BEntry cares about is a name in a directory .

Although it's possible to derive your own class from BEntry, there's no good reason to do so, and one good reason not to: The BDirectory class defines functions (such as FindEntry() ) that return BEntry objects to you. Such functions can't return instances of your derived class.


Talents and Abilities

A properly initialized BEntry object (we'll get to the rules of initialization later) knows the following:

A BEntry can do, or can be used for, the following things:

An important point regarding BEntry is that it can't access a file's data:

A BEntry can't read or write its entry's data or attributes. To do these things you need a BNode object.


Initializing and Traversing

There are a number of ways to initialize a BEntry object:

  • You can initialize it during construction.
  • You can use the SetTo() function.
  • You can use the assignment operator.
  • You can pass it as an argument to BDirectory's FindEntry() or BEntryList's GetNextEntry() function.
  • In all cases (except the assignment operator) you're asked if you want to "traverse" the entry during initialization. Traversal is used to "resolve" symbolic links:

    If you traverse during initialization, the initialized BEntry will point to the entry that the symbolic link is linked to.

    Link traversal is not supported in AADR9. It will be part of DR9 proper.

    For example, let's say /boot/lbj/fidoLink is linked to ./fido, to wit:

       $ cd /boot/lbj
       $ ln -s ./fido fidoLink

    Now let's make a traversed BEntry for fidoLink :

       /* The second argument is the traverse bool. */
       BEntry entry("/boot/lbj/fidoLink", true);

    If we ask for the entry's pathname...

       BPath path;
       entry.GetPath(&path);
       printf("Pathname:  %s\\n", path.Path());

    ...we see

       $ Pathname:  /boot/lbj/fido

    In other words, the BEntry refers to fido , not fidoLink.

    Traversal resolves nested links--it really wants to find a "real" file (or directory). If the entry that you're initializing to isn't a link, then traversal is a no-op (the traverse bool is ignored).

    In almost all cases you want to traverse--the traverse argument (to the constructor and SetTo(), etc.)--defaults to true in deference to this assumption.

    Checking the Initialization

    The SetTo() function returns a status code that tells you if the initialization was successful. To check the initialization for the other methods, you use the InitCheck() function:

       BEntry entry("/boot/lbj/fido");
       if (entry.InitCheck() != B_NO_ERROR)
          /* handle the error */

    Here we apply InitCheck() to the argument of a BDirectory::FindEntry() call:

       BDirectory dir("/boot/lbj");
       BEntry entry;
       
       dir.FindEntry("fido", &entry);
       if (entry.InitCheck() != B_NO_ERROR)
          /* handle the error */

    Some details...

    The InitCheck() value isn't cleared after you call the function, nor is it affected by anything (other than re-initializing) that you do to the BEntry object You can call InitCheck() as much as you want; it will always return the same value.

    InitCheck() does not tell you if the entry that the BEntry represents actually exists (as a file on disk). See Abstract Entries for more information.


    File Descriptors and Weight Comparisons

    Although it's not intuitively obvious, a BEntry object does consume a "file descriptor." For a BEntry, the file descriptor points into its parent directory.

    Your app has a limited number of file descriptors (currently 128, max), so you may not want to cache BEntry objects as your primary means for identifying an entry. If you're going to be dealing with a lot of entries and you want to keep track of them all, it's better to cache entry_ref structures.


    Abstract Entries

    As mentioned earlier, a BEntry's link to reality is in its identification of a named entry within a specific directory. Although the identified directory must exist, the name doesn't have to. In other words...

    A BEntry can represent a file that doesn't exist.

    For example, the following construction creates a BEntry object based on a BDirectory and a name:

       BEntry entry(someDir, "myFile.h");

    Let's assume that myFile.h doesn't exist. As long as the directory that's referred to by someDir does exist, then the construction will work (InitCheck() returns B_OK). However...

    Creating an abstract entry doesn't create a file, nor does it modify the parent directory.

    If you want to know if the entry actually exists, use the Exists() function. To turn an abstract BEntry into a real entry, you have to specify the flavor of node that you want the entry to contain:

    For example, let's say you want a BEntry that represents the directory /boot/lbj. If the BEntry is abstract, you want to create the directory. To do this, you ask for the entry's parent (as a BDirectory) and pass the entry's name to CreateDirectory() invoked on the parent directory:

       BDirectory dir;
       BEntry entry("/boot/lbj");
       char name[B_FILE_NAME_LENGTH];
       status_t err;
       
       /* Make sure the initialization worked. */
       if (entry.InitCheck() == B_OK)
          /* Now check for abstraction */
          if (!entry.Exists()) {
             entry.GetParent(&dir);
             entry.GetName(name);
       
             /* By passing dir as the second arg, we
              * re-initialize the object to
              * point to the new directory.
              */
             err = dir.CreateDirectory(name, &dir)
          }

    At this point, entry and dir both refer to /boot/lbj, the former as an entry, the latter as a node.


    Constructor and Destructor


    BEntry()

    
          BEntry(const BDirectory *dir, const char *path, bool traverse = TRUE)
          BEntry(const entry_ref *ref, bool traverse = TRUE)
          BEntry(const char *path, bool traverse = TRUE)
    
          BEntry()
          BEntry(const BEntry &entry)

    Creates a new BEntry object that represents the entry described by the arguments. See the analogous SetTo() functions for descriptions of the flavorful constructors.

  • The default constructor does nothing; it should be followed by a call to SetTo().
  • The copy constructor points the new object to the entry that's represented by the argument.
  • To check to see if an initialization was successful, call InitCheck().


    ~BEntry

    
          ~BEntry()

    Frees the BEntry's file descriptor and destroys the BEntry object.


    Member Functions


    GetRef(), GetParent(), GetName(), GetPath()

    
          status_t GetRef(entry_ref *ref) const
    
          status_t GetParent(BEntry *entry) const
          status_t GetParent(BDirectory *dir) const
    
          status_t GetName(char *buffer) const
    
          status_t GetPath(BPath *path) const

    These functions return obvious bits of information about the BEntry. The info is always returned in the argument; the arguments must be allocated before they're passed in.

  • GetRef() gets the entry_ref for this object.
  • GetParent() gets the parent directory as a BEntry or a BDirectory.
  • GetName() gets the leaf name of the object's entry.
  • GetPath() gets the full pathname, returned to you as a BPath object.
  • In all cases except GetName(), the argument is Unset() (or the equivalent) if the function is unsuccessful.

    RETURN VALUES

  • B_NO_ERROR. The information was successfully retrieved.
  • B_NO_INIT. This object isn't initialized.

  • InitCheck()

    
          status_t InitCheck(void) const

    Returns the status of the previous construction, assignment operation, or SetTo() call.

    RETURN VALUES

  • B_NO_ERROR. The initialization was successful.
  • B_NO_INIT. The object is uninitialized (this includes Unset()).
  • See SetTo() for other errors.

  • Rename(), MoveTo(), Remove()

    
          status_t Rename(const char *path)
    
          status_t MoveTo(BDirectory *dir, const char *path = NULL)
    
          status_t Remove(void)

    These functions push the BEntry's entry around.

    In all cases, this is updated to reflect the change to its entry. However...

    Remove() does not invalidate the BEntry. It simply makes it abstract (see "Abstract Entries" information on this topic).

    RETURN VALUES

  • B_NO_ERROR. Success.
  • B_NO_INIT. The BEntry is not initialized.
  • ENOENT. A directory to the location (for Rename() or MoveTo() ) doesn't exist, or the leaf name is already taken.

  • SetTo(), Unset()

    
          status_t SetTo(const entry_ref *ref, bool traverse = TRUE)
    
          status_t SetTo(const const char *path, bool traverse = TRUE)
    
          status_t SetTo(const BDirectory *dir, 
             const char *path,
             bool traverse = TRUE)
    
          void Unset(void)

    Frees the BEntry's current entry reference, and initializes it to refer to the entry identified by the arument(s).

    If traverse is true and the identified entry is a symbolic link, the link is traversed. If the argument is false and the entry is a link, the BEntry is initialized to point to the link itself. If the entry isn't a link, traverse is ignored. See "Initializing and Traversing" for more information.

    When you initialize a BEntry, you're describing a leaf name within a directory. The directory must exist, but the leaf doesn't have to. This allows you to create a BEntry to a file that doesn't exist (yet). See "Abstract Entries " for more information.

    Remember--successfully initializing a BEntry consumes a file descriptor.

    Unset() removes the object's association with its current entry, and sets InitCheck() to B_NO_INIT .

    RETURN VALUES

  • B_NO_ERROR. The BEntry was successfully initialized.
  • B_BAD_VALUE. Bad argument value; uninitialized ref or dir.
  • ENOENT. The directory part of the entry doesn't exist.

  • Operators


    = (assignment)

    
          BEntry& operator=(const BEntry &entry)

    In the expression

       BEntry a = b;

    BEntry a is initialized to refer to the same entry as b. To gauge the success of the assignment, you should call InitCheck() immediately afterwards. Assigning a BEntry to itself is safe.

    Assigning from an uninitialized BEntry is "successful": The assigned-to BEntry will also be uninitialized (B_NO_INIT).


    ==, != (comparison)

    
             bool operator==(const BEntry &entry) const
             bool operator!=(const BEntry &entry) const

    Two BEntry objects are said to be equal if they refer to the same entry, or if they're both uninitialized.




    The Be Book, HTML Edition, for Developer Release 9 of the Be OS.

    Copyright © 1997 Be, Inc. All rights reserved.

    Be, the Be logo, BeBox, BeOS, BeWare, and GeekPort are trademarks of Be, Inc.

    Last modified