mirror of
https://sourceware.org/git/glibc.git
synced 2024-12-22 02:40:08 +00:00
Make complete getcwd work in rtld
This commit is contained in:
parent
7fb90fb89b
commit
6fb2dde3f1
13
ChangeLog
13
ChangeLog
@ -3,15 +3,20 @@
|
||||
[BZ #12713]
|
||||
* sysdeps/unix/sysv/linux/getcwd.c: If getcwd syscall report
|
||||
ENAMETOOLONG use generic getcwd.
|
||||
* sysdeps/posix/getcwd.c: Add support to use openat.
|
||||
* sysdeps/posix/getcwd.c: Add support to use openat. Make usable
|
||||
in rtld. Use *stat64.
|
||||
* sysdeps/unix/sysv/linux/Makefile [subdir=elf] (sysdep-rtld-routines):
|
||||
Add dl-getcwd.
|
||||
Add dl-getcwd, dl-openat64, dl-opendir, dl-fxstatat64.
|
||||
* sysdeps/unix/sysv/linux/dl-getcwd.c: New file.
|
||||
* include/sys/stat.h: Define __fstatat macro.
|
||||
* sysdeps/unix/sysv/linux/dl-openat64.c: New file.
|
||||
* sysdeps/unix/sysv/linux/dl-opendir.c: New file.
|
||||
* sysdeps/unix/sysv/linux/dl-fxstat64.c: New file.
|
||||
* include/sys/stat.h: Define __fstatat, __lstat64, __fstat64, and
|
||||
__fstatat64 macros.
|
||||
* include/dirent.h: Add libc_hidden_proto for rewinddir.
|
||||
* dirent/rewinddir.c: Add libc_hidden_def.
|
||||
* sysdeps/mach/hurd/rewinddir.c: Likewise.
|
||||
* sysdeps/unix/rewinddir.c: Likewise.
|
||||
* sysdeps/unix/rewinddir.c: Likewise. Don't do locking outside libc.
|
||||
|
||||
* include/dirent.h (__alloc_dir): Add flags parameter.
|
||||
* sysdeps/unix/fdopendir.c (__fdopendir): Pass flags to __alloc_dir.
|
||||
|
@ -44,10 +44,14 @@ libc_hidden_proto (__fxstatat64)
|
||||
#define lstat(fname, buf) __lxstat (_STAT_VER, fname, buf)
|
||||
#define __lstat(fname, buf) __lxstat (_STAT_VER, fname, buf)
|
||||
#define lstat64(fname, buf) __lxstat64 (_STAT_VER, fname, buf)
|
||||
#define __lstat64(fname, buf) __lxstat64 (_STAT_VER, fname, buf)
|
||||
#define stat64(fname, buf) __xstat64 (_STAT_VER, fname, buf)
|
||||
#define fstat64(fd, buf) __fxstat64 (_STAT_VER, fd, buf)
|
||||
#define __fstat64(fd, buf) __fxstat64 (_STAT_VER, fd, buf)
|
||||
#define fstat(fd, buf) __fxstat (_STAT_VER, fd, buf)
|
||||
#define __fstat(fd, buf) __fxstat (_STAT_VER, fd, buf)
|
||||
#define __fstatat(dfd, fname, buf, flag) \
|
||||
__fxstatat (_STAT_VER, dfd, fname, buf, flag)
|
||||
#define __fstatat64(dfd, fname, buf, flag) \
|
||||
__fxstatat64 (_STAT_VER, dfd, fname, buf, flag)
|
||||
#endif
|
||||
|
@ -172,10 +172,10 @@ extern char *alloca ();
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#if defined _LIBC && !defined NOT_IN_libc
|
||||
#if defined _LIBC
|
||||
# include <not-cancel.h>
|
||||
#else
|
||||
# define openat_not_cancel_3(dfd, name, mode) openat (dfd, name, mode)
|
||||
# define openat64_not_cancel_3(dfd, name, mode) openat64 (dfd, name, mode)
|
||||
# define close_not_cancel_no_status(fd) close (fd)
|
||||
#endif
|
||||
|
||||
@ -197,7 +197,7 @@ extern char *alloca ();
|
||||
#endif
|
||||
|
||||
#ifndef __GNU_LIBRARY__
|
||||
# define __lstat stat
|
||||
# define __lstat64 stat64
|
||||
#endif
|
||||
|
||||
#ifndef _LIBC
|
||||
@ -209,9 +209,10 @@ extern char *alloca ();
|
||||
#endif
|
||||
|
||||
#ifdef __ASSUME_ATFCTS
|
||||
# define have_openat 1
|
||||
#else
|
||||
static int have_openat = 0;
|
||||
# define __have_atfcts 1
|
||||
#elif defined NOT_IN_libc && defined IS_IN_rtld
|
||||
static int __rtld_have_atfcts;
|
||||
# define __have_atfcts __rtld_have_atfcts
|
||||
#endif
|
||||
|
||||
/* Get the pathname of the current working directory, and put it in SIZE
|
||||
@ -268,39 +269,39 @@ __getcwd (buf, size)
|
||||
char *pathp = path + allocated;
|
||||
*--pathp = '\0';
|
||||
|
||||
struct stat st;
|
||||
if (__lstat (".", &st) < 0)
|
||||
struct stat64 st;
|
||||
if (__lstat64 (".", &st) < 0)
|
||||
goto lose;
|
||||
dev_t thisdev = st.st_dev;
|
||||
ino_t thisino = st.st_ino;
|
||||
|
||||
if (__lstat ("/", &st) < 0)
|
||||
if (__lstat64 ("/", &st) < 0)
|
||||
goto lose;
|
||||
dev_t rootdev = st.st_dev;
|
||||
ino_t rootino = st.st_ino;
|
||||
|
||||
while (!(thisdev == rootdev && thisino == rootino))
|
||||
{
|
||||
if (have_openat >= 0)
|
||||
if (__have_atfcts >= 0)
|
||||
{
|
||||
int mode = O_RDONLY;
|
||||
#ifdef O_CLOEXEC
|
||||
mode |= O_CLOEXEC;
|
||||
#endif
|
||||
fd = openat_not_cancel_3 (fd, "..", mode);
|
||||
fd = openat64_not_cancel_3 (fd, "..", mode);
|
||||
}
|
||||
else
|
||||
fd = -1;
|
||||
if (fd >= 0)
|
||||
{
|
||||
fd_needs_closing = true;
|
||||
if (__fstat (fd, &st) < 0)
|
||||
if (__fstat64 (fd, &st) < 0)
|
||||
goto lose;
|
||||
}
|
||||
#ifndef __ASSUME_ATFCTS
|
||||
else if (errno == ENOSYS)
|
||||
{
|
||||
have_openat = -1;
|
||||
__have_atfcts = -1;
|
||||
|
||||
/* Look at the parent directory. */
|
||||
if (dotp == dotlist)
|
||||
@ -345,7 +346,7 @@ __getcwd (buf, size)
|
||||
dotp -= 3;
|
||||
|
||||
/* Figure out if this directory is a mount point. */
|
||||
if (__lstat (dotp, &st) < 0)
|
||||
if (__lstat64 (dotp, &st) < 0)
|
||||
goto lose;
|
||||
}
|
||||
#endif
|
||||
@ -363,7 +364,7 @@ __getcwd (buf, size)
|
||||
bool mount_point = dotdev != thisdev;
|
||||
|
||||
/* Search for the last directory. */
|
||||
if (have_openat >= 0)
|
||||
if (__have_atfcts >= 0)
|
||||
dirstream = __fdopendir (fd);
|
||||
#ifndef __ASSUME_ATFCTS
|
||||
else
|
||||
@ -388,7 +389,7 @@ __getcwd (buf, size)
|
||||
/* When we've iterated through all directory entries
|
||||
without finding one with a matching d_ino, rewind the
|
||||
stream and consider each name again, but this time, using
|
||||
lstat. This is necessary in a chroot on at least one
|
||||
lstat64. This is necessary in a chroot on at least one
|
||||
system. */
|
||||
if (use_d_ino)
|
||||
{
|
||||
@ -413,14 +414,14 @@ __getcwd (buf, size)
|
||||
if (use_d_ino && !mount_point && (ino_t) d->d_ino != thisino)
|
||||
continue;
|
||||
|
||||
if (have_openat >= 0)
|
||||
if (__have_atfcts >= 0)
|
||||
{
|
||||
/* We don't fail here if we cannot stat() a directory entry.
|
||||
/* We don't fail here if we cannot stat64() a directory entry.
|
||||
This can happen when (network) filesystems fail. If this
|
||||
entry is in fact the one we are looking for we will find
|
||||
out soon as we reach the end of the directory without
|
||||
having found anything. */
|
||||
if (__fstatat (fd, d->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
|
||||
if (__fstatat64 (fd, d->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
|
||||
continue;
|
||||
}
|
||||
#ifndef __ASSUME_ATFCTS
|
||||
@ -436,12 +437,12 @@ __getcwd (buf, size)
|
||||
name[dotlist + dotsize - dotp] = '/';
|
||||
strcpy (&name[dotlist + dotsize - dotp + 1], d->d_name);
|
||||
# endif
|
||||
/* We don't fail here if we cannot stat() a directory entry.
|
||||
/* We don't fail here if we cannot stat64() a directory entry.
|
||||
This can happen when (network) filesystems fail. If this
|
||||
entry is in fact the one we are looking for we will find
|
||||
out soon as we reach the end of the directory without
|
||||
having found anything. */
|
||||
if (__lstat (name, &st) < 0)
|
||||
if (__lstat64 (name, &st) < 0)
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
@ -23,16 +23,19 @@
|
||||
#include <dirstream.h>
|
||||
|
||||
/* Rewind DIRP to the beginning of the directory. */
|
||||
/* XXX should be __rewinddir ? */
|
||||
void
|
||||
rewinddir (dirp)
|
||||
DIR *dirp;
|
||||
{
|
||||
#ifndef NOT_IN_libc
|
||||
__libc_lock_lock (dirp->lock);
|
||||
#endif
|
||||
(void) __lseek (dirp->fd, (off_t) 0, SEEK_SET);
|
||||
dirp->filepos = 0;
|
||||
dirp->offset = 0;
|
||||
dirp->size = 0;
|
||||
#ifndef NOT_IN_libc
|
||||
__libc_lock_unlock (dirp->lock);
|
||||
#endif
|
||||
}
|
||||
libc_hidden_def (rewinddir)
|
||||
|
@ -147,7 +147,8 @@ sysdep_routines += xstatconv internal_statvfs internal_statvfs64 \
|
||||
endif
|
||||
|
||||
ifeq ($(subdir),elf)
|
||||
sysdep-rtld-routines += dl-brk dl-sbrk dl-getcwd
|
||||
sysdep-rtld-routines += dl-brk dl-sbrk dl-getcwd dl-openat64 dl-opendir \
|
||||
dl-fxstatat64
|
||||
|
||||
CPPFLAGS-lddlibc4 += -DNOT_IN_libc
|
||||
endif
|
||||
|
6
sysdeps/unix/sysv/linux/dl-fxstatat64.c
Normal file
6
sysdeps/unix/sysv/linux/dl-fxstatat64.c
Normal file
@ -0,0 +1,6 @@
|
||||
/* In this implementation we do not really care whether the call fails
|
||||
because of missing kernel support since we do not even call the
|
||||
function in this case. */
|
||||
#undef __ASSUME_ATFCTS
|
||||
#define __ASSUME_ATFCTS 1
|
||||
#include "fxstatat64.c"
|
40
sysdeps/unix/sysv/linux/dl-openat64.c
Normal file
40
sysdeps/unix/sysv/linux/dl-openat64.c
Normal file
@ -0,0 +1,40 @@
|
||||
/* Copyright (C) 2011 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@gmain.com>, 2003.
|
||||
|
||||
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 <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sysdep.h>
|
||||
|
||||
|
||||
int
|
||||
openat64 (dfd, file, oflag)
|
||||
int dfd;
|
||||
const char *file;
|
||||
int oflag;
|
||||
{
|
||||
assert ((oflag & O_CREAT) == 0);
|
||||
|
||||
#ifdef __NR_openat
|
||||
return INLINE_SYSCALL (openat, 3, dfd, file, oflag | O_LARGEFILE);
|
||||
#else
|
||||
__set_errno (ENOSYS);
|
||||
return -1;
|
||||
#endif
|
||||
}
|
6
sysdeps/unix/sysv/linux/dl-opendir.c
Normal file
6
sysdeps/unix/sysv/linux/dl-opendir.c
Normal file
@ -0,0 +1,6 @@
|
||||
/* In this implementation we do not really care whether the opened
|
||||
file descriptor has the CLOEXEC bit set. The only call happens
|
||||
long before there is a call to fork or exec. */
|
||||
#undef __ASSUME_O_CLOEXEC
|
||||
#define __ASSUME_O_CLOEXEC 1
|
||||
#include <opendir.c>
|
@ -124,9 +124,6 @@ __getcwd (char *buf, size_t size)
|
||||
return buf;
|
||||
}
|
||||
|
||||
// XXX This should not be necessary but the full getcwd implementation
|
||||
// drags in too much for the current build proces of ld.so to handle
|
||||
#ifndef NOT_IN_libc
|
||||
/* The system call cannot handle paths longer than a page.
|
||||
Neither can the magic symlink in /proc/self. Just use the
|
||||
generic implementation right away. */
|
||||
@ -149,7 +146,6 @@ __getcwd (char *buf, size_t size)
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
# if __ASSUME_GETCWD_SYSCALL
|
||||
/* It should never happen that the `getcwd' syscall failed because
|
||||
@ -241,11 +237,7 @@ __getcwd (char *buf, size_t size)
|
||||
}
|
||||
weak_alias (__getcwd, getcwd)
|
||||
|
||||
// XXX This should not be necessary but the full getcwd implementation
|
||||
// drags in too much for the current build proces of ld.so to handle
|
||||
#ifndef NOT_IN_libc
|
||||
/* Get the code for the generic version. */
|
||||
#define GETCWD_RETURN_TYPE static char * internal_function
|
||||
#define __getcwd generic_getcwd
|
||||
#include <sysdeps/posix/getcwd.c>
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user