From: Eric Blake Date: Sat, 26 Sep 2009 21:18:13 +0000 (-0600) Subject: rename-dest-slash: merge into rename module X-Git-Tag: v0.1~5391 X-Git-Url: http://erislabs.org.uk/gitweb/?a=commitdiff_plain;h=130023629006f4f08a04efa4a1564208ad8ed340;p=gnulib.git rename-dest-slash: merge into rename module Tested that NetBSD workaround still passes unit test. * modules/rename-dest-slash (Status): Mark obsolete. (Depends-on): Add rename. (Files): Let rename do it all. * m4/rename.m4 (gl_FUNC_RENAME): Also test for NetBSD bugs, subsuming the test from gl_FUNC_RENAME_TRAILING_DEST_SLASH... * m4/rename-dest-slash.m4: ...so this file can be deleted. * lib/rename-dest-slash.c (rpl_rename_dest_slash): Delete. * lib/rename.c (rpl_rename): Update comments. Signed-off-by: Eric Blake --- diff --git a/ChangeLog b/ChangeLog index 7a90694bc..717c6f38c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,15 @@ 2009-10-02 Eric Blake + rename-dest-slash: merge into rename module + * modules/rename-dest-slash (Status): Mark obsolete. + (Depends-on): Add rename. + (Files): Let rename do it all. + * m4/rename.m4 (gl_FUNC_RENAME): Also test for NetBSD bugs, + subsuming the test from gl_FUNC_RENAME_TRAILING_DEST_SLASH... + * m4/rename-dest-slash.m4: ...so this file can be deleted. + * lib/rename-dest-slash.c (rpl_rename_dest_slash): Delete. + * lib/rename.c (rpl_rename): Update comments. + rename: fix cygwin 1.5.x bugs * m4/rename.m4 (gl_FUNC_RENAME): Detect cygwin bugs. * lib/rename.c (rpl_rename): Work around them. diff --git a/lib/rename-dest-slash.c b/lib/rename-dest-slash.c deleted file mode 100644 index 2014fb1c4..000000000 --- a/lib/rename-dest-slash.c +++ /dev/null @@ -1,96 +0,0 @@ -/* A rename wrapper to make tools like mv -- that would normally rely - on the underlying rename syscall -- work more consistently. - On at least NetBSD 1.6, `rename ("dir", "B/")' fails when B doesn't - exist, whereas it succeeds on Linux-2.6.x and Solaris 10. This wrapper - provides an interface for systems like the former so that the tools - (namely mv) relying on the rename syscall have more consistent - semantics. - - Copyright (C) 2006, 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 . */ - -/* written by Jim Meyering */ - -#include -#undef rename - -#include -#include -#include - -#include -#include -#include - -#include "dirname.h" -#include "same-inode.h" -#include "xalloc.h" - -static bool -has_trailing_slash (char const *file) -{ - /* Don't count "/", "//", etc., as having a trailing slash. */ - bool has_non_slash = false; - bool ends_in_slash = false; - - for (file += FILE_SYSTEM_PREFIX_LEN (file); *file; file++) - { - ends_in_slash = ISSLASH (*file); - has_non_slash |= ~ ends_in_slash; - } - - return has_non_slash & ends_in_slash; -} - -/* This is a rename wrapper for systems where the rename syscall - works differently than desired when SRC is a directory and DST does - not exist but is specified with a trailing slash. On NetBSD 6.1, - rename fails in that case. On Linux and Solaris systems, it succeeds. - This wrapper makes it succeed on NetBSD by running the originally - requested rename, and if it fails due to the above scenario, calling - it again with DST's trailing slashes removed. */ -int -rpl_rename_dest_slash (char const *src, char const *dst) -{ - struct stat sb; - struct stat db; - int ret_val; - - if (lstat (src, &sb)) - return -1; - if (lstat (dst, &db) == 0 && SAME_INODE (sb, db)) - return 0; - - ret_val = rename (src, dst); - - if (ret_val != 0 && errno == ENOENT && has_trailing_slash (dst)) - { - int rename_errno = ENOENT; - - /* Fail now, unless SRC is a directory. */ - if (lstat (src, &sb) == 0 && S_ISDIR (sb.st_mode)) - { - char *dst_temp = xstrdup (dst); - strip_trailing_slashes (dst_temp); - ret_val = rename (src, dst_temp); - rename_errno = errno; - free (dst_temp); - } - - errno = rename_errno; - } - - return ret_val; -} diff --git a/lib/rename.c b/lib/rename.c index 68ea8e808..a59328e5d 100644 --- a/lib/rename.c +++ b/lib/rename.c @@ -228,8 +228,10 @@ rpl_rename (char const *src, char const *dst) already covered that situation. But if there is any problem with a trailing slash on an existing source or destination, as in Solaris 9, or if a directory can overwrite a symlink, as on - Cygwin 1.5, then we must strip the offending slash and check that - we have not encountered a symlink instead of a directory. + Cygwin 1.5, or if directories cannot be created with trailing + slash, as on NetBSD 1.6, 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 diff --git a/m4/rename-dest-slash.m4 b/m4/rename-dest-slash.m4 deleted file mode 100644 index 2ddbbcbbb..000000000 --- a/m4/rename-dest-slash.m4 +++ /dev/null @@ -1,41 +0,0 @@ -# serial 4 - -# Copyright (C) 2006, 2009 Free Software Foundation, Inc. -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# Derived from rename.m4. - -# A rename wrapper to make tools like mv -- that would normally -# rely on the underlying rename syscall -- work more consistently. - -AC_DEFUN([gl_FUNC_RENAME_TRAILING_DEST_SLASH], -[ - AC_CACHE_CHECK([whether rename is broken with respect to destination slashes], - gl_cv_func_rename_trailing_dest_slash_bug, - [ - rm -rf conftest.d1 conftest.d2 - mkdir conftest.d1 || - AC_MSG_ERROR([cannot create temporary directory]) - AC_RUN_IFELSE([AC_LANG_SOURCE([[ -# include - int - main () - { - return (rename ("conftest.d1", "conftest.d2/") ? 1 : 0); - } - ]])], - [gl_cv_func_rename_trailing_dest_slash_bug=no], - [gl_cv_func_rename_trailing_dest_slash_bug=yes], - dnl When crosscompiling, assume rename is broken. - [gl_cv_func_rename_trailing_dest_slash_bug=yes]) - - rm -rf conftest.d1 conftest.d2 - ]) - if test $gl_cv_func_rename_trailing_dest_slash_bug = yes; then - AC_LIBOBJ([rename-dest-slash]) - AC_DEFINE([rename], [rpl_rename_dest_slash], - [Define to rpl_rename_dest_slash if the replacement function should be used.]) - fi -]) diff --git a/m4/rename.m4 b/m4/rename.m4 index c458f59c9..fc0d715b3 100644 --- a/m4/rename.m4 +++ b/m4/rename.m4 @@ -1,4 +1,4 @@ -# serial 18 +# serial 19 # Copyright (C) 2001, 2003, 2005, 2006, 2009 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation @@ -19,29 +19,33 @@ AC_DEFUN([gl_FUNC_RENAME], 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. + dnl NetBSD 1.6 mistakenly forbids rename("dir","name/"). + dnl The Solaris bug can be worked around without stripping + dnl trailing slash, while the NetBSD bug requires stripping; + dnl the two conditions can be distinguished by whether hard + dnl links are also broken. 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 || + [rm -rf conftest.f conftest.f1 conftest.d1 conftest.d2 + touch conftest.f && mkdir conftest.d1 || AC_MSG_ERROR([cannot create temporary files]) AC_RUN_IFELSE([AC_LANG_PROGRAM([[ # include # include -]], [return !rename ("conftest.f", "conftest.f1/");])], +]], [if (rename ("conftest.f", "conftest.f1/") == 0) return 1; + if (rename ("conftest.d1", "conftest.d2/") != 0) return 2;])], [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 + rm -rf conftest.f conftest.f1 conftest.d1 conftest.d2 ]) 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.]) + argument, such as on Solaris 10 or NetBSD 1.6.]) fi dnl SunOS 4.1.1_U1 mistakenly forbids rename("dir/","name"). @@ -72,6 +76,7 @@ AC_DEFUN([gl_FUNC_RENAME], argument, such as on Solaris 9 or cygwin 1.5.]) fi + dnl NetBSD 1.6 mistakenly reduces hard link count on rename("h1","h2"). dnl Cygwin 1.5.x mistakenly allows rename("dir","file"). dnl mingw mistakenly forbids rename("dir1","dir2"). dnl These bugs require stripping trailing slash to avoid corrupting @@ -81,15 +86,22 @@ AC_DEFUN([gl_FUNC_RENAME], [rm -rf conftest.f conftest.d1 conftest.d2 touch conftest.f && mkdir conftest.d1 conftest.d2 || AC_MSG_ERROR([cannot create temporary files]) - AC_RUN_IFELSE([AC_LANG_PROGRAM([[ + if ln conftest.f conftest.f1 && set x `ls -i conftest.f conftest.f1` && + test "$2" = "$4"; then + AC_RUN_IFELSE([AC_LANG_PROGRAM([[ # include # include ]], [if (rename ("conftest.d1", "conftest.d2") != 0) return 1; - if (rename ("conftest.d2", "conftest.f") == 0) return 2;])], - [gl_cv_func_rename_dest_works=yes], - [gl_cv_func_rename_dest_works=no], - dnl When crosscompiling, assume rename is broken. - [gl_cv_func_rename_dest_works="guessing no"]) + if (rename ("conftest.d2", "conftest.f") == 0) return 2; + if (rename ("conftest.f", "conftest.f1") + || rename ("conftest.f", "conftest.f")) return 3;])], + [gl_cv_func_rename_dest_works=yes], + [gl_cv_func_rename_dest_works=no], + dnl When crosscompiling, assume rename is broken. + [gl_cv_func_rename_dest_works="guessing no"]) + else + gl_cv_func_rename_dest_works="guessing no" + fi rm -rf conftest.f conftest.f1 conftest.d1 conftest.d2 ]) if test "x$gl_cv_func_rename_dest_works" != xyes; then @@ -97,6 +109,6 @@ AC_DEFUN([gl_FUNC_RENAME], REPLACE_RENAME=1 AC_DEFINE([RENAME_DEST_EXISTS_BUG], [1], [Define if rename does not work when the destination file exists, - as on Windows.]) + as with NetBSD 1.6 on hard links, or Windows on directories.]) fi ]) diff --git a/modules/rename-dest-slash b/modules/rename-dest-slash index c0bc98df4..f52b3b8d2 100644 --- a/modules/rename-dest-slash +++ b/modules/rename-dest-slash @@ -1,17 +1,18 @@ Description: rename() function: change the name or location of a file. +Status: +obsolete + +Notice: +This module is obsolete; use the rename module instead. + Files: -lib/rename-dest-slash.c -m4/rename-dest-slash.m4 Depends-on: -dirname -same-inode -xalloc +rename configure.ac: -gl_FUNC_RENAME_TRAILING_DEST_SLASH Makefile.am: