1
0
mirror of https://https.git.savannah.gnu.org/git/gnulib.git synced 2026-09-01 02:34:55 +00:00

mkfifo: new module

Solaris 9 mkfifo("name/",mode) mistakenly creates "name".
FreeBSD 7.2 mkfifo("dangling/",mode) mistakenly creates a fifo
at the target of "dangling".  Mingw lacks named pipes altogether,
but this at least avoids link failures.

* modules/mkfifo: New file.
* m4/mkfifo.m4 (gl_FUNC_MKFIFO): Likewise.
* lib/mkfifo.c (mkfifo): Likewise.
* m4/sys_stat_h.m4 (gl_SYS_STAT_H_DEFAULTS): Set witness
defaults.
* modules/sys_stat (Makefile.am): Substitute them.
* lib/sys_stat.in.h (mkfifo): Declare replacement.
* MODULES.html.sh (Support for systems lacking POSIX:2008):
Document it.
* doc/posix-functions/mkfifo.texi (mkfifo): Likewise.
* modules/mkfifo-tests: New test.
* tests/test-mkfifo.h (test_mkfifo): New file, borrowed in part
from test-mkfifoat.c.
* tests/test-mkfifo.c: New file.

Signed-off-by: Eric Blake <ebb9@byu.net>
This commit is contained in:
Eric Blake
2009-11-11 13:22:04 -07:00
parent dfd4d11c50
commit 08166afd73
12 changed files with 317 additions and 5 deletions
+16
View File
@@ -1,5 +1,21 @@
2009-11-11 Eric Blake <ebb9@byu.net>
mkfifo: new module
* modules/mkfifo: New file.
* m4/mkfifo.m4 (gl_FUNC_MKFIFO): Likewise.
* lib/mkfifo.c (mkfifo): Likewise.
* m4/sys_stat_h.m4 (gl_SYS_STAT_H_DEFAULTS): Set witness
defaults.
* modules/sys_stat (Makefile.am): Substitute them.
* lib/sys_stat.in.h (mkfifo): Declare replacement.
* MODULES.html.sh (Support for systems lacking POSIX:2008):
Document it.
* doc/posix-functions/mkfifo.texi (mkfifo): Likewise.
* modules/mkfifo-tests: New test.
* tests/test-mkfifo.h (test_mkfifo): New file, borrowed in part
from test-mkfifoat.c.
* tests/test-mkfifo.c: New file.
readlink: detect FreeBSD bug
* m4/readlink.m4 (gl_FUNC_READLINK): Also detect FreeBSD bug with
slash on symlink.
+1
View File
@@ -2287,6 +2287,7 @@ func_all_modules ()
func_module mbsnrtowcs
func_module mkdir
func_module mkdtemp
func_module mkfifo
func_module mkstemp
func_module netdb
func_module netinet_in
+8 -4
View File
@@ -4,15 +4,19 @@
POSIX specification: @url{http://www.opengroup.org/onlinepubs/9699919799/functions/mkfifo.html}
Gnulib module: ---
Gnulib module: mkfifo
Portability problems fixed by Gnulib:
@itemize
@item
This function mishandles trailing slash on some platforms:
FreeBSD 7.2, Solaris 9.
@item
This function is missing on some platforms; however, the replacement
always fails with @code{ENOSYS}:
mingw.
@end itemize
Portability problems not fixed by Gnulib:
@itemize
@item
This function is missing on some platforms:
mingw.
@end itemize
+58
View File
@@ -0,0 +1,58 @@
/* Create a named fifo.
Copyright (C) 2009 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 <http://www.gnu.org/licenses/>. */
/* written by Eric Blake */
#include <config.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#if !HAVE_MKFIFO
/* Mingw lacks mkfifo; always fail with ENOSYS. */
int
mkfifo (char const *name _UNUSED_PARAMETER_, mode_t mode _UNUSED_PARAMETER_)
{
errno = ENOSYS;
return -1;
}
#else /* HAVE_MKFIFO */
# undef mkfifo
/* Create a named fifo FILE, with access permissions in MODE. Work
around trailing slash bugs. */
int
rpl_mkfifo (char const *name, mode_t mode)
{
# if MKFIFO_TRAILING_SLASH_BUG
size_t len = strlen (name);
if (len && name[len - 1] == '/')
{
struct stat st;
if (stat (name, &st) == 0)
errno = EEXIST;
return -1;
}
# endif
return mkfifo (name, mode);
}
#endif /* HAVE_MKFIFO */
+17
View File
@@ -424,6 +424,23 @@ extern int mkdirat (int fd, char const *file, mode_t mode);
#endif
#if @GNULIB_MKFIFO@
# if @REPLACE_MKFIFO@
# undef mkfifo
# define mkfifo rpl_mkfifo
# endif
# if !@HAVE_MKFIFO@ || @REPLACE_MKFIFO@
int mkfifo (char const *file, mode_t mode);
# endif
#elif defined GNULIB_POSIXCHECK
# undef mkfifo
# define mkfifo(n,m) \
(GL_LINK_WARNING ("mkfifo is not portable - " \
"use gnulib module mkfifo for portability"), \
mkfifo (n, m))
#endif
#if @GNULIB_MKFIFOAT@
# if !@HAVE_MKFIFOAT@
int mkfifoat (int fd, char const *file, mode_t mode);
+45
View File
@@ -0,0 +1,45 @@
# serial 1
# See if we need to provide mkfifo replacement.
dnl Copyright (C) 2009 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.
# Written by Eric Blake.
AC_DEFUN([gl_FUNC_MKFIFO],
[
AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS])
AC_CHECK_FUNCS_ONCE([mkfifo])
if test $ac_cv_func_mkfifo = no; then
HAVE_MKFIFO=0
AC_LIBOBJ([mkfifo])
else
dnl Check for Solaris 9 and FreeBSD bug with trailing slash.
AC_CHECK_FUNCS_ONCE([lstat])
AC_CACHE_CHECK([whether mkfifo rejects trailing slashes],
[gl_cv_func_mkfifo_works],
[# Assume that if we have lstat, we can also check symlinks.
if test $ac_cv_func_lstat = yes; then
ln -s conftest.tmp conftest.lnk
fi
AC_RUN_IFELSE(
[AC_LANG_PROGRAM(
[[#include <sys/stat.h>
]], [[if (!mkfifo ("conftest.tmp/", 0600)) return 1;
#if HAVE_LSTAT
if (!mkfifo ("conftest.lnk/", 0600)) return 2;
#endif
]])],
[gl_cv_func_mkfifo_works=yes], [gl_cv_func_mkfifo_works=no],
[gl_cv_func_mkfifo_works="guessing no"])
rm -f conftest.tmp conftest.lnk])
if test "$gl_cv_func_mkfifo_works" != yes; then
AC_DEFINE([MKFIFO_TRAILING_SLASH_BUG], [1], [Define to 1 if mkfifo
does not reject trailing slash])
REPLACE_MKFIFO=1
AC_LIBOBJ([mkfifo])
fi
fi
])
+4 -1
View File
@@ -1,4 +1,4 @@
# sys_stat_h.m4 serial 19 -*- Autoconf -*-
# sys_stat_h.m4 serial 20 -*- Autoconf -*-
dnl Copyright (C) 2006-2009 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -45,6 +45,7 @@ AC_DEFUN([gl_SYS_STAT_H_DEFAULTS],
GNULIB_LCHMOD=0; AC_SUBST([GNULIB_LCHMOD])
GNULIB_LSTAT=0; AC_SUBST([GNULIB_LSTAT])
GNULIB_MKDIRAT=0; AC_SUBST([GNULIB_MKDIRAT])
GNULIB_MKFIFO=0; AC_SUBST([GNULIB_MKFIFO])
GNULIB_MKFIFOAT=0; AC_SUBST([GNULIB_MKFIFOAT])
GNULIB_MKNODAT=0; AC_SUBST([GNULIB_MKNODAT])
GNULIB_STAT=0; AC_SUBST([GNULIB_STAT])
@@ -56,6 +57,7 @@ AC_DEFUN([gl_SYS_STAT_H_DEFAULTS],
HAVE_LCHMOD=1; AC_SUBST([HAVE_LCHMOD])
HAVE_LSTAT=1; AC_SUBST([HAVE_LSTAT])
HAVE_MKDIRAT=1; AC_SUBST([HAVE_MKDIRAT])
HAVE_MKFIFO=1; AC_SUBST([HAVE_MKFIFO])
HAVE_MKFIFOAT=1; AC_SUBST([HAVE_MKFIFOAT])
HAVE_MKNODAT=1; AC_SUBST([HAVE_MKNODAT])
HAVE_UTIMENSAT=1; AC_SUBST([HAVE_UTIMENSAT])
@@ -64,6 +66,7 @@ AC_DEFUN([gl_SYS_STAT_H_DEFAULTS],
REPLACE_FUTIMENS=0; AC_SUBST([REPLACE_FUTIMENS])
REPLACE_LSTAT=0; AC_SUBST([REPLACE_LSTAT])
REPLACE_MKDIR=0; AC_SUBST([REPLACE_MKDIR])
REPLACE_MKFIFO=0; AC_SUBST([REPLACE_MKFIFO])
REPLACE_STAT=0; AC_SUBST([REPLACE_STAT])
REPLACE_UTIMENSAT=0; AC_SUBST([REPLACE_UTIMENSAT])
])
+25
View File
@@ -0,0 +1,25 @@
Description:
mkfifo(): create named FIFO
Files:
lib/mkfifo.c
m4/mkfifo.m4
Depends-on:
stat
sys_stat
configure.ac:
gl_FUNC_MKFIFO
gl_UNISTD_MODULE_INDICATOR([mkfifo])
Makefile.am:
Include:
<sys/stat.h>
License:
LGPL
Maintainer:
Eric Blake
+13
View File
@@ -0,0 +1,13 @@
Files:
tests/test-mkfifo.h
tests/test-mkfifo.c
Depends-on:
stdbool
symlink
configure.ac:
Makefile.am:
TESTS += test-mkfifo
check_PROGRAMS += test-mkfifo
+3
View File
@@ -33,6 +33,7 @@ sys/stat.h: sys_stat.in.h
-e 's|@''GNULIB_LCHMOD''@|$(GNULIB_LCHMOD)|g' \
-e 's|@''GNULIB_LSTAT''@|$(GNULIB_LSTAT)|g' \
-e 's|@''GNULIB_MKDIRAT''@|$(GNULIB_MKDIRAT)|g' \
-e 's|@''GNULIB_MKFIFO''@|$(GNULIB_MKFIFO)|g' \
-e 's|@''GNULIB_MKFIFOAT''@|$(GNULIB_MKFIFOAT)|g' \
-e 's|@''GNULIB_MKNODAT''@|$(GNULIB_MKNODAT)|g' \
-e 's|@''GNULIB_STAT''@|$(GNULIB_STAT)|g' \
@@ -43,6 +44,7 @@ sys/stat.h: sys_stat.in.h
-e 's|@''HAVE_LCHMOD''@|$(HAVE_LCHMOD)|g' \
-e 's|@''HAVE_LSTAT''@|$(HAVE_LSTAT)|g' \
-e 's|@''HAVE_MKDIRAT''@|$(HAVE_MKDIRAT)|g' \
-e 's|@''HAVE_MKFIFO''@|$(HAVE_MKFIFO)|g' \
-e 's|@''HAVE_MKFIFOAT''@|$(HAVE_MKFIFOAT)|g' \
-e 's|@''HAVE_MKNODAT''@|$(HAVE_MKNODAT)|g' \
-e 's|@''HAVE_UTIMENSAT''@|$(HAVE_UTIMENSAT)|g' \
@@ -51,6 +53,7 @@ sys/stat.h: sys_stat.in.h
-e 's|@''REPLACE_FUTIMENS''@|$(REPLACE_FUTIMENS)|g' \
-e 's|@''REPLACE_LSTAT''@|$(REPLACE_LSTAT)|g' \
-e 's|@''REPLACE_MKDIR''@|$(REPLACE_MKDIR)|g' \
-e 's|@''REPLACE_MKFIFO''@|$(REPLACE_MKFIFO)|g' \
-e 's|@''REPLACE_STAT''@|$(REPLACE_STAT)|g' \
-e 's|@''REPLACE_UTIMENSAT''@|$(REPLACE_UTIMENSAT)|g' \
-e '/definition of GL_LINK_WARNING/r $(LINK_WARNING_H)' \
+53
View File
@@ -0,0 +1,53 @@
/* Tests of mkfifo.
Copyright (C) 2009 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 <http://www.gnu.org/licenses/>. */
/* Written by Eric Blake <ebb9@byu.net>, 2009. */
#include <config.h>
#include <sys/stat.h>
#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-mkfifo.t"
#include "test-mkfifo.h"
int
main (void)
{
/* Remove any leftovers from a previous partial run. */
ASSERT (system ("rm -rf " BASE "*") == 0);
return test_mkfifo (mkfifo, true);
}
+74
View File
@@ -0,0 +1,74 @@
/* Tests of mkfifo and friends.
Copyright (C) 2009 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 <http://www.gnu.org/licenses/>. */
/* Written by Eric Blake <ebb9@byu.net>, 2009. */
/* This file is designed to test mkfifo(n,m), mknod(n,m|S_IFIFO,0),
mkfifoat(AT_FDCWD,n,m), and mknodat(AT_FDCWD,n,m|S_IFIFO,0). 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_mkfifo (int (*func) (char const *, mode_t), bool print)
{
int result = func (BASE "fifo", 0600);
struct stat st;
if (result == -1 && errno == ENOSYS)
{
if (print)
fputs ("skipping test: no support for named fifos\n", stderr);
return 77;
}
ASSERT (result == 0);
ASSERT (stat (BASE "fifo", &st) == 0);
ASSERT (S_ISFIFO (st.st_mode));
/* Sanity checks of failures. */
errno = 0;
ASSERT (func ("", S_IRUSR | S_IWUSR) == -1);
ASSERT (errno == ENOENT);
errno = 0;
ASSERT (func (".", 0600) == -1);
ASSERT (errno == EEXIST || errno == EINVAL);
errno = 0;
ASSERT (func (BASE "fifo", 0600) == -1);
ASSERT (errno == EEXIST);
ASSERT (unlink (BASE "fifo") == 0);
errno = 0;
ASSERT (func (BASE "fifo/", 0600) == -1);
ASSERT (errno == ENOENT || errno == ENOTDIR);
/* Test trailing slash behavior. */
if (symlink (BASE "fifo", BASE "link"))
{
if (print)
fputs ("skipping test: symlinks not supported on this file system\n",
stderr);
return 77;
}
errno = 0;
ASSERT (func (BASE "link", 0600) == -1);
ASSERT (errno == EEXIST);
errno = 0;
ASSERT (func (BASE "link/", 0600) == -1);
ASSERT (errno == EEXIST || errno == ENOENT || errno == ENOTDIR);
errno = 0;
ASSERT (unlink (BASE "fifo") == -1);
ASSERT (errno == ENOENT);
ASSERT (unlink (BASE "link") == 0);
return 0;
}