| version 1.36.2.3, 2006/01/01 23:12:36 |
version 1.37, 2005/07/04 20:44:47 |
|
|
| realpath(const char *path, char *resolved) |
realpath(const char *path, char *resolved) |
| { |
{ |
| struct stat sb; |
struct stat sb; |
| int idx = 0, n, nlnk = 0; |
int idx = 0, n, nlnk = 0, serrno = errno; |
| const char *q; |
const char *q; |
| char *p, wbuf[2][MAXPATHLEN]; |
char *p, wbuf[2][MAXPATHLEN]; |
| size_t len; |
size_t len; |
|
|
| * target to unresolved path. |
* target to unresolved path. |
| */ |
*/ |
| if (lstat(resolved, &sb) == -1) { |
if (lstat(resolved, &sb) == -1) { |
| |
/* Allow nonexistent component if this is the last one. */ |
| |
if ((*q == 0 || (*q == '/' && *(q + 1) == 0)) |
| |
&& errno == ENOENT) { |
| |
errno = serrno; |
| |
return (resolved); |
| |
} |
| |
return (NULL); |
| |
} |
| |
if (*q == '/' && !S_ISDIR(sb.st_mode)) { |
| |
errno = ENOTDIR; |
| return (NULL); |
return (NULL); |
| } |
} |
| if (S_ISLNK(sb.st_mode)) { |
if (S_ISLNK(sb.st_mode)) { |
|
|
| p = resolved; |
p = resolved; |
| goto loop; |
goto loop; |
| } |
} |
| if (*q == '/' && !S_ISDIR(sb.st_mode)) { |
|
| errno = ENOTDIR; |
|
| return (NULL); |
|
| } |
|
| |
|
| /* Advance both resolved and unresolved path. */ |
/* Advance both resolved and unresolved path. */ |
| p += 1 + q - path; |
p += 1 + q - path; |