Directory Scanning Library Module

The directory scanning library module has the file name dscan.c.

# Introduction

The directory scanning module/API will traverse one or more directories from a specific entry point matching file/directory names. This API is multi-platform. It will compile and run in under any OS that supports the POSIX 1003.1 directory system calls. This includes 16bit DOS, 32bit Windows, QNX (both RtP and 4.x), all versions of Unix and Mac OS X. This API does not use recursion to traverse the directory tree and is not subject to stack limitations and excessive memory consumption typical with recursive algorithms. Files and directory names are compared using the pmatch library function which supports using wildcards for pattern matching.

Here is a list of functions in the directory scanning module:

- dscan_findfirst
- dscan_findnext
- dscan_end
- dscan_ll_debug
- dscan_find
- dscan_sub
- dscan_add_sub
- dscan_chop_path
- dscan_match
- dscan_umatch
- dscan_set_flags
- dscan_set_current_path
- dscan_ll_delete
- dscan_ll_delete_all
- dscan_set_mvars
- dscan_delete_mvars
- dscan_ll_find
- dscan_ll_add
- dscan_header

# Using the API

To use the API, you start by calling the function dscan_findfirst which will initialize all the module variables. You should then enter a loop which will call the function dscan_findnext. Here is a simple sample program:

    #include "stdhead.h"
    #include "dscan.h"

    int main(void);

    int main(void)
    {
       char fname[1024];
       int ret;

       if ((ret = dscan_findfirst("/", "*.log", "fds", fname)) == 0)
          {
          printf("not found\n");
          return(0);
          }

       printf("found:ret=%d,fname=%s[%d]\n", ret, fname, strlen(fname));

       do
          {
          ret = dscan_findnext(fname);

          if (ret != 0)
             printf("found:ret=%d,fname=%s[%d]\n", ret, fname, strlen(fname));
          }
       while(ret != 0);

       return(0);
    }

You supply the scanning criteria to the dscan_findfirst function. The first parameter is the starting point in file system. The second parameter indicates what names to match including any wildcards. The third parameter consists of the flags and the last parameter is where the name (full path and name) of the found item is returned. Both dscan_findfirst and dscan_findnext will return a non-zero value if a match is found. The return code identifies the item type (file, directory or symbolic link). The type codes are defined in the header file dscan.h as:

       DSCAN_TYPE_FILE
       DSCAN_TYPE_DIR
       DSCAN_TYPE_SYMLINK

The flags (third) parameter may consist of any of the flags:

       f - scan for files
       d - scan for directories
       s - include sub-directories
       l - scan for symbolic links

One of f, d or l must be supplied. Scanning support for symbolic links is only available in Unix or Unix-like operating systems.

In the above example (based on Unix), the starting point is the root (/) searching for files (f) and directories (d) that have the .log extension. Sub-directories will also be scanned.

The dynamic memory that is used by dscan will automatically be de-allocated when there are no longer any matching items. If, however, you do not repeatedly call dscan_findnext, to logically conclude the scan, the memory in use by dscan will remain allocated. In this case, call the function dscan_end to force dscan to de-allocate all memory used.

Keep in mind that dscan may take some time to locate specific item(s) especially if a large disk with many files and directories is being scanned. Dscan has been built to use the logging manager if it is active. If you really want to know exactly what dscan is doing, just enable the log and be prepared for much information.

# Theory of Operation

Dscan maintains a link list of all directories currently being scanned. It starts by scanning the initial directory supplied in the function dscan_findfirst. All items in the directory are compared. The name of each sub-directory located is placed in a string delimited by DSCAN_SUB_DELIM. When there are no more items in the directory, each sub-directory name is appended to the current path and scanned again. When there are no more sub-directories, one level is removed from the current path and the cycle starts over again. Each time a specific directory has no more sub-directories to scan. It's entry in the link list is deleted.

This method has the benefit of very low memory consumption. The maximum number of items in the link list is tied directly to the depth of a specific directory structure. All link list and string memory in this API is dynamically allocated.

# Platform Specific Notes

Dscan operates on every platform in the same basic way. There are, however, some differences:

## 16bit DOS

When running under 16bit DOS, no support is available for Windows long file names. You may run a 16bit DOS version under 32bit Windows but the file names returned will always be the short names (8.3).

In keeping with the nature of DOS file names, file and directory comparisons are case insensitive.

## 32bit Windows

Like 16bit DOS, file and directory comparisons are case insensitive.

## Linux/Unix/QNX and Unix-like

Directory symbolic links are not traversed. This API detects the links themselves not the file or directory that the link points to

In keeping with the Unix-like OS, file and directory comparisons are case sensitive.

# Module Dependencies

The following modules are required along with this module:

- parse.c
- logger.c
- logman.c

# Module Header Files

This module requires the header files:

- stdhead.h
- dscan.h

# Module Functions

## dscan_findfirst

    Prototype  : int dscan_findfirst(char *p, char *fn, char *fl, char *rn)
    Parameters :
          Name : p
    Description: starting path

          Name : fn
    Description: name/pattern to locate

          Name : fl
    Description: scan flags (f, d, s, l)

          Name : rn
    Description: returned item full path and name

    Returns    : DSCAN_TYPE_FILE, DSCAN_TYPE_DIR or DSCAN_TYPE_SYMLINK upon match, zero otherwise

This function should be called first when starting a directory scan. The scan will proceed from the starting path continuing until a match is found or until there are no more directories to scan.

## dscan_findnext

    Prototype   : int dscan_findnext(char *rn)
    Parameters  :
          Name  : rn
    Description : returned item full path and name

    Returns     : DSCAN_TYPE_FILE, DSCAN_TYPE_DIR or DSCAN_TYPE_SYMLINK upon match, zero otherwise

This function will scan for subsequent files or directories. The function dscan_findfirst must have already been called first to initialize the scan.

## dscan_end

    Prototype   : void dscan_end(void)

This function will delete the scan link list and de-allocate all memory in use by dscan. Normally, when the scan process is brought to a natural conclusion (no more items found), dscan will automatically de-allocate its own memory. If however, you stop the scan before all items have been found, the memory used by dscan is still allocated. By calling this function, you can force dscan to release all used memory.

## dscan_ll_debug

    Prototype   : void dscan_ll_debug(void)

This function will output the entire current contents of the scan link list to the current log destination. For this function to operate properly, the logging manager must have already been started by calling the function logman_start.

## dscan_find

    Prototype   : static int dscan_find(char *fname)
    Parameters  :
          Name  : fname
    Description : output full path and name

    Returns     : DSCAN_TYPE_FILE, DSCAN_TYPE_DIR or DSCAN_TYPE_SYMLINK upon match, zero otherwise

This private function will scan the current directory for an item match.

## dscan_sub

    Prototype   : static int dscan_sub(void)

    Returns     : TRUE if another directory was located, FALSE otherwise

This private function will first attempt to obtain the name of one of the sub-directories in the current path that has been stored in the link list. If that fails, one directory level is removed from the current path.

## dscan_add_sub

    Prototype   : static void dscan_add_sub(struct dscan_entry *r, char *d)
    Parameters  :
          Name  : r
    Description : link list pointer to the current directory

          Name  : d
    Description : directory name (no path)

This private function will add the name of a sub-directory to the list of sub-directory names. The list of sub-directories is contained within a string in the link list delimited by DSCAN_SUB_DELIM.

## dscan_chop_path

    Prototype   : static int dscan_chop_path(void)

    Returns     : TRUE upon success, FALSE otherwise

This function will remove one directory level from the current path.

## dscan_match

    Prototype   : static int dscan_match(char *pat, char *fname)
    Parameters  :
          Name  : pat
    Description : pattern

          Name  : fname
    Description : file or directory name to match

    Returns     : TRUE upon match, FALSE otherwise

This function will perform a match of the file or directory name to match against the pattern. The Windows and DOS platforms will call dscan_umatch to perform a case insensitive match. This function will perform a case sensitive match. The actual pattern match is performed by the parse module function pmatch.

## dscan_umatch

    Prototype   : static int dscan_umatch(char *pat, char *fname)
    Parameters  :
          Name  : pat
    Description : pattern

          Name  : fname
    Description : file or directory name to match

    Returns     : TRUE upon match, FALSE otherwise

This private function will perform a match of the file or directory name to match against the pattern. This function will perform a case insensitive match. The actual pattern match is performed by the parse module function pmatch.

## dscan_set_flags

    Prototype   : static int dscan_set_flags(char *flags)
    Parameters  :
          Name  : flags
    Description : scan flags

    Returns     : TRUE upon success, FALSE otherwise

This private function will set the module global scan flags based on the supplied scan flags.

## dscan_set_current_path

    Prototype   : static int dscan_set_current_path(char *p)
    Parameters  :
          Name  : p
    Description : directory path

    Returns     : TRUE upon success, FALSE otherwise

This private function will set the global current path to the directory path.

## dscan_ll_delete

    Prototype   : static void dscan_ll_delete(char *p)
    Parameters  :
          Name  : p
    Description : full directory path

This private function will delete the full directory path entry from the link list.

## dscan_ll_delete_all

    Prototype   : static void dscan_ll_delete_all(void)

This private function will delete all entries in the link list.

## dscan_set_mvars

    Prototype   : static int dscan_set_mvars(char *p, char *f)
    Parameters  :
          Name  : p
    Description : starting directory path

          Name  : f
    Description : target file name/pattern

    Returns     : TRUE upon success, FALSE otherwise

This private function will set the module global variables to the supplied starting directory and the target file name/pattern.

## dscan_delete_mvars

    Prototype   : static void dscan_delete_mvars(void)

This private function will de-allocate the module global variables.

## dscan_ll_find

    Prototype   : static struct dscan_entry *dscan_ll_find(char *p)
    Parameters  :
          Name  : p
    Description : directory path

    Returns     : pointer to the link list upon success, NULL otherwise

This private function will attempt to locate a link list entry by the directory path.

## dscan_ll_add

    Prototype   : static struct dscan_entry *dscan_ll_add(char *p)
    Parameters  :
          Name  : p
    Description : directory path

    Returns     : pointer to the link list upon success, NULL otherwise

This private function will add an entry to the link list with the supplied directory path.

## dscan_header

    Prototype   : static void dscan_header(char *mname)
    Parameters  :
          Name  : mname
    Description : function name

This private function will create a log entry (if enabled) to indicate entry into a dscan function.

Goto Top | GPL Software Overview | GPL Library
Future Lab Home | Contact Webmaster | Feedback

Copyright © 2001-2006 Future Lab, Last Updated Jun 30, 2006