1 /* realpath.c - Return the canonicalized absolute pathname */
2
3 /* Written 2000 by Werner Almesberger */
4
5
6 #include <stdlib.h>
7 #include <unistd.h>
8 #include <string.h>
9 #include <limits.h>
10 #include <errno.h>
11 #include <sys/stat.h>
12
13
14 /* FIXME: buffer overrun possible, loops forever on cyclic symlinks */
15
16
17 /*
18 * Canonical name: never ends with a slash
19 */
20
resolve_path(char * path,char * result,char * pos)21 static int resolve_path(char *path,char *result,char *pos)
22 {
23 if (*path == '/') {
24 *result = '/';
25 pos = result+1;
26 path++;
27 }
28 *pos = 0;
29 if (!*path) return 0;
30 while (1) {
31 char *slash;
32 struct stat st;
33
34 slash = *path ? strchr(path,'/') : NULL;
35 if (slash) *slash = 0;
36 if (!path[0] || (path[0] == '.' &&
37 (!path[1] || (path[1] == '.' && !path[2])))) {
38 pos--;
39 if (pos != result && path[0] && path[1])
40 while (*--pos != '/');
41 }
42 else {
43 strcpy(pos,path);
44 if (lstat(result,&st) < 0) return -1;
45 if (S_ISLNK(st.st_mode)) {
46 char buf[PATH_MAX];
47
48 if (readlink(result,buf,sizeof(buf)) < 0) return -1;
49 *pos = 0;
50 if (slash) {
51 *slash = '/';
52 strcat(buf,slash);
53 }
54 strcpy(path,buf);
55 if (*path == '/') result[1] = 0;
56 pos = strchr(result,0);
57 continue;
58 }
59 pos = strchr(result,0);
60 }
61 if (slash) {
62 *pos++ = '/';
63 path = slash+1;
64 }
65 *pos = 0;
66 if (!slash) break;
67 }
68 return 0;
69 }
70
71
realpath(const char * path,char * resolved_path)72 char *realpath(const char *path,char *resolved_path)
73 {
74 char cwd[PATH_MAX];
75 char *path_copy;
76 int res;
77
78 if (!*path) {
79 errno = ENOENT; /* SUSv2 */
80 return NULL;
81 }
82 if (!getcwd(cwd,sizeof(cwd))) return NULL;
83 strcpy(resolved_path,"/");
84 if (resolve_path(cwd,resolved_path,resolved_path)) return NULL;
85 strcat(resolved_path,"/");
86 path_copy = strdup(path);
87 if (!path_copy) return NULL;
88 res = resolve_path(path_copy,resolved_path,strchr(resolved_path,0));
89 free(path_copy);
90 if (res) return NULL;
91 return resolved_path;
92 }
93