From c9d4e0fb8cb775288fbcdd0378d7306a38488c06 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Sat, 23 Jul 2011 19:52:42 -0600 Subject: [PATCH] win32: fix `copy-file' handling of file-exists error The specific error reported by CopyFileW doesn't seem to be documented. It's unclear whether Racket's old test for ERROR_EXISTS_ALREADY was the wrong choice (as opposed to ERROR_FILE_EXISTS) or whether some Windows versions use it; we test for both for now. Also, improve error reporting when an errno or GetLastError() value is available. Closes PR 12074 Merge to 5.1.2 --- src/racket/src/error.c | 27 ++++++++++++++++++++------- src/racket/src/file.c | 22 ++++++++++++++++++---- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/src/racket/src/error.c b/src/racket/src/error.c index dcae959205..4d2937ee08 100644 --- a/src/racket/src/error.c +++ b/src/racket/src/error.c @@ -202,12 +202,14 @@ Scheme_Config *scheme_init_error_escape_proc(Scheme_Config *config) %- = skip int %L = line number as intptr_t, -1 means no line - %e = error number for strerror() + %e = error number for strerror()/FormatMessage() %E = error number for platform-specific error string %Z = potential platform-specific error number; additional char* is either NULL or a specific error message %N = boolean then error number like %E (if boolean is 0) or error number for scheme_hostname_error() + %m = boolean then error number like %e, which + is used only if the boolean is 1 */ static intptr_t sch_vsprintf(char *s, intptr_t maxlen, const char *msg, va_list args, char **_s) @@ -259,6 +261,7 @@ static intptr_t sch_vsprintf(char *s, intptr_t maxlen, const char *msg, va_list ints[ip++] = mzVA_ARG(args, int); break; case 'N': + case 'm': ints[ip++] = mzVA_ARG(args, int); ints[ip++] = mzVA_ARG(args, int); break; @@ -389,14 +392,19 @@ static intptr_t sch_vsprintf(char *s, intptr_t maxlen, const char *msg, va_list } break; case 'e': + case 'm': case 'E': case 'Z': case 'N': { - int en, he; + int en, he, none = 0; char *es; - - if (type == 'N') { + + if (type == 'm') { + none = !ints[ip++]; + type = 'e'; + he = 0; + } else if (type == 'N') { he = ints[ip++]; type = 'E'; } else @@ -412,7 +420,7 @@ static intptr_t sch_vsprintf(char *s, intptr_t maxlen, const char *msg, va_list if (he) es = (char *)scheme_hostname_error(en); - if (en || es) { + if ((en || es) && !none) { #ifdef NO_STRERROR_AVAILABLE if (!es) es = "Unknown error"; @@ -443,8 +451,13 @@ static intptr_t sch_vsprintf(char *s, intptr_t maxlen, const char *msg, va_list sprintf((char *)t, "%s; errno=%d", es, en); tlen = strlen(t); } else { - t = "errno=?"; - tlen = 7; + if (none) { + t = ""; + tlen = 0; + } else { + t = "errno=?"; + tlen = 7; + } } } diff --git a/src/racket/src/file.c b/src/racket/src/file.c index 457a84c294..1d5aab7208 100644 --- a/src/racket/src/file.c +++ b/src/racket/src/file.c @@ -3835,7 +3835,7 @@ failed: static Scheme_Object *copy_file(int argc, Scheme_Object **argv) { char *src, *dest, *reason = NULL; - int pre_exists = 0; + int pre_exists = 0, has_err_val = 0, err_val = 0; Scheme_Object *bss, *bsd; if (!SCHEME_PATH_STRINGP(argv[0])) @@ -3886,12 +3886,16 @@ static Scheme_Object *copy_file(int argc, Scheme_Object **argv) s = fopen(src, "rb"); if (!s) { + err_val = errno; + has_err_val = 1; reason = "cannot open source file"; goto failed; } d = fopen(dest, "wb"); if (!d) { + err_val = errno; + has_err_val = 1; fclose(s); reason = "cannot open destination file"; goto failed; @@ -3917,6 +3921,8 @@ static Scheme_Object *copy_file(int argc, Scheme_Object **argv) else if (errno != EINTR) break; } + err_val = errno; + has_err_val = 0; reason = "cannot set destination's mode"; } else reason = "read or write failed"; @@ -3928,15 +3934,23 @@ static Scheme_Object *copy_file(int argc, Scheme_Object **argv) return scheme_void; reason = "copy failed"; - if (GetLastError() == ERROR_ALREADY_EXISTS) + err_val = GetLastError(); + if ((err_val == ERROR_FILE_EXISTS) + || (err_val == ERROR_ALREADY_EXISTS)) pre_exists = 1; + has_err_val = 1; #endif scheme_raise_exn(pre_exists ? MZEXN_FAIL_FILESYSTEM_EXISTS : MZEXN_FAIL_FILESYSTEM, - "copy-file: %s; cannot copy: %q to: %q", + "copy-file: %s; cannot copy: %q to: %q%s%m%s", reason, filename_for_error(argv[0]), - filename_for_error(argv[1])); + filename_for_error(argv[1]), + has_err_val ? " (" : "", + has_err_val, + err_val, + has_err_val ? ")" : ""); + return NULL; }