From d2d77c0eacd5e95e63cbea8abca35c70ce6a9a55 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Mon, 28 May 2007 12:43:30 +0000 Subject: [PATCH] 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. --- ChangeLog | 9 ++++++++ lib/lseek.c | 8 ++++++- lib/unistd_.h | 5 ++--- tests/test-lseek.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++--- tests/test-lseek.sh | 18 +++++++++++---- 5 files changed, 93 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 91eb8d1f3..253ae37b6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2007-05-28 Eric Blake + + 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 * tests/test-unistd.c: Test all the types that is expected diff --git a/lib/lseek.c b/lib/lseek.c index 3d2fd42eb..03830a9ac 100644 --- a/lib/lseek.c +++ b/lib/lseek.c @@ -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; diff --git a/lib/unistd_.h b/lib/unistd_.h index da165c5bf..ad1b265f4 100644 --- a/lib/unistd_.h +++ b/lib/unistd_.h @@ -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 diff --git a/tests/test-lseek.c b/tests/test-lseek.c index ae53d98ca..d70629e1c 100644 --- a/tests/test-lseek.c +++ b/tests/test-lseek.c @@ -19,11 +19,69 @@ #include +#include +#include #include +#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; } diff --git a/tests/test-lseek.sh b/tests/test-lseek.sh index 966dd2e89..e84c2bb49 100755 --- a/tests/test-lseek.sh +++ b/tests/test-lseek.sh @@ -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 -- 2.11.0