Mercurial > hg > octave-lojdl > gnulib-hg
changeset 12267:c400da5f66bb
mknod: new module
Solaris 9 mknod("name/",mode,dev) mistakenly creates "name" for
non-directory mode. FreeBSD 7.2 mknod("dangling/",mode,dev)
mistakenly creates the target of the symlink if run as root.
FreeBSD and OpenBSD mknod("fifo",S_IFIFO|mode,0) fails for non-root.
Use of mknod caused link failures on mingw.
* modules/mknod: New file.
* m4/mknod.m4 (gl_FUNC_MKNOD): Likewise.
* lib/mknod.c (mknod): 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 (mknod): Declare replacement.
* MODULES.html.sh (Support for systems lacking POSIX:2008):
Document it.
* doc/posix-functions/mknod.texi (mknod): Likewise.
* modules/mknod-tests: New test.
* tests/test-mknod.c: Likewise.
Signed-off-by: Eric Blake <ebb9@byu.net>
author | Eric Blake <ebb9@byu.net> |
---|---|
date | Wed, 11 Nov 2009 13:23:04 -0700 |
parents | 37fd04a02bc8 |
children | b537cb58d506 |
files | ChangeLog MODULES.html.sh doc/posix-functions/mknod.texi lib/mknod.c lib/sys_stat.in.h m4/mknod.m4 m4/sys_stat_h.m4 modules/mknod modules/mknod-tests modules/sys_stat tests/test-mknod.c |
diffstat | 11 files changed, 273 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,19 @@ 2009-11-11 Eric Blake <ebb9@byu.net> + mknod: new module + * modules/mknod: New file. + * m4/mknod.m4 (gl_FUNC_MKNOD): Likewise. + * lib/mknod.c (mknod): 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 (mknod): Declare replacement. + * MODULES.html.sh (Support for systems lacking POSIX:2008): + Document it. + * doc/posix-functions/mknod.texi (mknod): Likewise. + * modules/mknod-tests: New test. + * tests/test-mknod.c: Likewise. + mkfifo: new module * modules/mkfifo: New file. * m4/mkfifo.m4 (gl_FUNC_MKFIFO): Likewise.
--- a/MODULES.html.sh +++ b/MODULES.html.sh @@ -2288,6 +2288,7 @@ func_module mkdir func_module mkdtemp func_module mkfifo + func_module mknod func_module mkstemp func_module netdb func_module netinet_in
--- a/doc/posix-functions/mknod.texi +++ b/doc/posix-functions/mknod.texi @@ -4,15 +4,26 @@ POSIX specification: @url{http://www.opengroup.org/onlinepubs/9699919799/functions/mknod.html} -Gnulib module: --- +Gnulib module: mknod Portability problems fixed by Gnulib: @itemize +@item +This function requires super-user privileges to create a fifo: +FreeBSD 7.2, OpenBSD 3.8. +@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. +Use of this function for anything except fifos is not portable, +generally requiring super-user privileges and knowledge of supported +device numbers. @end itemize
new file mode 100644 --- /dev/null +++ b/lib/mknod.c @@ -0,0 +1,74 @@ +/* Create a device inode. + 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_MKNOD +/* Mingw lacks mknod; always fail with ENOSYS. */ + +int +mknod (char const *name _UNUSED_PARAMETER_, mode_t mode _UNUSED_PARAMETER_, + dev_t dev _UNUSED_PARAMETER_) +{ + errno = ENOSYS; + return -1; +} + +#else /* HAVE_MKNOD */ + +# undef mknod + +/* Create a file system node FILE, with access permissions and file + type in MODE, and device type in DEV. Usually, non-root + applications can only create named fifos (mode includes S_IFIFO), + with DEV set to 0. Also work around trailing slash bugs. */ + +int +rpl_mknod (char const *name, mode_t mode, dev_t dev) +{ +# if MKFIFO_TRAILING_SLASH_BUG + /* Trailing slash only makes sense for directories. Of course, + using mknod to create a directory is not very portable, so it may + still fail later on. */ + if (!S_ISDIR (mode)) + { + size_t len = strlen (name); + if (len && name[len - 1] == '/') + { + struct stat st; + if (stat (name, &st) == 0) + errno = EEXIST; + return -1; + } + } +# endif +# if MKNOD_FIFO_BUG + /* POSIX requires mknod to create fifos for non-privileged + processes, but BSD implementations fail with EPERM. */ + if (S_ISFIFO (mode) && dev == 0) + return mkfifo (name, mode & ~S_IFIFO); +# endif + return mknod (name, mode, dev); +} + +#endif /* HAVE_MKNOD */
--- a/lib/sys_stat.in.h +++ b/lib/sys_stat.in.h @@ -454,6 +454,23 @@ #endif +#if @GNULIB_MKNOD@ +# if @REPLACE_MKNOD@ +# undef mknod +# define mknod rpl_mknod +# endif +# if !@HAVE_MKNOD@ || @REPLACE_MKNOD@ +int mknod (char const *file, mode_t mode, dev_t dev); +# endif +#elif defined GNULIB_POSIXCHECK +# undef mknod +# define mknod(n,m,d) \ + (GL_LINK_WARNING ("mknod is not portable - " \ + "use gnulib module mknod for portability"), \ + mknod (n, m, d)) +#endif + + #if @GNULIB_MKNODAT@ # if !@HAVE_MKNODAT@ int mknodat (int fd, char const *file, mode_t mode, dev_t dev);
new file mode 100644 --- /dev/null +++ b/m4/mknod.m4 @@ -0,0 +1,45 @@ +# serial 1 +# See if we need to provide mknod 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_MKNOD], +[ + AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS]) + AC_REQUIRE([gl_FUNC_MKFIFO]) + AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) + AC_CHECK_FUNCS_ONCE([mknod]) + if test $ac_cv_func_mknod = no; then + HAVE_MKNOD=0 + AC_LIBOBJ([mknod]) + else + dnl Detect BSD bug, where mknod requires root privileges to create fifo. + AC_CACHE_CHECK([whether mknod can create fifo without root privileges], + [gl_cv_func_mknod_works], + [AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[#include <sys/stat.h> + #include <unistd.h> +]], [[/* Indeterminate for super-user, assume no. Why are you running + configure as root, anyway? */ + if (!geteuid ()) return 1; + if (mknod ("conftest.fifo", S_IFIFO | 0600, 0)) return 2;]])], + [gl_cv_func_mknod_works=yes], [gl_cv_func_mknod_works=no], + [gl_cv_func_mknod_works="guessing no"]) + rm -f conftest.fifo]) + if test "$gl_cv_func_mknod_works" != yes; then + AC_DEFINE([MKNOD_FIFO_BUG], [1], [Define to 1 if mknod cannot create + a fifo without super-user privileges]) + fi + dnl Systems that mishandle trailing slash on mkfifo also goof on mknod. + if test $REPLACE_MKFIFO = 1 || test "$gl_cv_func_mknod_works" != yes; then + REPLACE_MKNOD=1 + AC_LIBOBJ([mknod]) + fi + fi +])
--- a/m4/sys_stat_h.m4 +++ b/m4/sys_stat_h.m4 @@ -1,4 +1,4 @@ -# sys_stat_h.m4 serial 20 -*- Autoconf -*- +# sys_stat_h.m4 serial 21 -*- 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, @@ -47,6 +47,7 @@ GNULIB_MKDIRAT=0; AC_SUBST([GNULIB_MKDIRAT]) GNULIB_MKFIFO=0; AC_SUBST([GNULIB_MKFIFO]) GNULIB_MKFIFOAT=0; AC_SUBST([GNULIB_MKFIFOAT]) + GNULIB_MKNOD=0; AC_SUBST([GNULIB_MKNOD]) GNULIB_MKNODAT=0; AC_SUBST([GNULIB_MKNODAT]) GNULIB_STAT=0; AC_SUBST([GNULIB_STAT]) GNULIB_UTIMENSAT=0; AC_SUBST([GNULIB_UTIMENSAT]) @@ -59,6 +60,7 @@ HAVE_MKDIRAT=1; AC_SUBST([HAVE_MKDIRAT]) HAVE_MKFIFO=1; AC_SUBST([HAVE_MKFIFO]) HAVE_MKFIFOAT=1; AC_SUBST([HAVE_MKFIFOAT]) + HAVE_MKNOD=1; AC_SUBST([HAVE_MKNOD]) HAVE_MKNODAT=1; AC_SUBST([HAVE_MKNODAT]) HAVE_UTIMENSAT=1; AC_SUBST([HAVE_UTIMENSAT]) REPLACE_FSTAT=0; AC_SUBST([REPLACE_FSTAT]) @@ -67,6 +69,7 @@ REPLACE_LSTAT=0; AC_SUBST([REPLACE_LSTAT]) REPLACE_MKDIR=0; AC_SUBST([REPLACE_MKDIR]) REPLACE_MKFIFO=0; AC_SUBST([REPLACE_MKFIFO]) + REPLACE_MKNOD=0; AC_SUBST([REPLACE_MKNOD]) REPLACE_STAT=0; AC_SUBST([REPLACE_STAT]) REPLACE_UTIMENSAT=0; AC_SUBST([REPLACE_UTIMENSAT]) ])
new file mode 100644 --- /dev/null +++ b/modules/mknod @@ -0,0 +1,26 @@ +Description: +mknod(): create various special devices + +Files: +lib/mknod.c +m4/mknod.m4 + +Depends-on: +mkfifo +stat +sys_stat + +configure.ac: +gl_FUNC_MKNOD +gl_UNISTD_MODULE_INDICATOR([mknod]) + +Makefile.am: + +Include: +<sys/stat.h> + +License: +LGPL + +Maintainer: +Eric Blake
new file mode 100644 --- /dev/null +++ b/modules/mknod-tests @@ -0,0 +1,13 @@ +Files: +tests/test-mkfifo.h +tests/test-mknod.c + +Depends-on: +stdbool +symlink + +configure.ac: + +Makefile.am: +TESTS += test-mknod +check_PROGRAMS += test-mknod
--- a/modules/sys_stat +++ b/modules/sys_stat @@ -35,6 +35,7 @@ -e 's|@''GNULIB_MKDIRAT''@|$(GNULIB_MKDIRAT)|g' \ -e 's|@''GNULIB_MKFIFO''@|$(GNULIB_MKFIFO)|g' \ -e 's|@''GNULIB_MKFIFOAT''@|$(GNULIB_MKFIFOAT)|g' \ + -e 's|@''GNULIB_MKNOD''@|$(GNULIB_MKNOD)|g' \ -e 's|@''GNULIB_MKNODAT''@|$(GNULIB_MKNODAT)|g' \ -e 's|@''GNULIB_STAT''@|$(GNULIB_STAT)|g' \ -e 's|@''GNULIB_UTIMENSAT''@|$(GNULIB_UTIMENSAT)|g' \ @@ -46,6 +47,7 @@ -e 's|@''HAVE_MKDIRAT''@|$(HAVE_MKDIRAT)|g' \ -e 's|@''HAVE_MKFIFO''@|$(HAVE_MKFIFO)|g' \ -e 's|@''HAVE_MKFIFOAT''@|$(HAVE_MKFIFOAT)|g' \ + -e 's|@''HAVE_MKNOD''@|$(HAVE_MKNOD)|g' \ -e 's|@''HAVE_MKNODAT''@|$(HAVE_MKNODAT)|g' \ -e 's|@''HAVE_UTIMENSAT''@|$(HAVE_UTIMENSAT)|g' \ -e 's|@''REPLACE_FSTAT''@|$(REPLACE_FSTAT)|g' \ @@ -54,6 +56,7 @@ -e 's|@''REPLACE_LSTAT''@|$(REPLACE_LSTAT)|g' \ -e 's|@''REPLACE_MKDIR''@|$(REPLACE_MKDIR)|g' \ -e 's|@''REPLACE_MKFIFO''@|$(REPLACE_MKFIFO)|g' \ + -e 's|@''REPLACE_MKNOD''@|$(REPLACE_MKNOD)|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)' \
new file mode 100644 --- /dev/null +++ b/tests/test-mknod.c @@ -0,0 +1,62 @@ +/* Tests of mknod. + 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-mknod.t" + +#include "test-mkfifo.h" + +/* Wrapper around mknod, to create fifos. */ +static int +do_mknod (char const *name, mode_t mode) +{ + return mknod (name, mode | S_IFIFO, 0); +} + +int +main (void) +{ + /* Remove any leftovers from a previous partial run. */ + ASSERT (system ("rm -rf " BASE "*") == 0); + + /* We can only portably test creation of fifos. Anything else + requires root privileges and knowledge of device numbers. */ + return test_mkfifo (do_mknod, true); +}