# The Storage Kit: Index C Functions

Declared in: be/kernel/fs_index.h

Library: libroot.so

## Overview

Before a query can be performed on a file system, indices need to be established in which to search. An index contains a list of files that can be searched given a particular attribute and the desired value.

An index directory is, essentially, a list of the indices on a particular disk; it keeps track of the attributes that can be searched upon. Each disk has its own index directory. For instance, a disk might have the following indices in its index directory:

- MAIL:subject
- MAIL:from
- MAIL:to
- MAIL:priority

Each of these is the name of an index that can be queried using either the `fs_query` API or the BQuery class.

For example, if an e-mail program wishes to allow searching on the name of the sender of a message, it needs to create an index for the "sender" attribute. Once this index is established, any file that has the "sender" attribute added to it will be added to the "sender" index.

Files which had the "sender" attribute attached before the "sender" index was created, however, will not be in the index until their "sender" attribute is updated, at which time they will be added to the index. For this reason, you should consider installing your indices when your application is installed, or when it is initially launched.

Since each disk has its own index directory, if you want all disks to have your indices available, you need to create them on each device. You can do this by using the functions described here in conjunction with the `fs_info` functions.

There are three indices that are present on every disk:

Index | Meaning
name | The name of the file.
size | The size, in bytes, of the file.
last_modified | The date the file was last changed.

You can always perform queries in these indices. Their names are reserved; you can't create or remove indices by these names.

### The Index Directory

The following sample function opens the index directory for a specified device and, in a loop, reads every entry, printing their names to standard output. This presents a list of each index available on the disk.

       void ListIndex(int32 device)
       {
          DIR *d;
          index_info info;
          struct dirent *ent;

          d = fs_open_index_dir(device);
          if (!d) {
             fprintf(stderr, "Unable to open index.\\n");
             return;
          }

          while (ent = fs_read_index_dir(d)) {
             printf("%s\\n", ent->d_name);
          }
          fs_close_index_dir(d);
       }

After calling `fs_open_index_dir()` to open the index directory for the device passed into the function (and handling the error that might occur if that function fails), a `while` loop iterates through all the entries in the directory, calling `fs_read_index_dir()` to obtain the desired information, then printing that information to standard output.

When there are no indices left, `fs_read_index_dir()` returns `NULL` and the `while` loop exits. At this point, `fs_close_index_dir()` is called to close the index directory.

### Installing and Removing Indices

To install a new index, use the `fs_create_index()` function. For example, to create an index for the attribute "GOLF:Handicap" on device 4 you would do this:

       fs_create_index(4, "GOLF:Handicap", B_INT16_TYPE, 0);

This creates an empty index for the golf handicap attribute, which is stored as a 16-bit integer. Once the index has been created, any file that gets a "GOLF:Handicap" attribute added or changed will be indexed.

(You usually shouldn't hard-code a device number, of course; you can obtain a device number for a specific disk by using the `fs_info` functions or `stat()`.)

If you later need to remove the index, you can do so by calling `fs_remove_index()`, like this:

       fs_remove_index(4, "GOLF:Handicap");

You should be careful when deciding to delete an index. If the user still has files around that contain indexed attributes that they want to be able to search for--using the Find panel in the Tracker, for example--they will not be able to do so after the index has been removed. So you need to decide when it is appropriate to remove indices; the choice is yours, but choose wisely, or you might annoy users.

## Index Functions

### fs_close_index_dir()

          int fs_close_index_dir(DIR *dirp)

Closes the specified index directory and frees dirp. You should pass into this function the pointer returned from a previous `fs_open_index_dir`().

You should always use this function to close index directories after you finish using them.

If successful, this function returns 0; otherwise it returns -1and sets `errno` to one of the following codes.

- `B_FILE_ERROR`. Invalid directory reference specified.
- `B_BAD_FILE`. Invalid directory reference specified.

### fs_create_index()

          int fs_create_index(dev_t device,
             const char *name,
             int type,
             uint flags)

Creates a new index called name on the specified device. Once this has been done, adding an attribute named name to a file causes the file to be added to the name index, such that subsequent queries will be able to search for files that contain the name attribute.

type indicates the kind of data the attribute will contain. Standard types are defined in the be/support/TypeConstants.h header file.

flags is currently unused and should always be 0.

If successful, this function returns 0; otherwise it returns -1and sets `errno` to one of the following codes.

- `B_BAD_VALUE`. The device does not exist, or name is reserved.
- `B_NOT_ALLOWED`. The device is read-only.
- `B_NO_MEMORY`. Insufficient memory to complete the operation.
- `B_FILE_EXISTS`. The index name already exists.
- `B_DEVICE_FULL`. There's not enough room on the device to create the index.
- `B_FILE_ERROR`. Invalid directory reference.

### fs_open_index_dir()

          DIR *fs_open_index_dir(dev_t device)

Opens the index directory for the volume identified by device. Once open, you can retrieve the names of the indices on the volume by calling `fs_read_index_dir()`.

When you have finished using the index directory, call `fs_close_index_dir()` to close it.

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

If an error occurs while opening the index directory, this function returns `NULL` and sets `errno` to an appropriate value.

- `B_FILE_ERROR`. A file error prevented the operation.
- `B_BAD_VALUE`. Invalid device number specified.
- `B_LINK_LIMIT`. A cyclic 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_index_dir()

          struct dirent *fs_read_index_dir(DIR *dirp)

Reads the current entry from the open index directory referenced by dirp, and bumps the pointer to point to the next entry. dirp should have been obtained through a previous call to `fs_open_index_dir()`. The returned `dirent` pointer contains information about the index entry, including the name of the attribute represented by the index. This pointer belongs to the system; you must not delete it.

Through repeated calls to `fs_read_index_dir()`, you can obtain a list of all the indices available on the device. When you reach the end of the list, errno is set to `B_ENTRY_NOT_FOUND`.

If an error occurs, this function returns `NULL` and sets `errno` to an appropriate value.

- `B_FILE_ERROR`. Invalid file descriptor fd specified.
- `B_NOT_A_DIRECTORY`. dirp does not represent a valid index directory.
- `B_ENTRY_NOT_FOUND`. You've reached the end of the list.

### fs_remove_index()

          int fs_remove_index(dev_t device, const char *index_name)

Deletes the index named index_name from the specified device. Once the index is deleted, it will no longer be possible to use the query system to search for files with the corresponding attribute.

Use this function to remove an index that you no longer wish or need to be able to search upon. For example, if your application is being uninstalled by your user-friendly uninstaller program, and it's no longer meaningful to be able to search on a given attribute, you should use this function to delete the index for that attribute.

You should be careful when deciding whether or not to delete an index, however. If the user still has files around that they want to be able to search, using the Tracker's Find panel, for instance, and you've deleted the index for that attribute, they'll be most displeased. There's a grey area you need to wade through in determining whether or not to delete your indices; your decision needs to be based on the specifics of what your application does and how it will be used.

If the index is removed successfully, `fs_remove_index()` returns 0. Otherwise, it returns -1 and sets `errno` to an appropriate value.

- `B_FILE_ERROR`. A file system error prevented the operation.

- `B_BAD_VALUE`. Invalid device number specified.

- `B_NOT_ALLOWED`. Can't remove a system-reserved index ("name," "size," "last_modified"), or the device is read-only.

- `B_NO_MEMORY`. Insufficient memory to complete the operation.

- `B_ENTRY_NOT_FOUND`. The specified index does not exist.

### fs_rewind_index_dir()

          int fs_rewind_index_dir(DIR *dirp)

Rewinds the specified index directory to the beginning of its list of indices. This allows you to start over again at the top of a device's index directory and make your way down toward the bottom.

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

|  | Unlike the most of the other file system functions, `fs_rewind_index_dir()` doesn't set `errno`.

RETURN CODES

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

### fs_stat_index()

          int fs_stat_index(dev_t device,
             const char *index_name,
             struct index_info *info)

Returns, in the `index_info` structure pointed to by info, information about the index named index_name on the specified device.

The `index_info` structure is defined as follows:

       typedef struct index_info
       {
          uint32      type;
          off_t      size;
          time_t      modification_time;
          time_t      creation_time;
          uid_t      uid;
          gid_t      gid;
       }

type contains a code defining the format of the data contained by the attribute represented by the index; 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.

- `modification_time` contains the time the index was last changed, in seconds since January 1, 1970.

- `creation_time` contains the date and time the index was originally created, in seconds since January 1, 1970.

- `uid` contains the user ID of the owner of the index.

- `gid` contains the group ID of the owner of the index.

If the function is successful, it returns 0; otherwise, it returns -1 and sets errno to an appropriate value

- `B_ENTRY_NOT_FOUND`. The requested index was not found.
- `B_BAD_VALUE`. Invalid device number specified.

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

Copyright © 1998 Be, Inc. All rights reserved.

Last modified March 26, 1998.