* TextBoxTest: More of these tests work now.
[mono-project.git] / mono / utils / mono-path.c
blobc2a510ad586b8cf80933e2d33c088fefddcea75f
1 /*
2 * mono-path.c: Routines for handling path names.
3 *
4 * Authors:
5 * Gonzalo Paniagua Javier (gonzalo@novell.com)
6 * Miguel de Icaza (miguel@novell.com)
8 * (C) 2006 Novell, Inc. http://www.novell.com
11 #include <config.h>
12 #include <glib.h>
13 #include <errno.h>
14 #include <string.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17 /* This is only needed for the mono_path_canonicalize code, MAXSYMLINKS, could be moved */
18 #include <sys/param.h>
20 #include "mono-path.h"
22 /* Resolves '..' and '.' references in a path. If the path provided is relative,
23 * it will be relative to the current directory */
24 gchar *
25 mono_path_canonicalize (const char *path)
27 gchar *abspath, *pos, *lastpos, *dest;
28 int backc;
30 if (g_path_is_absolute (path)) {
31 abspath = g_strdup (path);
32 } else {
33 gchar *tmpdir = g_get_current_dir ();
34 abspath = g_build_filename (tmpdir, path, NULL);
35 g_free (tmpdir);
38 abspath = g_strreverse (abspath);
40 backc = 0;
41 dest = lastpos = abspath;
42 pos = strchr (lastpos, G_DIR_SEPARATOR);
44 while (pos != NULL) {
45 int len = pos - lastpos;
46 if (len == 1 && lastpos [0] == '.') {
47 // nop
48 } else if (len == 2 && lastpos [0] == '.' && lastpos [1] == '.') {
49 backc++;
50 } else if (len > 0) {
51 if (backc > 0) {
52 backc--;
53 } else {
54 if (dest != lastpos)
55 /* The two strings can overlap */
56 memmove (dest, lastpos, len + 1);
57 dest += len + 1;
60 lastpos = pos + 1;
61 pos = strchr (lastpos, G_DIR_SEPARATOR);
64 if (dest != lastpos) strcpy (dest, lastpos);
65 return g_strreverse (abspath);
69 * This ensures that the path that we store points to the final file
70 * not a path to a symlink.
72 gchar *
73 mono_path_resolve_symlinks (const char *path)
75 #if PLATFORM_WIN32
76 return mono_path_canonicalize (path);
77 #else
78 char *p, *concat, *dir;
79 char buffer [PATH_MAX+1];
80 int n, iterations = 0;
82 p = g_strdup (path);
83 do {
84 iterations++;
85 n = readlink (p, buffer, sizeof (buffer)-1);
86 if (n < 0){
87 char *copy = p;
88 p = mono_path_canonicalize (copy);
89 g_free (copy);
90 return p;
93 buffer [n] = 0;
94 if (!g_path_is_absolute (buffer)) {
95 dir = g_path_get_dirname (p);
96 concat = g_build_filename (dir, buffer, NULL);
97 g_free (dir);
98 } else {
99 concat = g_strdup (buffer);
101 g_free (p);
102 p = mono_path_canonicalize (concat);
103 g_free (concat);
104 } while (iterations < MAXSYMLINKS);
106 return p;
107 #endif