aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2005-12-02 21:55:54 +0000
committerUlrich Drepper <drepper@redhat.com>2005-12-02 21:55:54 +0000
commite186c703dc073b8be95d0bf893bb8ebb127fe02b (patch)
treebcb3f09e881383811b00aa8359cb2f71391b116b
parent975407d507f2e8ad6cbf366e22e0f41d598ddcee (diff)
downloadglibc-e186c703dc073b8be95d0bf893bb8ebb127fe02b.tar
glibc-e186c703dc073b8be95d0bf893bb8ebb127fe02b.tar.gz
glibc-e186c703dc073b8be95d0bf893bb8ebb127fe02b.tar.bz2
glibc-e186c703dc073b8be95d0bf893bb8ebb127fe02b.zip
* io/Makefile (routines): Add mknodat, xmknodat, mkdirat, mkfifoat.
(static-only-routines): Add mknodat. * io/Versions [GLIBC_2.4]: Add mkdirat, mkfifoat, __xmknodat. * io/sys/stat.h: Declare mkditat, mknodat, mkfifoat, __xmknodat. Define mknodat inline function. * include/sys/stat.h: Add hidden proto for __xmknodat. * sysdeps/generic/mkdirat.c: New file. * sysdeps/generic/mkfifoat.c: New file. * sysdeps/generic/mknodat.c: New file. * sysdeps/generic/xmknodat.c: New file. * sysdeps/unix/mkfifoat.c: New file. * sysdeps/unix/sysv/linux/mkdirat.c: New file. * sysdeps/unix/sysv/linux/xmknodat.c: New file. * sysdeps/generic/xmknod.c: Add one more parameter check.
-rw-r--r--ChangeLog18
-rw-r--r--NEWS4
-rw-r--r--include/sys/stat.h1
-rw-r--r--io/Makefile13
-rw-r--r--io/Versions1
-rw-r--r--io/sys/stat.h37
-rw-r--r--sysdeps/generic/mkdirat.c58
-rw-r--r--sysdeps/generic/mkfifoat.c60
-rw-r--r--sysdeps/generic/mknodat.c60
-rw-r--r--sysdeps/generic/xmknodat.c63
-rw-r--r--sysdeps/unix/mkfifoat.c32
-rw-r--r--sysdeps/unix/sysv/linux/mkdirat.c66
-rw-r--r--sysdeps/unix/sysv/linux/xmknodat.c75
13 files changed, 480 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog
index 1c3cc1ee26..9dd3bc2ee7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2005-12-02 Ulrich Drepper <drepper@redhat.com>
+
+ * io/Makefile (routines): Add mknodat, xmknodat, mkdirat, mkfifoat.
+ (static-only-routines): Add mknodat.
+ * io/Versions [GLIBC_2.4]: Add mkdirat, mkfifoat, __xmknodat.
+ * io/sys/stat.h: Declare mkditat, mknodat, mkfifoat, __xmknodat.
+ Define mknodat inline function.
+ * include/sys/stat.h: Add hidden proto for __xmknodat.
+ * sysdeps/generic/mkdirat.c: New file.
+ * sysdeps/generic/mkfifoat.c: New file.
+ * sysdeps/generic/mknodat.c: New file.
+ * sysdeps/generic/xmknodat.c: New file.
+ * sysdeps/unix/mkfifoat.c: New file.
+ * sysdeps/unix/sysv/linux/mkdirat.c: New file.
+ * sysdeps/unix/sysv/linux/xmknodat.c: New file.
+
+ * sysdeps/generic/xmknod.c: Add one more parameter check.
+
2005-11-28 Andreas Jaeger <aj@suse.de>
* sysdeps/unix/sysv/linux/mips/bits/mman.h (MREMAP_FIXED): Added,
diff --git a/NEWS b/NEWS
index 86c7b5e833..19c24c23dc 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-GNU C Library NEWS -- history of user-visible changes. 2005-11-11
+GNU C Library NEWS -- history of user-visible changes. 2005-12-02
Copyright (C) 1992-2002,2003,2004,2005 Free Software Foundation, Inc.
See the end for copying conditions.
@@ -28,7 +28,7 @@ Version 2.4
recommend using the stable 2.3 branch.
* New interfaces: fdopendir, openat, fstatat, fchownat, futimesat, renameat,
- unlinkat.
+ unlinkat, mkdirat, mkfifoat, mknodat.
Version 2.3.6
diff --git a/include/sys/stat.h b/include/sys/stat.h
index 2e2566d9ef..4a4d05d938 100644
--- a/include/sys/stat.h
+++ b/include/sys/stat.h
@@ -29,6 +29,7 @@ extern __inline__ int __mknod (__const char *__path, __mode_t __mode,
{
return __xmknod (_MKNOD_VER, __path, __mode, &__dev);
}
+libc_hidden_proto (__xmknodat)
/* The `stat', `fstat', `lstat' functions have to be handled special since
diff --git a/io/Makefile b/io/Makefile
index 9339ffe699..76e6072c4b 100644
--- a/io/Makefile
+++ b/io/Makefile
@@ -28,13 +28,14 @@ headers := sys/stat.h bits/stat.h sys/statfs.h bits/statfs.h sys/vfs.h \
routines := \
utime \
- mkfifo \
- stat fstat lstat mknod stat64 fstat64 lstat64 fstatat fstatat64 \
- xstat fxstat lxstat xmknod xstat64 fxstat64 lxstat64 \
+ mkfifo mkfifoat \
+ stat fstat lstat stat64 fstat64 lstat64 fstatat fstatat64 \
+ xstat fxstat lxstat xstat64 fxstat64 lxstat64 \
+ mknod mknodat xmknod xmknodat \
fxstatat fxstatat64 \
statfs fstatfs statfs64 fstatfs64 \
statvfs fstatvfs statvfs64 fstatvfs64 \
- umask chmod fchmod lchmod mkdir \
+ umask chmod fchmod lchmod mkdir mkdirat \
open open64 openat openat64 close \
read write lseek lseek64 access euidaccess \
fcntl flock lockf lockf64 \
@@ -54,8 +55,8 @@ routines := \
# These routines will be omitted from the libc shared object.
# Instead the static object files will be included in a special archive
# linked against when the shared library will be used.
-static-only-routines = stat fstat lstat mknod stat64 fstat64 lstat64 \
- fstatat fstatat64
+static-only-routines = stat fstat lstat stat64 fstat64 lstat64 \
+ fstatat fstatat64 mknod mknodat
others := pwd
test-srcs := ftwtest
diff --git a/io/Versions b/io/Versions
index 65ee77182e..05b9bfc185 100644
--- a/io/Versions
+++ b/io/Versions
@@ -100,6 +100,7 @@ libc {
GLIBC_2.4 {
fchownat;
__fxstatat; __fxstatat64;
+ mkdirat; mkfifoat; __xmknodat;
openat; openat64;
unlinkat;
}
diff --git a/io/sys/stat.h b/io/sys/stat.h
index 03152990e7..d164645a8e 100644
--- a/io/sys/stat.h
+++ b/io/sys/stat.h
@@ -305,6 +305,14 @@ extern __mode_t getumask (void) __THROW;
extern int mkdir (__const char *__path, __mode_t __mode)
__THROW __nonnull ((1));
+#ifdef __USE_GNU
+/* Like mkdir, create a new directory with permission bits MODE. But
+ interpret relative PATH names relative to the directory associated
+ with FD. */
+extern int mkdirat (int __fd, __const char *__path, __mode_t __mode)
+ __THROW __nonnull ((2));
+#endif
+
/* Create a device file named PATH, 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). */
@@ -313,10 +321,26 @@ extern int mknod (__const char *__path, __mode_t __mode, __dev_t __dev)
__THROW __nonnull ((1));
#endif
+#ifdef __USE_GNU
+/* Like mknod, create a new device file with permission bits MODE and
+ device number DEV. But interpret relative PATH names relative to
+ the directory associated with FD. */
+extern int mknodat (int __fd, __const char *__path, __mode_t __mode,
+ __dev_t __dev) __THROW __nonnull ((2));
+#endif
+
/* Create a new FIFO named PATH, with permission bits MODE. */
extern int mkfifo (__const char *__path, __mode_t __mode)
__THROW __nonnull ((1));
+
+#ifdef __USE_GNU
+/* Like mkfifo, create a new FIFO with permission bits MODE. But
+ interpret relative PATH names relative to the directory associated
+ with FD. */
+extern int mkfifoat (int __fd, __const char *__path, __mode_t __mode)
+ __THROW __nonnull ((2));
+#endif
/* To allow the `struct stat' structure and the file type `mode_t'
bits to vary without changing shared library major version number,
@@ -388,6 +412,10 @@ extern int __fxstatat64 (int __ver, int __fildes, __const char *__filename,
extern int __xmknod (int __ver, __const char *__path, __mode_t __mode,
__dev_t *__dev) __THROW __nonnull ((2, 4));
+extern int __xmknodat (int __ver, int __fd, __const char *__path,
+ __mode_t __mode, __dev_t *__dev)
+ __THROW __nonnull ((3, 5));
+
#if defined __GNUC__ && __GNUC__ >= 2
/* Inlined versions of the real stat and mknod functions. */
@@ -428,6 +456,15 @@ __NTH (mknod (__const char *__path, __mode_t __mode, __dev_t __dev))
}
# endif
+# ifdef __USE_GNU
+extern __inline__ int
+__NTH (mknodat (int __fd, __const char *__path, __mode_t __mode,
+ __dev_t __dev))
+{
+ return __xmknodat (_MKNOD_VER, __fd, __path, __mode, &__dev);
+}
+# endif
+
# if defined __USE_LARGEFILE64 \
&& (! defined __USE_FILE_OFFSET64 \
|| (defined __REDIRECT_NTH && defined __OPTIMIZE__))
diff --git a/sysdeps/generic/mkdirat.c b/sysdeps/generic/mkdirat.c
new file mode 100644
index 0000000000..ccea3aa8d8
--- /dev/null
+++ b/sysdeps/generic/mkdirat.c
@@ -0,0 +1,58 @@
+/* Copyright (C) 1991, 1995, 1996, 1997, 2005 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 <sys/types.h>
+
+
+/* Create a directory named PATH relative to FD with protections MODE. */
+int
+mkdirat (fd, path, mode)
+ int fd;
+ const char *path;
+ mode_t mode;
+{
+ if (path == NULL)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ if (fd != AT_FDCWD && path[0] != '/')
+ {
+ /* Check FD is associated with a directory. */
+ struct stat64 st;
+ if (__fxstat64 (_STAT_VER, fd, &st) != 0)
+ return -1;
+
+ if (!S_ISDIR (st.st_mode))
+ {
+ __set_errno (ENOTDIR);
+ return -1;
+ }
+ }
+
+ __set_errno (ENOSYS);
+ return -1;
+}
+stub_warning (mkdirat)
+
+#include <stub-tag.h>
diff --git a/sysdeps/generic/mkfifoat.c b/sysdeps/generic/mkfifoat.c
new file mode 100644
index 0000000000..48c38c8182
--- /dev/null
+++ b/sysdeps/generic/mkfifoat.c
@@ -0,0 +1,60 @@
+/* Copyright (C) 1991, 1995, 1996, 1997, 2005 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 <sys/types.h>
+
+
+/* Create a named pipe (FIFO) named PATH relative to FD with
+ protections MODE. */
+int
+mkfifoat (fd, path, mode)
+ int fd;
+ const char *path;
+ mode_t mode;
+{
+ if (path == NULL)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ if (fd != AT_FDCWD && path[0] != '/')
+ {
+ /* Check FD is associated with a directory. */
+ struct stat64 st;
+ if (__fxstat64 (_STAT_VER, fd, &st) != 0)
+ return -1;
+
+ if (!S_ISDIR (st.st_mode))
+ {
+ __set_errno (ENOTDIR);
+ return -1;
+ }
+ }
+
+ __set_errno (ENOSYS);
+ return -1;
+}
+
+
+stub_warning (mkfifoat)
+#include <stub-tag.h>
diff --git a/sysdeps/generic/mknodat.c b/sysdeps/generic/mknodat.c
new file mode 100644
index 0000000000..ac515b5b48
--- /dev/null
+++ b/sysdeps/generic/mknodat.c
@@ -0,0 +1,60 @@
+/* Copyright (C) 1995, 1996, 2001, 2005 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.
+
+ In addition to the permissions in the GNU Lesser General Public
+ License, the Free Software Foundation gives you unlimited
+ permission to link the compiled version of this file with other
+ programs, and to distribute those programs without any restriction
+ coming from the use of this file. (The GNU Lesser General Public
+ License restrictions do apply in other respects; for example, they
+ cover modification of the file, and distribution when not linked
+ into another program.)
+
+ Note that people who make modified versions of this file are not
+ obligated to grant this special exception for their modified
+ versions; it is their choice whether to do so. The GNU Lesser
+ General Public License gives permission to release a modified
+ version without this exception; this exception also makes it
+ possible to release a modified version which carries forward this
+ exception.
+
+ 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 <sys/types.h>
+#include <sys/stat.h>
+
+/* This definition is only used if inlining fails for this function; see
+ the last page of <sys/stat.h>. The real work is done by the `x'
+ function which is passed a version number argument. We arrange in the
+ makefile that when not inlined this function is always statically
+ linked; that way a dynamically-linked executable always encodes the
+ version number corresponding to the data structures it uses, so the `x'
+ functions in the shared library can adapt without needing to recompile
+ all callers. */
+
+int
+mknodat (int fd, const char *path, mode_t mode, dev_t dev)
+{
+ return __xmknodat (_MKNOD_VER, fd, path, mode, &dev);
+}
+
+
+/* Hide the symbol so that no definition but the one locally in the
+ executable or DSO is used. */
+#ifdef HAVE_DOT_HIDDEN
+asm (".hidden\tmknodat");
+#endif
diff --git a/sysdeps/generic/xmknodat.c b/sysdeps/generic/xmknodat.c
new file mode 100644
index 0000000000..56d88c7b0f
--- /dev/null
+++ b/sysdeps/generic/xmknodat.c
@@ -0,0 +1,63 @@
+/* Copyright (C) 2005 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 <sys/types.h>
+#include <sys/stat.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)
+{
+ if (vers != _MKNOD_VER)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ if (path == NULL)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ if (fd != AT_FDCWD && path[0] != '/')
+ {
+ /* Check FD is associated with a directory. */
+ struct stat64 st;
+ if (__fxstat64 (_STAT_VER, fd, &st) != 0)
+ return -1;
+
+ if (!S_ISDIR (st.st_mode))
+ {
+ __set_errno (ENOTDIR);
+ return -1;
+ }
+ }
+
+ __set_errno (ENOSYS);
+ return -1;
+}
+stub_warning (__xmknodat)
+
+libc_hidden_def (__xmknodat)
+#include <stub-tag.h>
diff --git a/sysdeps/unix/mkfifoat.c b/sysdeps/unix/mkfifoat.c
new file mode 100644
index 0000000000..5c4da2a982
--- /dev/null
+++ b/sysdeps/unix/mkfifoat.c
@@ -0,0 +1,32 @@
+/* Copyright (C) 2005 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 <sys/stat.h>
+
+
+/* Create a new FIFO with permission bits MODE. But interpret
+ relative PATH names relative to the directory associated with FD. */
+int
+mkfifoat (fd, file, mode)
+ int fd;
+ const char *file;
+ mode_t mode;
+{
+ dev_t dev = 0;
+ return __xmknodat (_MKNOD_VER, fd, file, mode | S_IFIFO, &dev);
+}
diff --git a/sysdeps/unix/sysv/linux/mkdirat.c b/sysdeps/unix/sysv/linux/mkdirat.c
new file mode 100644
index 0000000000..367441b05b
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mkdirat.c
@@ -0,0 +1,66 @@
+/* Copyright (C) 2005 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 <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sysdep-cancel.h>
+
+
+/* Create a new directory with permission bits MODE. But interpret
+ relative PATH names relative to the directory associated with FD. */
+int
+mkdirat (fd, file, mode)
+ int fd;
+ const char *file;
+ mode_t mode;
+{
+ char *buf = NULL;
+
+ if (fd != AT_FDCWD && file[0] != '/')
+ {
+ size_t filelen = strlen (file);
+ static const char procfd[] = "/proc/self/fd/%d/%s";
+ /* Buffer for the path name we are going to use. It consists of
+ - the string /proc/self/fd/
+ - the file descriptor number
+ - the file name provided.
+ The final NUL is included in the sizeof. A bit of overhead
+ due to the format elements compensates for possible negative
+ numbers. */
+ size_t buflen = sizeof (procfd) + sizeof (int) * 3 + filelen;
+ buf = alloca (buflen);
+
+ __snprintf (buf, buflen, procfd, fd, file);
+ file = buf;
+ }
+
+ INTERNAL_SYSCALL_DECL (err);
+ int res = INTERNAL_SYSCALL (mkdir, err, 2, file, mode);
+
+ if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0))
+ {
+ __atfct_seterrno (INTERNAL_SYSCALL_ERRNO (res, err), fd, buf);
+ res = -1;
+ }
+
+ return res;
+}
diff --git a/sysdeps/unix/sysv/linux/xmknodat.c b/sysdeps/unix/sysv/linux/xmknodat.c
new file mode 100644
index 0000000000..9332ae683e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/xmknodat.c
@@ -0,0 +1,75 @@
+/* Copyright (C) 2005 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 <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+
+#include <sysdep.h>
+#include <sys/syscall.h>
+#include <bp-checks.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 *file, mode_t mode, dev_t *dev)
+{
+ if (vers != _MKNOD_VER)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ char *buf = NULL;
+
+ if (fd != AT_FDCWD && file[0] != '/')
+ {
+ size_t filelen = strlen (file);
+ static const char procfd[] = "/proc/self/fd/%d/%s";
+ /* Buffer for the path name we are going to use. It consists of
+ - the string /proc/self/fd/
+ - the file descriptor number
+ - the file name provided.
+ The final NUL is included in the sizeof. A bit of overhead
+ due to the format elements compensates for possible negative
+ numbers. */
+ size_t buflen = sizeof (procfd) + sizeof (int) * 3 + filelen;
+ buf = alloca (buflen);
+
+ __snprintf (buf, buflen, procfd, fd, file);
+ file = buf;
+ }
+
+ /* We must convert the value to dev_t type used by the kernel. */
+ unsigned long long int k_dev = (*dev) & ((1ULL << 32) - 1);
+ if (k_dev != *dev)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ return INLINE_SYSCALL (mknod, 3, CHECK_STRING (file), mode,
+ (unsigned int) k_dev);
+}
+
+libc_hidden_def (__xmknodat)