File indexing completed on 2025-05-11 08:24:15
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 #if defined(LIBC_SCCS) && !defined(lint)
0030 static char sccsid[] = "@(#)realpath.c 8.1 (Berkeley) 2/16/94";
0031 #endif
0032 #include <sys/cdefs.h>
0033 __FBSDID("$FreeBSD: release/9.1.0/lib/libc/stdlib/realpath.c 240647 2012-09-18 13:03:00Z emaste $");
0034
0035 #if !defined(__rtems__)
0036 #include "namespace.h"
0037 #endif
0038 #include <sys/param.h>
0039 #include <sys/stat.h>
0040
0041 #include <errno.h>
0042 #include <stdlib.h>
0043 #include <string.h>
0044 #include <unistd.h>
0045 #if !defined(__rtems__)
0046 #include "un-namespace.h"
0047 #endif
0048
0049
0050
0051
0052
0053
0054 char *
0055 realpath(const char * __restrict path, char * __restrict resolved)
0056 {
0057 struct stat sb;
0058 char *p, *q, *s;
0059 size_t left_len, resolved_len;
0060 unsigned symlinks;
0061 int m, slen;
0062 char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
0063
0064 if (path == NULL) {
0065 errno = EINVAL;
0066 return (NULL);
0067 }
0068 if (path[0] == '\0') {
0069 errno = ENOENT;
0070 return (NULL);
0071 }
0072 if (resolved == NULL) {
0073 resolved = malloc(PATH_MAX);
0074 if (resolved == NULL)
0075 return (NULL);
0076 m = 1;
0077 } else
0078 m = 0;
0079 symlinks = 0;
0080 if (path[0] == '/') {
0081 resolved[0] = '/';
0082 resolved[1] = '\0';
0083 if (path[1] == '\0')
0084 return (resolved);
0085 resolved_len = 1;
0086 left_len = strlcpy(left, path + 1, sizeof(left));
0087 } else {
0088 if (getcwd(resolved, PATH_MAX) == NULL) {
0089 if (m)
0090 free(resolved);
0091 else {
0092 resolved[0] = '.';
0093 resolved[1] = '\0';
0094 }
0095 return (NULL);
0096 }
0097 resolved_len = strlen(resolved);
0098 left_len = strlcpy(left, path, sizeof(left));
0099 }
0100 if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
0101 if (m)
0102 free(resolved);
0103 errno = ENAMETOOLONG;
0104 return (NULL);
0105 }
0106
0107
0108
0109
0110 while (left_len != 0) {
0111
0112
0113
0114
0115 p = strchr(left, '/');
0116 s = p ? p : left + left_len;
0117 if (s - left >= sizeof(next_token)) {
0118 if (m)
0119 free(resolved);
0120 errno = ENAMETOOLONG;
0121 return (NULL);
0122 }
0123 memcpy(next_token, left, s - left);
0124 next_token[s - left] = '\0';
0125 left_len -= s - left;
0126 if (p != NULL)
0127 memmove(left, s + 1, left_len + 1);
0128 if (resolved[resolved_len - 1] != '/') {
0129 if (resolved_len + 1 >= PATH_MAX) {
0130 if (m)
0131 free(resolved);
0132 errno = ENAMETOOLONG;
0133 return (NULL);
0134 }
0135 resolved[resolved_len++] = '/';
0136 resolved[resolved_len] = '\0';
0137 }
0138 if (next_token[0] == '\0') {
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148 if (lstat(resolved, &sb) != 0) {
0149 if (m)
0150 free(resolved);
0151 return (NULL);
0152 }
0153 if (!S_ISDIR(sb.st_mode)) {
0154 if (m)
0155 free(resolved);
0156 errno = ENOTDIR;
0157 return (NULL);
0158 }
0159 continue;
0160 }
0161 else if (strcmp(next_token, ".") == 0)
0162 continue;
0163 else if (strcmp(next_token, "..") == 0) {
0164
0165
0166
0167
0168 if (resolved_len > 1) {
0169 resolved[resolved_len - 1] = '\0';
0170 q = strrchr(resolved, '/') + 1;
0171 *q = '\0';
0172 resolved_len = q - resolved;
0173 }
0174 continue;
0175 }
0176
0177
0178
0179
0180 resolved_len = strlcat(resolved, next_token, PATH_MAX);
0181 if (resolved_len >= PATH_MAX) {
0182 if (m)
0183 free(resolved);
0184 errno = ENAMETOOLONG;
0185 return (NULL);
0186 }
0187 if (lstat(resolved, &sb) != 0) {
0188 if (m)
0189 free(resolved);
0190 return (NULL);
0191 }
0192 if (S_ISLNK(sb.st_mode)) {
0193 if (symlinks++ > MAXSYMLINKS) {
0194 if (m)
0195 free(resolved);
0196 errno = ELOOP;
0197 return (NULL);
0198 }
0199 slen = readlink(resolved, symlink, sizeof(symlink) - 1);
0200 if (slen < 0) {
0201 if (m)
0202 free(resolved);
0203 return (NULL);
0204 }
0205 symlink[slen] = '\0';
0206 if (symlink[0] == '/') {
0207 resolved[1] = 0;
0208 resolved_len = 1;
0209 } else if (resolved_len > 1) {
0210
0211 resolved[resolved_len - 1] = '\0';
0212 q = strrchr(resolved, '/') + 1;
0213 *q = '\0';
0214 resolved_len = q - resolved;
0215 }
0216
0217
0218
0219
0220
0221
0222 if (p != NULL) {
0223 if (symlink[slen - 1] != '/') {
0224 if (slen + 1 >= sizeof(symlink)) {
0225 if (m)
0226 free(resolved);
0227 errno = ENAMETOOLONG;
0228 return (NULL);
0229 }
0230 symlink[slen] = '/';
0231 symlink[slen + 1] = 0;
0232 }
0233 left_len = strlcat(symlink, left,
0234 sizeof(symlink));
0235 if (left_len >= sizeof(left)) {
0236 if (m)
0237 free(resolved);
0238 errno = ENAMETOOLONG;
0239 return (NULL);
0240 }
0241 }
0242 left_len = strlcpy(left, symlink, sizeof(left));
0243 }
0244 }
0245
0246
0247
0248
0249
0250 if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
0251 resolved[resolved_len - 1] = '\0';
0252 return (resolved);
0253 }