about summary refs log tree commit diff
path: root/sysdeps/posix/ttyname_r.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/posix/ttyname_r.c')
-rw-r--r--sysdeps/posix/ttyname_r.c30
1 files changed, 21 insertions, 9 deletions
diff --git a/sysdeps/posix/ttyname_r.c b/sysdeps/posix/ttyname_r.c
index d7f6026d8a..5b62826a19 100644
--- a/sysdeps/posix/ttyname_r.c
+++ b/sysdeps/posix/ttyname_r.c
@@ -36,7 +36,7 @@ int
 __ttyname_r (fd, buf, buflen)
      int fd;
      char *buf;
-     int buflen;
+     size_t buflen;
 {
   static const char dev[] = "/dev";
   struct stat st;
@@ -50,21 +50,24 @@ __ttyname_r (fd, buf, buflen)
      the loop.  */
   if (buflen < (int) (sizeof (dev) + 1))
     {
-      __set_errno (EINVAL);
-      return -1;
+      __set_errno (ERANGE);
+      return ERANGE;
     }
 
   if (!__isatty (fd))
-    return -1;
+    {
+      __set_errno (ENOTTY);
+      return ENOTTY;
+    }
 
   if (fstat (fd, &st) < 0)
-    return -1;
+    return errno;
   mydev = st.st_dev;
   myino = st.st_ino;
 
   dirstream = opendir (dev);
   if (dirstream == NULL)
-    return -1;
+    return errno;
 
   /* Prepare the result buffer.  */
   memcpy (buf, dev, sizeof (dev) - 1);
@@ -75,9 +78,16 @@ __ttyname_r (fd, buf, buflen)
     if ((ino_t) d->d_fileno == myino)
       {
 	char *cp;
+	size_t needed = _D_EXACT_NAMLEN (d) + 1;
+
+	if (needed > buflen)
+	  {
+	    (void) closedir (dirstream);
+	    __set_errno (ERANGE);
+	    return ERANGE;
+	  }
 
-	cp = __stpncpy (&buf[sizeof (dev)], d->d_name,
-			MIN ((int) (_D_EXACT_NAMLEN (d) + 1), buflen));
+	cp = __stpncpy (&buf[sizeof (dev)], d->d_name, needed);
 	cp[0] = '\0';
 
 	if (stat (buf, &st) == 0 && st.st_dev == mydev)
@@ -90,6 +100,8 @@ __ttyname_r (fd, buf, buflen)
 
   (void) closedir (dirstream);
   __set_errno (save);
-  return -1;
+  /* It is not clear what to return in this case.  `isatty' says FD
+     refers to a TTY but no entry in /dev has this inode.  */
+  return ENOTTY;
 }
 weak_alias (__ttyname_r, ttyname_r)