X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Futils%2Fmono-path.c;h=88b5d25a71904ff89e0923b1b7f967034f0b3c34;hb=4f0280a587fb46f9c1278c633cfb9a98ec720e01;hp=c2a510ad586b8cf80933e2d33c088fefddcea75f;hpb=3d693eeb90339833968d66c3dc9fde2fa3ba2cef;p=mono.git diff --git a/mono/utils/mono-path.c b/mono/utils/mono-path.c index c2a510ad586..88b5d25a719 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) { @@ -30,11 +44,19 @@ mono_path_canonicalize (const char *path) if (g_path_is_absolute (path)) { abspath = g_strdup (path); } else { +#ifdef __native_client__ + gchar *tmpdir = "."; + abspath = g_build_filename (tmpdir, path, NULL); +#else gchar *tmpdir = g_get_current_dir (); abspath = g_build_filename (tmpdir, path, NULL); g_free (tmpdir); +#endif } +#ifdef HOST_WIN32 + g_strdelimit (abspath, "/", '\\'); +#endif abspath = g_strreverse (abspath); backc = 0; @@ -60,21 +82,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 +144,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 }