From 2f45acc353ef4116714ea582434c7a8318e3e486 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Wed, 30 Sep 2009 21:57:58 -0600 Subject: [PATCH] rename: fix Solaris 10 bug rename("file","name/") mistakenly succeeded. But since Solaris 10 already obeys POSIX behavior on rename("link/","name"), we avoid blindly forcing GNU behavior of rejecting symlinks with trailing slash. * m4/rename.m4 (gl_FUNC_RENAME): Detect Solaris bug. * lib/rename.c (rpl_rename): Don't cripple POSIX behavior if this was the only bug. Signed-off-by: Eric Blake --- ChangeLog | 5 +++++ lib/rename.c | 28 ++++++++++++++++++++++------ m4/rename.m4 | 32 ++++++++++++++++++++++++++++++-- 3 files changed, 57 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4b78fa0d0c..8c38c9c5b7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2009-10-02 Eric Blake + rename: fix Solaris 10 bug + * m4/rename.m4 (gl_FUNC_RENAME): Detect Solaris bug. + * lib/rename.c (rpl_rename): Don't cripple POSIX behavior if this + was the only bug. + rename: fix Solaris 9 bug * lib/rename.c (rpl_rename): Rewrite to recognize trailing slash on non-directory. Avoid calling exit. diff --git a/lib/rename.c b/lib/rename.c index 0709759841..22310be330 100644 --- a/lib/rename.c +++ b/lib/rename.c @@ -136,7 +136,7 @@ rpl_rename (char const *src, char const *dst) # if RENAME_DEST_EXISTS_BUG # error Please report your platform and this message to bug-gnulib@gnu.org. -# elif RENAME_TRAILING_SLASH_BUG +# elif RENAME_TRAILING_SLASH_SOURCE_BUG || RENAME_TRAILING_SLASH_DEST_BUG # include # include @@ -192,10 +192,24 @@ rpl_rename (char const *src, char const *dst) return -1; } - /* If stripping the trailing slashes changes from a directory to a - symlink, follow the GNU behavior of rejecting the rename. - Technically, we could follow the POSIX behavior by chasing a - readlink trail, but that is counter-intuitive and harder. */ +# if RENAME_TRAILING_SLASH_SOURCE_BUG + /* If the only bug was that a trailing slash was allowed on a + non-existing file destination, as in Solaris 10, then we've + already covered that situation. But if there is any problem with + a trailing slash on an existing source or destination, as in + Solaris 9, then we must strip the offending slash and check that + we have not encountered a symlink instead of a directory. + + Stripping a trailing slash interferes with POSIX semantics, where + rename behavior on a symlink with a trailing slash operates on + the corresponding target directory. We prefer the GNU semantics + of rejecting any use of a symlink with trailing slash, but do not + enforce them, since Solaris 10 is able to obey POSIX semantics + and there might be clients expecting it, as counter-intuitive as + those semantics are. + + Technically, we could also follow the POSIX behavior by chasing a + readlink trail, but that is harder to implement. */ if (src_slash) { src_temp = strdup (src); @@ -234,6 +248,8 @@ rpl_rename (char const *src, char const *dst) else if (S_ISLNK (dst_st.st_mode)) goto out; } +# endif /* RENAME_TRAILING_SLASH_SOURCE_BUG */ + ret_val = rename (src_temp, dst_temp); rename_errno = errno; out: @@ -244,5 +260,5 @@ rpl_rename (char const *src, char const *dst) errno = rename_errno; return ret_val; } -# endif /* RENAME_TRAILING_SLASH_BUG */ +# endif /* RENAME_TRAILING_SLASH_*_BUG */ #endif /* ! W32 platform */ diff --git a/m4/rename.m4 b/m4/rename.m4 index 2c0d5e86f0..04921faf58 100644 --- a/m4/rename.m4 +++ b/m4/rename.m4 @@ -1,4 +1,4 @@ -# serial 16 +# serial 17 # Copyright (C) 2001, 2003, 2005, 2006, 2009 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation @@ -18,8 +18,36 @@ AC_DEFUN([gl_FUNC_RENAME], AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([gl_STDIO_H_DEFAULTS]) + dnl Solaris 10 mistakenly allows rename("file","name/"). + dnl This particular condition can be worked around without stripping + dnl trailing slash. + AC_CACHE_CHECK([whether rename honors trailing slash on destination], + [gl_cv_func_rename_slash_dst_works], + [rm -rf conftest.f conftest.f1 + touch conftest.f || + AC_MSG_ERROR([cannot create temporary files]) + AC_RUN_IFELSE([AC_LANG_PROGRAM([[ +# include +# include +]], [return !rename ("conftest.f", "conftest.f1/");])], + [gl_cv_func_rename_slash_dst_works=yes], + [gl_cv_func_rename_slash_dst_works=no], + dnl When crosscompiling, assume rename is broken. + [gl_cv_func_rename_slash_dst_works="guessing no"]) + rm -rf conftest.f conftest.f1 + ]) + if test "x$gl_cv_func_rename_slash_dst_works" != xyes; then + AC_LIBOBJ([rename]) + REPLACE_RENAME=1 + AC_DEFINE([RENAME_TRAILING_SLASH_DEST_BUG], [1], + [Define if rename does not correctly handle slashes on the destination + argument, such as on Solaris 10.]) + fi + dnl SunOS 4.1.1_U1 mistakenly forbids rename("dir/","name"). dnl Solaris 9 mistakenly allows rename("file/","name"). + dnl These bugs require stripping trailing slash to avoid corrupting + dnl symlinks with a trailing slash. AC_CACHE_CHECK([whether rename honors trailing slash on source], [gl_cv_func_rename_slash_src_works], [rm -rf conftest.f conftest.d1 conftest.d2 @@ -39,7 +67,7 @@ AC_DEFUN([gl_FUNC_RENAME], if test "x$gl_cv_func_rename_slash_src_works" != xyes; then AC_LIBOBJ([rename]) REPLACE_RENAME=1 - AC_DEFINE([RENAME_TRAILING_SLASH_BUG], [1], + AC_DEFINE([RENAME_TRAILING_SLASH_SOURCE_BUG], [1], [Define if rename does not correctly handle slashes on the source argument, such as on Solaris 9 or cygwin 1.5.]) fi -- 2.30.2