diff options
author | Ulrich Drepper <drepper@redhat.com> | 2009-11-24 18:50:32 -0800 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2009-11-24 18:50:32 -0800 |
commit | aa9890239a2aef81e64f3f22a31c7e01b6501f69 (patch) | |
tree | 9f11b2e9d90685e5c9b15a69e7ffefd259e4777e | |
parent | 0f622686af3ae5a8f03dae886b08c260b38bda16 (diff) | |
download | glibc-aa9890239a2aef81e64f3f22a31c7e01b6501f69.tar.gz glibc-aa9890239a2aef81e64f3f22a31c7e01b6501f69.tar.xz glibc-aa9890239a2aef81e64f3f22a31c7e01b6501f69.zip |
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.
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | include/stdlib.h | 3 | ||||
-rw-r--r-- | sysdeps/unix/grantpt.c | 11 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/ptsname.c | 35 |
4 files changed, 38 insertions, 21 deletions
diff --git a/ChangeLog b/ChangeLog index 173fe780f8..4f74b500f0 100644 --- a/ChangeLog +++ b/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. diff --git a/include/stdlib.h b/include/stdlib.h index d90e6ff4fe..f540bece9c 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -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); diff --git a/sysdeps/unix/grantpt.c b/sysdeps/unix/grantpt.c index 2a7a963162..260e8273f8 100644 --- a/sysdeps/unix/grantpt.c +++ b/sysdeps/unix/grantpt.c @@ -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) diff --git a/sysdeps/unix/sysv/linux/ptsname.c b/sysdeps/unix/sysv/linux/ptsname.c index 9c364b18b4..ba7c791c9f 100644 --- a/sysdeps/unix/sysv/linux/ptsname.c +++ b/sysdeps/unix/sysv/linux/ptsname.c @@ -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) @@ -93,7 +89,7 @@ __ptsname_r (int fd, char *buf, size_t buflen) if (__ioctl (fd, TIOCGPTN, &ptyno) == 0) { /* Buffer we use to print the number in. For a maximum size for - `int' of 8 bytes we never need more than 20 digits. */ + `int' of 8 bytes we never need more than 20 digits. */ char numbuf[21]; const char *devpts = _PATH_DEVPTS; const size_t devptslen = strlen (_PATH_DEVPTS); @@ -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) + 2.1.115 these are no longer supported. */ + 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) |