[Midnightbsd-cvs] src [10541] trunk/lib/libc/stdlib/realpath.c: update realpath
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Thu Jun 7 19:03:10 EDT 2018
Revision: 10541
http://svnweb.midnightbsd.org/src/?rev=10541
Author: laffer1
Date: 2018-06-07 19:03:09 -0400 (Thu, 07 Jun 2018)
Log Message:
-----------
update realpath
Modified Paths:
--------------
trunk/lib/libc/stdlib/realpath.c
Modified: trunk/lib/libc/stdlib/realpath.c
===================================================================
--- trunk/lib/libc/stdlib/realpath.c 2018-06-07 23:02:50 UTC (rev 10540)
+++ trunk/lib/libc/stdlib/realpath.c 2018-06-07 23:03:09 UTC (rev 10541)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* Copyright (c) 2003 Constantin S. Svintsoff <kostik at iclub.nsu.ru>
*
@@ -30,7 +31,7 @@
static char sccsid[] = "@(#)realpath.c 8.1 (Berkeley) 2/16/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: stable/10/lib/libc/stdlib/realpath.c 319131 2017-05-29 13:00:39Z kib $");
#include "namespace.h"
#include <sys/param.h>
@@ -47,31 +48,16 @@
* components. Returns (resolved) on success, or (NULL) on failure,
* in which case the path which caused trouble is left in (resolved).
*/
-char *
-realpath(const char * __restrict path, char * __restrict resolved)
+static char *
+realpath1(const char *path, char *resolved)
{
struct stat sb;
- char *p, *q, *s;
- size_t left_len, resolved_len;
+ char *p, *q;
+ size_t left_len, resolved_len, next_token_len;
unsigned symlinks;
- int m, slen;
+ ssize_t slen;
char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
- if (path == NULL) {
- errno = EINVAL;
- return (NULL);
- }
- if (path[0] == '\0') {
- errno = ENOENT;
- return (NULL);
- }
- if (resolved == NULL) {
- resolved = malloc(PATH_MAX);
- if (resolved == NULL)
- return (NULL);
- m = 1;
- } else
- m = 0;
symlinks = 0;
if (path[0] == '/') {
resolved[0] = '/';
@@ -82,12 +68,8 @@
left_len = strlcpy(left, path + 1, sizeof(left));
} else {
if (getcwd(resolved, PATH_MAX) == NULL) {
- if (m)
- free(resolved);
- else {
- resolved[0] = '.';
- resolved[1] = '\0';
- }
+ resolved[0] = '.';
+ resolved[1] = '\0';
return (NULL);
}
resolved_len = strlen(resolved);
@@ -94,8 +76,6 @@
left_len = strlcpy(left, path, sizeof(left));
}
if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
- if (m)
- free(resolved);
errno = ENAMETOOLONG;
return (NULL);
}
@@ -109,22 +89,21 @@
* and its length.
*/
p = strchr(left, '/');
- s = p ? p : left + left_len;
- if (s - left >= sizeof(next_token)) {
- if (m)
- free(resolved);
- errno = ENAMETOOLONG;
- return (NULL);
+
+ next_token_len = p != NULL ? 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) {
- if (m)
- free(resolved);
errno = ENAMETOOLONG;
return (NULL);
}
@@ -132,31 +111,11 @@
resolved[resolved_len] = '\0';
}
if (next_token[0] == '\0') {
- /*
- * Handle consequential slashes. The path
- * before slash shall point to a directory.
- *
- * Only the trailing slashes are not covered
- * by other checks in the loop, but we verify
- * the prefix for any (rare) "//" or "/\0"
- * occurence to not implement lookahead.
- */
- if (lstat(resolved, &sb) != 0) {
- if (m)
- free(resolved);
- return (NULL);
- }
- if (!S_ISDIR(sb.st_mode)) {
- if (m)
- free(resolved);
- errno = ENOTDIR;
- return (NULL);
- }
+ /* 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 "/"
@@ -175,27 +134,24 @@
*/
resolved_len = strlcat(resolved, next_token, PATH_MAX);
if (resolved_len >= PATH_MAX) {
- if (m)
- free(resolved);
errno = ENAMETOOLONG;
return (NULL);
}
- if (lstat(resolved, &sb) != 0) {
- if (m)
- free(resolved);
+ if (lstat(resolved, &sb) != 0)
return (NULL);
- }
if (S_ISLNK(sb.st_mode)) {
if (symlinks++ > MAXSYMLINKS) {
- if (m)
- free(resolved);
errno = ELOOP;
return (NULL);
}
- slen = readlink(resolved, symlink, sizeof(symlink) - 1);
- if (slen < 0) {
- if (m)
- free(resolved);
+ 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;
return (NULL);
}
symlink[slen] = '\0';
@@ -202,9 +158,8 @@
if (symlink[0] == '/') {
resolved[1] = 0;
resolved_len = 1;
- } 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;
@@ -218,8 +173,6 @@
if (p != NULL) {
if (symlink[slen - 1] != '/') {
if (slen + 1 >= sizeof(symlink)) {
- if (m)
- free(resolved);
errno = ENAMETOOLONG;
return (NULL);
}
@@ -228,14 +181,15 @@
}
left_len = strlcat(symlink, left,
sizeof(symlink));
- if (left_len >= sizeof(left)) {
- if (m)
- free(resolved);
+ if (left_len >= sizeof(symlink)) {
errno = ENAMETOOLONG;
return (NULL);
}
}
left_len = strlcpy(left, symlink, sizeof(left));
+ } else if (!S_ISDIR(sb.st_mode) && p != NULL) {
+ errno = ENOTDIR;
+ return (NULL);
}
}
@@ -247,3 +201,29 @@
resolved[resolved_len - 1] = '\0';
return (resolved);
}
+
+char *
+realpath(const char * __restrict path, char * __restrict resolved)
+{
+ char *m, *res;
+
+ if (path == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ if (path[0] == '\0') {
+ errno = ENOENT;
+ return (NULL);
+ }
+ if (resolved != NULL) {
+ m = NULL;
+ } else {
+ m = resolved = malloc(PATH_MAX);
+ if (resolved == NULL)
+ return (NULL);
+ }
+ res = realpath1(path, resolved);
+ if (res == NULL)
+ free(m);
+ return (res);
+}
More information about the Midnightbsd-cvs
mailing list