This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] [Hurd] Fix linkat() with AT_SYMLINK_FOLLOW


Hi,

My copyright assignment for GNU libc should be on file now, so here's one patch
I had pending submission.

This fixes linkat() with AT_SYMLINK_FOLLOW in flags, which is currently
returning EINVAL.

Cheers,
Emilio


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.

diff --git a/hurd/hurd/fd.h b/hurd/hurd/fd.h
index d1aa867..2473476 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 7f55527..728a970 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 1942144..f8406a5 100644
--- a/sysdeps/mach/hurd/linkat.c
+++ b/sysdeps/mach/hurd/linkat.c
@@ -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 overriden by AT_SYMLINK_FOLLOW in FLAGS.  */
+  oldfile = __file_name_lookup_at (fromfd, flags, from, O_NOLINK, 0);
   if (oldfile == MACH_PORT_NULL)
     return -1;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]