# The Storage Kit: Query C Functions

Declared in: be/kernel/fs_query.h

Library: libroot.so

## Overview

Normally, when you want to perform a file system query, you would use the BQuery class, which is a nice, clean, object-oriented way to do it. If you have an aversion to object-oriented programming, however, or you're writing a simple C program and would rather use C functions instead, then you've come to the right place.

Be aware that, currently, you can't perform "live" queries at the C level. If you want a live query, you have to use a BQuery object.

### Opening, Reading, and Closing a Query

To begin a query, you call `fs_open_query()`. `fs_open_query()` performs a "one-shot" query: It lets you ask for all the files that fulfill certain criteria right now. This criteria is expressed as a "predicate" string. This is a formula that lists the attribute values that you're interested in. A simple predicate takes the form

|  | attribute op value

For example, you can look for files that are larger than 5K by supplying a string that looks like this:

       "size > 5000"

Simple predicates can be grouped and combined to create more complex predicates. Here we look for files named "fido" that are greater than 5K:

       "(name = fido) && (size > 5000)"

For a full description of the predicate format, see The Predicate, Attributes, and Indices in the BQuery class description, but be aware of this difference:

- The `fs_query` functions don't let you "push" elements onto the predicate; all predicates must be expressed as strings.

Once the query has been opened, you can step through the files that fulfill the predicate through iterated calls to `fs_read_query()`. When all the winning files have been visited, `fs_read_query()` returns `NULL`.

When you've finished using your query, you must close it by using the `fs_close_query()` function.

### An Example

The following sample demonstrates very briefly how to perform a simple, non-live query. In this example, we're searching for all C header files on the device specified by devnum.

       void sample_query(dev_t devnum) {
          DIR      *q;
          dirent_t   *   d;

          q = fs_open_query(devnum, "name=*.h", 0);
          if (q) {
             while (d = fs_read_query(q)) {
             ...
             }
             fs_close_query(q);
          }
       }

The code opens the query by calling `fs_open_query()`, then, calls `fs_read_query()` in a loop until `NULL` is returned. Once that happens, `fs_close_query()` is used to close the query.

## Query Functions

### fs_close_query()

          int fs_close_query(DIR *dir)

Closes a query which was previously opened using the `fs_open_query()` function. You pass in the DIR * returned by either of these functions. The pointer dir is freed by this function.

If the query closes successfully, `fs_close_query()` returns 0; otherwise, it returns -1 and sets `errno` to an appropriate value.

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

### fs_open_query()

          DIR *fs_open_query(dev_t device,
             const char *query,
             uint32 flags)

Opens a new query on the specified device. The query string is the criteria or "predicate" that describes the files that you're looking for. For information on how to construct the query string, see the BQuery class. Note that you can't use the "push" method: fs_open_query() only understands predicate strings.

flags is currently unused; pass 0 as its value.

The pointer returned by this function is used to identify your query to the other query functions; you should not dispose of it yourself--this will be done for you when you call `fs_close_query()`. If the query couldn't be opened, the function returns `NULL` and sets `errno` to an appropriate value.

- `B_ENTRY_NOT_FOUND.,path` does not exist, or is `NULL` or an empty string.
- `B_BAD_VALUE`. device does not specify a valid device, query is `NULL` or an invalid expression, or a live query was requested without specifying a valid port.
- `B_NO_MEMORY`. Insufficient memory to complete the operation.
- `B_FILE_ERROR`. A file system error prevented the operation from succeeding.
- `B_BUSY`. A busy node could not be accessed.
- `B_NO_MORE_FDS`. All file descriptors are in use (too many open files).
- `E2BIG`. query expression is too big.

### fs_read_query()

          dirent *fs_read_query(DIR *d)

Returns the next item that matches the specified query. The d argument should have been gotten from a previous call to `fs_open_query()`; it identifies the particular query from which to read.

You mustn't free the pointer returned to you by this function.

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

- `B_FILE_ERROR`. A file system error prevented the operation from succeeding.
- `B_BAD_VALUE`. An error occurred processing the query predicate.
- `B_ENTRY_NOT_FOUND`. No more matches.
- `B_NOT_A_DIRECTORY`. A non-directory node was found where a directory was expected.
- `B_INTERRUPTED`. A signal interrupted the read.
- `E2BIG`. Query predicate is too big.

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

Copyright © 1998 Be, Inc. All rights reserved.

Last modified March 26, 1998.