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

 

resolve_path

#include "sfldir.h"
char *
resolve_path (
    const char *old_path)

Synopsis

Accepts a path consisting of zero or more directory names and optionally a filename plus extension. Removes '.' and '..' if they occur in the path. '..' is resolved by also removing the preceding directory name, if any. Returns the address of the resulting path, in a static area that is overwritten by each call. The returned path may be empty. Under OS/2 and MS-DOS, treats '\' and '/' both as directory separators. A '..' directory at the start of the path resolves into nothing. If the input path started with '/', the returned path also does, else it does not. For compatibility with DOS-based systems, '...' is treated as '../..', '....' as '../../..', and so on.

Source Code - (sfldir.c)

{
#if (defined (__UNIX__) || defined (MSDOS_FILESYSTEM) || defined (__VMS__))
    static char
        new_path [PATH_MAX];            /*  Returned path value              */
    char
        *new_ptr,                       /*  Pointer into new_path            */
        last_char = '/';                /*  Start of path counts as delim    */
    int
        nbr_dots;                       /*  Size of '..', '...' specifier    */

    ASSERT (old_path);
    ASSERT (strlen (old_path) < PATH_MAX);

    new_ptr = new_path;
    while (*old_path)
      {
        if (path_delimiter (last_char) && *old_path == '.')
          {
            /*  Handle one or more dots followed by a path delimiter         */
            nbr_dots = 0;               /*  Count number of dots             */
            while (old_path [nbr_dots] == '.')
                nbr_dots++;

            if (path_delimiter (old_path [nbr_dots]))
              {
                old_path += nbr_dots;   /*  Skip past dots                   */
                if (*old_path)
                    old_path++;         /*    and past / if any              */

                /*  Now backtrack in new path, dropping directories as       */
                /*  many times as needed (0 or more times)                   */
                while (nbr_dots > 1)
                  {
                    if (new_ptr > new_path + 1)
                      {
                        new_ptr--;      /*  Drop delimiter                   */
                        while (new_ptr > new_path)
                          {
                            if (path_delimiter (*(new_ptr - 1)))
                                break;  /*    and end after delimiter        */
                            new_ptr--;
                          }
                      }
                    else
                        break;          /*  At start of name - finish        */
                    nbr_dots--;
                  }
              }
            else
                /*  Handle '.something'                                      */
                last_char = *new_ptr++ = *old_path++;
          }
        else
            last_char = *new_ptr++ = *old_path++;
      }

    *new_ptr = '\0';                    /*  Terminate string nicely          */
    return (new_path);
#else

    return ((char *) old_path);         /*  Path resolution not supported    */
#endif
}

| << | < | > | >> iMatix Copyright © 1996-98 iMatix