OSDN Git Service

r288@cf-ppc-macosx: monabuilder | 2008-12-07 13:17:34 +0900
[pf3gnuchains/pf3gnuchains3x.git] / newlib / libc / sys / linux / realpath.c
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
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
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 }