summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKen Brown <kbrown@cornell.edu>2019-12-27 17:17:35 -0500
committerKen Brown <kbrown@cornell.edu>2020-01-17 10:27:48 -0500
commit6cc05784e16af56750417b73d778efb09c3b122e (patch)
tree203af440538a710b74f92f1fdaf39bdad29fc43d
parent35a1a6dbdf03df1e33bae51f679820a3a868d0c0 (diff)
downloadcygnal-6cc05784e16af56750417b73d778efb09c3b122e.tar.gz
cygnal-6cc05784e16af56750417b73d778efb09c3b122e.tar.bz2
cygnal-6cc05784e16af56750417b73d778efb09c3b122e.zip
Cygwin: readlinkat: allow pathname to be empty
Following Linux, allow the pathname argument to be an empty string, provided the dirfd argument refers to a symlink opened with O_PATH | O_NOFOLLOW. The readlinkat call then operates on that symlink.
-rw-r--r--winsup/cygwin/syscalls.cc19
1 files changed, 17 insertions, 2 deletions
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 038a316db..282d9e0ee 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -4979,8 +4979,23 @@ readlinkat (int dirfd, const char *__restrict pathname, char *__restrict buf,
__try
{
char *path = tp.c_get ();
- if (gen_full_path_at (path, dirfd, pathname))
- __leave;
+ int res = gen_full_path_at (path, dirfd, pathname);
+ if (res)
+ {
+ if (errno != ENOENT)
+ __leave;
+ /* pathname is an empty string. This is OK if dirfd refers
+ to a symlink that was opened with O_PATH | O_NOFOLLOW.
+ In this case, readlinkat operates on the symlink. */
+ cygheap_fdget cfd (dirfd);
+ if (cfd < 0)
+ __leave;
+ if (!(cfd->issymlink ()
+ && cfd->get_flags () & O_PATH
+ && cfd->get_flags () & O_NOFOLLOW))
+ __leave;
+ strcpy (path, cfd->get_name ());
+ }
return readlink (path, buf, bufsize);
}
__except (EFAULT) {}