]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Hurd: Fix linkat symlink handling.
authorEmilio Pozuelo Monfort <pochu27@gmail.com>
Wed, 2 Jun 2010 17:24:59 +0000 (10:24 -0700)
committerPetr Baudis <pasky@suse.cz>
Tue, 9 Nov 2010 00:36:03 +0000 (01:36 +0100)
(cherry picked from commit 2a50c07836d2750baf70442f8f760bf6cd43b3af)

ChangeLog
hurd/hurd/fd.h
hurd/lookup-at.c
sysdeps/mach/hurd/linkat.c

index cadc5dcc30ec28b5f6001ff412bf64b225eabb4d..156de9a8a746b7722d18745dbc85cbf6f88984ad 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2010-06-02  Emilio Pozuelo Monfort  <pochu27@gmail.com>
+
+       * hurd/lookup-at.c (__file_name_lookup_at): Accept
+       AT_SYMLINK_FOLLOW in AT_FLAGS.  Fail with EINVAL if both
+       AT_SYMLINK_FOLLOW and AT_SYMLINK_NOFOLLOW are present
+       in AT_FLAGS.
+       * hurd/hurd/fd.h (__file_name_lookup_at): Update comment.
+       * sysdeps/mach/hurd/linkat.c (linkat): Pass O_NOLINK in FLAGS.
+
 2010-11-03  H.J. Lu  <hongjiu.lu@intel.com>
 
        [BZ #12191]
index d1aa867cbfd8c71f2758a5b56d806c540a53435c..24734760845ceba14b3acca27fe46682647893f2 100644 (file)
@@ -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);
index 7f55527d8be0759e5efe8f7536fba0ee130a64da..728a97090935aa5e9f93a6b12e2f214673a28257 100644 (file)
@@ -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);
 
index 1942144e0faff2c406e12efc539c1a1eaae28459..062d913e3d8a01fc301ca7ca9e191f21cd9d2f68 100644 (file)
@@ -1,5 +1,5 @@
 /* Make a link between file names relative to open directories.  Hurd version.
-   Copyright (C) 2006 Free Software Foundation, Inc.
+   Copyright (C) 2006,2010 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -38,7 +38,9 @@ linkat (fromfd, from, tofd, to, flags)
   file_t oldfile, linknode, todir;
   char *toname;
 
-  oldfile = __file_name_lookup_at (fromfd, flags, from, 0, 0);
+  /* POSIX says linkat doesn't follow symlinks by default, so pass
+     O_NOLINK.  That can be overridden by AT_SYMLINK_FOLLOW in FLAGS.  */
+  oldfile = __file_name_lookup_at (fromfd, flags, from, O_NOLINK, 0);
   if (oldfile == MACH_PORT_NULL)
     return -1;