|
| iMatix home page | << | < | > | >> |
SFLVersion 2.11 |
#include "sfldir.h"
char *
resolve_path (
const char *old_path)
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.
{
#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
}
| | << | < | > | >> |
|