changeset 12096:1f43035b0900

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 <ebb9@byu.net>
author Eric Blake <ebb9@byu.net>
date Sat, 26 Sep 2009 15:18:13 -0600
parents 724dd32f13f7
children bb32464985d7
files ChangeLog lib/rename-dest-slash.c lib/rename.c m4/rename-dest-slash.m4 m4/rename.m4 modules/rename-dest-slash
diffstat 6 files changed, 48 insertions(+), 160 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
 2009-10-02  Eric Blake  <ebb9@byu.net>
 
+	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.
deleted file mode 100644
--- 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 <http://www.gnu.org/licenses/>.  */
-
-/* written by Jim Meyering */
-
-#include <config.h>
-#undef rename
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#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;
-}
--- a/lib/rename.c
+++ b/lib/rename.c
@@ -228,8 +228,10 @@
      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
deleted file mode 100644
--- 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 <stdio.h>
-        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
-])
--- 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_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 <stdio.h>
 #       include <stdlib.h>
-]], [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 @@
        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 @@
     [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 <stdio.h>
 #       include <stdlib.h>
 ]], [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 @@
     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
 ])
--- 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: