bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: mingw lseek bug


From: Eric Blake
Subject: Re: mingw lseek bug
Date: Mon, 28 May 2007 06:42:40 -0600
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.10) Gecko/20070221 Thunderbird/1.5.0.10 Mnenhy/0.7.5.666

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

According to Bruno Haible on 5/24/2007 6:12 PM:

Hi Bruno,

>> * tests/test-lseek.c: New file.
> 
> It would be better if it would also test errno.

Done like so (and fixing a bug it uncovered in the meantime):

2007-05-28  Eric Blake  <address@hidden>

        * 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.

- --
Don't work too hard, make some time for fun as well!

Eric Blake             address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFGWs4/84KuGfSFAYARAlk6AJ94MJFUZEZjAmKvGoZ2BknUhujCAwCgjlGT
SvWD/p3FB8ZrjtcMEVWCNi4=
=XOCj
-----END PGP SIGNATURE-----
Index: lib/lseek.c
===================================================================
RCS file: /sources/gnulib/gnulib/lib/lseek.c,v
retrieving revision 1.1
diff -u -p -r1.1 lseek.c
--- lib/lseek.c 24 May 2007 16:59:20 -0000      1.1
+++ lib/lseek.c 28 May 2007 12:32:22 -0000
@@ -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: lib/unistd_.h
===================================================================
RCS file: /sources/gnulib/gnulib/lib/unistd_.h,v
retrieving revision 1.9
diff -u -p -r1.9 unistd_.h
--- lib/unistd_.h       24 May 2007 16:59:21 -0000      1.9
+++ lib/unistd_.h       28 May 2007 12:32:22 -0000
@@ -188,9 +188,8 @@ extern int getlogin_r (char *name, 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: tests/test-lseek.c
===================================================================
RCS file: /sources/gnulib/gnulib/tests/test-lseek.c,v
retrieving revision 1.1
diff -u -p -r1.1 test-lseek.c
--- tests/test-lseek.c  24 May 2007 16:59:22 -0000      1.1
+++ tests/test-lseek.c  28 May 2007 12:32:22 -0000
@@ -19,11 +19,67 @@
 
 #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 1; *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;
+  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: tests/test-lseek.sh
===================================================================
RCS file: /sources/gnulib/gnulib/tests/test-lseek.sh,v
retrieving revision 1.1
diff -u -p -r1.1 test-lseek.sh
--- tests/test-lseek.sh 24 May 2007 16:59:22 -0000      1.1
+++ tests/test-lseek.sh 28 May 2007 12:32:22 -0000
@@ -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

reply via email to

[Prev in Thread] Current Thread [Next in Thread]