# The Storage Kit: Attribute C Functions

Declared in: be/kernel/fs_attr.h

Library: libroot.so

## Overview

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.

- `B_FILE_ERROR`. Invalid directory reference specified.

### 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.

- `B_FILE_ERROR`. Invalid file descriptor, or a file error prevented the operation.
- `B_ENTRY_NOT_FOUND`. No matching attribute was found for the specified file.
- `B_NAME_TOO_LONG`. path is longer than `B_PATH_NAME_LENGTH` characters.
- `B_LINK_LIMIT`. A loop was detected in the directory structure.
- `B_NO_MEMORY`. Insufficient memory to complete the operation.
- `B_BUSY`. The specified file is currently in use.
- `B_NO_MORE_FDS`. Too many open files; all file descriptors are in use.

### 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.

- `B_FILE_ERROR`. Invalid file descriptor fd specified.
- `B_ENTRY_NOT_FOUND`. No matching attribute was found for the specified file descriptor.

### 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 .

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`.

- `B_FILE_ERROR`. Invalid directory reference specified.
- `B_NOT_A_DIRECTORY`. The attribute directory is invalid.
- `B_ENTRY_NOT_FOUND`. You've reached the end of the attribute directory.

### 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.

- `B_FILE_ERROR`. fd is invalid, or file opened with read-only access.
- `B_BAD_VALUE`. Invalid attribute name specified.
- `B_NOT_ALLOWED`. Disk containing the file is read-only.
- `B_ENTRY_NOT_FOUND`. No matching attribute was found.

### 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

- `B_OK`. Success.
- `B_FILE_ERROR`. Invalid directory reference specified.

### 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.

- `B_ENTRY_NOT_FOUND`. The requested attribute was not found for the file.
- `B_FILE_ERROR`. Invalid file descriptor specified.

### 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.

- `B_BAD_VALUE`. The attribute name is too long or is an empty string.
- `B_NO_MEMORY`. Insufficient memory to complete the operation.
- `B_FILE_ERROR`. Invalid file descriptor fd specified, or the the file is read-only.

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

Copyright © 1998 Be, Inc. All rights reserved.

Last modified March 26, 1998.