Hi, The documented open() bug on Solaris [7-9] and HP-UX 11.00 exists also as a bug in fopen(). I'm applying this to fix it:
2008-08-30 Bruno Haible <[EMAIL PROTECTED]> * m4/fopen.m4 (gl_FUNC_FOPEN): Test against bug with trailing slash. Code copied from m4/open.m4. * lib/fopen.c (rpl_fopen): Return NULL if the mode specifies write access and the filename ends in a slash. Code copied from lib/open.c. * doc/posix-functions/fopen.texi: Document bug with trailing slash. * tests/test-fopen.c (main): Check against bug with trailing slash. *** doc/posix-functions/fopen.texi.orig 2008-08-30 14:37:20.000000000 +0200 --- doc/posix-functions/fopen.texi 2008-08-30 14:18:12.000000000 +0200 *************** *** 9,14 **** --- 9,18 ---- Portability problems fixed by Gnulib: @itemize @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: + HP-UX 11.00, Solaris 9. + @item On Windows platforms (excluding Cygwin), this function does usually not recognize the @file{/dev/null} filename. @end itemize *** lib/fopen.c.orig 2008-08-30 14:37:20.000000000 +0200 --- lib/fopen.c 2008-08-30 14:25:06.000000000 +0200 *************** *** 1,5 **** /* Open a stream to a file. ! Copyright (C) 2007 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 --- 1,5 ---- /* Open a stream to a file. ! Copyright (C) 2007-2008 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 *************** *** 21,32 **** --- 21,61 ---- /* Specification. */ #include <stdio.h> + #include <errno.h> #include <string.h> FILE * rpl_fopen (const char *filename, const char *mode) #undef fopen { + #if FOPEN_TRAILING_SLASH_BUG + /* If the filename ends in a slash and a mode that requires write access is + specified, 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." + If the named file already exists as a directory, then if a mode that + requires write access is specified, fopen() must fail because POSIX + <http://www.opengroup.org/susv3/functions/fopen.html> says that it + fails with errno = EISDIR in this case. + If the named file does not exist or does not name a directory, then + fopen() must fail since the file does not contain a '.' directory. */ + if (mode[0] == 'w' || mode[0] == 'a') + { + size_t len = strlen (filename); + if (len > 0 && filename[len - 1] == '/') + { + errno = EISDIR; + return NULL; + } + } + #endif + #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ if (strcmp (filename, "/dev/null") == 0) filename = "NUL"; *** m4/fopen.m4.orig 2008-08-30 14:37:20.000000000 +0200 --- m4/fopen.m4 2008-08-30 14:17:43.000000000 +0200 *************** *** 1,5 **** ! # fopen.m4 serial 1 ! dnl Copyright (C) 2007 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. --- 1,5 ---- ! # fopen.m4 serial 2 ! dnl Copyright (C) 2007-2008 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. *************** *** 13,17 **** --- 13,50 ---- REPLACE_FOPEN=1 AC_LIBOBJ([fopen]) ;; + *) + dnl fopen("foo/", "w") should not create a file when the file name has a + dnl trailing slash. + AC_CACHE_CHECK([whether fopen recognizes a trailing slash], + [gl_cv_func_fopen_slash], + [ + AC_TRY_RUN([ + #include <stddef.h> + #include <stdio.h> + int main () + { + return fopen ("conftest.sl/", "w") != NULL; + }], [gl_cv_func_fopen_slash=yes], [gl_cv_func_fopen_slash=no], + [ + changequote(,)dnl + case "$host_os" in + solaris2.[0-9]*) gl_cv_func_fopen_slash="guessing no" ;; + hpux*) gl_cv_func_fopen_slash="guessing no" ;; + *) gl_cv_func_fopen_slash="guessing yes" ;; + esac + changequote([,])dnl + ]) + rm -f conftest.sl + ]) + case "$gl_cv_func_fopen_slash" in + *no) + AC_DEFINE([FOPEN_TRAILING_SLASH_BUG], 1, + [Define to 1 if fopen() fails to recognize a trailing slash.]) + REPLACE_FOPEN=1 + AC_LIBOBJ([fopen]) + ;; + esac + ;; esac ]) *** tests/test-fopen.c.orig 2008-08-30 14:37:20.000000000 +0200 --- tests/test-fopen.c 2008-08-30 14:33:10.000000000 +0200 *************** *** 36,41 **** --- 36,43 ---- int main () { + ASSERT (fopen ("nonexist.ent/", "w") == NULL); + ASSERT (fopen ("/dev/null", "r") != NULL); return 0;