From b56d279b172fbe78dee2fb1d29cae9c9c5c6d1c4 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 28 Sep 2018 12:41:12 -0400 Subject: [PATCH] unix: do not require PATH_MAX to be defined Some platforms (e.g. GNU/Hurd) do not define PATH_MAX. Add a few other variants and a fallback constant. Also use alternatives where possible: * For readlink(), use lstat() to read the length of the link first. If it is not a symlink, report EINVAL before trying to allocate. If the size reports as zero, fall back one of the PATH_MAX variants. * For realpath(), POSIX 2008 allows us to pass a NULL buffer to tell it to malloc() internally. This patch was inspired by downstream patches in Debian packaging. PR-URL: https://github.com/libuv/libuv/pull/2008 Reviewed-By: Anna Henningsen Reviewed-By: Ben Noordhuis Reviewed-By: Colin Ihrig Reviewed-By: Sakthipriyan Vairamani Reviewed-By: Santiago Gimeno Bug-Debian: https://bugs.debian.org/897061 Bug-Debian: https://bugs.debian.org/909011 Bug-Ubuntu: https://bugs.launchpad.net/bugs/1792647 Inspired-by: Mauricio Faria de Oliveira Inspired-by: Samuel Thibault --- src/unix/fs.c | 47 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/src/unix/fs.c b/src/unix/fs.c index 3db5f89c..9068d4b1 100644 --- a/src/unix/fs.c +++ b/src/unix/fs.c @@ -358,19 +358,22 @@ static ssize_t uv__fs_scandir(uv_fs_t* req) { return n; } +#if defined(_POSIX_PATH_MAX) +# define UV__FS_PATH_MAX _POSIX_PATH_MAX +#elif defined(PATH_MAX) +# define UV__FS_PATH_MAX PATH_MAX +#else +# define UV__FS_PATH_MAX_FALLBACK 8192 +# define UV__FS_PATH_MAX UV__FS_PATH_MAX_FALLBACK +#endif static ssize_t uv__fs_pathmax_size(const char* path) { ssize_t pathmax; pathmax = pathconf(path, _PC_PATH_MAX); - if (pathmax == -1) { -#if defined(PATH_MAX) - return PATH_MAX; -#else -#error "PATH_MAX undefined in the current platform" -#endif - } + if (pathmax == -1) + pathmax = UV__FS_PATH_MAX; return pathmax; } @@ -381,7 +384,28 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) { char* buf; char* newbuf; +#if defined(UV__FS_PATH_MAX_FALLBACK) + /* We may not have a real PATH_MAX. Read size of link. */ + struct stat st; + int ret; + ret = lstat(req->path, &st); + if (ret != 0) + return -1; + if (!S_ISLNK(st.st_mode)) { + errno = EINVAL; + return -1; + } + + maxlen = st.st_size; + + /* According to readlink(2) lstat can report st_size == 0 + for some symlinks, such as those in /proc or /sys. */ + if (maxlen == 0) + maxlen = uv__fs_pathmax_size(req->path); +#else maxlen = uv__fs_pathmax_size(req->path); +#endif + buf = uv__malloc(maxlen); if (buf == NULL) { @@ -419,9 +443,15 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) { } static ssize_t uv__fs_realpath(uv_fs_t* req) { - ssize_t len; char* buf; +#if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L + buf = realpath(req->path, NULL); + if (buf == NULL) + return -1; +#else + ssize_t len; + len = uv__fs_pathmax_size(req->path); buf = uv__malloc(len + 1); @@ -434,6 +464,7 @@ static ssize_t uv__fs_realpath(uv_fs_t* req) { uv__free(buf); return -1; } +#endif req->ptr = buf;