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

 

file_where

#include "sflfile.h"
char *
file_where (
    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. Also adds an extension if this is required. 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 more is r, a, or s. If the path is NULL or empty, it is ignored. Otherwise, the path is translated as an environment variable, and cut into a list of directory names. The path is cut up 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', searches the current directory before considering the path value. When the path cannot be translated, and is not null or empty, it is used as a literal 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 a default or mandatory extension. If ext starts with a dot, it is mandatory and always used. Otherwise it is used only if the name does not already have an extension. If ext is NULL or empty, it is ignored. 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         */
    char
        *curdir;
    Bool
        search_curdir = TRUE;           /*  Look in current directory?       */

    ASSERT (name);
    if (ext != NULL && *ext)            /*  Append extension if not null     */
      {                                 /*    to get name + ext into         */
        if (ext [0] == '.')             /*    work_name.                     */
            fixed extension (work_name, name, ext);
        else
            default extension (work_name, name, ext);
      }
    else
        strcpy (work_name, name);
#if (NAMEFOLD == TRUE)
    strupc (work_name);                 /*  Fold to uppercase if needed      */
#endif

    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       */
        return (work_name);

    if (mode == 's')                    /*  Get specific directory name      */
      {
        if (fully_specified (work_name))
            strncpy (full_name, work_name, sizeof (full_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, prefix with current directory if not an   */
    /*  absolute filename, then return the resulting filename                */
    if (search_curdir && file exists (work_name))
      {
        if (fully_specified (work_name))
            strncpy (full_name, work_name, sizeof (full_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 (!pathptr)                       /*  Now we need a path               */
        return (NULL);                  /*   - if none defined, give up      */

    for (;;)                            /*  Try each path component          */
      {
        pathptr = build_next_path (full_name, pathptr, work_name);
        if (file exists (full_name))
            return (full_name);         /*  Until we find one,               */

        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