The Storage Kit Table of Contents     The Storage Kit Index

Attribute C Functions

Declared in: be/kernel/fs_attr.h

Library: libroot.so

The BeOS supports a powerful system of attributes that can be attached to files. Once these attributes are attached, you can query the file system for attributes whose values match certain specifications; this is discussed in the section on the fs_query functions, and in the section on the BQuery class.

Before you can perform these queries, however, you need to attach attributes to the file. There are two ways to do this. The typical mechanism for attaching attributes to files is through the BNode class, which provides a convenient interface for doing this. This section discusses the lower-level way to do this, by calling the C fs_attr functions directly.

This collection of functions also lets you look at the attributes attached to a file, get their names and sizes, and read their contents.

The fs_attr functions make use of directory pointers (DIR *). While these are true directory pointers, the data they hold aren't useful outside the fs_attr API; they're basically magic cookies that represent the file's attribute directory. Likewise, the dirent structures returned by some of these functions are also not useful outside this API.


An Example

Before dropping straight into the reference on the fs_attr API, let's have a look at a simple sample of how to use some of its features. The sample code fragment below opens the attribute directory for a file named /boot/home/dirtylaundry and scans through all the attributes in the file, fetching their names and values.

   DIR *d;
   dirent_t *ent;
   attr_info info;
   int fd;
   char *buffer;
   
   d = fs_open_attr_dir("/boot/home/dirtylaundry");
   if (d) {
      while (ent = fs_read_attr_dir(d)) {
      fd = open("/boot/home/dirtylaundry", O_RDONLY);
      fs_stat_attr(fd, ent->d_name, &info);
      buffer = (char *) malloc((size_t) info.size);
      if (buffer) 
         fs_read_attr(fd, ent->d_name, info.type, 0, buffer,
                info.size);
      ...
      close(fd);
      fs_close_attr_dir(d);
   }

This snippet begins by opening the attribute directory for the file, using the fs_open_attr_dir() function. If this is successful, it returns a pointer to a directory that contains the list of attributes. A while loop is used to read into ent each attribute from the attribute directory by calling fs_read_attr_dir(). The information this call provides includes the size and type of the attribute, as well as its name.

Once we know the name of the attribute, we can obtain the type and size of the attribute by calling fs_stat_attr(); now we have all the information needed to get the value of the attribute. After allocating a buffer to contain the value of the attribute, we pass the attribute's name (ent->d_name), and the type and size (info.type and info.size) into the fs_read_attr() function. The value of the attribute is stored in the buffer we specify.

This sample skimps a bit on error handling; you'll do better, of course.


Attribute Functions


fs_close_attr_dir

                                                         
  

int fs_close_attr_dir(DIR *dirp)

Closes the specified attribute directory. You should pass into this function the pointer returned when you called fs_open_attr_dir() or fs_fopen_attr_dir().

If successful, this function returns 0; otherwise it returns -1 and sets errno to a descriptive code.


fs_fopen_attr_dir() see fs_open_attr_dir()


fs_open_attr_dir() , fs_fopen_attr_dir()

                                                         
  

DIR *fs_open_attr_dir(const char *path)

DIR *fs_fopen_attr_dir(int fd)

Opens the attribute directory for the file specified by pathname or file descriptor.

The attribute directory for a file contains a list of the attributes that are attached to the file. Once the attribute directory is open, you can use the fs_read_attr_dir() function to find out which attributes are present.

If the directory is opened successfully, a pointer to the directory structure is returned. This pointer should be passed to the other fs_attr functions to read entries from the attribute directory, as well as to close the directory when you're finished with it.

If an error occurs while opening the attribute directory, this function returns NULL and sets errno to one of the values listed below.


fs_read_attr

                                                         
  

ssize_t fs_read_attr(int fd,
      const char *attribute,
      uint32 type,
      off_t pos,
      void *buffer,
      size_t count)

Reads the attribute of the type and name specified by type and attribute from the file descriptor fd. The attribute's data is read starting at the offset pos and stored in the buffer. count specifies the maximum number of bytes to be read.

The type can be any of the standard BeOS type definitions, such as B_STRING_TYPE. See the header file be/support/TypeConstants.h for a complete list of these types. Note that the type of the attribute is a hint only; there's no reason you can't read a B_STRING_TYPE attribute as an integer (except that the data would probably not make any sense if you did).

If the attribute is read successfully, fs_read_attr() returns the actual number of bytes of data read from the attribute into the buffer. If an error occurs, this function returns -1 sets errno to an appropriate value.


fs_read_attr_dir

                                                         
  

struct dirent *fs_read_attr_dir(DIR *dirp)

Reads the current attribute from the specified attribute directory, and bumps the dirp so it points to the next attribute. The dirp pointer that you pass to this function should have been retrieved through a previous call to fs_open_attr_dir() or fs_fopen_attr_dir().

A pointer to a dirent structure is returned. This structure contains information about the attribute. Do not dispose of or alter the data contained by this pointer; it belongs to the operating system.

Once a file's attribute directory has been opened, you can loop over this function to iteratively retrieve the names of all the attributes in the file. An attribute's name is recorded in the d_name field of the dirent structure; see the example in  "An Example" on page193.

This function doesn't let you get the type or value of an attribute. For that, use fs_stat_attr().

If you're looking for files that have a particular value for one or more attributes, however, you should try using the fs_query functions, which allow you to more easily establish complex search operations on the values of one or more attributes.

If an error occurs (including reaching the end of the directory), this function returns NULL.


fs_remove_attr()

                                                         
  

int fs_remove_attr(int fd, const char *attribute)

Deletes the named attribute from the file given by the file descriptor fd.

If the function is successful, fs_remove_attr() returns 0. Otherwise, it returns -1 and sets errno to an appropriate value.


fs_rewind_attr_dir()

                                                         
  

int fs_rewind_attr_dir(DIR *dirp)

Rewinds the attribute directory to the beginning. This lets you start over again at the top of a file's attribute directory and read your way down toward the bottom.

Returns a result code specifying whether or not the operation was successful.

 
Unlike most of the other file system C functions, fs_rewind_attr_dir() doesn't set errno.


RETURN CODES


fs_stat_attr

                                                         
  

int fs_stat_attr(int fd,
      const char *name,
      struct attr_info *info)

Returns, in the attr_info structure pointed to by info, the type and size of the specified attribute on the file whose descriptor is specified by fd.

The attr_info structure is defined as follows:

   typedef struct attr_info
   {
      uint32      type;
      off_t      size;
   }

type contains a code defining the format of the data contained by the attribute; standard values for this field are defined in the be/support/TypeConstants.h header file.

size specifies the size of the data the attribute contains.

Upon success, the function returns 0. Otherwise, it returns -1 and sets errno to an appropriate value.


fs_write_attr()

                                                         
  

ssize_t fs_write_attr(int fd,
      const char *attribute,
      uint32 type,
      off_t pos,
      const void *buffer,
      size_t count)

Sets the value of the named attribute to the data in the specified buffer. The data's type is specified by type and should be one of the codes defined in be/support/TypeConstants.h. The length of the data to be written is specified by count.

 
At this time, writing at an offset within an attribute is not fully supported, so you should always specify a pos of 0 to write at the beginning of the attribute.


If the attribute already has a value, this function wholly replaces that value with the new data—even if the new data is smaller than the existing data.

 
Under the Be File System, files have a special attribute storage area which contains the smaller attributes. When this space is filled up, or an attribute too large to fit into the space is added to the file, additional disk blocks are allocated for the new attributes. However, only one attribute is written per block in these additional blocks. The moral of the story is: use attributes wisely. They can be your friends, but if you overuse them, you'll bloat your files.


Upon success, the function returns the number of bytes that were actually written. Otherwise, it returns -1 and sets errno to an appropriate value.


The Storage Kit Table of Contents     The Storage Kit Index


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

Copyright © 2000 Be, Inc. All rights reserved..