When we handle file-system directories, we have to call apr_dir_open() at first. By apr_dir_open(), we have an apr_dir_t object. All we can do with apr_dir_t is to scan the directory. The API is apr_dir_read(). Finally, we call apr_dir_close() to close the directory. The prototype declarations are as follows:
/* excerpted from apr_file_info.h */
APR_DECLARE(apr_status_t) apr_dir_open(apr_dir_t **new_dir,
const char *dirname,
apr_pool_t *pool);
APR_DECLARE(apr_status_t) apr_dir_read(apr_finfo_t *finfo, apr_int32_t wanted,
apr_dir_t *thedir);
APR_DECLARE(apr_status_t) apr_dir_close(apr_dir_t *thedir);
The first argument of apr_dir_open() is result argument. By which, we can get a newly created apr_dir_t object. The second argument is directory name. The third argument is memory pool to use.
The first argument of apr_dir_read() is result argument. As mentioned earlier, apr_finfo_t is complete type. Thus, we have to allocate its memory explicitly. apr_dir_read() returns an entry of the directory by apr_finfo_t. The entry is either file or directory. The second argument is bit-wised flag. The flags are defined in apr_file_info.h with APR_FINFO_ prefix, such as APR_FINFO_SIZE, APR_FINFO_TYPE and APR_FINFO_NAME. The third argument is apr_dir_t object to scan.
Here is a sample code:
/* pseudo code about apr_dir_read() */
/* no error checks */
apr_pool_t *mp;
apr_pool_create(&mp, NULL);
const char *dirpath = "/home";/* directory path to scan */
apr_dir_t *dir;
apr_dir_open(&dir, dirpath, mp);/* create the apr_dir_t object */
apr_finfo_t dirent;
apr_dir_read(&dirent, APR_FINFO_DIRENT, dir);/* the apr_finfo_t object filled */
/* dirent is the first entry of the directory.
* the entry is either file or directory. */
apr_dir_close(dir);
In the sample code above we call apr_dir_read() only once, but we usually call apr_dir_read() multiple times to scan all files under the directory. To scan all files, we just keep calling apr_dir_read() while it returns APR_SUCCESS. Take a look at dir-sample.c about precise usage.
/* pseudo code about apr_dir_read() loop. error checks omitted */
/* typical while loop of apr_dir_read() */
apr_dir_open(&dir, dirpath, mp);
while ((apr_dir_read(&dirent, APR_FINFO_NAME, dir)) == APR_SUCCESS) {
printf("file name is %s\n", dirent.name);
}
apr_dir_close(dir);
As you can imagine, apr_dir_t object has the current position. Calling apr_dir_read() makes the position move forward. We can rewind the (internal)position by apr_dir_rewind(). All the operations we can do with the position are just these two, moving forward and rewinding.
As you see in dir-sample.c, if you scan directories recursively, you need to call apr_dir_open() recursively.
REMARK: On Unix, apr_dir_read() returns apr_finfo_t object whose apr_file_t::fname is NULL