Optimize grantpt.
authorUlrich Drepper <drepper@redhat.com>
Wed, 25 Nov 2009 02:50:32 +0000 (18:50 -0800)
committerUlrich Drepper <drepper@redhat.com>
Wed, 25 Nov 2009 02:50:32 +0000 (18:50 -0800)
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.

ChangeLog
include/stdlib.h
sysdeps/unix/grantpt.c
sysdeps/unix/sysv/linux/ptsname.c

index 173fe78..4f74b50 100644 (file)
--- 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.
index d90e6ff..f540bec 100644 (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);
 
index 2a7a963..260e827 100644 (file)
@@ -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)
index 9c364b1..ba7c791 100644 (file)
@@ -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)