Mercurial > hg > octave-lyh > gnulib-hg
changeset 11478:df9a59a3f8bc
Make rename replace existing destinations on Windows.
author | Ben Pfaff <blp@cs.stanford.edu> |
---|---|
date | Tue, 07 Apr 2009 20:41:15 -0700 |
parents | 63b291ae83b6 |
children | 2e168b9fc9aa |
files | ChangeLog doc/posix-functions/rename.texi lib/rename.c m4/rename.m4 |
diffstat | 4 files changed, 151 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2009-03-20 Ben Pfaff <blp@gnu.org> + + Make rename replace existing destinations on Windows. + * m4/rename.m4: Add test for Mingw. + * lib/rename.c: Add rename replacement that uses MoveFileEx with + MOVEFILE_REPLACE_EXISTING to replace existing destination files. + * doc/posix-functions/rename.texi: Document. + 2009-04-10 Bruno Haible <bruno@clisp.org> New include file "iconveh.h".
--- a/doc/posix-functions/rename.texi +++ b/doc/posix-functions/rename.texi @@ -12,8 +12,15 @@ This function does not work when the source file name ends in a slash on some platforms: SunOS 4.1. +@item +This function will not replace an existing destination on some +platforms: +mingw. @end itemize Portability problems not fixed by Gnulib: @itemize +This function will not replace a destination that is currently opened +by any process: +mingw. @end itemize
--- a/lib/rename.c +++ b/lib/rename.c @@ -1,8 +1,9 @@ -/* Work around the bug in some systems whereby rename fails when the source - file has a trailing slash. The rename functions of SunOS 4.1.1_U1 and - mips-dec-ultrix4.4 have this bug. +/* 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 Free Software Foundation, Inc. + 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 @@ -22,6 +23,113 @@ #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> @@ -54,3 +162,4 @@ return ret_val; } +#endif /* RENAME_TRAILING_SLASH_BUG */
--- a/m4/rename.m4 +++ b/m4/rename.m4 @@ -1,4 +1,4 @@ -# serial 11 +# serial 12 # Copyright (C) 2001, 2003, 2005, 2006, 2009 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation @@ -15,7 +15,8 @@ AC_DEFUN([gl_FUNC_RENAME], [ - AC_CACHE_CHECK([whether rename is broken], + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_CACHE_CHECK([whether rename is broken with a trailing slash], gl_cv_func_rename_trailing_slash_bug, [ rm -rf conftest.d1 conftest.d2 @@ -37,13 +38,29 @@ rm -rf conftest.d1 conftest.d2 ]) - if test $gl_cv_func_rename_trailing_slash_bug = yes; then + AC_CACHE_CHECK([whether rename is broken when the destination exists], + gl_cv_func_rename_dest_exists_bug, + [ + case "$host_os" in + mingw*) gl_cv_func_rename_dest_exists_bug=yes ;; + *) gl_cv_func_rename_dest_exists_bug=no ;; + esac + ]) + if test $gl_cv_func_rename_trailing_slash_bug = yes || + test $gl_cv_func_rename_dest_exists_bug = yes; then AC_LIBOBJ([rename]) AC_DEFINE([rename], [rpl_rename], [Define to rpl_rename if the replacement function should be used.]) - AC_DEFINE([RENAME_TRAILING_SLASH_BUG], [1], - [Define if rename does not work for source file names with a trailing - slash, like the one from SunOS 4.1.1_U1.]) + if test $gl_cv_func_rename_trailing_slash_bug; then + AC_DEFINE([RENAME_TRAILING_SLASH_BUG], [1], + [Define if rename does not work for source file names with a trailing + slash, like the one from SunOS 4.1.1_U1.]) + fi + if test $gl_cv_func_rename_dest_exists_bug; then + AC_DEFINE([RENAME_DEST_EXISTS_BUG], [1], + [Define if rename does not work when the destination file exists, + as on Windows.]) + fi gl_PREREQ_RENAME fi ])