about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog28
-rw-r--r--hurd/Makefile4
-rw-r--r--hurd/hurd/fd.h18
-rw-r--r--hurd/hurd/lookup.h34
-rw-r--r--hurd/hurdlookup.c14
-rw-r--r--hurd/lookup-at.c110
-rw-r--r--malloc/malloc.c3
-rw-r--r--sysdeps/mach/hurd/faccessat.c70
-rw-r--r--sysdeps/mach/hurd/fchmodat.c44
-rw-r--r--sysdeps/mach/hurd/fchownat.c46
-rw-r--r--sysdeps/mach/hurd/fxstatat.c33
-rw-r--r--sysdeps/mach/hurd/fxstatat64.c46
-rw-r--r--sysdeps/mach/hurd/linkat.c66
-rw-r--r--sysdeps/mach/hurd/mkdirat.c42
-rw-r--r--sysdeps/mach/hurd/open.c8
-rw-r--r--sysdeps/mach/hurd/open64.c1
-rw-r--r--sysdeps/mach/hurd/openat.c62
-rw-r--r--sysdeps/mach/hurd/openat64.c1
-rw-r--r--sysdeps/mach/hurd/symlinkat.c74
-rw-r--r--sysdeps/mach/hurd/unlinkat.c55
-rw-r--r--sysdeps/mach/hurd/xmknod.c90
-rw-r--r--sysdeps/mach/hurd/xmknodat.c118
22 files changed, 858 insertions, 109 deletions
diff --git a/ChangeLog b/ChangeLog
index 18d6f49f1f..70083ec7c9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -13,6 +13,34 @@
 
 2006-03-05  Roland McGrath  <roland@frob.com>
 
+	* sysdeps/mach/hurd/faccessat.c: New file.
+	* sysdeps/mach/hurd/fchmodat.c: New file.
+	* sysdeps/mach/hurd/fchownat.c: New file.
+	* sysdeps/mach/hurd/fxstatat.c: New file.
+	* sysdeps/mach/hurd/fxstatat64.c: New file.
+	* sysdeps/mach/hurd/linkat.c: New file.
+	* sysdeps/mach/hurd/mkdirat.c: New file.
+	* sysdeps/mach/hurd/openat.c: New file.
+	* sysdeps/mach/hurd/openat64.c: New file.
+	* sysdeps/mach/hurd/symlinkat.c: New file.
+	* sysdeps/mach/hurd/unlinkat.c: New file.
+	* sysdeps/mach/hurd/xmknod.c (__xmknod): Just call __xmknodat.
+	Guts move to ...
+	* sysdeps/mach/hurd/xmknodat.c: ... here, new file.
+
+	* hurd/lookup-at.c: New file.
+	* hurd/Makefile (routines): Add it.
+	* hurd/hurd/fd.h: Declare __file_name_lookup_at,
+	__file_name_split_at and __directory_name_split_at.
+
+	* hurd/hurd/lookup.h: Declare {,__}hurd_directory_name_split.
+
+	* hurd/hurdlookup.c (__hurd_directory_name_split): Use __memrchr
+	unconditionally.
+
+	* sysdeps/mach/hurd/open.c: Define {,__,__libc_,}open64 as aliases.
+	* sysdeps/mach/hurd/open64.c: New file.
+
 	* sysdeps/posix/sysconf.c (__sysconf): Use #if _POSIX_FOO > 0
 	rather than #ifdef _POSIX_FOO for options.  We should return -1
 	at runtime for an option defined to 0 at compile time.
diff --git a/hurd/Makefile b/hurd/Makefile
index 5d99429f79..ab5a8485a2 100644
--- a/hurd/Makefile
+++ b/hurd/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1991,92,93,94,95,96,97,98,99,2001,2002,2004
+# Copyright (C) 1991,92,93,94,95,96,97,98,99,2001,2002,2004,2006
 #	Free Software Foundation, Inc.
 # This file is part of the GNU C Library.
 
@@ -46,7 +46,7 @@ server-interfaces	:= hurd/msg faultexc
 
 routines = hurdstartup hurdinit \
 	   hurdid hurdpid hurdrlimit hurdprio hurdexec hurdselect \
-	   hurdlookup lookup-retry \
+	   hurdlookup lookup-retry lookup-at \
 	   get-host set-host \
 	   path-lookup \
 	   setauth \
diff --git a/hurd/hurd/fd.h b/hurd/hurd/fd.h
index 198791b807..ad11367f3b 100644
--- a/hurd/hurd/fd.h
+++ b/hurd/hurd/fd.h
@@ -1,5 +1,5 @@
 /* File descriptors.
-   Copyright (C) 1993,94,95,96,97,98,99,2000,01,02
+   Copyright (C) 1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2006
    	Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -240,5 +240,21 @@ extern int _hurd_select (int nfds, struct pollfd *pollfds,
 			 const struct timespec *timeout,
 			 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.  */
+extern file_t __file_name_lookup_at (int fd, int at_flags,
+				     const char *file_name,
+				     int flags, mode_t mode);
+
+/* Variant of file_name_split used in *at function implementations.  */
+extern file_t __file_name_split_at (int fd, const char *file_name,
+				    char **name);
+
+/* Variant of directory_name_split used in *at function implementations.  */
+extern file_t __directory_name_split_at (int fd, const char *directory_name,
+					 char **name);
+
+
 
 #endif	/* hurd/fd.h */
diff --git a/hurd/hurd/lookup.h b/hurd/hurd/lookup.h
index faa35e0bf6..1d013d9537 100644
--- a/hurd/hurd/lookup.h
+++ b/hurd/hurd/lookup.h
@@ -1,5 +1,5 @@
 /* Declarations of file name translation functions for the GNU Hurd.
-   Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1997, 2006 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
@@ -76,8 +76,8 @@ error_t __hurd_file_name_split (error_t (*use_init_port)
 				  (int which,
 				   error_t (*operate) (mach_port_t)),
 				file_t (*get_dtable_port) (int fd),
-				error_t (*lookup)
-				  (file_t dir, char *name, int flags, mode_t mode,
+				error_t (*lookup) (file_t dir, char *name,
+						   int flags, mode_t mode,
 				   retry_type *do_retry, string_t retry_name,
 				   mach_port_t *result),
 				const char *file_name,
@@ -86,13 +86,37 @@ error_t hurd_file_name_split (error_t (*use_init_port)
 			        (int which,
 				 error_t (*operate) (mach_port_t)),
 			      file_t (*get_dtable_port) (int fd),
-			      error_t (*lookup)
-				(file_t dir, char *name, int flags, mode_t mode,
+			      error_t (*lookup) (file_t dir, char *name,
+						 int flags, mode_t mode,
 				 retry_type *do_retry, string_t retry_name,
 				 mach_port_t *result),
 			      const char *file_name,
 			      file_t *dir, char **name);
 
+/* Split DIRECTORY into a parent directory and a name within the directory.
+   This is the same as hurd_file_name_split, but ignores trailing slashes.  */
+
+error_t __hurd_directory_name_split (error_t (*use_init_port)
+				  (int which,
+				   error_t (*operate) (mach_port_t)),
+				file_t (*get_dtable_port) (int fd),
+				error_t (*lookup) (file_t dir, char *name,
+						   int flags, mode_t mode,
+				   retry_type *do_retry, string_t retry_name,
+				   mach_port_t *result),
+				const char *directory_name,
+				file_t *dir, char **name);
+error_t hurd_directory_name_split (error_t (*use_init_port)
+				   (int which,
+				    error_t (*operate) (mach_port_t)),
+				   file_t (*get_dtable_port) (int fd),
+				   error_t (*lookup) (file_t dir, char *name,
+						      int flags, mode_t mode,
+				    retry_type *do_retry, string_t retry_name,
+				    mach_port_t *result),
+				   const char *directory_name,
+				   file_t *dir, char **name);
+
 
 /* Process the values returned by `dir_lookup' et al, and loop doing
    `dir_lookup' calls until one returns FS_RETRY_NONE.  The arguments
diff --git a/hurd/hurdlookup.c b/hurd/hurdlookup.c
index 77de27150a..8270132b90 100644
--- a/hurd/hurdlookup.c
+++ b/hurd/hurdlookup.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992,93,94,95,96,97,99,2001,2004
+/* Copyright (C) 1992,1993,1994,1995,1996,1997,1999,2001,2004,2006
 	Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -184,19 +184,7 @@ __hurd_directory_name_split (error_t (*use_init_port)
 	--lastslash;
 
       /* Find the last one earlier in the string, before the trailing ones.  */
-#if __GLIBC__ > 2 || __GLIBC_MINOR__ >= 2
       lastslash = __memrchr (file_name, '/', lastslash - file_name);
-#else
-      /* Keep backing up, looking for a slash.  */
-      do
-	if (lastslash == file_name)
-	  {
-	    /* Hit the start with no slash.  */
-	    lastslash = NULL;
-	    break;
-	  }
-      while (*lastslash-- != '/');
-#endif
     }
 
   if (lastslash != NULL)
diff --git a/hurd/lookup-at.c b/hurd/lookup-at.c
new file mode 100644
index 0000000000..a2d50cb192
--- /dev/null
+++ b/hurd/lookup-at.c
@@ -0,0 +1,110 @@
+/* Lookup helper function for Hurd implementation of *at functions.
+   Copyright (C) 2006 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <hurd.h>
+#include <hurd/lookup.h>
+#include <hurd/fd.h>
+#include <string.h>
+#include <fcntl.h>
+
+file_t
+__file_name_lookup_at (int fd, int at_flags,
+		       const char *file_name, int flags, mode_t mode)
+{
+  error_t err;
+  file_t result;
+
+  flags |= (at_flags & AT_SYMLINK_NOFOLLOW) ? O_NOLINK : 0;
+  at_flags &= ~AT_SYMLINK_NOFOLLOW;
+  if (at_flags != 0)
+    return __hurd_fail (EINVAL);
+
+  if (fd == AT_FDCWD || file_name[0] == '/')
+    return __file_name_lookup (file_name, flags, mode);
+
+  file_t startdir;
+  error_t use_init_port (int which, error_t (*operate) (mach_port_t))
+    {
+      return (which == INIT_PORT_CWDIR ? (*operate) (startdir) :
+	      _hurd_ports_use (which, operate));
+    }
+
+  err = HURD_DPORT_USE (fd, (startdir = port,
+			     __hurd_file_name_lookup (&use_init_port,
+						      &__getdport, NULL,
+						      file_name,
+						      flags,
+						      mode & ~_hurd_umask,
+						      &result)));
+
+  return err ? (__hurd_dfail (fd, err), MACH_PORT_NULL) : result;
+}
+
+file_t
+__file_name_split_at (int fd, const char *file_name, char **name)
+{
+  error_t err;
+  file_t result;
+
+  if (fd == AT_FDCWD || file_name[0] == '/')
+    return __file_name_split (file_name, name);
+
+  err = __hurd_file_name_split (&_hurd_ports_use, &__getdport, 0,
+				file_name, &result, name);
+
+  file_t startdir;
+  error_t use_init_port (int which, error_t (*operate) (mach_port_t))
+  {
+    return (which == INIT_PORT_CWDIR ? (*operate) (startdir) :
+	    _hurd_ports_use (which, operate));
+  }
+
+  err = HURD_DPORT_USE (fd, (startdir = port,
+			     __hurd_file_name_split (&use_init_port,
+						     &__getdport, 0,
+						     file_name,
+						     &result, name)));
+
+  return err ? (__hurd_dfail (fd, err), MACH_PORT_NULL) : result;
+}
+
+file_t
+__directory_name_split_at (int fd, const char *directory_name, char **name)
+{
+  error_t err;
+  file_t result;
+
+  if (fd == AT_FDCWD || directory_name[0] == '/')
+    return __directory_name_split (directory_name, name);
+
+  file_t startdir;
+  error_t use_init_port (int which, error_t (*operate) (mach_port_t))
+    {
+      return (which == INIT_PORT_CWDIR ? (*operate) (startdir) :
+	      _hurd_ports_use (which, operate));
+    }
+
+  err = HURD_DPORT_USE (fd, (startdir = port,
+			     __hurd_directory_name_split (&use_init_port,
+							  &__getdport, 0,
+							  directory_name,
+							  &result, name)));
+
+  return err ? (__hurd_dfail (fd, err), MACH_PORT_NULL) : result;
+}
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 5fbd268fed..da230d3493 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -385,7 +385,8 @@ extern "C" {
    powerpc32.  For the time being, changing this is causing more
    compatibility problems due to malloc_get_state/malloc_set_state than
    will returning blocks not adequately aligned for long double objects
-   under -mlong-double-128.  */
+   under -mlong-double-128.
+
 #define MALLOC_ALIGNMENT       (2 * SIZE_SZ < __alignof__ (long double) \
 				? __alignof__ (long double) : 2 * SIZE_SZ)
 */
diff --git a/sysdeps/mach/hurd/faccessat.c b/sysdeps/mach/hurd/faccessat.c
new file mode 100644
index 0000000000..bb3c9fe19f
--- /dev/null
+++ b/sysdeps/mach/hurd/faccessat.c
@@ -0,0 +1,70 @@
+/* Test for access to file, relative to open directory.  Hurd version.
+   Copyright (C) 2006 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+int
+faccessat (fd, file, type, flag)
+     int fd;
+     const char *file;
+     int type;
+     int flag;
+{
+  error_t err;
+  file_t port;
+  int allowed, flags;
+
+  if ((flag & AT_EACCESS) == 0)
+    {
+      if (fd == AT_FDCWD || file[0] == '/')
+	return __access (file, type);
+      __set_errno (ENOTSUP);	/* XXX later */
+      return -1;
+    }
+
+  port = __file_name_lookup_at (fd, flag &~ AT_EACCESS, file, 0, 0);
+  if (port == MACH_PORT_NULL)
+    return -1;
+
+  /* Find out what types of access we are allowed to this file.  */
+  err = __file_check_access (port, &allowed);
+  __mach_port_deallocate (__mach_task_self (), port);
+  if (err)
+    return __hurd_fail (err);
+
+  flags = 0;
+  if (type & R_OK)
+    flags |= O_READ;
+  if (type & W_OK)
+    flags |= O_WRITE;
+  if (type & X_OK)
+    flags |= O_EXEC;
+
+  if (flags & ~allowed)
+    /* We are not allowed all the requested types of access.  */
+    return __hurd_fail (EACCES);
+
+  return 0;
+}
diff --git a/sysdeps/mach/hurd/fchmodat.c b/sysdeps/mach/hurd/fchmodat.c
new file mode 100644
index 0000000000..d27e845274
--- /dev/null
+++ b/sysdeps/mach/hurd/fchmodat.c
@@ -0,0 +1,44 @@
+/* Change the protections of file relative to open directory.  Hurd version.
+   Copyright (C) 2006 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+int
+fchmodat (fd, file, mode, flag)
+     int fd;
+     const char *file;
+     mode_t mode;
+     int flag;
+{
+  error_t err;
+  file_t port = __file_name_lookup_at (fd, flag, file, 0, 0);
+  if (port == MACH_PORT_NULL)
+    return -1;
+  err = __file_chmod (port, mode);
+  __mach_port_deallocate (__mach_task_self (), port);
+  if (err)
+    return __hurd_fail (err);
+  return 0;
+}
diff --git a/sysdeps/mach/hurd/fchownat.c b/sysdeps/mach/hurd/fchownat.c
new file mode 100644
index 0000000000..1b99b29272
--- /dev/null
+++ b/sysdeps/mach/hurd/fchownat.c
@@ -0,0 +1,46 @@
+/* Change owner and group of a file relative to open directory.  Hurd version.
+   Copyright (C) 2006 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+/* Change the owner and group of FILE.  */
+int
+fchownat (fd, file, owner, group, flag)
+     int fd;
+     const char *file;
+     uid_t owner;
+     gid_t group;
+     int flag;
+{
+  error_t err;
+  file_t port = __file_name_lookup_at (fd, flag, file, 0, 0);
+  if (port == MACH_PORT_NULL)
+    return -1;
+  err = __file_chown (port, owner, group);
+  __mach_port_deallocate (__mach_task_self (), port);
+  if (err)
+    return __hurd_fail (err);
+  return 0;
+}
diff --git a/sysdeps/mach/hurd/fxstatat.c b/sysdeps/mach/hurd/fxstatat.c
new file mode 100644
index 0000000000..dd9d2796eb
--- /dev/null
+++ b/sysdeps/mach/hurd/fxstatat.c
@@ -0,0 +1,33 @@
+/* Get information about file named relative to open directory.  Hurd version.
+   Copyright (C) 2006 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <stddef.h>
+#include <sys/stat.h>
+
+#include "xstatconv.c"
+
+int
+__fxstatat (int vers, int fd, const char *filename, struct stat *buf, int flag)
+{
+  struct stat64 buf64;
+  return (__fxstatat64 (vers, fd, filename, &buf64, flag)
+	  ?: xstat64_conv (buf, &buf64));
+}
+libc_hidden_def (__fxstatat)
diff --git a/sysdeps/mach/hurd/fxstatat64.c b/sysdeps/mach/hurd/fxstatat64.c
new file mode 100644
index 0000000000..6862e80d52
--- /dev/null
+++ b/sysdeps/mach/hurd/fxstatat64.c
@@ -0,0 +1,46 @@
+/* Get information about file named relative to open directory.  Hurd version.
+   Copyright (C) 2006 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <sys/stat.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+/* Get information about the file descriptor FD in BUF.  */
+int
+__fxstatat64 (int vers, int fd, const char *filename, struct stat64 *buf,
+	      int flag)
+{
+  error_t err;
+  io_t port;
+
+  if (vers != _STAT_VER)
+    return __hurd_fail (EINVAL);
+
+  port = __file_name_lookup_at (fd, flag, filename, 0, 0);
+  if (port == MACH_PORT_NULL)
+    return -1;
+
+  err = __io_stat (port, buf);
+  __mach_port_deallocate (__mach_task_self (), port);
+
+  return __hurd_fail (err);
+}
diff --git a/sysdeps/mach/hurd/linkat.c b/sysdeps/mach/hurd/linkat.c
new file mode 100644
index 0000000000..1942144e0f
--- /dev/null
+++ b/sysdeps/mach/hurd/linkat.c
@@ -0,0 +1,66 @@
+/* Make a link between file names relative to open directories.  Hurd version.
+   Copyright (C) 2006 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+
+/* Make a link to FROM relative to FROMFD called TO relative to TOFD.  */
+int
+linkat (fromfd, from, tofd, to, flags)
+     int fromfd;
+     const char *from;
+     int tofd;
+     const char *to;
+     int flags;
+{
+  error_t err;
+  file_t oldfile, linknode, todir;
+  char *toname;
+
+  oldfile = __file_name_lookup_at (fromfd, flags, from, 0, 0);
+  if (oldfile == MACH_PORT_NULL)
+    return -1;
+
+  /* The file_getlinknode RPC returns the port that should be passed to
+     the receiving filesystem (the one containing TODIR) in dir_link.  */
+
+  err = __file_getlinknode (oldfile, &linknode);
+  __mach_port_deallocate (__mach_task_self (), oldfile);
+  if (err)
+    return __hurd_fail (err);
+
+  todir = __file_name_split_at (tofd, to, &toname);
+  if (todir != MACH_PORT_NULL)
+    {
+      err = __dir_link (todir, linknode, toname, 1);
+      __mach_port_deallocate (__mach_task_self (), todir);
+    }
+  __mach_port_deallocate (__mach_task_self (), linknode);
+  if (todir == MACH_PORT_NULL)
+    return -1;
+
+  if (err)
+    return __hurd_fail (err);
+  return 0;
+}
diff --git a/sysdeps/mach/hurd/mkdirat.c b/sysdeps/mach/hurd/mkdirat.c
new file mode 100644
index 0000000000..321d59f2fd
--- /dev/null
+++ b/sysdeps/mach/hurd/mkdirat.c
@@ -0,0 +1,42 @@
+/* Create a directory named relative to another open directory.  Hurd version.
+   Copyright (C) 1991,1993,1994,1995,1996,1997,2002,2006
+	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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <stddef.h>
+#include <sys/stat.h>
+#include <hurd.h>
+
+int
+mkdirat (fd, path, mode)
+     int fd;
+     const char *path;
+     mode_t mode;
+{
+  error_t err;
+  const char *name;
+  file_t parent = __directory_name_split (path, (char **) &name);
+  if (parent == MACH_PORT_NULL)
+    return -1;
+  err = __dir_mkdir (parent, name, mode & ~_hurd_umask);
+  __mach_port_deallocate (__mach_task_self (), parent);
+  if (err)
+    return __hurd_fail (err);
+  return 0;
+}
diff --git a/sysdeps/mach/hurd/open.c b/sysdeps/mach/hurd/open.c
index dd575a47b1..bdfed5e311 100644
--- a/sysdeps/mach/hurd/open.c
+++ b/sysdeps/mach/hurd/open.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992,93,94,95,97,2000,2002 Free Software Foundation, Inc.
+/* Copyright (C) 1992,93,94,95,97,2000,2002,2006 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
@@ -51,3 +51,9 @@ libc_hidden_def (__libc_open)
 weak_alias (__libc_open, __open)
 libc_hidden_weak (__open)
 weak_alias (__libc_open, open)
+
+/* open64 is just the same as open for us.  */
+weak_alias (__libc_open, __libc_open64)
+weak_alias (__libc_open, __open64)
+libc_hidden_weak (_open64)
+weak_alias (__libc_open, open64)
diff --git a/sysdeps/mach/hurd/open64.c b/sysdeps/mach/hurd/open64.c
new file mode 100644
index 0000000000..018ac94f28
--- /dev/null
+++ b/sysdeps/mach/hurd/open64.c
@@ -0,0 +1 @@
+/* open64 is defined in open.c as an alias.  */
diff --git a/sysdeps/mach/hurd/openat.c b/sysdeps/mach/hurd/openat.c
new file mode 100644
index 0000000000..1faf857e16
--- /dev/null
+++ b/sysdeps/mach/hurd/openat.c
@@ -0,0 +1,62 @@
+/* openat -- Open a file named relative to an open directory.  Hurd version.
+   Copyright (C) 2006 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <sys/stat.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+/* Open FILE with access OFLAG.  Interpret relative paths relative to
+   the directory associated with FD.  If OFLAG includes O_CREAT, a
+   third argument is the file protection.  */
+int
+__openat (fd, file, oflag)
+     int fd;
+     const char *file;
+     int oflag;
+{
+  int mode;
+  io_t port;
+
+  if (oflag & O_CREAT)
+    {
+      va_list arg;
+      va_start (arg, oflag);
+      mode = va_arg (arg, int);
+      va_end (arg);
+    }
+  else
+    mode = 0;
+
+  port = __file_name_lookup_at (fd, 0, file, oflag, mode);
+  if (port == MACH_PORT_NULL)
+    return -1;
+
+  return _hurd_intern_fd (port, oflag, 1);
+}
+libc_hidden_def (__openat)
+weak_alias (__openat, openat)
+
+/* openat64 is just the same as openat for us.  */
+weak_alias (__openat, __openat64)
+libc_hidden_weak (__openat64)
+weak_alias (__openat, openat64)
diff --git a/sysdeps/mach/hurd/openat64.c b/sysdeps/mach/hurd/openat64.c
new file mode 100644
index 0000000000..15d9d6a183
--- /dev/null
+++ b/sysdeps/mach/hurd/openat64.c
@@ -0,0 +1 @@
+/* openat64 is defined in openat.c as an alias.  */
diff --git a/sysdeps/mach/hurd/symlinkat.c b/sysdeps/mach/hurd/symlinkat.c
new file mode 100644
index 0000000000..9a51c66d8d
--- /dev/null
+++ b/sysdeps/mach/hurd/symlinkat.c
@@ -0,0 +1,74 @@
+/* Create a symbolic link named relative to an open directory.  Hurd version.
+   Copyright (C) 1991,1992,1993,1994,1995,1996,1997,2006
+	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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/paths.h>
+#include <hurd/fd.h>
+#include <string.h>
+
+
+/* Make a link to FROM called TO relative to FD.  */
+int
+symlinkat (from, fd, to)
+     const char *from;
+     int fd;
+     const char *to;
+{
+  error_t err;
+  file_t dir, node;
+  char *name;
+  const size_t len = strlen (from) + 1;
+  char buf[sizeof (_HURD_SYMLINK) + len];
+
+  /* A symlink is a file whose translator is "/hurd/symlink\0target\0".  */
+
+  memcpy (buf, _HURD_SYMLINK, sizeof (_HURD_SYMLINK));
+  memcpy (&buf[sizeof (_HURD_SYMLINK)], from, len);
+
+  dir = __file_name_split_at (fd, to, &name);
+  if (dir == MACH_PORT_NULL)
+    return -1;
+
+  /* Create a new, unlinked node in the target directory.  */
+  err = __dir_mkfile (dir, O_WRITE, 0777 & ~_hurd_umask, &node);
+
+  if (! err)
+    /* Set the node's translator to make it a symlink.  */
+    err = __file_set_translator (node,
+				 FS_TRANS_EXCL|FS_TRANS_SET,
+				 FS_TRANS_EXCL|FS_TRANS_SET, 0,
+				 buf, sizeof (_HURD_SYMLINK) + len,
+				 MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND);
+
+  if (! err)
+    /* Link the node, now a valid symlink, into the target directory.  */
+    err = __dir_link (dir, node, name, 1);
+
+  __mach_port_deallocate (__mach_task_self (), dir);
+  __mach_port_deallocate (__mach_task_self (), node);
+
+  if (err)
+    return __hurd_fail (err);
+  return 0;
+}
diff --git a/sysdeps/mach/hurd/unlinkat.c b/sysdeps/mach/hurd/unlinkat.c
new file mode 100644
index 0000000000..7740c5a297
--- /dev/null
+++ b/sysdeps/mach/hurd/unlinkat.c
@@ -0,0 +1,55 @@
+/* unlinkat -- Remove a name relative to an open directory.  Hurd version.
+   Copyright (C) 2006 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+
+/* Remove the link named NAME.  */
+int
+unlinkat (fd, name, flag)
+     int fd;
+     const char *name;
+     int flag;
+{
+  error_t err;
+  file_t dir;
+  const char *file;
+
+  if ((flag &~ AT_REMOVEDIR) != 0)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  dir = __directory_name_split_at (fd, name, (char **) &file);
+  if (dir == MACH_PORT_NULL)
+    return -1;
+
+  err = ((flag & AT_REMOVEDIR) ? __dir_rmdir : __dir_unlink) (dir, file);
+  __mach_port_deallocate (__mach_task_self (), dir);
+
+  if (err)
+    return __hurd_fail (err);
+  return 0;
+}
diff --git a/sysdeps/mach/hurd/xmknod.c b/sysdeps/mach/hurd/xmknod.c
index aaa6771cd8..5f40188fb6 100644
--- a/sysdeps/mach/hurd/xmknod.c
+++ b/sysdeps/mach/hurd/xmknod.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991,1992,1993,1994,1995,1996,1999,2002,2005
+/* Copyright (C) 1991,1992,1993,1994,1995,1996,1999,2002,2005,2006
 	Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -18,13 +18,10 @@
    02111-1307 USA.  */
 
 #include <errno.h>
-#include <sys/stat.h>
-#include <hurd.h>
-#include <hurd/paths.h>
 #include <fcntl.h>
-#include "stdio-common/_itoa.h"
-#include <string.h>
+#include <stddef.h>
 #include <sys/types.h>
+#include <sys/stat.h>
 
 
 /* Create a device file named FILE_NAME, with permission and special bits MODE
@@ -33,85 +30,6 @@
 int
 __xmknod (int vers, const char *file_name, mode_t mode, dev_t *dev)
 {
-  error_t err;
-  file_t dir, node;
-  char *name;
-  char buf[100], *bp;
-  const char *translator;
-  size_t len;
-
-  if (vers != _MKNOD_VER)
-    return __hurd_fail (EINVAL);
-
-  if (S_ISCHR (mode))
-    {
-      translator = _HURD_CHRDEV;
-      len = sizeof (_HURD_CHRDEV);
-    }
-  else if (S_ISBLK (mode))
-    {
-      translator = _HURD_BLKDEV;
-      len = sizeof (_HURD_BLKDEV);
-    }
-  else if (S_ISFIFO (mode))
-    {
-      translator = _HURD_FIFO;
-      len = sizeof (_HURD_FIFO);
-    }
-  else if (S_ISREG (mode))
-    {
-      translator = NULL;
-      len = 0;
-    }
-  else
-    {
-      errno = EINVAL;
-      return -1;
-    }
-
-  if (translator != NULL && ! S_ISFIFO (mode))
-    {
-      /* We set the translator to "ifmt\0major\0minor\0", where IFMT
-	 depends on the S_IFMT bits of our MODE argument, and MAJOR and
-	 MINOR are ASCII decimal (octal or hex would do as well)
-	 representations of our arguments.  Thus the convention is that
-	 CHRDEV and BLKDEV translators are invoked with two non-switch
-	 arguments, giving the major and minor device numbers in %i format. */
-
-      bp = buf + sizeof (buf);
-      *--bp = '\0';
-      bp = _itoa (minor (*dev), bp, 10, 0);
-      *--bp = '\0';
-      bp = _itoa (major (*dev), bp, 10, 0);
-      memcpy (bp - len, translator, len);
-      translator = bp - len;
-      len = buf + sizeof (buf) - translator;
-    }
-
-  dir = __file_name_split (file_name, &name);
-  if (dir == MACH_PORT_NULL)
-    return -1;
-
-  /* Create a new, unlinked node in the target directory.  */
-  err = __dir_mkfile (dir, O_WRITE, (mode & ~S_IFMT) & ~_hurd_umask, &node);
-
-  if (! err && translator != NULL)
-    /* Set the node's translator to make it a device.  */
-    err = __file_set_translator (node,
-				 FS_TRANS_EXCL | FS_TRANS_SET,
-				 FS_TRANS_EXCL | FS_TRANS_SET, 0,
-				 translator, len,
-				 MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND);
-
-  if (! err)
-    /* Link the node, now a valid device, into the target directory.  */
-    err = __dir_link (dir, node, name, 1);
-
-  __mach_port_deallocate (__mach_task_self (), dir);
-  __mach_port_deallocate (__mach_task_self (), node);
-
-  if (err)
-    return __hurd_fail (err);
-  return 0;
+  return __xmknodat (vers, AT_FDCWD, file_name, mode, dev);
 }
 libc_hidden_def (__xmknod)
diff --git a/sysdeps/mach/hurd/xmknodat.c b/sysdeps/mach/hurd/xmknodat.c
new file mode 100644
index 0000000000..b2227593c9
--- /dev/null
+++ b/sysdeps/mach/hurd/xmknodat.c
@@ -0,0 +1,118 @@
+/* Create a device file relative to an open directory.  Hurd version.
+   Copyright (C) 1991,1992,1993,1994,1995,1996,1999,2002,2005,2006
+	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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <sys/stat.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+#include <hurd/paths.h>
+#include <fcntl.h>
+#include "stdio-common/_itoa.h"
+#include <string.h>
+#include <sys/types.h>
+
+/* Create a device file named PATH relative to FD, with permission and
+   special bits MODE and device number DEV (which can be constructed
+   from major and minor device numbers with the `makedev' macro
+   above).  */
+int
+__xmknodat (int vers, int fd, const char *path, mode_t mode, dev_t *dev)
+{
+  error_t err;
+  file_t dir, node;
+  char *name;
+  char buf[100], *bp;
+  const char *translator;
+  size_t len;
+
+  if (vers != _MKNOD_VER)
+    return __hurd_fail (EINVAL);
+
+  if (S_ISCHR (mode))
+    {
+      translator = _HURD_CHRDEV;
+      len = sizeof (_HURD_CHRDEV);
+    }
+  else if (S_ISBLK (mode))
+    {
+      translator = _HURD_BLKDEV;
+      len = sizeof (_HURD_BLKDEV);
+    }
+  else if (S_ISFIFO (mode))
+    {
+      translator = _HURD_FIFO;
+      len = sizeof (_HURD_FIFO);
+    }
+  else if (S_ISREG (mode))
+    {
+      translator = NULL;
+      len = 0;
+    }
+  else
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  if (translator != NULL && ! S_ISFIFO (mode))
+    {
+      /* We set the translator to "ifmt\0major\0minor\0", where IFMT
+	 depends on the S_IFMT bits of our MODE argument, and MAJOR and
+	 MINOR are ASCII decimal (octal or hex would do as well)
+	 representations of our arguments.  Thus the convention is that
+	 CHRDEV and BLKDEV translators are invoked with two non-switch
+	 arguments, giving the major and minor device numbers in %i format. */
+
+      bp = buf + sizeof (buf);
+      *--bp = '\0';
+      bp = _itoa (minor (*dev), bp, 10, 0);
+      *--bp = '\0';
+      bp = _itoa (major (*dev), bp, 10, 0);
+      memcpy (bp - len, translator, len);
+      translator = bp - len;
+      len = buf + sizeof (buf) - translator;
+    }
+
+  dir = __file_name_split_at (fd, path, &name);
+  if (dir == MACH_PORT_NULL)
+    return -1;
+
+  /* Create a new, unlinked node in the target directory.  */
+  err = __dir_mkfile (dir, O_WRITE, (mode & ~S_IFMT) & ~_hurd_umask, &node);
+
+  if (! err && translator != NULL)
+    /* Set the node's translator to make it a device.  */
+    err = __file_set_translator (node,
+				 FS_TRANS_EXCL | FS_TRANS_SET,
+				 FS_TRANS_EXCL | FS_TRANS_SET, 0,
+				 translator, len,
+				 MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND);
+
+  if (! err)
+    /* Link the node, now a valid device, into the target directory.  */
+    err = __dir_link (dir, node, name, 1);
+
+  __mach_port_deallocate (__mach_task_self (), dir);
+  __mach_port_deallocate (__mach_task_self (), node);
+
+  if (err)
+    return __hurd_fail (err);
+  return 0;
+}