avoid a made-up OS error in rename-file-or-directory

On Unix and OS X, the check to avoid replacing an existing
file or directory is made by Racket, rather than the OS,
so don't claim a system error if the operation fails for
that reason.

Also, update the docs to clarify that the check is not
atomic with the move.

Closes issue #1158
This commit is contained in:
Matthew Flatt 2016-02-18 12:28:55 -07:00
parent 79fcdf4201
commit 0133954c84
2 changed files with 13 additions and 7 deletions

View File

@ -300,7 +300,8 @@ renamed successfully, the @exnraise[exn:fail:filesystem].
This procedure can be used to move a file/directory to a different This procedure can be used to move a file/directory to a different
directory (on the same filesystem) as well as rename a file/directory within directory (on the same filesystem) as well as rename a file/directory within
a directory. Unless @racket[exists-ok?] is provided as a true value, a directory. Unless @racket[exists-ok?] is provided as a true value,
@racket[new] cannot refer to an existing file or directory. Even if @racket[new] cannot refer to an existing file or directory, but the
check is not atomic with the rename operation on Unix and Mac OS X. Even if
@racket[exists-ok?] is true, @racket[new] cannot refer to an existing @racket[exists-ok?] is true, @racket[new] cannot refer to an existing
file when @racket[old] is a directory, and vice versa. file when @racket[old] is a directory, and vice versa.

View File

@ -4291,9 +4291,17 @@ static Scheme_Object *rename_file(int argc, Scheme_Object **argv)
# define MOVE_ERRNO_FORMAT "%E" # define MOVE_ERRNO_FORMAT "%E"
# else # else
if (!exists_ok && (scheme_file_exists(dest) || scheme_directory_exists(dest))) { if (!exists_ok && (scheme_file_exists(dest) || scheme_directory_exists(dest))) {
exists_ok = -1; /* We use a specialized error message here, because it's not
errno = EEXIST; a system error (e.g., setting `errno` to `EEXIST` would
goto failed; be a lie). */
scheme_raise_exn((exists_ok < 0) ? MZEXN_FAIL_FILESYSTEM_EXISTS : MZEXN_FAIL_FILESYSTEM,
"rename-file-or-directory: cannot rename file or directory;\n"
" the destination path already exists\n"
" source path: %q\n"
" dest path: %q",
filename_for_error(argv[0]),
filename_for_error(argv[1]));
return NULL;
} }
while (1) { while (1) {
@ -4305,9 +4313,6 @@ static Scheme_Object *rename_file(int argc, Scheme_Object **argv)
# define MOVE_ERRNO_FORMAT "%e" # define MOVE_ERRNO_FORMAT "%e"
# endif # endif
#ifndef DOS_FILE_SYSTEM
failed:
#endif
scheme_raise_exn((exists_ok < 0) ? MZEXN_FAIL_FILESYSTEM_EXISTS : MZEXN_FAIL_FILESYSTEM, scheme_raise_exn((exists_ok < 0) ? MZEXN_FAIL_FILESYSTEM_EXISTS : MZEXN_FAIL_FILESYSTEM,
"rename-file-or-directory: cannot rename file or directory\n" "rename-file-or-directory: cannot rename file or directory\n"
" source path: %q\n" " source path: %q\n"