X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Futils%2Fmono-path.c;h=0a443aa41f76c1a977ac108b5e0a4a635651ae6e;hb=1e726ce7a38a92860acab28f4427813d2ba14c13;hp=c2a510ad586b8cf80933e2d33c088fefddcea75f;hpb=9d61782c6e2392d7ceec2006b35be582598a70ae;p=mono.git diff --git a/mono/utils/mono-path.c b/mono/utils/mono-path.c index c2a510ad586..0a443aa41f7 100644 --- a/mono/utils/mono-path.c +++ b/mono/utils/mono-path.c @@ -13,14 +13,28 @@ #include #include #include +#ifdef HAVE_UNISTD_H #include +#endif /* This is only needed for the mono_path_canonicalize code, MAXSYMLINKS, could be moved */ +#ifdef HAVE_SYS_PARAM_H #include +#endif #include "mono-path.h" +/* Embedded systems lack MAXSYMLINKS */ +#ifndef MAXSYMLINKS +#define MAXSYMLINKS 3 +#endif + /* Resolves '..' and '.' references in a path. If the path provided is relative, * it will be relative to the current directory */ + +/* For Native Client, the above is not true. Since there is no getcwd we fill */ +/* in the file being passed in relative to '.' and don't resolve it */ + +/* There are a couple of tests for this method in mono/test/mono-path.cs */ gchar * mono_path_canonicalize (const char *path) { @@ -35,6 +49,9 @@ mono_path_canonicalize (const char *path) g_free (tmpdir); } +#ifdef HOST_WIN32 + g_strdelimit (abspath, "/", '\\'); +#endif abspath = g_strreverse (abspath); backc = 0; @@ -60,21 +77,40 @@ mono_path_canonicalize (const char *path) lastpos = pos + 1; pos = strchr (lastpos, G_DIR_SEPARATOR); } + +#ifdef HOST_WIN32 + /* Avoid removing the first '\' for UNC paths. We must make sure that it's indeed an UNC path + by checking if the \\ pair happens exactly at the end of the string. + */ + if (*(lastpos-1) == G_DIR_SEPARATOR && *(lastpos-2) == G_DIR_SEPARATOR && *lastpos == 0) + lastpos = lastpos-1; +#endif if (dest != lastpos) strcpy (dest, lastpos); - return g_strreverse (abspath); + + g_strreverse (abspath); + + /* We strip away all trailing dir separators. This is not correct for the root directory, + * since we'll return an empty string, so re-append a dir separator if there is none in the + * result */ + if (strchr (abspath, G_DIR_SEPARATOR) == NULL) { + int len = strlen (abspath); + abspath = g_realloc (abspath, len + 2); + abspath [len] = G_DIR_SEPARATOR; + abspath [len+1] = 0; + } + + return abspath; } /* * This ensures that the path that we store points to the final file * not a path to a symlink. */ -gchar * -mono_path_resolve_symlinks (const char *path) +#if !defined(PLATFORM_NO_SYMLINKS) +static gchar * +resolve_symlink (const char *path) { -#if PLATFORM_WIN32 - return mono_path_canonicalize (path); -#else char *p, *concat, *dir; char buffer [PATH_MAX+1]; int n, iterations = 0; @@ -103,6 +139,39 @@ mono_path_resolve_symlinks (const char *path) g_free (concat); } while (iterations < MAXSYMLINKS); + return p; +} +#endif + +gchar * +mono_path_resolve_symlinks (const char *path) +{ +#if defined(PLATFORM_NO_SYMLINKS) + return mono_path_canonicalize (path); +#else + gchar **split = g_strsplit (path, G_DIR_SEPARATOR_S, -1); + gchar *p = g_strdup (""); + int i; + + for (i = 0; split [i] != NULL; i++) { + gchar *tmp = NULL; + + // resolve_symlink of "" goes into canonicalize which resolves to cwd + if (strcmp (split [i], "") != 0) { + tmp = g_strdup_printf ("%s%s", p, split [i]); + g_free (p); + p = resolve_symlink (tmp); + g_free (tmp); + } + + if (split [i+1] != NULL) { + tmp = g_strdup_printf ("%s%s", p, G_DIR_SEPARATOR_S); + g_free (p); + p = tmp; + } + } + + g_strfreev (split); return p; #endif }