* 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.
This commit is contained in:
Ulrich Drepper 2005-12-02 21:55:54 +00:00
parent 975407d507
commit e186c703dc
13 changed files with 480 additions and 8 deletions

View file

@ -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,

4
NEWS
View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -100,6 +100,7 @@ libc {
GLIBC_2.4 {
fchownat;
__fxstatat; __fxstatat64;
mkdirat; mkfifoat; __xmknodat;
openat; openat64;
unlinkat;
}

View file

@ -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__))

58
sysdeps/generic/mkdirat.c Normal file
View file

@ -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>

View file

@ -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>

60
sysdeps/generic/mknodat.c Normal file
View file

@ -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

View file

@ -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>

32
sysdeps/unix/mkfifoat.c Normal file
View file

@ -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);
}

View file

@ -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;
}

View file

@ -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)