mirror of
https://sourceware.org/git/glibc.git
synced 2024-12-22 10:50:07 +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>
|
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
|
* sysdeps/unix/grantpt.c (grantpt): Use CLOSE_ALL_FDS is available
|
||||||
before the exec.
|
before the exec.
|
||||||
* sysdeps/unix/sysv/linux/grantpt.c: New file.
|
* sysdeps/unix/sysv/linux/grantpt.c: New file.
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
/* Now define the internal interfaces. */
|
/* Now define the internal interfaces. */
|
||||||
#ifndef __Need_M_And_C
|
#ifndef __Need_M_And_C
|
||||||
|
# include <sys/stat.h>
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
|
|
||||||
@ -77,6 +78,8 @@ extern int __clearenv (void);
|
|||||||
extern char *__canonicalize_file_name (__const char *__name);
|
extern char *__canonicalize_file_name (__const char *__name);
|
||||||
extern char *__realpath (__const char *__name, char *__resolved);
|
extern char *__realpath (__const char *__name, char *__resolved);
|
||||||
extern int __ptsname_r (int __fd, char *__buf, size_t __buflen);
|
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 __getpt (void);
|
||||||
extern int __posix_openpt (int __oflag);
|
extern int __posix_openpt (int __oflag);
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
this buffer, a sufficiently long buffer is allocated using malloc,
|
this buffer, a sufficiently long buffer is allocated using malloc,
|
||||||
and returned in PTS. 0 is returned upon success, -1 otherwise. */
|
and returned in PTS. 0 is returned upon success, -1 otherwise. */
|
||||||
static int
|
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;
|
int rv;
|
||||||
char *buf = *pts;
|
char *buf = *pts;
|
||||||
@ -49,7 +49,7 @@ pts_name (int fd, char **pts, size_t buf_len)
|
|||||||
|
|
||||||
if (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 != 0)
|
||||||
{
|
{
|
||||||
if (rv == ENOTTY)
|
if (rv == ENOTTY)
|
||||||
@ -107,8 +107,9 @@ grantpt (int fd)
|
|||||||
char _buf[512];
|
char _buf[512];
|
||||||
#endif
|
#endif
|
||||||
char *buf = _buf;
|
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;
|
int save_errno = errno;
|
||||||
|
|
||||||
@ -127,10 +128,6 @@ grantpt (int fd)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct stat64 st;
|
|
||||||
if (__xstat64 (_STAT_VER, buf, &st) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
/* Make sure that we own the device. */
|
/* Make sure that we own the device. */
|
||||||
uid_t uid = __getuid ();
|
uid_t uid = __getuid ();
|
||||||
if (st.st_uid != uid)
|
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.
|
This file is part of the GNU C Library.
|
||||||
Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998.
|
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
|
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;
|
int save_errno = errno;
|
||||||
struct stat64 st;
|
|
||||||
unsigned int ptyno;
|
unsigned int ptyno;
|
||||||
|
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
@ -121,20 +117,20 @@ __ptsname_r (int fd, char *buf, size_t buflen)
|
|||||||
return ERANGE;
|
return ERANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (__fxstat64 (_STAT_VER, fd, &st) < 0)
|
if (__fxstat64 (_STAT_VER, fd, stp) < 0)
|
||||||
return errno;
|
return errno;
|
||||||
|
|
||||||
/* Check if FD really is a master pseudo terminal. */
|
/* Check if FD really is a master pseudo terminal. */
|
||||||
if (! MASTER_P (st.st_rdev))
|
if (! MASTER_P (stp->st_rdev))
|
||||||
{
|
{
|
||||||
__set_errno (ENOTTY);
|
__set_errno (ENOTTY);
|
||||||
return ENOTTY;
|
return ENOTTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
ptyno = minor (st.st_rdev);
|
ptyno = minor (stp->st_rdev);
|
||||||
/* This is for the old BSD pseudo terminals. As of Linux
|
/* This is for the old BSD pseudo terminals. As of Linux
|
||||||
2.1.115 these are no longer supported. */
|
2.1.115 these are no longer supported. */
|
||||||
if (major (st.st_rdev) == 4)
|
if (major (stp->st_rdev) == 4)
|
||||||
ptyno -= 128;
|
ptyno -= 128;
|
||||||
|
|
||||||
if (ptyno / 16 >= strlen (__libc_ptyname1))
|
if (ptyno / 16 >= strlen (__libc_ptyname1))
|
||||||
@ -149,12 +145,12 @@ __ptsname_r (int fd, char *buf, size_t buflen)
|
|||||||
p[2] = '\0';
|
p[2] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (__xstat64 (_STAT_VER, buf, &st) < 0)
|
if (__xstat64 (_STAT_VER, buf, stp) < 0)
|
||||||
return errno;
|
return errno;
|
||||||
|
|
||||||
/* Check if the name we're about to return really corresponds to a
|
/* Check if the name we're about to return really corresponds to a
|
||||||
slave pseudo terminal. */
|
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. */
|
/* This really is a configuration problem. */
|
||||||
__set_errno (ENOTTY);
|
__set_errno (ENOTTY);
|
||||||
@ -164,4 +160,15 @@ __ptsname_r (int fd, char *buf, size_t buflen)
|
|||||||
__set_errno (save_errno);
|
__set_errno (save_errno);
|
||||||
return 0;
|
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)
|
weak_alias (__ptsname_r, ptsname_r)
|
||||||
|
Loading…
Reference in New Issue
Block a user