X-Git-Url: https://git.saurik.com/apple/libc.git/blobdiff_plain/ad3c9f2af814c84582fdd1649e49ec4f68572c5a..aa54d2fad3d9038b43475aa93c76795c5141a993:/stdlib/FreeBSD/realpath.c diff --git a/stdlib/FreeBSD/realpath.c b/stdlib/FreeBSD/realpath.c index 234bce9..15cf79e 100644 --- a/stdlib/FreeBSD/realpath.c +++ b/stdlib/FreeBSD/realpath.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/realpath.c,v 1.20 2003/05/28 08:23:01 fj #include #include "un-namespace.h" + struct attrs { u_int32_t len; attrreference_t name; @@ -55,7 +56,7 @@ struct attrs { }; #ifndef BUILDING_VARIANT -__private_extern__ struct attrlist _rp_alist = { +__private_extern__ const struct attrlist _rp_alist = { ATTR_BIT_MAP_COUNT, 0, ATTR_CMN_NAME | ATTR_CMN_DEVID | ATTR_CMN_OBJTYPE | ATTR_CMN_OBJID, @@ -65,7 +66,7 @@ __private_extern__ struct attrlist _rp_alist = { 0, }; #else /* BUILDING_VARIANT */ -__private_extern__ struct attrlist _rp_alist; +extern const struct attrlist _rp_alist; #endif /* BUILDING_VARIANT */ extern char * __private_getcwd(char *, size_t, int); @@ -82,10 +83,11 @@ realpath(const char *path, char inresolved[PATH_MAX]) { struct attrs attrs; struct stat sb; - char *p, *q, *s; - size_t left_len, resolved_len, save_resolved_len; + char *p, *q; + size_t left_len, resolved_len, save_resolved_len, next_token_len; unsigned symlinks; - int serrno, slen, useattrs, islink; + int serrno, useattrs, islink; + ssize_t slen; char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX]; dev_t dev, lastdev; struct statfs sfs; @@ -104,6 +106,7 @@ realpath(const char *path, char inresolved[PATH_MAX]) return (NULL); } #endif /* __DARWIN_UNIX03 */ + /* * Extension to the standard; if inresolved == NULL, allocate memory */ @@ -171,16 +174,18 @@ error_return: * and its length. */ p = strchr(left, '/'); - s = p ? p : left + left_len; - if (s - left >= sizeof(next_token)) { - errno = ENAMETOOLONG; - goto error_return; + next_token_len = p ? p - left : left_len; + memcpy(next_token, left, next_token_len); + next_token[next_token_len] = '\0'; + + if (p != NULL) { + left_len -= next_token_len + 1; + memmove(left, p + 1, left_len + 1); + } else { + left[0] = '\0'; + left_len = 0; } - memcpy(next_token, left, s - left); - next_token[s - left] = '\0'; - left_len -= s - left; - if (p != NULL) - memmove(left, s + 1, left_len + 1); + if (resolved[resolved_len - 1] != '/') { if (resolved_len + 1 >= PATH_MAX) { errno = ENAMETOOLONG; @@ -189,11 +194,12 @@ error_return: resolved[resolved_len++] = '/'; resolved[resolved_len] = '\0'; } - if (next_token[0] == '\0') + if (next_token[0] == '\0') { + /* Handle consequential slashes. */ continue; - else if (strcmp(next_token, ".") == 0) + } else if (strcmp(next_token, ".") == 0) { continue; - else if (strcmp(next_token, "..") == 0) { + } else if (strcmp(next_token, "..") == 0) { /* * Strip the last path component except when we have * single "/" @@ -224,7 +230,7 @@ error_return: errno = ENAMETOOLONG; goto error_return; } - if (getattrlist(resolved, &_rp_alist, &attrs, sizeof(attrs), FSOPT_NOFOLLOW) == 0) { + if (getattrlist(resolved, (void *)&_rp_alist, &attrs, sizeof(attrs), FSOPT_NOFOLLOW) == 0) { useattrs = 1; islink = (attrs.type == VLNK); dev = attrs.dev; @@ -296,8 +302,14 @@ error_return: errno = ELOOP; goto error_return; } - slen = readlink(resolved, symlink, sizeof(symlink) - 1); - if (slen < 0) { + slen = readlink(resolved, symlink, sizeof(symlink)); + if (slen <= 0 || slen >= sizeof(symlink)) { + if (slen < 0) + ; /* keep errno from readlink(2) call */ + else if (slen == 0) + errno = ENOENT; + else + errno = ENAMETOOLONG; goto error_return; } symlink[slen] = '\0'; @@ -305,9 +317,8 @@ error_return: resolved[1] = 0; resolved_len = 1; lastdev = rootdev; - } else if (resolved_len > 1) { + } else { /* Strip the last path component. */ - resolved[resolved_len - 1] = '\0'; q = strrchr(resolved, '/') + 1; *q = '\0'; resolved_len = q - resolved; @@ -327,8 +338,8 @@ error_return: symlink[slen] = '/'; symlink[slen + 1] = 0; } - left_len = strlcat(symlink, left, sizeof(left)); - if (left_len >= sizeof(left)) { + left_len = strlcat(symlink, left, sizeof(symlink)); + if (left_len >= sizeof(symlink)) { errno = ENAMETOOLONG; goto error_return; }