The Storage Kit: BStatable

Derived from: (none)

Declared in: be/StorageKit/BStatable.h

Library: libbe.so


Overview

BStatable is a pure abstract class that provides functionality for its two derived class, BEntry and BNode. The BStatable functions let you get and set "statistical" information about an entry in the file system. You can...

  • Determine whether an entry is a file, directory, or symbolic link.
  • Get and set an entry's owner, group, and permissions.
  • Get and set an entry's creation, modification, and access times.
  • Get and set the size of the entry's data (not counting attributes).
  • Get a BVolume object for the entry's volume.
  • Get the node_ref for an entry (and pass it to watch_node(), most likely).

  • Relationship to stat()

    The BStatable functions are covers for the POSIX stat() call. stat() retrieves a file-specific stat structure, which records the statistics listed above (and then some). Although BStatable was designed to hide stat details, you can get the stat structure through the GetStat() function. The stat structure is described in The stat Structure at the end of this specification.

    stat() is notorious for being expensive. Furthermore, the stat structure is stale as soon as it gets back from the stat() call. So...

    If you're concerned with efficiency, be aware that every BStatable function (the "setters" as well as the "getters") performs a stat(). For example, calling GetOwner() and then GetGroup() results in two stat() calls. If you want to look at lot of fields (within the same stat structure) all at once, you might consider using BStatable's GetStat() function.

    As for integrity, BStatable info-getting functions are obviously in the same boat as the stat() call itself: The retrieved data isn't guaranteed to be in synch with the actual state of the stat()'d item.

    The BDirectory class also defines a stat-retrieving function that, in some cases, can be more efficient than the GetStat() function defined here:

    The BDirectory::GetStatFor() function retrieves the stat structure for a named entry within a directory. If you're interested in getting stat information for a series of entries within the same directory, you should use this function. You have to call it iteratively (once for each entry), but the accumulation of the iterated calls will be faster than the GetStat() calls made on the analogous BEntry objects.


    Accessing Unreadable and Unwritable Entries

    BStatable isn't thwarted by file permissions: If you can construct a valid BEntry to an item, then you can invoke any of the info-getting BStatable functions on that object:

    The BStatable functions aren't denied even if the entry that you're looking at is read-protected. However, you can only invoke the info-setting functions if the entry allows writing.

    Similarly, you can get stat info for a locked file, but you won't be able to write the info (through functions such as SetOwner() ) unless your object holds the lock. See BNode for more on locking.

    Be aware that...

    Currently, permissions are not enforced as strongly as they could be . If you're looking at a read-only volume, then you won't be able to modify any stat information. Beyond that (in other words, on writable volumes), the only stat- modifying operation that's denied on a read-only file is SetSize(): You can't modify the data in a file that's read-protected against you.


    Other Details

    You rarely set stat information.

    In practice, you rarely use BStatable's info-setting functions. Setting information such as when a file was created, who owns it, or how big it is, is the responsibility of the system and the privilege of the user. For example, when you Write() to a BFile object, the system automatically updates the size and modification date for the file.

    The BStatable functions only apply to existing entries.

    As explained in BEntry, it's possible to create "abstract" BEntry objects; in other words, objects that don't correspond to actual files on the disk. However, you can't get (or set) BStatable information for abstract entries. The BStatable functions return EINVAL if the invoked-upon entry is abstract.


    Member Functions


    GetCreationTime(), SetCreationTime(), GetModificationTime() , SetModificationTime(), GetAccessTime(), SetAccessTime()

    
          status_t GetCreationTime(time_t *ctime) const
          status_t SetCreationTime(time_t ctime)
    
          status_t GetModificationTime(time_t *mtime) const
          status_t SetModificationTime(time_t mtime)
    
          status_t GetAccessTime(time_t *atime) const
          status_t SetAccessTime(time_t atime)

    Access time is currently unused.

    These function let you get and set the time at which the item was created, last modified, and last accessed (opened). The measure of time is given as seconds since (the beginning of ) January 1, 1970.

    Note that the time quanta that stat uses is seconds; the rest of the BeOS measures time in microseconds (bigtime_t).

    RETURN VALUES

  • B_NO_ERROR. Success.
  • B_PERMISSION_DENIED. You tried to set a time field for a file on a read-only volume.
  • B_NO_MEMORY. Couldn't get the necessary resources to complete the transaction.
  • EINVAL. The entry doesn't exist.

  • GetNodeRef()

    
          status_t GetNodeRef(node_ref *nref) const

    Copies the item's node_ref structure into the nref argument, which must be allocated.

    Typically, you use an entry's node_ref as a key to the Node Monitor by passing the node_ref structure to the watch_node() function. The Node Monitor watches the node for specific changes; see The Node Monitor for details.

    As a convenience, you can use a node_ref structure to initialize a BDirectory object (through the constructor or BDirectory::SetTo() function).

    RETURN VALUES

  • B_NO_ERROR. Success.
  • B_NO_MEMORY. Couldn't get the necessary resources to complete the transaction.
  • EINVAL. The entry doesn't exist.

  • GetOwner(), SetOwner(), GetGroup(), SetGroup(), GetPermissions(), SetPermissions()

    
          status_t GetOwner(uid_t *owner) const
          status_t SetOwner(uid_t owner)
    
          status_t GetGroup(gid_t *group) const
          status_t SetGroup(gid_t group) 
    
          status_t GetPermissions(mode_t *perms) const
          status_t SetPermissions(mode_t perms) 

    In AADR9 owner, group, and permissions are mostly ignored by the Be file system. In particular, all users are "root" and there's only one group.

    These functions set and get the owner, group, and read/write/execute permissions for the entry:

    The uid_t, gid_t, and mode_t types used here are standard POSIX types. All three are 32-bit unsigned integers and are defined in headers/posix/sys/types.h.

    The owner and group encodings must match values found in the system's user and group database files [which are as yet unspecified].

    The permissions value is a combination of the following bitfield constants (defined in headers/posix/sys/stat.h):

  • S_IRUSR owner's read bit.
  • S_IWUSR owner's write bit.
  • S_IXUSR owner's execute bit.
  • S_IRGRP group's read bit.
  • S_IWGRP group's write bit.
  • S_IXGRP group's execute bit.
  • S_IROTH others' read bit.
  • S_IWOTH others' write bit.
  • S_IXOTH others' execute bit.
  • For example:

       /* Is a file readable by everybody? */
       mode_t perms;
       if (entry.GetPermissions(&perms) < B_NO_ERROR)
          /* handle the error... */
       
       if (perms & S_ISROTH)
          // Yes it is
       else
          // No it isn't

    RETURN VALUES

  • B_NO_ERROR. Success.
  • B_PERMISSION_DENIED. You tried to set permissions on a read-only volume.
  • EISDIR. You tried to set the size of a directory.
  • EINVAL. The entry doesn't exist.
  • ENOSPC. Disk full?

  • GetSize(), SetSize()

    
          status_t GetSize(off_t *size) const
          status_t SetSize(off_t size) const

    These functions get and set the size of the entry's data portion (in bytes). Only the "used" portions of the entry's file blocks is counted; the amount of storage the entry actually requires (i.e. the number of blocks the entry consumes) may be larger than the size given here.

    The size measurement doesn't include the entry's attributes.

    SetSize() really does modify the file--it adds new storage to the end, or removes data from the end of the file, as needed. You can only set the size of a plain file or symbolic link (as opposed to a directory).

    Setting the size of a symbolic link is a very odd thing to do.

    RETURN VALUES

  • B_NO_ERROR. Success.
  • B_PERMISSION_DENIED. You tried to set the size for a file on a read-only volume.
  • B_NO_MEMORY. Couldn't get the necessary resources to complete the transaction.
  • EISDIR. You tried to set the size of a directory.
  • EINVAL. The entry doesn't exist.
  • ENOSPC. Disk full?

  • GetStat()

    
          virtual status_t GetStat(struct stat *st) const

    GetStat() returns the stat structure for the item. The structure is copied into the st argument, which must be allocated. The stat structure is described in The stat Structure, below. The BStatable object does not cache the stat structure; every time you call GetStat(), fresh stat information is retrieved.

    RETURN VALUES

  • B_NO_ERROR. Success.
  • B_NO_MEMORY. Couldn't get the necessary resources to complete the transaction.
  • EINVAL. The entry doesn't exist.

  • The stat Structure

    Declared in: posix/sys/stat.h

    The stat structure looks like this:

       typedef struct stat {
           dev_t         st_dev;
           ino_t         st_ino;
           mode_t         st_mode;
           nlink_t         st_nlink; 
           uid_t         st_uid;
           gid_t         st_gid;
           off_t         st_size;
           dev_t         st_rdev;
           size_t         st_blksize;
           time_t         st_atime; 
           time_t         st_mtime;
           time_t         st_ctime;
       } stat;

    The structure isn't typdef'd in AADR9.

    And the fields are...

  • st_dev identifies the entry's device.
  • st_ino is the entry's "inode" number.
  • By combining st_dev and st_ino you can roll your own node_ref:

       node_ref nref;
       stat st;
       
       if (file.GetStat(&st) == B_NO_ERROR) {
          nref.dev = st.st_dev;
          nref.node = st.st_ino;
       }

    Meanwhile...

       if (S_ISREG(st.st_mode))
          /* it's a "regular" file */
          else if (S_ISDIR(st.st_mode))
             /* it's a directory */
             else if (S_ISLINK(st.st_mode))
                /* it's a symbolic link */

        





    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