1 /* A rename wrapper to make tools like mv -- that would normally rely
2 on the underlying rename syscall -- work more consistently.
3 On at least NetBSD 1.6, `rename ("dir", "B/")' fails when B doesn't
4 exist, whereas it succeeds on Linux-2.6.x and Solaris 10. This wrapper
5 provides an interface for systems like the former so that the tools
6 (namely mv) relying on the rename syscall have more consistent
9 Copyright (C) 2006 Free Software Foundation, Inc.
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
25 /* written by Jim Meyering */
30 #include <sys/types.h>
42 has_trailing_slash (char const *file, size_t len)
44 /* Don't count "/" as having a trailing slash. */
48 char last = file[len - 1];
49 return ISSLASH (last);
52 /* This is a rename wrapper for systems where the rename syscall
53 works differently than desired when SRC is a directory and DST does
54 not exist but is specified with a trailing slash. On NetBSD 6.1,
55 rename fails in that case. On Linux and Solaris systems, it succeeds.
56 This wrapper makes it succeed on NetBSD by running the originally
57 requested rename, and if it fails due to the above scenario, calling
58 it again with DST's trailing slashes removed. */
60 rpl_rename_dest_slash (char const *src, char const *dst)
63 int ret_val = rename (src, dst);
64 if (ret_val == 0 || errno != ENOENT)
68 /* Fail now, unless SRC is a directory. */
70 if (lstat (src, &sb) != 0 || ! S_ISDIR (sb.st_mode))
74 /* Don't call rename again if there are no trailing slashes. */
76 if ( ! has_trailing_slash (dst, d_len))
81 dst_temp = xmemdup (dst, d_len + 1);
82 strip_trailing_slashes (dst_temp);
84 ret_val = rename (src, dst_temp);