From 2a50c07836d2750baf70442f8f760bf6cd43b3af Mon Sep 17 00:00:00 2001 From: Emilio Pozuelo Monfort Date: Wed, 2 Jun 2010 10:24:59 -0700 Subject: [PATCH] Hurd: Fix linkat symlink handling. --- ChangeLog | 9 +++++++++ hurd/hurd/fd.h | 5 +++-- hurd/lookup-at.c | 6 ++++++ sysdeps/mach/hurd/linkat.c | 6 ++++-- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 918f67511a..d5f9d30334 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2010-06-02 Emilio Pozuelo Monfort + + * 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-05-28 Luis Machado * sysdeps/powerpc/powerpc32/power7/memcpy.S: Exchange srdi for srwi. 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); diff --git a/sysdeps/mach/hurd/linkat.c b/sysdeps/mach/hurd/linkat.c index 1942144e0f..062d913e3d 100644 --- a/sysdeps/mach/hurd/linkat.c +++ b/sysdeps/mach/hurd/linkat.c @@ -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; -- 2.11.4.GIT