* 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 <bruno@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 <bruno@clisp.org>
open tests: Enhance test.
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:
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
--- /dev/null
+/* 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);
+}
#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
/* 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)
--- /dev/null
+# 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
+])
-# 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
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])
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])
--- /dev/null
+# 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
+])
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
--- /dev/null
+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
-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' \
lib/open.c
m4/open.m4
m4/open-cloexec.m4
+m4/open-slash.m4
m4/mode_t.m4
Depends-on:
#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