>From f120c3d08c0d8c2d0a743bf08dd876949f0edb75 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Tue, 5 Jan 2021 04:48:20 +0100 Subject: [PATCH 2/2] mkfifoat: Work around trailing slash bug in mknodat() on AIX 7.2. * m4/mkfifoat.m4 (gl_FUNC_MKFIFOAT): Set also REPLACE_MKNODAT. * lib/sys_stat.in.h (mknodat): Consider REPLACE_MKNODAT. * lib/mknodat.c: Add an overriding implementation of mknodat(). * m4/sys_stat_h.m4 (gl_SYS_STAT_H_DEFAULTS): Initialize REPLACE_MKNODAT. * modules/sys_stat (Makefile.am): Substitute REPLACE_MKNODAT. * modules/mkfifoat (Depends-on, configure.ac): Consider REPLACE_MKNODAT. * doc/posix-functions/mknodat.texi: Mention the AIX bug. --- ChangeLog | 9 ++++++ doc/posix-functions/mknodat.texi | 4 +++ lib/mknodat.c | 60 ++++++++++++++++++++++++++++++++-------- lib/sys_stat.in.h | 16 +++++++++-- m4/mkfifoat.m4 | 8 ++++-- m4/sys_stat_h.m4 | 3 +- modules/mkfifoat | 4 +-- modules/sys_stat | 1 + 8 files changed, 87 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index d8c44de..a579efc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ 2021-01-04 Bruno Haible + mkfifoat: Work around trailing slash bug in mknodat() on AIX 7.2. + * m4/mkfifoat.m4 (gl_FUNC_MKFIFOAT): Set also REPLACE_MKNODAT. + * lib/sys_stat.in.h (mknodat): Consider REPLACE_MKNODAT. + * lib/mknodat.c: Add an overriding implementation of mknodat(). + * m4/sys_stat_h.m4 (gl_SYS_STAT_H_DEFAULTS): Initialize REPLACE_MKNODAT. + * modules/sys_stat (Makefile.am): Substitute REPLACE_MKNODAT. + * modules/mkfifoat (Depends-on, configure.ac): Consider REPLACE_MKNODAT. + * doc/posix-functions/mknodat.texi: Mention the AIX bug. + mkfifoat: Work around trailing slash bug in mkfifoat() on AIX 7.2. * m4/mkfifoat.m4 (gl_FUNC_MKFIFOAT): Add a test whether mkfifoat rejects trailing slashes. Set REPLACE_MKFIFOAT if not. diff --git a/doc/posix-functions/mknodat.texi b/doc/posix-functions/mknodat.texi index c98c648..0658ed3 100644 --- a/doc/posix-functions/mknodat.texi +++ b/doc/posix-functions/mknodat.texi @@ -12,6 +12,10 @@ Portability problems fixed by Gnulib: This function is missing on some platforms: glibc 2.3.6, Mac OS X 10.13, FreeBSD 6.0, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 5.1, HP-UX 11, IRIX 6.5, Solaris 10, Cygwin 1.5.x, mingw, MSVC 14, Android 4.4. But the replacement function is not safe to be used in libraries and is not multithread-safe. +@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: +AIX 7.2. @end itemize Portability problems not fixed by Gnulib: diff --git a/lib/mknodat.c b/lib/mknodat.c index 68ece60..6d0f677 100644 --- a/lib/mknodat.c +++ b/lib/mknodat.c @@ -23,9 +23,45 @@ #include -#if !HAVE_MKNOD +#if HAVE_MKNODAT # include +# include +# include + +int +rpl_mknodat (int fd, char const *file, mode_t mode, dev_t dev) +#undef mknodat +{ + /* Use the original mknodat(), but correct the trailing slash handling. */ + size_t len = strlen (file); + if (len && file[len - 1] == '/') + { + struct stat st; + + if (fstatat (fd, file, &st, AT_SYMLINK_NOFOLLOW) < 0) + { + if (errno == EOVERFLOW) + /* It's surely a file, not a directory. */ + errno = ENOTDIR; + } + else + { + /* It's a directory, otherwise fstatat() would have reported an error + ENOTDIR. */ + errno = EEXIST; + } + return -1; + } + + return mknodat (fd, file, mode, dev); +} + +#else + +# if !HAVE_MKNOD + +# include /* Mingw lacks mknod, so this wrapper is trivial. */ @@ -37,7 +73,7 @@ mknodat (int fd _GL_UNUSED, char const *path _GL_UNUSED, return -1; } -#else +# else /* Create a file system node FILE relative to directory FD, with access permissions and file type in MODE, and device type in DEV. @@ -47,14 +83,16 @@ mknodat (int fd _GL_UNUSED, char const *path _GL_UNUSED, 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 +# 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 #endif diff --git a/lib/sys_stat.in.h b/lib/sys_stat.in.h index 936f2e4..283ed55 100644 --- a/lib/sys_stat.in.h +++ b/lib/sys_stat.in.h @@ -766,13 +766,25 @@ _GL_WARN_ON_USE (mknod, "mknod is not portable - " #if @GNULIB_MKNODAT@ -# if !@HAVE_MKNODAT@ +# if @REPLACE_MKNODAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mknodat +# define mknodat rpl_mknodat +# endif +_GL_FUNCDECL_RPL (mknodat, int, + (int fd, char const *file, mode_t mode, dev_t dev) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (mknodat, int, + (int fd, char const *file, mode_t mode, dev_t dev)); +# else +# if !@HAVE_MKNODAT@ _GL_FUNCDECL_SYS (mknodat, int, (int fd, char const *file, mode_t mode, dev_t dev) _GL_ARG_NONNULL ((2))); -# endif +# endif _GL_CXXALIAS_SYS (mknodat, int, (int fd, char const *file, mode_t mode, dev_t dev)); +# endif _GL_CXXALIASWARN (mknodat); #elif defined GNULIB_POSIXCHECK # undef mknodat diff --git a/m4/mkfifoat.m4 b/m4/mkfifoat.m4 index c4491ad..4daf4d8 100644 --- a/m4/mkfifoat.m4 +++ b/m4/mkfifoat.m4 @@ -1,4 +1,4 @@ -# serial 4 +# serial 5 # See if we need to provide mkfifoat/mknodat replacement. dnl Copyright (C) 2009-2021 Free Software Foundation, Inc. @@ -52,7 +52,11 @@ AC_DEFUN([gl_FUNC_MKFIFOAT], ]) case "$gl_cv_func_mkfifoat_works" in *yes) ;; - *) REPLACE_MKFIFOAT=1 ;; + *) + REPLACE_MKFIFOAT=1 + dnl mknodat() has the same bug as mkfifoat(). + REPLACE_MKNODAT=1 + ;; esac else # No known system has mkfifoat but not mknodat diff --git a/m4/sys_stat_h.m4 b/m4/sys_stat_h.m4 index 7852075..23cbdd2 100644 --- a/m4/sys_stat_h.m4 +++ b/m4/sys_stat_h.m4 @@ -1,4 +1,4 @@ -# sys_stat_h.m4 serial 37 -*- Autoconf -*- +# sys_stat_h.m4 serial 38 -*- Autoconf -*- dnl Copyright (C) 2006-2021 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -106,6 +106,7 @@ AC_DEFUN([gl_SYS_STAT_H_DEFAULTS], REPLACE_MKFIFO=0; AC_SUBST([REPLACE_MKFIFO]) REPLACE_MKFIFOAT=0; AC_SUBST([REPLACE_MKFIFOAT]) REPLACE_MKNOD=0; AC_SUBST([REPLACE_MKNOD]) + REPLACE_MKNODAT=0; AC_SUBST([REPLACE_MKNODAT]) REPLACE_STAT=0; AC_SUBST([REPLACE_STAT]) REPLACE_UTIMENSAT=0; AC_SUBST([REPLACE_UTIMENSAT]) ]) diff --git a/modules/mkfifoat b/modules/mkfifoat index f91d64c..b78efd3 100644 --- a/modules/mkfifoat +++ b/modules/mkfifoat @@ -11,7 +11,7 @@ m4/mkfifoat.m4 Depends-on: sys_stat extensions -fstatat [test $REPLACE_MKFIFOAT = 1] +fstatat [test $REPLACE_MKFIFOAT = 1 || test $REPLACE_MKNODAT = 1] at-internal [test $HAVE_MKFIFOAT = 0 || test $HAVE_MKNODAT = 0] errno [test $HAVE_MKFIFOAT = 0 || test $HAVE_MKNODAT = 0] fchdir [test $HAVE_MKFIFOAT = 0 || test $HAVE_MKNODAT = 0] @@ -28,7 +28,7 @@ gl_FUNC_MKFIFOAT if test $HAVE_MKFIFOAT = 0 || test $REPLACE_MKFIFOAT = 1; then AC_LIBOBJ([mkfifoat]) fi -if test $HAVE_MKNODAT = 0; then +if test $HAVE_MKNODAT = 0 || test $REPLACE_MKNODAT = 1; then AC_LIBOBJ([mknodat]) fi gl_SYS_STAT_MODULE_INDICATOR([mkfifoat]) diff --git a/modules/sys_stat b/modules/sys_stat index 3da1272..2697197 100644 --- a/modules/sys_stat +++ b/modules/sys_stat @@ -75,6 +75,7 @@ sys/stat.h: sys_stat.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNU -e 's|@''REPLACE_MKFIFO''@|$(REPLACE_MKFIFO)|g' \ -e 's|@''REPLACE_MKFIFOAT''@|$(REPLACE_MKFIFOAT)|g' \ -e 's|@''REPLACE_MKNOD''@|$(REPLACE_MKNOD)|g' \ + -e 's|@''REPLACE_MKNODAT''@|$(REPLACE_MKNODAT)|g' \ -e 's|@''REPLACE_STAT''@|$(REPLACE_STAT)|g' \ -e 's|@''REPLACE_UTIMENSAT''@|$(REPLACE_UTIMENSAT)|g' \ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ -- 2.7.4