diff options
-rw-r--r-- | ChangeLog | 15 | ||||
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | include/fcntl.h | 3 | ||||
-rw-r--r-- | io/Makefile | 2 | ||||
-rw-r--r-- | io/Versions | 3 | ||||
-rw-r--r-- | io/linkat.c | 51 | ||||
-rw-r--r-- | io/readlinkat.c | 50 | ||||
-rw-r--r-- | io/symlinkat.c | 49 | ||||
-rw-r--r-- | posix/unistd.h | 18 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/linkat.c | 87 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/readlinkat.c | 69 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/symlinkat.c | 67 |
12 files changed, 415 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog index 3ed4698053..6b76452de1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2005-12-15 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/renameat.c: Move errno setting code in + separate function __atfct_seterrno_2. + * include/fcntl.h: Declare __atfct_seterrno_2. + * posix/unistd.h: Declare linkat, symlinkat, readlinkat. + * io/Makefile (routines): Add linkat, symlinkat, readlinkat. + * io/Versions [GLIBC_2.4]: Export linkat, symlinkat, readlinkat. + * io/linkat.c: New file. + * io/readlinkat.c: New file. + * io/symlinkat.c: New file. + * sysdeps/unix/sysv/linux/linkat.c: New file. + * sysdeps/unix/sysv/linux/readlinkat.c: New file. + * sysdeps/unix/sysv/linux/symlinkat.c: New file. + 2005-12-15 Roland McGrath <roland@redhat.com> [BZ #1997] diff --git a/NEWS b/NEWS index 19c24c23dc..41755c383b 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -GNU C Library NEWS -- history of user-visible changes. 2005-12-02 +GNU C Library NEWS -- history of user-visible changes. 2005-12-15 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, mkdirat, mkfifoat, mknodat. + unlinkat, mkdirat, mkfifoat, mknodat, linkat, symlinkat, readlinkat. Version 2.3.6 diff --git a/include/fcntl.h b/include/fcntl.h index 6080faba3e..610e322cfd 100644 --- a/include/fcntl.h +++ b/include/fcntl.h @@ -21,5 +21,8 @@ libc_hidden_proto (__fcntl) /* Helper functions for the various *at functions. For Linux. */ extern void __atfct_seterrno (int errval, int fd, const char *buf) attribute_hidden; +extern void __atfct_seterrno_2 (int errval, int fd1, const char *buf1, + int fd2, const char *buf2) + attribute_hidden; #endif diff --git a/io/Makefile b/io/Makefile index 76e6072c4b..4731e24d24 100644 --- a/io/Makefile +++ b/io/Makefile @@ -45,7 +45,7 @@ routines := \ getcwd getwd getdirname \ chown fchown lchown fchownat \ ttyname ttyname_r isatty \ - link symlink readlink \ + link linkat symlink symlinkat readlink readlinkat \ unlink unlinkat rmdir \ ftw ftw64 fts poll \ posix_fadvise posix_fadvise64 \ diff --git a/io/Versions b/io/Versions index 05b9bfc185..2f0f94f3bb 100644 --- a/io/Versions +++ b/io/Versions @@ -100,8 +100,11 @@ libc { GLIBC_2.4 { fchownat; __fxstatat; __fxstatat64; + linkat; mkdirat; mkfifoat; __xmknodat; openat; openat64; + readlinkat; + symlinkat; unlinkat; } } diff --git a/io/linkat.c b/io/linkat.c new file mode 100644 index 0000000000..6420d50334 --- /dev/null +++ b/io/linkat.c @@ -0,0 +1,51 @@ +/* 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 <unistd.h> + + +/* Make a link to FROM relative to FROMFD called TO relative to TOFD. */ +int +linkat (fromfd, from, tofd, to) + int fromfd; + const char *from; + int tofd; + const char *to; +{ + if (from == NULL || to == NULL) + { + __set_errno (EINVAL); + return -1; + } + + if ((tofd != AT_FDCWD && tofd < 0 && *to != '/') + || (fromfd != AT_FDCWD && fromfd < 0 && *from != '/')) + { + __set_errno (EBADF); + return -1; + } + + __set_errno (ENOSYS); + return -1; +} +stub_warning (linkat) + +#include <stub-tag.h> diff --git a/io/readlinkat.c b/io/readlinkat.c new file mode 100644 index 0000000000..c6a032c474 --- /dev/null +++ b/io/readlinkat.c @@ -0,0 +1,50 @@ +/* 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 <unistd.h> + +/* Read the contents of the symbolic link PATH relative to FD into no + more than LEN bytes of BUF. The contents are not null-terminated. + Returns the number of characters read, or -1 for errors. */ +int +readlinkat (fd, path, buf, len) + int fd; + const char *path; + char *buf; + size_t len; +{ + if (path == NULL) + { + __set_errno (EINVAL); + return -1; + } + + if (fd != AT_FDCWD && fd < 0 && *path != '/') + { + __set_errno (EBADF); + return -1; + } + + __set_errno (ENOSYS); + return -1; +} +stub_warning (readlinkat) + +#include <stub-tag.h> diff --git a/io/symlinkat.c b/io/symlinkat.c new file mode 100644 index 0000000000..5c2f3f553a --- /dev/null +++ b/io/symlinkat.c @@ -0,0 +1,49 @@ +/* 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 <unistd.h> + + +/* Make a link to FROM called TO relative to FD. */ +int +symlinkat (from, fd, to) + const char *from; + int fd; + const char *to; +{ + if (from == NULL || to == NULL) + { + __set_errno (EINVAL); + return -1; + } + + if (fd != AT_FDCWD && fd < 0 && *to != '/') + { + __set_errno (EBADF); + return -1; + } + + __set_errno (ENOSYS); + return -1; +} +stub_warning (symlinkat) + +#include <stub-tag.h> diff --git a/posix/unistd.h b/posix/unistd.h index 86e0e9e659..9684126eaa 100644 --- a/posix/unistd.h +++ b/posix/unistd.h @@ -742,6 +742,13 @@ extern int ttyslot (void) __THROW; extern int link (__const char *__from, __const char *__to) __THROW __nonnull ((1, 2)) __wur; +#ifdef __USE_GNU +/* Like link but relative paths in TO and FROM are interpreted relative + to FROMFD and TOFD respectively. */ +extern int linkat (int __fromfd, __const char *__from, int __tofd, + __const char *__to) __THROW __nonnull ((2, 4)) __wur; +#endif + #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K /* Make a symbolic link to FROM named TO. */ extern int symlink (__const char *__from, __const char *__to) @@ -754,6 +761,17 @@ extern int readlink (__const char *__restrict __path, char *__restrict __buf, size_t __len) __THROW __nonnull ((1, 2)) __wur; #endif /* Use BSD. */ +#ifdef __USE_GNU +/* Like symlink but a relative path in TO is interpreted relative to TOFD. */ +extern int symlinkat (__const char *__from, int __tofd, + __const char *__to) __THROW __nonnull ((1, 3)) __wur; + +/* Like readlink but a relative PATH is interpreted relative to FD. */ +extern int readlinkat (int __fd, __const char *__restrict __path, + char *__restrict __buf, size_t __len) + __THROW __nonnull ((2, 3)) __wur; +#endif + /* Remove the link NAME. */ extern int unlink (__const char *__name) __THROW __nonnull ((1)); diff --git a/sysdeps/unix/sysv/linux/linkat.c b/sysdeps/unix/sysv/linux/linkat.c new file mode 100644 index 0000000000..8ebff74215 --- /dev/null +++ b/sysdeps/unix/sysv/linux/linkat.c @@ -0,0 +1,87 @@ +/* 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 <string.h> +#include <stdio.h> +#include <sysdep.h> +#include <unistd.h> + + +/* Make a link to FROM named TO but relative paths in TO and FROM are + interpreted relative to FROMFD and TOFD respectively. */ +int +linkat (fromfd, from, tofd, to) + int fromfd; + const char *from; + int tofd; + const char *to; +{ + static const char procfd[] = "/proc/self/fd/%d/%s"; + char *buffrom = NULL; + + if (fromfd != AT_FDCWD && from[0] != '/') + { + size_t filelen = strlen (from); + /* 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; + buffrom = alloca (buflen); + + __snprintf (buffrom, buflen, procfd, fromfd, from); + from = buffrom; + } + + char *bufto = NULL; + + if (tofd != AT_FDCWD && to[0] != '/') + { + size_t filelen = strlen (to); + /* 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; + bufto = alloca (buflen); + + __snprintf (bufto, buflen, procfd, tofd, to); + to = bufto; + } + + INTERNAL_SYSCALL_DECL (err); + + int result = INTERNAL_SYSCALL (link, err, 2, from, to); + + if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0)) + { + __atfct_seterrno_2 (INTERNAL_SYSCALL_ERRNO (result, err), tofd, bufto, + fromfd, buffrom); + result = -1; + } + + return result; +} diff --git a/sysdeps/unix/sysv/linux/readlinkat.c b/sysdeps/unix/sysv/linux/readlinkat.c new file mode 100644 index 0000000000..42c3877bd7 --- /dev/null +++ b/sysdeps/unix/sysv/linux/readlinkat.c @@ -0,0 +1,69 @@ +/* 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 <stdlib.h> +#include <string.h> +#include <sysdep.h> +#include <unistd.h> + + +/* Read the contents of the symbolic link PATH relative to FD into no + more than LEN bytes of BUF. */ +int +readlinkat (fd, path, buf, len) + int fd; + const char *path; + char *buf; + size_t len; +{ + char *pathbuf = NULL; + + if (fd != AT_FDCWD && path[0] != '/') + { + size_t pathlen = strlen (path); + 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 + pathlen; + pathbuf = __alloca (buflen); + + __snprintf (pathbuf, buflen, procfd, fd, path); + path = pathbuf; + } + + INTERNAL_SYSCALL_DECL (err); + + int result = INTERNAL_SYSCALL (readlink, err, 3, path, buf, len); + + if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0)) + { + __atfct_seterrno (INTERNAL_SYSCALL_ERRNO (result, err), fd, pathbuf); + result = -1; + } + + return result; +} diff --git a/sysdeps/unix/sysv/linux/symlinkat.c b/sysdeps/unix/sysv/linux/symlinkat.c new file mode 100644 index 0000000000..211b49c299 --- /dev/null +++ b/sysdeps/unix/sysv/linux/symlinkat.c @@ -0,0 +1,67 @@ +/* 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 <stdlib.h> +#include <string.h> +#include <sysdep.h> +#include <unistd.h> + + +/* Make a symbolic link to FROM named TO relative to TOFD. */ +int +symlinkat (from, tofd, to) + const char *from; + int tofd; + const char *to; +{ + char *buf = NULL; + + if (tofd != AT_FDCWD && to[0] != '/') + { + size_t tolen = strlen (to); + 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 + tolen; + buf = __alloca (buflen); + + __snprintf (buf, buflen, procfd, tofd, to); + to = buf; + } + + INTERNAL_SYSCALL_DECL (err); + + int result = INTERNAL_SYSCALL (symlink, err, 2, from, to); + + if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0)) + { + __atfct_seterrno (INTERNAL_SYSCALL_ERRNO (result, err), tofd, buf); + result = -1; + } + + return result; +} |