The creat() function not only has some of the bugs that open() has
(w.r.t. file names that end in a slash). It also crashes when passed
a mode with executable bits, e.g.
   creat ("file", 0700);
on MSVC 14.

I'm therefore adding a new module that works around both issues.
Tested on AIX 7.1, HP-UX 11.31, Solaris 9.


2019-09-15  Bruno Haible  <br...@clisp.org>

        open tests: Enhance test.
        * tests/test-open.h (test_open): Test the creation of an executable
        regular file. Also improve initial cleanup.

        creat: New module.
        * lib/fcntl.in.h (creat): New declaration.
        * lib/creat.c: New file, based on lib/open.c.
        * m4/creat.m4: New file.
        * m4/open-slash.m4: New file, extracted from m4/open.m4.
        * m4/open.m4 (gl_FUNC_OPEN): Move trailing-slash test to open-slash.m4.
        Invoke gl_OPEN_TRAILING_SLASH_BUG.
        * modules/open (Files): Add m4/open-slash.m4.
        * m4/fcntl_h.m4 (gl_FCNTL_H_DEFAULTS): Initialize GNULIB_CREAT,
        REPLACE_CREAT.
        * modules/fcntl-h (Makefile.am): Substitute GNULIB_CREAT, REPLACE_CREAT.
        * modules/creat: New file.
        * tests/test-fcntl-h-c++.cc (creat): Check signature.
        * doc/posix-functions/creat.texi: Mention the new module.

        creat: Add tests.
        * tests/test-creat.c: New file, based on tests/test-open.h.
        * modules/creat-tests: New file.
>From 9e75623a64a07215f2c7811e0356697d6df10fa2 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Sun, 15 Sep 2019 14:41:57 +0200
Subject: [PATCH 1/3] open tests: Enhance test.

* tests/test-open.h (test_open): Test the creation of an executable
regular file. Also improve initial cleanup.
---
 ChangeLog         | 6 ++++++
 tests/test-open.h | 9 +++++++++
 2 files changed, 15 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index c94ebeb..9f97bb0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2019-09-15  Bruno Haible  <br...@clisp.org>
 
+	open tests: Enhance test.
+	* tests/test-open.h (test_open): Test the creation of an executable
+	regular file. Also improve initial cleanup.
+
+2019-09-15  Bruno Haible  <br...@clisp.org>
+
 	intprops tests: Avoid build failure with HP-UX cc.
 	* tests/test-intprops.c: Disable a check that makes HP cc choke with
 	"error 4018: Macro param too large after substitution - use -H option.".
diff --git a/tests/test-open.h b/tests/test-open.h
index e5c47d2..c0290ee 100644
--- a/tests/test-open.h
+++ b/tests/test-open.h
@@ -37,8 +37,11 @@ static ALWAYS_INLINE int
 test_open (int (*func) (char const *, int, ...), bool print)
 {
   int fd;
+
   /* Remove anything from prior partial run.  */
   unlink (BASE "file");
+  unlink (BASE "e.exe");
+  unlink (BASE "link");
 
   /* Cannot create directory.  */
   errno = 0;
@@ -51,6 +54,11 @@ test_open (int (*func) (char const *, int, ...), bool print)
   ASSERT (0 <= fd);
   ASSERT (close (fd) == 0);
 
+  /* Create an executable regular file.  */
+  fd = func (BASE "e.exe", O_CREAT | O_RDONLY, 0700);
+  ASSERT (0 <= fd);
+  ASSERT (close (fd) == 0);
+
   /* Trailing slash handling.  */
   errno = 0;
   ASSERT (func (BASE "file/", O_RDONLY) == -1);
@@ -98,6 +106,7 @@ test_open (int (*func) (char const *, int, ...), bool print)
 
   /* Cleanup.  */
   ASSERT (unlink (BASE "file") == 0);
+  ASSERT (unlink (BASE "e.exe") == 0);
   ASSERT (unlink (BASE "link") == 0);
 
   return 0;
-- 
2.7.4

>From c5f7c7c69b3b986c49930c1c7ac37c552a3be738 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Sun, 15 Sep 2019 17:41:29 +0200
Subject: [PATCH 2/3] creat: New module.

* lib/fcntl.in.h (creat): New declaration.
* lib/creat.c: New file, based on lib/open.c.
* m4/creat.m4: New file.
* m4/open-slash.m4: New file, extracted from m4/open.m4.
* m4/open.m4 (gl_FUNC_OPEN): Move trailing-slash test to open-slash.m4.
Invoke gl_OPEN_TRAILING_SLASH_BUG.
* modules/open (Files): Add m4/open-slash.m4.
* m4/fcntl_h.m4 (gl_FCNTL_H_DEFAULTS): Initialize GNULIB_CREAT,
REPLACE_CREAT.
* modules/fcntl-h (Makefile.am): Substitute GNULIB_CREAT, REPLACE_CREAT.
* modules/creat: New file.
* tests/test-fcntl-h-c++.cc (creat): Check signature.
* doc/posix-functions/creat.texi: Mention the new module.
---
 ChangeLog                      | 17 +++++++++
 doc/posix-functions/creat.texi | 17 ++++++---
 lib/creat.c                    | 78 ++++++++++++++++++++++++++++++++++++++++++
 lib/fcntl.in.h                 | 22 +++++++++++-
 m4/creat.m4                    | 23 +++++++++++++
 m4/fcntl_h.m4                  |  4 ++-
 m4/open-slash.m4               | 59 ++++++++++++++++++++++++++++++++
 m4/open.m4                     | 41 +---------------------
 modules/creat                  | 29 ++++++++++++++++
 modules/fcntl-h                |  2 ++
 modules/open                   |  1 +
 tests/test-fcntl-h-c++.cc      |  4 +++
 12 files changed, 250 insertions(+), 47 deletions(-)
 create mode 100644 lib/creat.c
 create mode 100644 m4/creat.m4
 create mode 100644 m4/open-slash.m4
 create mode 100644 modules/creat

diff --git a/ChangeLog b/ChangeLog
index 9f97bb0..f7309fa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,22 @@
 2019-09-15  Bruno Haible  <br...@clisp.org>
 
+	creat: New module.
+	* lib/fcntl.in.h (creat): New declaration.
+	* lib/creat.c: New file, based on lib/open.c.
+	* m4/creat.m4: New file.
+	* m4/open-slash.m4: New file, extracted from m4/open.m4.
+	* m4/open.m4 (gl_FUNC_OPEN): Move trailing-slash test to open-slash.m4.
+	Invoke gl_OPEN_TRAILING_SLASH_BUG.
+	* modules/open (Files): Add m4/open-slash.m4.
+	* m4/fcntl_h.m4 (gl_FCNTL_H_DEFAULTS): Initialize GNULIB_CREAT,
+	REPLACE_CREAT.
+	* modules/fcntl-h (Makefile.am): Substitute GNULIB_CREAT, REPLACE_CREAT.
+	* modules/creat: New file.
+	* tests/test-fcntl-h-c++.cc (creat): Check signature.
+	* doc/posix-functions/creat.texi: Mention the new module.
+
+2019-09-15  Bruno Haible  <br...@clisp.org>
+
 	open tests: Enhance test.
 	* tests/test-open.h (test_open): Test the creation of an executable
 	regular file. Also improve initial cleanup.
diff --git a/doc/posix-functions/creat.texi b/doc/posix-functions/creat.texi
index f144777..f7b86a7 100644
--- a/doc/posix-functions/creat.texi
+++ b/doc/posix-functions/creat.texi
@@ -4,10 +4,21 @@
 
 POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/creat.html}
 
-Gnulib module: ---
+Gnulib module: creat
 
 Portability problems fixed by Gnulib:
 @itemize
+@item
+This function does not support modes with execution bits (such as 0700)
+on some platforms:
+MSVC 14.
+@item
+On platforms where @code{off_t} is a 32-bit type, @code{creat} may not work
+correctly with files larger than 2 GB.  (Cf. @code{AC_SYS_LARGEFILE}.)
+@item
+This function does not fail when the file name argument ends in a slash
+and (without the slash) names a nonexistent file, on some platforms:
+FreeBSD 7.2, AIX 7.1, HP-UX 11.31, Solaris 9.
 @end itemize
 
 Portability problems not fixed by Gnulib:
@@ -16,8 +27,4 @@ Portability problems not fixed by Gnulib:
 On Windows, this function returns a file handle in @code{O_TEXT} mode.  If you
 need a file handle in @code{O_BINARY} mode, you need to use the function
 @code{open} instead.
-@item
-On platforms where @code{off_t} is a 32-bit type, @code{creat} may not work
-correctly to create files larger than 2 GB.  The fix is to use the
-@code{AC_SYS_LARGEFILE} macro.
 @end itemize
diff --git a/lib/creat.c b/lib/creat.c
new file mode 100644
index 0000000..f66430d
--- /dev/null
+++ b/lib/creat.c
@@ -0,0 +1,78 @@
+/* Create a file.
+   Copyright (C) 2007-2019 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* If the user's config.h happens to include <fcntl.h>, let it include only
+   the system's <fcntl.h> here, so that orig_creat doesn't recurse to
+   rpl_creat.  */
+#define __need_system_fcntl_h
+#include <config.h>
+
+/* Get the original definition of creat.  It might be defined as a macro.  */
+#include <fcntl.h>
+#include <sys/types.h>
+#undef __need_system_fcntl_h
+
+static int
+orig_creat (const char *filename, mode_t mode)
+{
+  return creat (filename, mode);
+}
+
+/* Specification.  */
+/* Write "fcntl.h" here, not <fcntl.h>, otherwise OSF/1 5.1 DTK cc eliminates
+   this include because of the preliminary #include <fcntl.h> above.  */
+#include "fcntl.h"
+
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+
+int
+creat (const char *filename, mode_t mode)
+{
+#if OPEN_TRAILING_SLASH_BUG
+  /* If the filename ends in a slash, then fail.
+     Rationale: POSIX <http://www.opengroup.org/susv3/basedefs/xbd_chap04.html>
+     says that
+       "A pathname that contains at least one non-slash character and that
+        ends with one or more trailing slashes shall be resolved as if a
+        single dot character ( '.' ) were appended to the pathname."
+     and
+       "The special filename dot shall refer to the directory specified by
+        its predecessor."
+     creat() is defined as being equivalent to open() with flags
+     O_CREAT | O_TRUNC | O_WRONLY.  Therefore:
+     If the named file already exists as a directory, then creat() must fail
+     with errno = EISDIR.
+     If the named file does not exist or does not name a directory, then
+     creat() must fail since creat() cannot create directories.  */
+  {
+    size_t len = strlen (filename);
+    if (len > 0 && filename[len - 1] == '/')
+      {
+        errno = EISDIR;
+        return -1;
+      }
+  }
+#endif
+
+#if defined _WIN32 && !defined __CYGWIN__
+  /* Remap the 'x' bits to the 'r' bits.  */
+  mode = (mode & ~0111) | ((mode & 0111) << 2);
+#endif
+
+  return orig_creat (filename, mode);
+}
diff --git a/lib/fcntl.in.h b/lib/fcntl.in.h
index eb70dc6..557e6c1 100644
--- a/lib/fcntl.in.h
+++ b/lib/fcntl.in.h
@@ -67,7 +67,7 @@
 #endif
 
 /* Native Windows platforms declare open(), creat() in <io.h>.  */
-#if (@GNULIB_OPEN@ || defined GNULIB_POSIXCHECK) \
+#if (@GNULIB_CREAT@ || @GNULIB_OPEN@ || defined GNULIB_POSIXCHECK) \
     && (defined _WIN32 && ! defined __CYGWIN__)
 # include <io.h>
 #endif
@@ -82,6 +82,26 @@
 
 /* Declare overridden functions.  */
 
+#if @GNULIB_CREAT@
+# if @REPLACE_CREAT@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef creat
+#   define creat rpl_creat
+#  endif
+_GL_FUNCDECL_RPL (creat, int, (const char *filename, mode_t mode)
+                             _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (creat, int, (const char *filename, mode_t mode));
+# else
+_GL_CXXALIAS_SYS (creat, int, (const char *filename, mode_t mode));
+# endif
+_GL_CXXALIASWARN (creat);
+#elif defined GNULIB_POSIXCHECK
+# undef creat
+/* Assume creat is always declared.  */
+_GL_WARN_ON_USE (creat, "creat is not always POSIX compliant - "
+                 "use gnulib module creat for portability");
+#endif
+
 #if @GNULIB_FCNTL@
 # if @REPLACE_FCNTL@
 #  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
diff --git a/m4/creat.m4 b/m4/creat.m4
new file mode 100644
index 0000000..a428a72
--- /dev/null
+++ b/m4/creat.m4
@@ -0,0 +1,23 @@
+# creat.m4 serial 1
+dnl Copyright (C) 2019 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_CREAT],
+[
+  AC_REQUIRE([AC_CANONICAL_HOST])
+  case "$host_os" in
+    mingw*)
+      REPLACE_CREAT=1
+      ;;
+    *)
+      gl_OPEN_TRAILING_SLASH_BUG
+      case "$gl_cv_func_open_slash" in
+        *no)
+          REPLACE_CREAT=1
+          ;;
+      esac
+      ;;
+  esac
+])
diff --git a/m4/fcntl_h.m4 b/m4/fcntl_h.m4
index a86fdae..60dc5e2 100644
--- a/m4/fcntl_h.m4
+++ b/m4/fcntl_h.m4
@@ -1,4 +1,4 @@
-# serial 15
+# serial 16
 # Configure fcntl.h.
 dnl Copyright (C) 2006-2007, 2009-2019 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
@@ -37,6 +37,7 @@ AC_DEFUN([gl_FCNTL_MODULE_INDICATOR],
 
 AC_DEFUN([gl_FCNTL_H_DEFAULTS],
 [
+  GNULIB_CREAT=0;        AC_SUBST([GNULIB_CREAT])
   GNULIB_FCNTL=0;        AC_SUBST([GNULIB_FCNTL])
   GNULIB_NONBLOCKING=0;  AC_SUBST([GNULIB_NONBLOCKING])
   GNULIB_OPEN=0;         AC_SUBST([GNULIB_OPEN])
@@ -44,6 +45,7 @@ AC_DEFUN([gl_FCNTL_H_DEFAULTS],
   dnl Assume proper GNU behavior unless another module says otherwise.
   HAVE_FCNTL=1;          AC_SUBST([HAVE_FCNTL])
   HAVE_OPENAT=1;         AC_SUBST([HAVE_OPENAT])
+  REPLACE_CREAT=0;       AC_SUBST([REPLACE_CREAT])
   REPLACE_FCNTL=0;       AC_SUBST([REPLACE_FCNTL])
   REPLACE_OPEN=0;        AC_SUBST([REPLACE_OPEN])
   REPLACE_OPENAT=0;      AC_SUBST([REPLACE_OPENAT])
diff --git a/m4/open-slash.m4 b/m4/open-slash.m4
new file mode 100644
index 0000000..a8756ae
--- /dev/null
+++ b/m4/open-slash.m4
@@ -0,0 +1,59 @@
+# open-slash.m4 serial 1
+dnl Copyright (C) 2007-2019 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl Tests whether open() and creat() recognize a trailing slash.
+dnl Sets gl_cv_func_open_slash.
+AC_DEFUN([gl_OPEN_TRAILING_SLASH_BUG],
+[
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  dnl open("foo/") should not create a file when the file name has a
+  dnl trailing slash.  FreeBSD only has the problem on symlinks.
+  AC_CHECK_FUNCS_ONCE([lstat])
+  AC_CACHE_CHECK([whether open recognizes a trailing slash],
+    [gl_cv_func_open_slash],
+    [# Assume that if we have lstat, we can also check symlinks.
+     if test $ac_cv_func_lstat = yes; then
+       touch conftest.tmp
+       ln -s conftest.tmp conftest.lnk
+     fi
+     AC_RUN_IFELSE(
+       [AC_LANG_SOURCE([[
+#include <fcntl.h>
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+int main ()
+{
+  int result = 0;
+#if HAVE_LSTAT
+  if (open ("conftest.lnk/", O_RDONLY) != -1)
+    result |= 1;
+#endif
+  if (open ("conftest.sl/", O_CREAT, 0600) >= 0)
+    result |= 2;
+  return result;
+}]])],
+       [gl_cv_func_open_slash=yes],
+       [gl_cv_func_open_slash=no],
+       [
+changequote(,)dnl
+        case "$host_os" in
+          freebsd* | aix* | hpux* | solaris2.[0-9] | solaris2.[0-9].*)
+            gl_cv_func_open_slash="guessing no" ;;
+          *)
+            gl_cv_func_open_slash="guessing yes" ;;
+        esac
+changequote([,])dnl
+       ])
+     rm -f conftest.sl conftest.tmp conftest.lnk
+    ])
+  case "$gl_cv_func_open_slash" in
+    *no)
+      AC_DEFINE([OPEN_TRAILING_SLASH_BUG], [1],
+        [Define to 1 if open() fails to recognize a trailing slash.])
+      ;;
+  esac
+])
diff --git a/m4/open.m4 b/m4/open.m4
index 5d73f4d..6cf0beb 100644
--- a/m4/open.m4
+++ b/m4/open.m4
@@ -19,48 +19,9 @@ AC_DEFUN([gl_FUNC_OPEN],
       if test "$gl_cv_macro_O_CLOEXEC" != yes; then
         REPLACE_OPEN=1
       fi
-      AC_CACHE_CHECK([whether open recognizes a trailing slash],
-        [gl_cv_func_open_slash],
-        [# Assume that if we have lstat, we can also check symlinks.
-          if test $ac_cv_func_lstat = yes; then
-            touch conftest.tmp
-            ln -s conftest.tmp conftest.lnk
-          fi
-          AC_RUN_IFELSE(
-            [AC_LANG_SOURCE([[
-#include <fcntl.h>
-#if HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-int main ()
-{
-  int result = 0;
-#if HAVE_LSTAT
-  if (open ("conftest.lnk/", O_RDONLY) != -1)
-    result |= 1;
-#endif
-  if (open ("conftest.sl/", O_CREAT, 0600) >= 0)
-    result |= 2;
-  return result;
-}]])],
-            [gl_cv_func_open_slash=yes],
-            [gl_cv_func_open_slash=no],
-            [
-changequote(,)dnl
-             case "$host_os" in
-               freebsd* | aix* | hpux* | solaris2.[0-9] | solaris2.[0-9].*)
-                 gl_cv_func_open_slash="guessing no" ;;
-               *)
-                 gl_cv_func_open_slash="guessing yes" ;;
-             esac
-changequote([,])dnl
-            ])
-          rm -f conftest.sl conftest.tmp conftest.lnk
-        ])
+      gl_OPEN_TRAILING_SLASH_BUG
       case "$gl_cv_func_open_slash" in
         *no)
-          AC_DEFINE([OPEN_TRAILING_SLASH_BUG], [1],
-            [Define to 1 if open() fails to recognize a trailing slash.])
           REPLACE_OPEN=1
           ;;
       esac
diff --git a/modules/creat b/modules/creat
new file mode 100644
index 0000000..d95d6ba
--- /dev/null
+++ b/modules/creat
@@ -0,0 +1,29 @@
+Description:
+creat() function: create a file.
+
+Files:
+lib/creat.c
+m4/creat.m4
+m4/open-slash.m4
+
+Depends-on:
+fcntl-h
+largefile
+
+configure.ac:
+gl_FUNC_CREAT
+if test $REPLACE_CREAT = 1; then
+  AC_LIBOBJ([creat])
+fi
+gl_FCNTL_MODULE_INDICATOR([creat])
+
+Makefile.am:
+
+Include:
+<fcntl.h>
+
+License:
+LGPLv2+
+
+Maintainer:
+all
diff --git a/modules/fcntl-h b/modules/fcntl-h
index eeac31f..ff74dec 100644
--- a/modules/fcntl-h
+++ b/modules/fcntl-h
@@ -31,12 +31,14 @@ fcntl.h: fcntl.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H)
 	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
 	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
 	      -e 's|@''NEXT_FCNTL_H''@|$(NEXT_FCNTL_H)|g' \
+	      -e 's/@''GNULIB_CREAT''@/$(GNULIB_CREAT)/g' \
 	      -e 's/@''GNULIB_FCNTL''@/$(GNULIB_FCNTL)/g' \
 	      -e 's/@''GNULIB_NONBLOCKING''@/$(GNULIB_NONBLOCKING)/g' \
 	      -e 's/@''GNULIB_OPEN''@/$(GNULIB_OPEN)/g' \
 	      -e 's/@''GNULIB_OPENAT''@/$(GNULIB_OPENAT)/g' \
 	      -e 's|@''HAVE_FCNTL''@|$(HAVE_FCNTL)|g' \
 	      -e 's|@''HAVE_OPENAT''@|$(HAVE_OPENAT)|g' \
+	      -e 's|@''REPLACE_CREAT''@|$(REPLACE_CREAT)|g' \
 	      -e 's|@''REPLACE_FCNTL''@|$(REPLACE_FCNTL)|g' \
 	      -e 's|@''REPLACE_OPEN''@|$(REPLACE_OPEN)|g' \
 	      -e 's|@''REPLACE_OPENAT''@|$(REPLACE_OPENAT)|g' \
diff --git a/modules/open b/modules/open
index 62c1a05..91debfc 100644
--- a/modules/open
+++ b/modules/open
@@ -5,6 +5,7 @@ Files:
 lib/open.c
 m4/open.m4
 m4/open-cloexec.m4
+m4/open-slash.m4
 m4/mode_t.m4
 
 Depends-on:
diff --git a/tests/test-fcntl-h-c++.cc b/tests/test-fcntl-h-c++.cc
index 31a2ad2..16e3c6f 100644
--- a/tests/test-fcntl-h-c++.cc
+++ b/tests/test-fcntl-h-c++.cc
@@ -24,6 +24,10 @@
 #include "signature.h"
 
 
+#if GNULIB_TEST_CREAT
+SIGNATURE_CHECK (GNULIB_NAMESPACE::creat, int, (const char *, mode_t));
+#endif
+
 #if GNULIB_TEST_FCNTL
 SIGNATURE_CHECK (GNULIB_NAMESPACE::fcntl, int, (int, int, ...));
 #endif
-- 
2.7.4

>From 01c0052307a4c87926b664d288fa5ba801eaa8ff Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Sun, 15 Sep 2019 17:42:47 +0200
Subject: [PATCH 3/3] creat: Add tests.

* tests/test-creat.c: New file, based on tests/test-open.h.
* modules/creat-tests: New file.
---
 ChangeLog           |  4 ++++
 modules/creat-tests | 12 +++++++++++
 tests/test-creat.c  | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 78 insertions(+)
 create mode 100644 modules/creat-tests
 create mode 100644 tests/test-creat.c

diff --git a/ChangeLog b/ChangeLog
index f7309fa..1c7ca6b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2019-09-15  Bruno Haible  <br...@clisp.org>
 
+	creat: Add tests.
+	* tests/test-creat.c: New file, based on tests/test-open.h.
+	* modules/creat-tests: New file.
+
 	creat: New module.
 	* lib/fcntl.in.h (creat): New declaration.
 	* lib/creat.c: New file, based on lib/open.c.
diff --git a/modules/creat-tests b/modules/creat-tests
new file mode 100644
index 0000000..4e61fcc
--- /dev/null
+++ b/modules/creat-tests
@@ -0,0 +1,12 @@
+Files:
+tests/test-creat.c
+tests/signature.h
+tests/macros.h
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-creat
+check_PROGRAMS += test-creat
diff --git a/tests/test-creat.c b/tests/test-creat.c
new file mode 100644
index 0000000..8db3548
--- /dev/null
+++ b/tests/test-creat.c
@@ -0,0 +1,62 @@
+/* Test of creating a file.
+   Copyright (C) 2007-2019 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include <fcntl.h>
+
+#include "signature.h"
+SIGNATURE_CHECK (creat, int, (const char *, mode_t));
+
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "macros.h"
+
+#define BASE "test-creat.t"
+
+int
+main (void)
+{
+  int fd;
+
+  /* Remove anything from prior partial run.  */
+  unlink (BASE "file");
+  unlink (BASE "e.exe");
+
+  /* Cannot create directory.  */
+  errno = 0;
+  ASSERT (creat ("nonexist.ent/", 0600) == -1);
+  ASSERT (errno == ENOTDIR || errno == EISDIR || errno == ENOENT
+          || errno == EINVAL);
+
+  /* Create a regular file.  */
+  fd = creat (BASE "file", 0600);
+  ASSERT (0 <= fd);
+  ASSERT (close (fd) == 0);
+
+  /* Create an executable regular file.  */
+  fd = creat (BASE "e.exe", 0700);
+  ASSERT (0 <= fd);
+  ASSERT (close (fd) == 0);
+
+  /* Cleanup.  */
+  ASSERT (unlink (BASE "file") == 0);
+  ASSERT (unlink (BASE "e.exe") == 0);
+
+  return 0;
+}
-- 
2.7.4

Reply via email to