| /* Work around rename bugs in some systems. On SunOS 4.1.1_U1 |
| and mips-dec-ultrix4.4, rename fails when the source file has |
| a trailing slash. On mingw, rename fails when the destination |
| exists. |
| |
| Copyright (C) 2001, 2002, 2003, 2005, 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 Volker Borchert */ |
| |
| #include <config.h> |
| #undef rename |
| |
| #if RENAME_DEST_EXISTS_BUG |
| /* This replacement must come first, otherwise when cross |
| * compiling to Windows we will guess that it has the trailing |
| * slash bug and entirely miss this one. */ |
| #include <errno.h> |
| |
| #define WIN32_LEAN_AND_MEAN |
| #include <windows.h> |
| |
| /* Rename the file SRC to DST. This replacement is necessary on |
| Windows, on which the system rename function will not replace |
| an existing DST. */ |
| int |
| rpl_rename (char const *src, char const *dst) |
| { |
| int error; |
| |
| /* MoveFileEx works if SRC is a directory without any flags, |
| but fails with MOVEFILE_REPLACE_EXISTING, so try without |
| flags first. */ |
| if (MoveFileEx (src, dst, 0)) |
| return 0; |
| |
| /* Retry with MOVEFILE_REPLACE_EXISTING if the move failed |
| * due to the destination already existing. */ |
| error = GetLastError (); |
| if (error == ERROR_FILE_EXISTS || error == ERROR_ALREADY_EXISTS) |
| { |
| if (MoveFileEx (src, dst, MOVEFILE_REPLACE_EXISTING)) |
| return 0; |
| |
| error = GetLastError (); |
| } |
| |
| switch (error) |
| { |
| case ERROR_FILE_NOT_FOUND: |
| case ERROR_PATH_NOT_FOUND: |
| case ERROR_BAD_PATHNAME: |
| case ERROR_DIRECTORY: |
| errno = ENOENT; |
| break; |
| |
| case ERROR_ACCESS_DENIED: |
| case ERROR_SHARING_VIOLATION: |
| errno = EACCES; |
| break; |
| |
| case ERROR_OUTOFMEMORY: |
| errno = ENOMEM; |
| break; |
| |
| case ERROR_CURRENT_DIRECTORY: |
| errno = EBUSY; |
| break; |
| |
| case ERROR_NOT_SAME_DEVICE: |
| errno = EXDEV; |
| break; |
| |
| case ERROR_WRITE_PROTECT: |
| errno = EROFS; |
| break; |
| |
| case ERROR_WRITE_FAULT: |
| case ERROR_READ_FAULT: |
| case ERROR_GEN_FAILURE: |
| errno = EIO; |
| break; |
| |
| case ERROR_HANDLE_DISK_FULL: |
| case ERROR_DISK_FULL: |
| case ERROR_DISK_TOO_FRAGMENTED: |
| errno = ENOSPC; |
| break; |
| |
| case ERROR_FILE_EXISTS: |
| case ERROR_ALREADY_EXISTS: |
| errno = EEXIST; |
| break; |
| |
| case ERROR_BUFFER_OVERFLOW: |
| case ERROR_FILENAME_EXCED_RANGE: |
| errno = ENAMETOOLONG; |
| break; |
| |
| case ERROR_INVALID_NAME: |
| case ERROR_DELETE_PENDING: |
| errno = EPERM; /* ? */ |
| break; |
| |
| #ifndef ERROR_FILE_TOO_LARGE |
| /* This value is documented but not defined in all versions of windows.h. */ |
| #define ERROR_FILE_TOO_LARGE 223 |
| #endif |
| case ERROR_FILE_TOO_LARGE: |
| errno = EFBIG; |
| break; |
| |
| default: |
| errno = EINVAL; |
| break; |
| } |
| |
| return -1; |
| } |
| #elif RENAME_TRAILING_SLASH_BUG |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include "dirname.h" |
| #include "xalloc.h" |
| |
| /* Rename the file SRC to DST, removing any trailing |
| slashes from SRC. Needed for SunOS 4.1.1_U1. */ |
| |
| int |
| rpl_rename (char const *src, char const *dst) |
| { |
| char *src_temp; |
| int ret_val; |
| size_t s_len = strlen (src); |
| |
| if (s_len && src[s_len - 1] == '/') |
| { |
| src_temp = xstrdup (src); |
| strip_trailing_slashes (src_temp); |
| } |
| else |
| src_temp = (char *) src; |
| |
| ret_val = rename (src_temp, dst); |
| |
| if (src_temp != src) |
| free (src_temp); |
| |
| return ret_val; |
| } |
| #endif /* RENAME_TRAILING_SLASH_BUG */ |