about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog3
-rw-r--r--io/Makefile2
-rw-r--r--io/tst-fcntl.c196
3 files changed, 200 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 5ff289c43d..7e388d6147 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 2000-10-26  Ulrich Drepper  <drepper@redhat.com>
 
+	* io/Makefile (tests): Add tst-fcntl.
+	* io/tst-fcntl.c: New file.
+
 	* posix/Makefile (tests): Add tst-chmod.
 	(tst-chmod-ARGS): Define.
 	* posix/tst-chmod.c: New file.
diff --git a/io/Makefile b/io/Makefile
index c7f02d618e..0d528cc1a5 100644
--- a/io/Makefile
+++ b/io/Makefile
@@ -55,7 +55,7 @@ static-only-routines = stat fstat lstat mknod stat64 fstat64 lstat64
 
 others		:= pwd
 test-srcs	:= ftwtest
-tests		:= test-utime test-stat test-lfs tst-getcwd
+tests		:= test-utime test-stat test-lfs tst-getcwd tst-fcntl
 
 distribute	:= ftwtest-sh
 
diff --git a/io/tst-fcntl.c b/io/tst-fcntl.c
new file mode 100644
index 0000000000..eeb21e3814
--- /dev/null
+++ b/io/tst-fcntl.c
@@ -0,0 +1,196 @@
+/* Tests for fcntl.
+   Copyright (C) 2000 Free Software Foundation, Inc.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+
+/* Prototype for our test function.  */
+extern void do_prepare (int argc, char *argv[]);
+extern int do_test (int argc, char *argv[]);
+
+/* We have a preparation function.  */
+#define PREPARE do_prepare
+
+#include "../test-skeleton.c"
+
+
+/* Name of the temporary files.  */
+static char *name;
+
+void
+do_prepare (int argc, char *argv[])
+{
+   char name_len;
+
+   name_len = strlen (test_dir);
+   name = malloc (name_len + sizeof ("/fcntlXXXXXX"));
+   mempcpy (mempcpy (name, test_dir, name_len),
+	    "/fcntlXXXXXX", sizeof ("/fcntlXXXXXX"));
+   add_temp_file (name);
+}
+
+
+int
+do_test (int argc, char *argv[])
+{
+  int fd;
+  int fd2;
+  int fd3;
+  struct stat64 st;
+  int val;
+  int result = 0;
+
+  /* Create the temporary file.  */
+  fd = mkstemp (name);
+  if (fd == -1)
+    {
+      printf ("cannot open temporary file: %m\n");
+      return 1;
+    }
+  if (fstat64 (fd, &st) != 0)
+    {
+      printf ("cannot stat test file: %m\n");
+      return 1;
+    }
+  if (! S_ISREG (st.st_mode) || st.st_size != 0)
+    {
+      puts ("file not created correctly");
+      return 1;
+    }
+
+  /* Get the flags with fcntl().  */
+  val = fcntl (fd, F_GETFL);
+  if (val == -1)
+    {
+      printf ("fcntl(fd, F_GETFL) failed: %m\n");
+      result = 1;
+    }
+  else if ((val & O_ACCMODE) != O_RDWR)
+    {
+      puts ("temporary file not opened for read and write");
+      result = 1;
+    }
+
+  /* Set the flags to something else.  */
+  if (fcntl (fd, F_SETFL, O_RDONLY) == -1)
+    {
+      printf ("fcntl(fd, F_SETFL, O_RDONLY) failed: %m\n");
+      result = 1;
+    }
+
+  val = fcntl (fd, F_GETFL);
+  if (val == -1)
+    {
+      printf ("fcntl(fd, F_GETFL) after F_SETFL failed: %m\n");
+      result = 1;
+    }
+  else if ((val & O_ACCMODE) != O_RDWR)
+    {
+      puts ("temporary file access mode changed");
+      result = 1;
+    }
+
+  /* Set the flags to something else.  */
+  if (fcntl (fd, F_SETFL, O_APPEND) == -1)
+    {
+      printf ("fcntl(fd, F_SETFL, O_APPEND) failed: %m\n");
+      result = 1;
+    }
+
+  val = fcntl (fd, F_GETFL);
+  if (val == -1)
+    {
+      printf ("fcntl(fd, F_GETFL) after second F_SETFL failed: %m\n");
+      result = 1;
+    }
+  else if ((val & O_APPEND) == 0)
+    {
+      puts ("O_APPEND not set");
+      result = 1;
+    }
+
+  val = fcntl (fd, F_GETFD);
+  if (val == -1)
+    {
+      printf ("fcntl(fd, F_GETFD) failed: %m\n");
+      result = 1;
+    }
+  else if (fcntl (fd, F_SETFD, val | FD_CLOEXEC) == -1)
+    {
+      printf ("fcntl(fd, F_SETFD, FD_CLOEXEC) failed: %m\n");
+      result = 1;
+    }
+  else
+    {
+      val = fcntl (fd, F_GETFD);
+      if (val == -1)
+	{
+	  printf ("fcntl(fd, F_GETFD) after F_SETFD failed: %m\n");
+	  result = 1;
+	}
+      else if ((val & FD_CLOEXEC) == 0)
+	{
+	  puts ("FD_CLOEXEC not set");
+	  result = 1;
+	}
+    }
+
+  /* Get a number of a free descriptor.  If /dev/null is not available
+     don't continue testing.  */
+  fd2 = open (_PATH_DEVNULL, O_RDWR);
+  if (fd2 == -1)
+    return result;
+  close (fd2);
+
+  fd3 = fcntl (fd, F_DUPFD, fd2 + 1);
+  if (fd3 == -1)
+    {
+      printf ("fcntl(fd, F_DUPFD, %d) failed: %m\n", fd2 + 1);
+      result = 1;
+    }
+  else if (fd3 <= fd2)
+    {
+      printf ("F_DUPFD returned %d which is not larger than %d\n", fd3, fd2);
+      result = 1;
+    }
+
+  if (fd3 != -1)
+    {
+      val = fcntl (fd3, F_GETFD);
+      if (val == -1)
+	{
+	  printf ("fcntl(fd3, F_GETFD) after F_DUPFD failed: %m\n");
+	  result = 1;
+	}
+      else if ((val & FD_CLOEXEC) != 0)
+	{
+	  puts ("FD_CLOEXEC still set");
+	  result = 1;
+	}
+
+      close (fd3);
+    }
+
+  return result;
+}