diff options
author | Eric Blake <ebb9@byu.net> | 2009-11-07 21:34:32 -0700 |
---|---|---|
committer | Eric Blake <ebb9@byu.net> | 2009-11-09 06:36:00 -0700 |
commit | 48e988340f85e568ceb9ac1f4bf5824fddf1fd0d (patch) | |
tree | 1c6d25b4261bcdb2b10fb8908c2f7e81f98041cf /tests | |
parent | 349396ebfcce12ee8f927fedf82067414c427093 (diff) | |
download | gnulib-48e988340f85e568ceb9ac1f4bf5824fddf1fd0d.tar.gz |
open: detect FreeBSD bug
open("link-to-file/", O_RDONLY) mistakenly succeeds. The previous
patch was enough to fix utimens when no fd is involved, but this is
necessary for futimens to pass.
* m4/open.m4 (gl_FUNC_OPEN): Also detect FreeBSD bug with slash on
symlink.
* doc/posix-functions/open.texi (open): Document the bug.
* doc/posix-functions/utimes.texi (utimes): Likewise.
* tests/test-open.h (test_open): Add parameters, and test symlink
handling.
* tests/test-open.c (main): Adjust caller.
* tests/test-fcntl-safer.c (main): Likewise.
* modules/open-tests (Depends-on): Add stdbool, symlink.
* modules/fcntl-safer-tests (Depends-on): Likewise.
* tests/test-openat.c (main): Add test-open tests.
Signed-off-by: Eric Blake <ebb9@byu.net>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/test-fcntl-safer.c | 20 | ||||
-rw-r--r-- | tests/test-open.c | 20 | ||||
-rw-r--r-- | tests/test-open.h | 56 | ||||
-rw-r--r-- | tests/test-openat.c | 54 |
4 files changed, 111 insertions, 39 deletions
diff --git a/tests/test-fcntl-safer.c b/tests/test-fcntl-safer.c index 33c7c2cd8a..15f6e2ca6c 100644 --- a/tests/test-fcntl-safer.c +++ b/tests/test-fcntl-safer.c @@ -20,6 +20,24 @@ #include "fcntl--.h" +#include <errno.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#define ASSERT(expr) \ + do \ + { \ + if (!(expr)) \ + { \ + fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \ + fflush (stderr); \ + abort (); \ + } \ + } \ + while (0) + #define BASE "test-fcntl-safer.t" #include "test-open.h" @@ -27,5 +45,5 @@ int main (void) { - return test_open (); + return test_open (open, true); } diff --git a/tests/test-open.c b/tests/test-open.c index 738934e124..37109a58a1 100644 --- a/tests/test-open.c +++ b/tests/test-open.c @@ -20,6 +20,24 @@ #include <fcntl.h> +#include <errno.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#define ASSERT(expr) \ + do \ + { \ + if (!(expr)) \ + { \ + fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \ + fflush (stderr); \ + abort (); \ + } \ + } \ + while (0) + #define BASE "test-open.t" #include "test-open.h" @@ -27,5 +45,5 @@ int main (void) { - return test_open (); + return test_open (open, true); } diff --git a/tests/test-open.h b/tests/test-open.h index 4dba767087..9b43945825 100644 --- a/tests/test-open.h +++ b/tests/test-open.h @@ -16,29 +16,14 @@ /* Written by Bruno Haible <bruno@clisp.org>, 2007. */ -/* Include <config.h> and a form of <fcntl.h> first. */ - -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -#define ASSERT(expr) \ - do \ - { \ - if (!(expr)) \ - { \ - fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \ - fflush (stderr); \ - abort (); \ - } \ - } \ - while (0) - -/* Test fopen. Assumes BASE is defined. */ +/* This file is designed to test both open(n,buf[,mode]) and + openat(AT_FDCWD,n,buf[,mode]). FUNC is the function to test. + Assumes that BASE and ASSERT are already defined, and that + appropriate headers are already included. If PRINT, warn before + skipping symlink tests with status 77. */ static int -test_open (void) +test_open (int (*func) (char const *, int, ...), bool print) { int fd; /* Remove anything from prior partial run. */ @@ -46,40 +31,57 @@ test_open (void) /* Cannot create directory. */ errno = 0; - ASSERT (open ("nonexist.ent/", O_CREAT | O_RDONLY, 0600) == -1); + ASSERT (func ("nonexist.ent/", O_CREAT | O_RDONLY, 0600) == -1); ASSERT (errno == ENOTDIR || errno == EISDIR || errno == ENOENT || errno == EINVAL); /* Create a regular file. */ - fd = open (BASE "file", O_CREAT | O_RDONLY, 0600); + fd = func (BASE "file", O_CREAT | O_RDONLY, 0600); ASSERT (0 <= fd); ASSERT (close (fd) == 0); /* Trailing slash handling. */ errno = 0; - ASSERT (open (BASE "file/", O_RDONLY) == -1); + ASSERT (func (BASE "file/", O_RDONLY) == -1); ASSERT (errno == ENOTDIR || errno == EISDIR || errno == EINVAL); /* Directories cannot be opened for writing. */ errno = 0; - ASSERT (open (".", O_WRONLY) == -1); + ASSERT (func (".", O_WRONLY) == -1); ASSERT (errno == EISDIR || errno == EACCES); /* /dev/null must exist, and be writable. */ - fd = open ("/dev/null", O_RDONLY); + fd = func ("/dev/null", O_RDONLY); ASSERT (0 <= fd); { char c; ASSERT (read (fd, &c, 1) == 0); } ASSERT (close (fd) == 0); - fd = open ("/dev/null", O_WRONLY); + fd = func ("/dev/null", O_WRONLY); ASSERT (0 <= fd); ASSERT (write (fd, "c", 1) == 1); ASSERT (close (fd) == 0); + /* Symlink handling, where supported. */ + if (symlink (BASE "file", BASE "link") != 0) + { + ASSERT (unlink (BASE "file") == 0); + if (print) + fputs ("skipping test: symlinks not supported on this file system\n", + stderr); + return 77; + } + errno = 0; + ASSERT (func (BASE "link/", O_RDONLY) == -1); + ASSERT (errno == ENOTDIR); + fd = func (BASE "link", O_RDONLY); + ASSERT (0 <= fd); + ASSERT (close (fd) == 0); + /* Cleanup. */ ASSERT (unlink (BASE "file") == 0); + ASSERT (unlink (BASE "link") == 0); return 0; } diff --git a/tests/test-openat.c b/tests/test-openat.c index 6e5c5199cb..77185cc45a 100644 --- a/tests/test-openat.c +++ b/tests/test-openat.c @@ -20,6 +20,9 @@ #include <fcntl.h> +#include <errno.h> +#include <stdarg.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -28,20 +31,51 @@ do \ { \ if (!(expr)) \ - { \ - fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \ - fflush (stderr); \ - abort (); \ - } \ + { \ + fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \ + fflush (stderr); \ + abort (); \ + } \ } \ while (0) +#define BASE "test-openat.t" + +#include "test-open.h" + +static int dfd = AT_FDCWD; + +/* Wrapper around openat to test open behavior. */ +static int +do_open (char const *name, int flags, ...) +{ + if (flags & O_CREAT) + { + mode_t mode = 0; + va_list arg; + va_start (arg, flags); + + /* We have to use PROMOTED_MODE_T instead of mode_t, otherwise GCC 4 + creates crashing code when 'mode_t' is smaller than 'int'. */ + mode = va_arg (arg, PROMOTED_MODE_T); + + va_end (arg); + return openat (dfd, name, flags, mode); + } + return openat (dfd, name, flags); +} + int main (void) { - /* FIXME - add more tests. For example, share /dev/null and - trailing slash tests with test-open, and do more checks for - proper fd handling. */ + int result; + + /* Basic checks. */ + result = test_open (do_open, false); + dfd = open (".", O_RDONLY); + ASSERT (0 <= dfd); + ASSERT (test_open (do_open, false) == result); + ASSERT (close (dfd) == 0); /* Check that even when *-safer modules are in use, plain openat can land in fd 0. Do this test last, since it is destructive to @@ -49,12 +83,12 @@ main (void) ASSERT (close (STDIN_FILENO) == 0); ASSERT (openat (AT_FDCWD, ".", O_RDONLY) == STDIN_FILENO); { - int dfd = open (".", O_RDONLY); + dfd = open (".", O_RDONLY); ASSERT (STDIN_FILENO < dfd); ASSERT (chdir ("..") == 0); ASSERT (close (STDIN_FILENO) == 0); ASSERT (openat (dfd, ".", O_RDONLY) == STDIN_FILENO); ASSERT (close (dfd) == 0); } - return 0; + return result; } |