X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=lib%2Frename-dest-slash.c;h=80660768a10736a7e48c912bd4ad4dd526d06ead;hb=8ec8f4b42e39d3aaf2dda06c38b8db00efcc69f5;hp=2c73f06d23b242f54f64ec089a4e7f455754e22a;hpb=23ba046d0ad85ab6e288a70902c0e0589169ff65;p=gnulib.git diff --git a/lib/rename-dest-slash.c b/lib/rename-dest-slash.c index 2c73f06d2..80660768a 100644 --- a/lib/rename-dest-slash.c +++ b/lib/rename-dest-slash.c @@ -8,10 +8,10 @@ Copyright (C) 2006 Free Software Foundation, Inc. - This program is free software; you can redistribute it and/or modify + 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 2, or (at your option) - any later version. + 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 @@ -19,8 +19,7 @@ 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + along with this program. If not, see . */ /* written by Jim Meyering */ @@ -31,22 +30,27 @@ #include #include +#include #include #include -#include #include "dirname.h" #include "xalloc.h" -static inline bool -has_trailing_slash (char const *file, size_t len) +static bool +has_trailing_slash (char const *file) { - /* Don't count "/" as having a trailing slash. */ - if (len <= FILE_SYSTEM_PREFIX_LEN (file) + 1) - return false; + /* Don't count "/", "//", etc., as having a trailing slash. */ + bool has_non_slash = false; + bool ends_in_slash = false; - char last = file[len - 1]; - return ISSLASH (last); + 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 @@ -59,31 +63,25 @@ has_trailing_slash (char const *file, size_t len) int rpl_rename_dest_slash (char const *src, char const *dst) { - size_t d_len; int ret_val = rename (src, dst); - if (ret_val == 0 || errno != ENOENT) - return ret_val; - - /* Don't call rename again if there are no trailing slashes. */ - d_len = strlen (dst); - if ( ! has_trailing_slash (dst, d_len)) - return ret_val; - - { - /* Fail now, unless SRC is a directory. */ - struct stat sb; - if (lstat (src, &sb) != 0 || ! S_ISDIR (sb.st_mode)) - return ret_val; - } - - { - char *dst_temp; - dst_temp = xmemdup (dst, d_len + 1); - strip_trailing_slashes (dst_temp); - - ret_val = rename (src, dst_temp); - free (dst_temp); - } + + if (ret_val != 0 && errno == ENOENT && has_trailing_slash (dst)) + { + int rename_errno = ENOENT; + + /* Fail now, unless SRC is a directory. */ + struct stat sb; + 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; }