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

 

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 a freshly-allocated string containing the resulting path. The caller must free this string using mem_free() when finished with it. The returned path may be empty. Under OS/2 and 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__))
    char
        *new_path,                      /*  Newly-allocated path             */
        *new_ptr,                       /*  Pointer into new_path            */
        last_char = '/';                /*  Start of path counts as delim    */
    int
        nbr_dots;                       /*  Size of '..', '...' specifier    */

    ASSERT (old_path);

    new_path = mem_strdup (old_path);
    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 (mem_strdup (old_path));     /*  Path resolution not supported    */
#endif
}

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