test-open: on GNU/Hurd, /dev/null is a directory
authorEric Blake <ebb9@byu.net>
Sat, 3 Oct 2009 00:06:21 +0000 (18:06 -0600)
committerEric Blake <ebb9@byu.net>
Sat, 3 Oct 2009 00:25:47 +0000 (18:25 -0600)
* tests/test-fopen.h (main): Rename...
(test_fopen): ...to this.  Use a guaranteed non-directory when
confirming open behavior on trailing slash.
* tests/test-openat-safer.c (main): Likewise.
* tests/test-open.h (main): Likewise....
(test_open): ...to this.
* tests/test-fopen.c (main): Adjust caller.
* tests/test-fopen-safer.c (main): Likewise.
* tests/test-open.c (main): Likewise.
* tests/test-fcntl-safer.c (main): Likewise.
Reported by Samuel Thibault.

Signed-off-by: Eric Blake <ebb9@byu.net>
ChangeLog
tests/test-fcntl-safer.c
tests/test-fopen-safer.c
tests/test-fopen.c
tests/test-fopen.h
tests/test-open.c
tests/test-open.h
tests/test-openat-safer.c

index 1125c58dcfbf1000617e649098779e254915c83c..3ef349e998613da93bc3fa311f7429d6b9f55df7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 2009-10-02  Eric Blake  <ebb9@byu.net>
 
+       test-open: on GNU/Hurd, /dev/null is a directory
+       * tests/test-fopen.h (main): Rename...
+       (test_fopen): ...to this.  Use a guaranteed non-directory when
+       confirming open behavior on trailing slash.
+       * tests/test-openat-safer.c (main): Likewise.
+       * tests/test-open.h (main): Likewise....
+       (test_open): ...to this.
+       * tests/test-fopen.c (main): Adjust caller.
+       * tests/test-fopen-safer.c (main): Likewise.
+       * tests/test-open.c (main): Likewise.
+       * tests/test-fcntl-safer.c (main): Likewise.
+       Reported by Samuel Thibault.
+
        rename, fchdir: don't ignore chdir failure
        * lib/fchdir.c (get_name): Abort on unexpected chdir failure.
        * lib/rename.c (rpl_rename) [W32]: Likewise.
index 3b3ff751398c87cb3423948d6de512830b60fd5c..433160bf66d8522a0d909f192aaf9de292e973b8 100644 (file)
 
 #include "fcntl--.h"
 
+#define BASE "test-fcntl-safer.t"
+
 #include "test-open.h"
+
+int
+main ()
+{
+  return test_open ();
+}
index 701af354c1e85c77066475ecb64b19b1ac72552d..e6133649d7a4080fda045d23b8ca7263fada2664 100644 (file)
 
 #include "stdio--.h"
 
+#define BASE "test-fopen-safer.t"
+
 #include "test-fopen.h"
+
+int
+main ()
+{
+  return test_fopen ();
+}
index 473d274f4767b3d5c72d492b660fcd1600dc4120..6efd48064328bcb0284b49566c1897bc7e0d647a 100644 (file)
 
 #include <stdio.h>
 
+#define BASE "test-fopen.t"
+
 #include "test-fopen.h"
+
+int
+main ()
+{
+  return test_fopen ();
+}
index b1dafbb21300ca3380880289c8d52b189ef62094..01369f83c4439105492ba741b4e937eaa8af238d 100644 (file)
@@ -18,7 +18,9 @@
 
 /* Include <config.h> and a form of <stdio.h> first.  */
 
+#include <errno.h>
 #include <stdlib.h>
+#include <unistd.h>
 
 #define ASSERT(expr) \
   do                                                                        \
     }                                                                       \
   while (0)
 
-int
-main ()
+/* Test fopen.  Assumes BASE is defined.  */
+
+static int
+test_fopen (void)
 {
+  FILE *f;
+  /* Remove anything from prior partial run.  */
+  unlink (BASE "file");
+
+  /* Read requires existing file.  */
+  errno = 0;
+  ASSERT (fopen (BASE "file", "r") == NULL);
+  ASSERT (errno == ENOENT);
+
+  /* Write can create a file.  */
+  f = fopen (BASE "file", "w");
+  ASSERT (f);
+  ASSERT (fclose (f) == 0);
+
+  /* Trailing slash is invalid on non-directory.  */
+  errno = 0;
+  ASSERT (fopen (BASE "file/", "r") == NULL);
+  ASSERT (errno == ENOTDIR || errno == EISDIR);
+
+  /* Cannot create a directory.  */
+  errno = 0;
   ASSERT (fopen ("nonexist.ent/", "w") == NULL);
-  ASSERT (fopen ("/dev/null/", "r") == NULL);
+  ASSERT (errno == ENOTDIR || errno == EISDIR || errno == ENOENT);
+
+  /* Directories cannot be opened for writing.  */
+  errno = 0;
+  ASSERT (fopen (".", "w") == NULL);
+  ASSERT (errno == EISDIR || errno == EINVAL);
+
+  /* /dev/null must exist, and be writable.  */
+  f = fopen ("/dev/null", "r");
+  ASSERT (f);
+  ASSERT (fclose (f) == 0);
+  f = fopen ("/dev/null", "w");
+  ASSERT (f);
+  ASSERT (fclose (f) == 0);
 
-  ASSERT (fopen ("/dev/null", "r") != NULL);
+  /* Cleanup.  */
+  ASSERT (unlink (BASE "file") == 0);
 
   return 0;
 }
index df7e36fd83afcca6f7a867af3f4339fd6943073b..6b97e184d39fc3328ff65bd28cbf2db265223416 100644 (file)
 
 #include <fcntl.h>
 
+#define BASE "test-open.t"
+
 #include "test-open.h"
+
+int
+main ()
+{
+  return test_open ();
+}
index 466cab3d0eb73ec287d1202885bc1904c0b8961d..738103792a5dac44a0ed545a9706a63000fbc8f5 100644 (file)
 
 /* 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                                                                        \
     }                                                                       \
   while (0)
 
-int
-main ()
+/* Test fopen.  Assumes BASE is defined.  */
+
+static int
+test_open (void)
 {
-  ASSERT (open ("nonexist.ent/", O_CREAT | O_RDONLY, 0600) < 0);
-  ASSERT (open ("/dev/null/", O_RDONLY) < 0);
+  int fd;
+  /* Remove anything from prior partial run.  */
+  unlink (BASE "file");
+
+  /* Cannot create directory.  */
+  errno = 0;
+  ASSERT (open ("nonexist.ent/", O_CREAT | O_RDONLY, 0600) == -1);
+  ASSERT (errno == ENOTDIR || errno == EISDIR || errno == ENOENT);
+
+  /* Create a regular file.  */
+  fd = open (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 (errno == ENOTDIR || errno == EISDIR);
+
+  /* Directories cannot be opened for writing.  */
+  errno = 0;
+  ASSERT (open (".", O_WRONLY) == -1);
+  ASSERT (errno == EISDIR);
+
+  /* /dev/null must exist, and be writable.  */
+  fd = open ("/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);
+  ASSERT (0 <= fd);
+  ASSERT (write (fd, "c", 1) == 1);
+  ASSERT (close (fd) == 0);
 
-  ASSERT (open ("/dev/null", O_RDONLY) >= 0);
+  /* Cleanup.  */
+  ASSERT (unlink (BASE "file") == 0);
 
   return 0;
 }
index 47d3ada9804f21bf1ba2e09baf22edae8a1e28d3..7e44d674dc3782f83afd4a27f345093a63863a0c 100644 (file)
@@ -45,6 +45,8 @@ static FILE *myerr;
     }                                                                        \
   while (0)
 
+#define witness "test-openat-safer.txt"
+
 int
 main ()
 {
@@ -53,7 +55,6 @@ main ()
   int dfd;
   int fd;
   char buf[2];
-  const char *witness = "test-openat-safer.txt";
 
   /* We close fd 2 later, so save it in fd 10.  */
   if (dup2 (STDERR_FILENO, BACKUP_STDERR_FILENO) != BACKUP_STDERR_FILENO
@@ -96,15 +97,14 @@ main ()
          ASSERT (openat (-1, ".", O_RDONLY) == -1);
          ASSERT (errno == EBADF);
 
-         /* Check for trailing slash and /dev/null handling; the
-            particular errno might be ambiguous.  */
+         /* Check for trailing slash and /dev/null handling.  */
          errno = 0;
          ASSERT (openat (dfd, "nonexist.ent/", O_CREAT | O_RDONLY,
                          S_IRUSR | S_IWUSR) == -1);
-         /* ASSERT (errno == ENOTDIR); */
+         ASSERT (errno == ENOTDIR || errno == EISDIR || errno == ENOENT);
          errno = 0;
-         ASSERT (openat (dfd, "/dev/null/", O_RDONLY) == -1);
-         /* ASSERT (errno == ENOTDIR); */
+         ASSERT (openat (dfd, witness "/", O_RDONLY) == -1);
+         ASSERT (errno == ENOTDIR || errno == EISDIR);
          /* Using a bad directory is okay for absolute paths.  */
          fd = openat (-1, "/dev/null", O_WRONLY);
          ASSERT (STDERR_FILENO < fd);