From 892e407c5f5e06fa8c0ca9250b3bc99851c6a61d Mon Sep 17 00:00:00 2001 From: Tomas Bzatek Date: Fri, 13 Jun 2008 14:17:54 +0200 Subject: Symlink resolving code, disabled by default --- common/strutils.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) (limited to 'common/strutils.c') diff --git a/common/strutils.c b/common/strutils.c index 3f390d9..5d9fa65 100644 --- a/common/strutils.c +++ b/common/strutils.c @@ -19,6 +19,7 @@ #include #include +#include #include "strutils.h" @@ -89,3 +90,105 @@ char* extract_file_path(const char *APath) snprintf(ANewPath, file_part - APath + 2, "%s", APath); return ANewPath; } + + + + + + + + +// canonicalize_filename() is stolen from glib-2.16 +// Copyright (C) 2006-2007 Alexander Larsson +static char * +canonicalize_filename (const char *filename) +{ + char *canon, *start, *p, *q; + int i; + + canon = g_strdup (filename); + + start = (char *)g_path_skip_root (canon); + + /* POSIX allows double slashes at the start to + * mean something special (as does windows too). + * So, "//" != "/", but more than two slashes + * is treated as "/". + */ + i = 0; + for (p = start - 1; + (p >= canon) && + G_IS_DIR_SEPARATOR (*p); + p--) + i++; + if (i > 2) + { + i -= 1; + start -= i; + memmove (start, start+i, strlen (start+i)+1); + } + + p = start; + while (*p != 0) + { + if (p[0] == '.' && (p[1] == 0 || G_IS_DIR_SEPARATOR (p[1]))) + { + memmove (p, p+1, strlen (p+1)+1); + } + else if (p[0] == '.' && p[1] == '.' && (p[2] == 0 || G_IS_DIR_SEPARATOR (p[2]))) + { + q = p + 2; + /* Skip previous separator */ + p = p - 2; + if (p < start) + p = start; + while (p > start && !G_IS_DIR_SEPARATOR (*p)) + p--; + if (G_IS_DIR_SEPARATOR (*p)) + *p++ = G_DIR_SEPARATOR; + memmove (p, q, strlen (q)+1); + } + else + { + /* Skip until next separator */ + while (*p != 0 && !G_IS_DIR_SEPARATOR (*p)) + p++; + + if (*p != 0) + { + /* Canonicalize one separator */ + *p++ = G_DIR_SEPARATOR; + } + } + + /* Remove additional separators */ + q = p; + while (*q && G_IS_DIR_SEPARATOR (*q)) + q++; + + if (p != q) + memmove (p, q, strlen (q)+1); + } + + /* Remove trailing slashes */ + if (p > start && G_IS_DIR_SEPARATOR (*(p-1))) + *(p-1) = 0; + + return canon; +} + + +char* resolve_relative(const char *source, const char *point_to) +{ + if (source == NULL) return NULL; + if (point_to == NULL) return strdup(source); + if (g_path_is_absolute(point_to)) return strdup(point_to); + + char *rel = g_build_filename(source, point_to, NULL); + log("resolve_relative: rel = '%s'\n", rel); + char *canon = canonicalize_filename(rel); + log("resolve_relative: canon = '%s'\n", canon); + free(rel); + + return canon; +} -- cgit v1.2.3