summary refs log tree commit diff
path: root/hurd
diff options
context:
space:
mode:
Diffstat (limited to 'hurd')
-rw-r--r--hurd/hurd/fd.h5
-rw-r--r--hurd/lookup-at.c6
2 files changed, 9 insertions, 2 deletions
diff --git a/hurd/hurd/fd.h b/hurd/hurd/fd.h
index d1aa867cbf..2473476084 100644
--- a/hurd/hurd/fd.h
+++ b/hurd/hurd/fd.h
@@ -254,8 +254,9 @@ extern int _hurd_select (int nfds, struct pollfd *pollfds,
 			 const sigset_t *sigmask);
 
 /* Variant of file_name_lookup used in *at function implementations.
-   AT_FLAGS should contain only AT_SYMLINK_NOFOLLOW; other bits
-   cause EINVAL.  */
+   AT_FLAGS may only contain AT_SYMLINK_FOLLOW or AT_SYMLINK_NOFOLLOW,
+   which will remove and add O_NOLINK from FLAGS respectively.
+   Other bits cause EINVAL.  */
 extern file_t __file_name_lookup_at (int fd, int at_flags,
 				     const char *file_name,
 				     int flags, mode_t mode);
diff --git a/hurd/lookup-at.c b/hurd/lookup-at.c
index 7f55527d8b..728a970909 100644
--- a/hurd/lookup-at.c
+++ b/hurd/lookup-at.c
@@ -30,8 +30,14 @@ __file_name_lookup_at (int fd, int at_flags,
   error_t err;
   file_t result;
 
+  if ((at_flags & AT_SYMLINK_FOLLOW) && (at_flags & AT_SYMLINK_NOFOLLOW))
+    return (__hurd_fail (EINVAL), MACH_PORT_NULL);
+
   flags |= (at_flags & AT_SYMLINK_NOFOLLOW) ? O_NOLINK : 0;
   at_flags &= ~AT_SYMLINK_NOFOLLOW;
+  if (at_flags & AT_SYMLINK_FOLLOW)
+    flags &= ~O_NOLINK;
+  at_flags &= ~AT_SYMLINK_FOLLOW;
   if (at_flags != 0)
     return (__hurd_fail (EINVAL), MACH_PORT_NULL);