summaryrefslogtreecommitdiff
path: root/common/strutils.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/strutils.c')
-rw-r--r--common/strutils.c103
1 files changed, 103 insertions, 0 deletions
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 <stdio.h>
#include <string.h>
+#include <glib.h>
#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 <alexl@redhat.com>
+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;
+}