mirror of
https://sourceware.org/git/glibc.git
synced 2024-12-22 02:40:08 +00:00
Optimize grantpt.
grantpt was performing two consecutive calls to stat with the same file name. Avoid this by creating a special version of the ptsname function which allows to pass the stat result back to the caller.
This commit is contained in:
parent
0f622686af
commit
aa9890239a
10
ChangeLog
10
ChangeLog
@ -1,5 +1,15 @@
|
||||
2009-11-24 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* sysdeps/unix/grantpt.c (pts_name): Take additional parameter,
|
||||
pass it on to __ptsname_internal.
|
||||
(grantpt): Pass stat64 pointer to pts_name. Remove stat call here.
|
||||
* sysdeps/unix/sysv/linux/ptsname.c (__ptsname_internal): New function.
|
||||
All the code from __ptsname_r but take additional parameter. Use that
|
||||
instead of pointer to local stat64 variable.
|
||||
(__ptsname_r): Call __ptsname_internal with pointer to local stat64
|
||||
variable.
|
||||
* include/stdlib.h: Declare __ptsname_internal.
|
||||
|
||||
* sysdeps/unix/grantpt.c (grantpt): Use CLOSE_ALL_FDS is available
|
||||
before the exec.
|
||||
* sysdeps/unix/sysv/linux/grantpt.c: New file.
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
/* Now define the internal interfaces. */
|
||||
#ifndef __Need_M_And_C
|
||||
# include <sys/stat.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
@ -77,6 +78,8 @@ extern int __clearenv (void);
|
||||
extern char *__canonicalize_file_name (__const char *__name);
|
||||
extern char *__realpath (__const char *__name, char *__resolved);
|
||||
extern int __ptsname_r (int __fd, char *__buf, size_t __buflen);
|
||||
extern int __ptsname_internal (int fd, char *buf, size_t buflen,
|
||||
struct stat64 *stp);
|
||||
extern int __getpt (void);
|
||||
extern int __posix_openpt (int __oflag);
|
||||
|
||||
|
@ -38,7 +38,7 @@
|
||||
this buffer, a sufficiently long buffer is allocated using malloc,
|
||||
and returned in PTS. 0 is returned upon success, -1 otherwise. */
|
||||
static int
|
||||
pts_name (int fd, char **pts, size_t buf_len)
|
||||
pts_name (int fd, char **pts, size_t buf_len, struct stat64 *stp)
|
||||
{
|
||||
int rv;
|
||||
char *buf = *pts;
|
||||
@ -49,7 +49,7 @@ pts_name (int fd, char **pts, size_t buf_len)
|
||||
|
||||
if (buf_len)
|
||||
{
|
||||
rv = __ptsname_r (fd, buf, buf_len);
|
||||
rv = __ptsname_internal (fd, buf, buf_len, stp);
|
||||
if (rv != 0)
|
||||
{
|
||||
if (rv == ENOTTY)
|
||||
@ -107,8 +107,9 @@ grantpt (int fd)
|
||||
char _buf[512];
|
||||
#endif
|
||||
char *buf = _buf;
|
||||
struct stat64 st;
|
||||
|
||||
if (__builtin_expect (pts_name (fd, &buf, sizeof (_buf)), 0))
|
||||
if (__builtin_expect (pts_name (fd, &buf, sizeof (_buf), &st), 0))
|
||||
{
|
||||
int save_errno = errno;
|
||||
|
||||
@ -127,10 +128,6 @@ grantpt (int fd)
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct stat64 st;
|
||||
if (__xstat64 (_STAT_VER, buf, &st) < 0)
|
||||
goto cleanup;
|
||||
|
||||
/* Make sure that we own the device. */
|
||||
uid_t uid = __getuid ();
|
||||
if (st.st_uid != uid)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1998, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1998, 2000, 2001, 2002, 2009 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998.
|
||||
|
||||
@ -67,14 +67,10 @@ ptsname (int fd)
|
||||
}
|
||||
|
||||
|
||||
/* Store at most BUFLEN characters of the pathname of the slave pseudo
|
||||
terminal associated with the master FD is open on in BUF.
|
||||
Return 0 on success, otherwise an error number. */
|
||||
int
|
||||
__ptsname_r (int fd, char *buf, size_t buflen)
|
||||
__ptsname_internal (int fd, char *buf, size_t buflen, struct stat64 *stp)
|
||||
{
|
||||
int save_errno = errno;
|
||||
struct stat64 st;
|
||||
unsigned int ptyno;
|
||||
|
||||
if (buf == NULL)
|
||||
@ -121,20 +117,20 @@ __ptsname_r (int fd, char *buf, size_t buflen)
|
||||
return ERANGE;
|
||||
}
|
||||
|
||||
if (__fxstat64 (_STAT_VER, fd, &st) < 0)
|
||||
if (__fxstat64 (_STAT_VER, fd, stp) < 0)
|
||||
return errno;
|
||||
|
||||
/* Check if FD really is a master pseudo terminal. */
|
||||
if (! MASTER_P (st.st_rdev))
|
||||
if (! MASTER_P (stp->st_rdev))
|
||||
{
|
||||
__set_errno (ENOTTY);
|
||||
return ENOTTY;
|
||||
}
|
||||
|
||||
ptyno = minor (st.st_rdev);
|
||||
ptyno = minor (stp->st_rdev);
|
||||
/* This is for the old BSD pseudo terminals. As of Linux
|
||||
2.1.115 these are no longer supported. */
|
||||
if (major (st.st_rdev) == 4)
|
||||
if (major (stp->st_rdev) == 4)
|
||||
ptyno -= 128;
|
||||
|
||||
if (ptyno / 16 >= strlen (__libc_ptyname1))
|
||||
@ -149,12 +145,12 @@ __ptsname_r (int fd, char *buf, size_t buflen)
|
||||
p[2] = '\0';
|
||||
}
|
||||
|
||||
if (__xstat64 (_STAT_VER, buf, &st) < 0)
|
||||
if (__xstat64 (_STAT_VER, buf, stp) < 0)
|
||||
return errno;
|
||||
|
||||
/* Check if the name we're about to return really corresponds to a
|
||||
slave pseudo terminal. */
|
||||
if (! S_ISCHR (st.st_mode) || ! SLAVE_P (st.st_rdev))
|
||||
if (! S_ISCHR (stp->st_mode) || ! SLAVE_P (stp->st_rdev))
|
||||
{
|
||||
/* This really is a configuration problem. */
|
||||
__set_errno (ENOTTY);
|
||||
@ -164,4 +160,15 @@ __ptsname_r (int fd, char *buf, size_t buflen)
|
||||
__set_errno (save_errno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Store at most BUFLEN characters of the pathname of the slave pseudo
|
||||
terminal associated with the master FD is open on in BUF.
|
||||
Return 0 on success, otherwise an error number. */
|
||||
int
|
||||
__ptsname_r (int fd, char *buf, size_t buflen)
|
||||
{
|
||||
struct stat64 st;
|
||||
return __ptsname_internal (fd, buf, buflen, &st);
|
||||
}
|
||||
weak_alias (__ptsname_r, ptsname_r)
|
||||
|
Loading…
Reference in New Issue
Block a user