BDirectory

Derived from: BNode, BEntryList

Declared in: be/storage/Directory.h

Library: libbe.so

[method summary]

A BDirectory object gives you access to the contents of a directory. A BDirectory's primary features are:

Unlike the other BNode classes, a BDirectory knows its own entry (GetEntry()), and can be initialized with a node_ref structure.


Retrieving Entries

The BDirectory functions that let you iterate over a directory's entries are inherited from BEntryList:

status_t GetNextEntry(BEntry *entry, bool traverse = true);
status_t GetNextRef(entry_ref *ref);
int32 GetNextDirents(dirent *buf, size_t length, int32 count = INT_MAX)

For the basic story on these functions, see the BEntryList class and the function descriptions below. In addition to the info you'll find there, you should be aware of the following:


Creating New Directories

To create a new directory, you can use BDirectory's CreateDirectory() function. The function creates a single new directory as identified by its argument. The new directory will be a subdirectory of the invoked-upon BDirectory's directory.

You can also create an entire path full of new directories through the global create_directory() function. This convenient function attempts to create all "missing" directories along the path that you pass in.


Finding a Directory

The find_directory() function gives you the pathnames for pre-defined directories. These directories, such as those that store Be-supplied applications and user-defined preferences settings, are represented by directory_which constants. These constants are not strings; you can't use them directly. You have to pass them through find_directory().

Note that the BDirectory class itself doesn't let you find directories on the basis of the directory_which constants--you have to use the find_directory() function (which is documented at the end of this class description).


Node Monitoring a Directory

The following description is a brief, directory-specific view into the Node Monitor. For the full story, see "The Node Monitor" section of this chapter.

You can monitor changes to the contents of a directory by passing a BDirectory's node_ref and the B_WATCH_DIRECTORY flag to the Node Monitor's watch_node() function. As with all invocations of watch_node(), you also have to pass a BMessenger (the "target") that will receive the Node Monitor notifications; here, we use be_app_messenger:

   BDirectory dir("/boot/home");
   node_ref nref;
   status_t err;
   
   if (dir.InitCheck() == B_OK) {
      dir.GetNodeRef(&nref);
      err = watch_node(&nref, B_WATCH_DIRECTORY, be_app_messenger);
      if (err != B_OK)
         /* handle the error */
   }

The following changes to the monitored directory cause BMessages to be sent to the target. The what field for all Node Monitor messages is B_NODE_MONITOR; the "opcode" field (an integer code) describes the activity:

The B_WATCH_DIRECTORY flag (by itself) doesn't monitor changes to the directory's own entry. For example, if you change the name of the directory that you're monitoring, the target isn't sent a message. If you want a BDirectory to watch changes to itself, you have to throw in one of the other Node Monitor flags (B_WATCH_NAME, B_WATCH_STAT, or B_WATCH_ATTR).

The other fields in the Node Monitor message describe the entry that changed. The set of fields depends on the opcode (the following is a summary of the list given in Notification Messages in the Node Monitor documentation):

B_ENTRY_CREATED

Field Type Description
"device" B_INT32_TYPE dev_t of the directory's device.
"directory" B_INT64_TYPE ino_t (node number) of the directory.
"node" B_INT64_TYPE ino_t of the new entry's node.
"name" B_STRING_TYPE The name of the new entry.

B_ENTRY_MOVED

The "device", "node", and "name" fields are the same as for B_ENTRY_CREATED, plus...

Field Type Description
"from_directory" B_INT64_TYPE The ino_t number of the old directory.
"to_directory" B_INT64_TYPE The ino_t number of the new directory.

B_ENTRY_REMOVED

The B_ENTRY_REMOVED message takes the same form as B_ENTRY_CREATED, but without the "name" field. This, obviously, can be a problem--what good is it if you're told that a file has been removed, but you're not told the file's name? In some cases, simply being told that a file has been removed actually is good enough: You can simply re-read the contents of the directory.


Constructor and Destructor


BDirectory()

      BDirectory(const entry_ref *ref)
      BDirectory(const node_ref *nref)
      BDirectory(const BEntry *entry)
      BDirectory(const char *path)
      BDirectory(const BDirectory *dir, const char *path)
      BDirectory(void)
      BDirectory(const BDirectory &directory)

Creates a new BDirectory object that represents the directory as given by the arguments. See the analogous SetTo() functions for descriptions of the flavorful constructors.

To check to see if an initialization was successful, call InitCheck().


~BDirectory()

      virtual ~BDirectory()

Deletes the object.


Member Functions


Contains()

      bool Contains(const char *path, int32 nodeFlags = B_ANY_NODE) const
      bool Contains(const BEntry *entry, int32 nodeFlags = B_ANY_NODE) const

Returns true if path or entry is contained within this directory, or in any of its subdirectories (no matter how deep). You can use the nodeFlags argument to limit the search to a particular flavor of node:


CountEntries() see GetNextEntry()


CreateDirectory() see CreateFile()


CreateFile(), CreateDirectory(), CreateSymLink()

      status_t CreateFile(const char *path, BFile *file, bool failIfExists = false)
      status_t CreateDirectory(const char *path, BDirectory *dir)
      status_t CreateSymLink(const char *path, const char *linkToPath, BSymLink *link)

These functions create a new file, directory, or symbolic link. The new node is located at path. If path is relative, it's reckoned off of the directory represented by this BDirectory; if it's absolute, the path of this BDirectory is ignored.

The object argument (the BDirectory, BFile, or BSymLink) may be NULL. If the function fails, the object argument, if non-NULL, is Unset().

RETURN CODES


CreateSymLink() see CreateFile()


FindEntry()

      status_t FindEntry(const char *path, BEntry *entry, bool traverse = false) const

Finds the entry with the given name, and sets the second argument to refer to that entry.

If path isn't found, the second argument is automatically Unset(). To find out why the lookup failed, invoke InitCheck() on the entry argument:

   BEntry entry;
   status_t err;
   
   if (dir.FindEntry("aFile", &entry) != B_OK) {
      err = entry.InitCheck();
   }

The direct return value is also informative, but it may not be as precise as the InitCheck() value.

RETURN CODES


GetEntry()

      status_t GetEntry(BEntry *entry) const

Initializes entry to represent this BDirectory. If the initialization fails, entry is Unset().

RETURN CODES


GetNextDirents() see GetNextEntry()


GetNextEntry(), GetNextRef(), GetNextDirents(), CountEntries(), Rewind()

      virtual status_t GetNextEntry(BEntry *entry, bool traverse = false)
      virtual status_t GetNextRef(entry_ref *ref)
      virtual int32  GetNextDirents(dirent *buf, size_t bufsize, int32 count = INT_MAX)
      virtual int32 CountEntries(void)
      virtual status_t Rewind(void)

The three GetNext...() functions retrieve the "next" entry that lives in the BDirectory and returns it as a BEntry, entry_ref, or dirent structure.

Currently, GetNextDirents() only reads one dirent at a time, no matter how many you ask for.

GetNextEntry() and GetNextRef() are reasonably clear; the dirent version deserves more explanation. You'll find this explanation (and an example) in the BEntryList class. Also, keep in mind that the set of candidate entries is different for the dirent version: GetNextDirents() finds all entries, including the entries for "." and "..". The other two versions skip these entries.

When you're done reading the BDirectory's entries, you can rewind the object's entry iterator by calling Rewind().

CountEntries() returns the number of entries (not counting "." and "..") in the directory.

Never call CountEntries() while you're iterating through the directory. CountEntries() does a rewind, iterates through the entries, and then rewinds again.

RETURN CODES


GetNextRef() see GetNextEntry()


GetStatFor()

      status_t GetStatFor(const char *path, stat *st) const

Gets the stat structure for the entry designated by path. path must be relative, and is reckoned off of the BDirectory's directory. This is, primarily, a convenience function; but it's also provided for efficiency.

RETURN CODES


IsRootDirectory()

      bool IsRootDirectory(void) const

Returns true if this BDirectory represents a root directory. A root directory is the directory that's at the root of a volume's file hierarchy. Every volume has exactly one root directory; all other files in the volume's hierarchy descend from the root directory.


Rewind() see GetNextEntry()


SetTo(), Unset()

      status_t SetTo(const entry_ref *ref)
      status_t SetTo(const node_ref *nref)
      status_t SetTo(const BEntry *entry)
      status_t SetTo(const char *path)
      status_t SetTo(const BDirectory *dir, const char *path)
      void Unset(void)

Closes the BDirectory's current directory (if any), and initializes the object to open the directory as given by the arguments.

If the specification results in a symbolic link that resolves to a directory, then the linked-to directory is opened. If the specification is (or resolves to) a regular file, the initialization fails.

RETURN CODES


Operators


= (assignment)

      BDirectory& operator=(const BDirectory &directory)

In the expression

   BDirectory a = b;

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

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


C Functions


create_directory()

      status_t create_directory(const char *path, mode_t mode)

Creates all missing directories along the path specified by path.

RETURN CODES


find_directory()

      status_t find_directory(directory_which which, dev_t volume, bool create_it, 
         char *path_string, int32 length)
      status_t find_directory(directory_which which, BPath *path_obj, 
         bool create_it = false, BVolume *volume = NULL)

The first version of this function can be used in either C or C++ code. The second version is for C++ code only.

Finds the path to the directory symbolized by which and copies it into path_string, or uses it to initialize path_obj.

The directory_which constants are described in the Global Functions, Constants, and Defined Types section at the end of this chapter.

RETURN CODES






The Be Book, in lovely HTML, for BeOS Release 4.

Copyright © 1998 Be, Inc. All rights reserved.

Last modified March 1, 1998.