Mercurial > hg > octave-lojdl > gnulib-hg
changeset 12268:b537cb58d506
mkfifoat: use new modules for Solaris and BSD bugs
Pick up Solaris 9 and BSD fixes to mkfifo and mknod. No known
system has mknodat but broken mknod, so there is no need for
rpl_mkfifoat or rpl_mknodat. Split mknodat into its own file.
* m4/mkfifoat.m4 (gl_FUNC_MKFIFOAT): Simplify.
* lib/mkfifoat.c (mknodat): Split...
* lib/mknodat.c (mknodat): ...into new file.
* modules/mkfifoat (Files): Ship new file.
(Depends-on): Add mkfifo, mknod.
* modules/mkfifoat-tests (Files): Reuse mkfifo tests.
(Depends-on): Add symlink.
* tests/test-mkfifoat.c (main): Enhance test. Drop portions now
redundant with test_mkfifo.h.
(do_mkfifoat, do_mknodat): New helpers.
Signed-off-by: Eric Blake <ebb9@byu.net>
author | Eric Blake <ebb9@byu.net> |
---|---|
date | Wed, 11 Nov 2009 14:22:44 -0700 |
parents | c400da5f66bb |
children | 4758cd4c9683 |
files | ChangeLog lib/mkfifoat.c lib/mknodat.c m4/mkfifoat.m4 modules/mkfifoat modules/mkfifoat-tests tests/test-mkfifoat.c |
diffstat | 7 files changed, 129 insertions(+), 90 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,17 @@ 2009-11-11 Eric Blake <ebb9@byu.net> + mkfifoat: use new modules for Solaris and BSD bugs + * m4/mkfifoat.m4 (gl_FUNC_MKFIFOAT): Simplify. + * lib/mkfifoat.c (mknodat): Split... + * lib/mknodat.c (mknodat): ...into new file. + * modules/mkfifoat (Files): Ship new file. + (Depends-on): Add mkfifo, mknod. + * modules/mkfifoat-tests (Files): Reuse mkfifo tests. + (Depends-on): Add symlink. + * tests/test-mkfifoat.c (main): Enhance test. Drop portions now + redundant with test_mkfifo.h. + (do_mkfifoat, do_mknodat): New helpers. + mknod: new module * modules/mknod: New file. * m4/mknod.m4 (gl_FUNC_MKNOD): Likewise.
--- a/lib/mkfifoat.c +++ b/lib/mkfifoat.c @@ -20,38 +20,15 @@ #include <sys/stat.h> -#ifndef HAVE_MKFIFO -# define HAVE_MKFIFO 0 -#endif -#ifndef HAVE_MKNOD -# define HAVE_MKNOD 0 -#endif - -/* For now, all known systems either have both mkfifo and mknod, or - neither. If this is not true, we can implement the portable - aspects of one using the other (POSIX only requires mknod to create - fifos; all other uses of mknod are for root users and outside the - realm of POSIX). */ -#if HAVE_MKNOD != HAVE_MKFIFO -# error Please report this message and your system to bug-gnulib@gnu.org. -#endif - #if !HAVE_MKFIFO -/* Mingw lacks mkfifo and mknod, so this wrapper is trivial. */ # include <errno.h> +/* Mingw lacks mkfifo, so this wrapper is trivial. */ + int mkfifoat (int fd _UNUSED_PARAMETER_, char const *path _UNUSED_PARAMETER_, - mode_t mode _UNUSED_PARAMETER_) -{ - errno = ENOSYS; - return -1; -} - -int -mknodat (int fd _UNUSED_PARAMETER_, char const *path _UNUSED_PARAMETER_, - mode_t mode _UNUSED_PARAMETER_, dev_t dev _UNUSED_PARAMETER_) + mode_t mode _UNUSED_PARAMETER_) { errno = ENOSYS; return -1; @@ -75,22 +52,4 @@ # undef AT_FUNC_POST_FILE_PARAM_DECLS # undef AT_FUNC_POST_FILE_ARGS -/* Create a file system node FILE relative to directory FD, with - access permissions and file type in MODE, and device type in DEV. - Usually, non-root applications can only create named fifos, with - DEV set to 0. If possible, create the node without changing the - working directory. Otherwise, resort to using save_cwd/fchdir, - then mknod/restore_cwd. If either the save_cwd or the restore_cwd - fails, then give a diagnostic and exit nonzero. */ - -# define AT_FUNC_NAME mknodat -# define AT_FUNC_F1 mknod -# define AT_FUNC_POST_FILE_PARAM_DECLS , mode_t mode, dev_t dev -# define AT_FUNC_POST_FILE_ARGS , mode, dev -# include "at-func.c" -# undef AT_FUNC_NAME -# undef AT_FUNC_F1 -# undef AT_FUNC_POST_FILE_PARAM_DECLS -# undef AT_FUNC_POST_FILE_ARGS - #endif /* HAVE_MKFIFO */
new file mode 100644 --- /dev/null +++ b/lib/mknodat.c @@ -0,0 +1,57 @@ +/* Create an inode relative to an open directory. + 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> + +#if !HAVE_MKNOD + +# include <errno.h> + +/* Mingw lacks mknod, so this wrapper is trivial. */ + +int +mknodat (int fd _UNUSED_PARAMETER_, char const *path _UNUSED_PARAMETER_, + mode_t mode _UNUSED_PARAMETER_, dev_t dev _UNUSED_PARAMETER_) +{ + errno = ENOSYS; + return -1; +} + +#else /* HAVE_MKFIFO */ + +/* Create a file system node FILE relative to directory FD, with + access permissions and file type in MODE, and device type in DEV. + Usually, non-root applications can only create named fifos, with + DEV set to 0. If possible, create the node without changing the + working directory. Otherwise, resort to using save_cwd/fchdir, + then mknod/restore_cwd. If either the save_cwd or the restore_cwd + fails, then give a diagnostic and exit nonzero. */ + +# define AT_FUNC_NAME mknodat +# define AT_FUNC_F1 mknod +# define AT_FUNC_POST_FILE_PARAM_DECLS , mode_t mode, dev_t dev +# define AT_FUNC_POST_FILE_ARGS , mode, dev +# include "at-func.c" +# undef AT_FUNC_NAME +# undef AT_FUNC_F1 +# undef AT_FUNC_POST_FILE_PARAM_DECLS +# undef AT_FUNC_POST_FILE_ARGS + +#endif /* HAVE_MKFIFO */
--- a/m4/mkfifoat.m4 +++ b/m4/mkfifoat.m4 @@ -1,4 +1,4 @@ -# serial 1 +# serial 2 # See if we need to provide mkfifoat/mknodat replacement. dnl Copyright (C) 2009 Free Software Foundation, Inc. @@ -13,11 +13,12 @@ AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS]) AC_REQUIRE([gl_FUNC_OPENAT]) AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) - AC_CHECK_FUNCS_ONCE([mkfifo mknod mkfifoat mknodat]) + AC_CHECK_FUNCS_ONCE([mkfifoat mknodat]) if test $ac_cv_func_mkfifoat = no; then # No known system has mkfifoat but not mknodat HAVE_MKFIFOAT=0 HAVE_MKNODAT=0 AC_LIBOBJ([mkfifoat]) + AC_LIBOBJ([mknodat]) fi ])
--- a/modules/mkfifoat +++ b/modules/mkfifoat @@ -3,11 +3,14 @@ Files: lib/mkfifoat.c +lib/mknodat.c m4/mkfifoat.m4 Depends-on: extensions fcntl-h +mkfifo +mknod openat sys_stat
--- a/modules/mkfifoat-tests +++ b/modules/mkfifoat-tests @@ -1,7 +1,9 @@ Files: +tests/test-mkfifo.h tests/test-mkfifoat.c Depends-on: +symlink configure.ac:
--- a/tests/test-mkfifoat.c +++ b/tests/test-mkfifoat.c @@ -22,6 +22,7 @@ #include <fcntl.h> #include <errno.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -31,17 +32,23 @@ do \ { \ if (!(expr)) \ - { \ - fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \ - fflush (stderr); \ - abort (); \ - } \ + { \ + fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \ + fflush (stderr); \ + abort (); \ + } \ } \ while (0) +#define BASE "test-mkfifoat.t" + +#include "test-mkfifo.h" + typedef int (*test_func) (int, char const *, mode_t); -/* Wrapper to make testing mknodat easier. */ +static int dfd = AT_FDCWD; + +/* Wrapper to test mknodat like mkfifoat. */ static int test_mknodat (int fd, char const *name, mode_t mode) { @@ -49,73 +56,71 @@ return mknodat (fd, name, mode | S_IFIFO, 0); } +/* Wrapper to test mkfifoat like mkfifo. */ +static int +do_mkfifoat (char const *name, mode_t mode) +{ + return mkfifoat (dfd, name, mode); +} + +/* Wrapper to test mknodat like mkfifo. */ +static int +do_mknodat (char const *name, mode_t mode) +{ + return mknodat (dfd, name, mode | S_IFIFO, 0); +} + int main (void) { int i; test_func funcs[2] = { mkfifoat, test_mknodat }; - const char *fifo = "test-mkfifoat.fifo"; + int result; - /* Create handle for future use. */ - int dfd = openat (AT_FDCWD, ".", O_RDONLY); - ASSERT (0 <= dfd); + /* Remove any leftovers from a previous partial run. */ + ASSERT (system ("rm -rf " BASE "*") == 0); -#if !HAVE_MKFIFO - fputs ("skipping test: no support for named fifos\n", stderr); - return 77; -#endif + /* Basic tests. */ + result = test_mkfifo (do_mkfifoat, true); + ASSERT (test_mkfifo (do_mknodat, false) == result); + dfd = open (".", O_RDONLY); + ASSERT (0 <= dfd); + ASSERT (test_mkfifo (do_mkfifoat, false) == result); + ASSERT (test_mkfifo (do_mknodat, false) == result); - /* Clean up anything from previous incomplete test. */ - remove (fifo); - - /* Test both functions. */ + /* Test directory-relative handling of both functions. */ for (i = 0; i < 2; i++) { struct stat st; test_func func = funcs[i]; - /* Sanity checks of failures. */ - errno = 0; - ASSERT (func (AT_FDCWD, "", 0600) == -1); - ASSERT (errno == ENOENT); - errno = 0; - ASSERT (func (dfd, "", S_IRUSR | S_IWUSR) == -1); - ASSERT (errno == ENOENT); + /* Create fifo while cwd is '.', then stat it from '..'. */ + ASSERT (func (AT_FDCWD, BASE "fifo", 0600) == 0); errno = 0; - ASSERT (func (AT_FDCWD, ".", 0600) == -1); - /* POSIX requires EEXIST, but Solaris gives EINVAL. */ - ASSERT (errno == EEXIST || errno == EINVAL); - errno = 0; - ASSERT (func (dfd, ".", 0600) == -1); - ASSERT (errno == EEXIST || errno == EINVAL); - - /* Create fifo while cwd is '.', then stat it from '..'. */ - ASSERT (func (AT_FDCWD, fifo, 0600) == 0); - errno = 0; - ASSERT (func (dfd, fifo, 0600) == -1); + ASSERT (func (dfd, BASE "fifo", 0600) == -1); ASSERT (errno == EEXIST); ASSERT (chdir ("..") == 0); errno = 0; - ASSERT (fstatat (AT_FDCWD, fifo, &st, 0) == -1); + ASSERT (fstatat (AT_FDCWD, BASE "fifo", &st, 0) == -1); ASSERT (errno == ENOENT); memset (&st, 0, sizeof st); - ASSERT (fstatat (dfd, fifo, &st, 0) == 0); + ASSERT (fstatat (dfd, BASE "fifo", &st, 0) == 0); ASSERT (S_ISFIFO (st.st_mode)); - ASSERT (unlinkat (dfd, fifo, 0) == 0); + ASSERT (unlinkat (dfd, BASE "fifo", 0) == 0); /* Create fifo while cwd is '..', then stat it from '.'. */ - ASSERT (func (dfd, fifo, 0600) == 0); + ASSERT (func (dfd, BASE "fifo", 0600) == 0); ASSERT (fchdir (dfd) == 0); errno = 0; - ASSERT (func (AT_FDCWD, fifo, 0600) == -1); + ASSERT (func (AT_FDCWD, BASE "fifo", 0600) == -1); ASSERT (errno == EEXIST); memset (&st, 0, sizeof st); - ASSERT (fstatat (AT_FDCWD, fifo, &st, AT_SYMLINK_NOFOLLOW) == 0); + ASSERT (fstatat (AT_FDCWD, BASE "fifo", &st, AT_SYMLINK_NOFOLLOW) == 0); ASSERT (S_ISFIFO (st.st_mode)); memset (&st, 0, sizeof st); - ASSERT (fstatat (dfd, fifo, &st, AT_SYMLINK_NOFOLLOW) == 0); + ASSERT (fstatat (dfd, BASE "fifo", &st, AT_SYMLINK_NOFOLLOW) == 0); ASSERT (S_ISFIFO (st.st_mode)); - ASSERT (unlink (fifo) == 0); + ASSERT (unlink (BASE "fifo") == 0); } ASSERT (close (dfd) == 0);