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 mono_path_canonicalize (const char *path
)
36 gchar
*abspath
, *pos
, *lastpos
, *dest
;
39 if (g_path_is_absolute (path
)) {
40 abspath
= g_strdup (path
);
42 gchar
*tmpdir
= g_get_current_dir ();
43 abspath
= g_build_filename (tmpdir
, path
, NULL
);
48 g_strdelimit (abspath
, "/", '\\');
50 abspath
= g_strreverse (abspath
);
53 dest
= lastpos
= abspath
;
54 pos
= strchr (lastpos
, G_DIR_SEPARATOR
);
57 int len
= pos
- lastpos
;
58 if (len
== 1 && lastpos
[0] == '.') {
60 } else if (len
== 2 && lastpos
[0] == '.' && lastpos
[1] == '.') {
67 /* The two strings can overlap */
68 memmove (dest
, lastpos
, len
+ 1);
73 pos
= strchr (lastpos
, G_DIR_SEPARATOR
);
76 #ifdef HOST_WIN32 /* For UNC paths the first '\' is removed. */
77 if (*(lastpos
-1) == G_DIR_SEPARATOR
&& *(lastpos
-2) == G_DIR_SEPARATOR
)
81 if (dest
!= lastpos
) strcpy (dest
, lastpos
);
82 return g_strreverse (abspath
);
86 * This ensures that the path that we store points to the final file
87 * not a path to a symlink.
89 #if !defined(PLATFORM_NO_SYMLINKS)
91 resolve_symlink (const char *path
)
93 char *p
, *concat
, *dir
;
94 char buffer
[PATH_MAX
+1];
95 int n
, iterations
= 0;
100 n
= readlink (p
, buffer
, sizeof (buffer
)-1);
103 p
= mono_path_canonicalize (copy
);
109 if (!g_path_is_absolute (buffer
)) {
110 dir
= g_path_get_dirname (p
);
111 concat
= g_build_filename (dir
, buffer
, NULL
);
114 concat
= g_strdup (buffer
);
117 p
= mono_path_canonicalize (concat
);
119 } while (iterations
< MAXSYMLINKS
);
126 mono_path_resolve_symlinks (const char *path
)
128 #if defined(PLATFORM_NO_SYMLINKS)
129 return mono_path_canonicalize (path
);
131 gchar
**split
= g_strsplit (path
, G_DIR_SEPARATOR_S
, -1);
132 gchar
*p
= g_strdup ("");
135 for (i
= 0; split
[i
] != NULL
; i
++) {
138 // resolve_symlink of "" goes into canonicalize which resolves to cwd
139 if (strcmp (split
[i
], "") != 0) {
140 tmp
= g_strdup_printf ("%s%s", p
, split
[i
]);
142 p
= resolve_symlink (tmp
);
146 if (split
[i
+1] != NULL
) {
147 tmp
= g_strdup_printf ("%s%s", p
, G_DIR_SEPARATOR_S
);