2 * mono-path.c: Routines for handling path names.
5 * Gonzalo Paniagua Javier (gonzalo@novell.com)
6 * Miguel de Icaza (miguel@novell.com)
8 * (C) 2006 Novell, Inc. http://www.novell.com
19 /* This is only needed for the mono_path_canonicalize code, MAXSYMLINKS, could be moved */
20 #ifdef HAVE_SYS_PARAM_H
21 #include <sys/param.h>
24 #include "mono-path.h"
26 /* Embedded systems lack MAXSYMLINKS */
31 /* Resolves '..' and '.' references in a path. If the path provided is relative,
32 * it will be relative to the current directory */
34 /* For Native Client, the above is not true. Since there is no getcwd we fill */
35 /* in the file being passed in relative to '.' and don't resolve it */
37 mono_path_canonicalize (const char *path)
39 gchar *abspath, *pos, *lastpos, *dest;
42 if (g_path_is_absolute (path)) {
43 abspath = g_strdup (path);
45 #ifdef __native_client__
47 abspath = g_build_filename (tmpdir, path, NULL);
49 gchar *tmpdir = g_get_current_dir ();
50 abspath = g_build_filename (tmpdir, path, NULL);
56 g_strdelimit (abspath, "/", '\\');
58 abspath = g_strreverse (abspath);
61 dest = lastpos = abspath;
62 pos = strchr (lastpos, G_DIR_SEPARATOR);
65 int len = pos - lastpos;
66 if (len == 1 && lastpos [0] == '.') {
68 } else if (len == 2 && lastpos [0] == '.' && lastpos [1] == '.') {
75 /* The two strings can overlap */
76 memmove (dest, lastpos, len + 1);
81 pos = strchr (lastpos, G_DIR_SEPARATOR);
84 #ifdef HOST_WIN32 /* For UNC paths the first '\' is removed. */
85 if (*(lastpos-1) == G_DIR_SEPARATOR && *(lastpos-2) == G_DIR_SEPARATOR)
89 if (dest != lastpos) strcpy (dest, lastpos);
90 return g_strreverse (abspath);
94 * This ensures that the path that we store points to the final file
95 * not a path to a symlink.
97 #if !defined(PLATFORM_NO_SYMLINKS)
99 resolve_symlink (const char *path)
101 char *p, *concat, *dir;
102 char buffer [PATH_MAX+1];
103 int n, iterations = 0;
108 n = readlink (p, buffer, sizeof (buffer)-1);
111 p = mono_path_canonicalize (copy);
117 if (!g_path_is_absolute (buffer)) {
118 dir = g_path_get_dirname (p);
119 concat = g_build_filename (dir, buffer, NULL);
122 concat = g_strdup (buffer);
125 p = mono_path_canonicalize (concat);
127 } while (iterations < MAXSYMLINKS);
134 mono_path_resolve_symlinks (const char *path)
136 #if defined(PLATFORM_NO_SYMLINKS)
137 return mono_path_canonicalize (path);
139 gchar **split = g_strsplit (path, G_DIR_SEPARATOR_S, -1);
140 gchar *p = g_strdup ("");
143 for (i = 0; split [i] != NULL; i++) {
146 // resolve_symlink of "" goes into canonicalize which resolves to cwd
147 if (strcmp (split [i], "") != 0) {
148 tmp = g_strdup_printf ("%s%s", p, split [i]);
150 p = resolve_symlink (tmp);
154 if (split [i+1] != NULL) {
155 tmp = g_strdup_printf ("%s%s", p, G_DIR_SEPARATOR_S);