Improve lseek module.
authorEric Blake <ebb9@byu.net>
Mon, 28 May 2007 12:43:30 +0000 (12:43 +0000)
committerEric Blake <ebb9@byu.net>
Mon, 28 May 2007 12:43:30 +0000 (12:43 +0000)
* lib/lseek.c (rpl_lseek): Detect EBADF on mingw.
* lib/unistd_.h (lseek): Scale back link warning message.
* tests/test-lseek.c: Beef up test.
* tests/test-lseek.sh: Exercise more facets of lseek.
Reported by Bruno Haible.

ChangeLog
lib/lseek.c
lib/unistd_.h
tests/test-lseek.c
tests/test-lseek.sh

index 91eb8d1..253ae37 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2007-05-28  Eric Blake  <ebb9@byu.net>
+
+       Improve lseek module.
+       * lib/lseek.c (rpl_lseek): Detect EBADF on mingw.
+       * lib/unistd_.h (lseek): Scale back link warning message.
+       * tests/test-lseek.c: Beef up test.
+       * tests/test-lseek.sh: Exercise more facets of lseek.
+       Reported by Bruno Haible.
+
 2007-05-28  Bruno Haible  <bruno@clisp.org>
 
        * tests/test-unistd.c: Test all the types that <unistd.h> is expected
index 3d2fd42..03830a9 100644 (file)
@@ -31,7 +31,13 @@ off_t
 rpl_lseek (int fd, off_t offset, int whence)
 {
   /* mingw lseek mistakenly succeeds on pipes, sockets, and terminals.  */
-  if (GetFileType ((HANDLE) _get_osfhandle (fd)) != FILE_TYPE_DISK)
+  HANDLE h = (HANDLE) _get_osfhandle (fd);
+  if (h == INVALID_HANDLE_VALUE)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  if (GetFileType (h) != FILE_TYPE_DISK)
     {
       errno = ESPIPE;
       return -1;
index da165c5..ad1b265 100644 (file)
@@ -188,9 +188,8 @@ extern int getlogin_r (char *name, size_t size);
 #elif defined GNULIB_POSIXCHECK
 # undef lseek
 # define lseek(f,o,w) \
-    (GL_LINK_WARNING ("lseek does not fail with ESPIPE on non-seekable " \
-                      "files on some systems - " \
-                      "use gnulib module lseek for portability"), \
+    (GL_LINK_WARNING ("lseek does not fail with ESPIPE on pipes on some " \
+                      "systems - use gnulib module lseek for portability"), \
      lseek (f, o, w))
 #endif
 
index ae53d98..d70629e 100644 (file)
 
 #include <config.h>
 
+#include <errno.h>
+#include <stdio.h>
 #include <unistd.h>
 
+#define ASSERT(expr) \
+  do                                                                        \
+    {                                                                       \
+      if (!(expr))                                                          \
+        {                                                                   \
+          fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
+          abort ();                                                         \
+        }                                                                   \
+    }                                                                       \
+  while (0)
+
+/* ARGC must be 2; *ARGV[1] is '0' if stdin and stdout are files, '1'
+   if they are pipes, and '2' if they are closed.  Check for proper
+   semantics of lseek.  */
 int
-main ()
+main (int argc, char **argv)
 {
-  /* Exit with success only if stdin is seekable.  */
-  return lseek (0, (off_t)0, SEEK_CUR) < 0;
+  if (argc != 2)
+    return 2;
+  switch (*argv[1])
+    {
+    case '0': /* regular files */
+      ASSERT (lseek (0, (off_t)2, SEEK_SET) == 2);
+      ASSERT (lseek (0, (off_t)-4, SEEK_CUR) == -1);
+      ASSERT (errno == EINVAL);
+      errno = 0;
+      ASSERT (lseek (0, (off_t)0, SEEK_CUR) == 2);
+      ASSERT (lseek (0, (off_t)0, (SEEK_SET | SEEK_CUR | SEEK_END) + 1) == -1);
+      ASSERT (errno == EINVAL);
+      ASSERT (lseek (1, (off_t)2, SEEK_SET) == 2);
+      errno = 0;
+      ASSERT (lseek (1, (off_t)-4, SEEK_CUR) == -1);
+      ASSERT (errno == EINVAL);
+      errno = 0;
+      ASSERT (lseek (1, (off_t)0, SEEK_CUR) == 2);
+      ASSERT (lseek (1, (off_t)0, (SEEK_SET | SEEK_CUR | SEEK_END) + 1) == -1);
+      ASSERT (errno == EINVAL);
+      break;
+
+    case '1': /* pipes */
+      errno = 0;
+      ASSERT (lseek (0, (off_t)0, SEEK_CUR) == -1);
+      ASSERT (errno == ESPIPE);
+      errno = 0;
+      ASSERT (lseek (1, (off_t)0, SEEK_CUR) == -1);
+      ASSERT (errno == ESPIPE);
+      break;
+
+    case '2': /* closed */
+      errno = 0;
+      ASSERT (lseek (0, (off_t)0, SEEK_CUR) == -1);
+      ASSERT (errno == EBADF);
+      errno = 0;
+      ASSERT (lseek (1, (off_t)0, SEEK_CUR) == -1);
+      ASSERT (errno == EBADF);
+      break;
+
+    default:
+      return 1;
+    }
+  return 0;
 }
index 966dd2e..e84c2bb 100755 (executable)
@@ -1,7 +1,17 @@
 #!/bin/sh
 
-# Succeed on seekable stdin
-./test-lseek${EXEEXT} < "$srcdir/test-lseek.sh" || exit 1
-# Fail on pipe stdin
-echo hi | ./test-lseek${EXEEXT} && exit 1
+tmpfiles=
+trap 'rm -fr $tmpfiles' 1 2 3 15
+
+tmpfiles=t-lseek.tmp
+# seekable files
+./test-lseek${EXEEXT} 0 < "$srcdir/test-lseek.sh" > t-lseek.tmp || exit 1
+
+# pipes
+echo hi | ./test-lseek${EXEEXT} 1 | cat || exit 1
+
+# closed descriptors
+./test-lseek${EXEEXT} 2 <&- >&- || exit 1
+
+rm -rf $tmpfiles
 exit 0