| iMatix home page
| << | < | > | >>
SFL Logo SFL
Version 2.11

 

file_where_ext

#include "sflfile.h"
char *
file_where_ext (
    char mode,
    const char *path,
    const char *name,
    const char **ext)

Synopsis

Scans a user-specified path symbol for a specific file, and returns the fully-specified filename. Can also scan a series of file extensions while looking for the file in the path. The extensions are scanned in each directory in the path prior to moving on to the next directory. The mode argument can be one of: r, w, a, or s for read, write, append, or static. The function tries to locate existing files somewhere on the path. New files are always created in the current directory. Static files are created in the first directory on the path. The path argument is only used when mode is r, a, or s. If the path is NULL or empty, it is ignored. Otherwise, the path is translated as an environment variable. If the path cannot be translated, it is used as a literal value. The path is then cut into a list of directory names, as follows:
MS-DOS directory names separated by ';'. ;; means current.
OS/2 directory names separated by ';'. ;; means current.
Unix directory names separated by ':'. :: means current.
VMS directory names separated by ','. " ", means current.
Other single directory name.
When the mode is 'r' or 'a', it searches the current directory before considering the path value. The name argument is the filename with or without extension. It will be prefixed by the path and suffixed by the extension, if required. The ext argument is an array of default or mandatory extensions. If the extension starts with a dot, it is mandatory and will override any existing extension. Otherwise it is used only if the name does not already have an extension. The filename will be tried as supplied if ext is NULL, or if it has an extension, and one or more of the entries is a default extension. The first extension, if any, is always used in 'w' mode and 's' mode. The last path component and extension will be used in 'a' mode, if either is supplied. The total length of a name including path, name, extension, and any delimiters is FILE_NAME_MAX. Names are truncated if too long. The maximum size of one directory component is FILE_DIR_MAX chars. All parameters are case-sensitive; the precise effect of this depends on the system. On MS-DOS, filenames are always folded to uppercase, but the path must be supplied in uppercase correctly. On UNIX, all parameters are case sensitive. On VMS, path and filenames are folded into uppercase. Returns a pointer to a static character array containing the filename; if mode is 'r' and the file does not exist, returns NULL. If the mode is 'w', 'a', or 's', always returns a valid filename. Under VMS, all filenames are handled in POSIX mode, i.e. /disk/path/file instead of $disk:[path]file.

Source Code - (sflfile.c)

{
    const char
        *pathptr;                       /*  End of directory in path         */
    const char
        **extptr;                       /*  Pointer to next extension        */
    char
        *curdir;
    Bool
        search_curdir = TRUE;           /*  Look in current directory?       */

    ASSERT (name);
    if (!name)
        return NULL;

    if (path != NULL && *path)          /*  Get value of path, or NULL       */
      {
        pathptr = getenv (path);        /*  Translate path symbol            */
        if (pathptr == NULL)
          {
            pathptr = path;             /*  If not found, use literally      */
            search_curdir = FALSE;      /*  Path now takes priority          */
          }
#if (PATHFOLD == TRUE)                  /*  Fold to uppercase if necessary   */
        if (pathptr)
          {
            ASSERT (strlen (pathptr) < PATH_MAX);
            strcpy (path_name, pathptr);
            strupc (path_name);
            pathptr = path_name;        /*  Redirect to uppercase version    */
          }
#endif
      }
    else
        pathptr = NULL;

#if (defined (MSDOS_FILESYSTEM))
    /*  Normalise the path value by changing any slashes to backslashes      */
    if (pathptr)
      {
        if (pathptr != path_name)
          {
            strcpy (path_name, pathptr);
            pathptr = path_name;
          }
        strconvch (path_name, '/', '\\');
      }
#endif

    /*  Take care of 'w' and 's' options first                               */
    if (mode == 'w')                    /*  Create output file locally       */
      {
        if (ext != NULL && ext [0] != NULL)
            add extension (work_name, name, ext [0]);
        else
            strcpy (work_name, name);
#if (NAMEFOLD == TRUE)
        strupc (work_name);             /*  Fold to uppercase if needed      */
#endif

        return (work_name);
      }

    if (mode == 's')                    /*  Get specific directory name      */
      {
        if (ext != NULL && ext [0] != NULL)
            add extension (work_name, name, ext [0]);
        else
            strcpy (work_name, name);
#if (NAMEFOLD == TRUE)
        strupc (work_name);             /*  Fold to uppercase if needed      */
#endif

        if (fully_specified (work_name))
            strcpy (full_name, work_name);
        else
        if (pathptr && file is directory (pathptr))
            build_next_path (full_name, pathptr, work_name);
        else
#if (defined (MSDOS_FILESYSTEM))
            build_next_path (full_name, ".\\", work_name);
#else
            build_next_path (full_name, "./", work_name);
#endif
        return (full_name);
      }

    /*  If file exists as defined (with one of the extensions), prefix with  */
    /*  current directory if not an absolute filename, then return the       */
    /*  resulting filename                                                   */
    if (search_curdir)
      {
        extptr = ext;
        do
          {
            if (extptr != NULL && *extptr != NULL)
                add extension (work_name, name, *extptr);
            else
                strcpy (work_name, name);
#if (NAMEFOLD == TRUE)
            strupc (work_name);         /*  Fold to uppercase if needed      */
#endif

            if (file exists (work_name))
              {
                if (fully_specified (work_name))
                    strcpy (full_name, work_name);
                else
                  {
                    curdir = get curdir ();
                    snprintf (full_name, sizeof (full_name),
			                 "%s%s", curdir, work_name);
                    mem_free (curdir);
                  }
#if (defined (MSDOS_FILESYSTEM))
                strconvch (full_name, '/', '\\');
#endif
                return (full_name);     /*  Then return path + name + ext    */
              }

            if (extptr)
                extptr++;
          }
         while (extptr != NULL && *extptr != NULL);
      }

    if (!pathptr)                       /*  We need a path to look further   */
        return (NULL);                  /*   - if none defined, give up      */

    for (;;)                            /*  Try each path component          */
      {                                 /*   - and extension within that     */
        const char *savedptr = pathptr;
        extptr = ext;

        do
          {
            const char *extension = NULL;

            if (extptr != NULL && *extptr != NULL)
                extension = *extptr;

            pathptr = build_next_path_ext (full_name, savedptr,
                                           name,      extension);

            if (file exists (full_name))
                return (full_name);     /*  Until we find one that matches   */

            if (extptr)
                extptr++;
          }
        while (extptr != NULL && *extptr != NULL);

        if (*pathptr == '\0')           /*    or we come to the end of       */
          {                             /*    the path                       */
            if (mode == 'r')
                return (NULL);          /*  Input file was not found...      */
            else
                return (full_name);
          }
      }
}

| << | < | > | >> iMatix Copyright © 1996-2000 iMatix Corporation