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
This commit is contained in:
Matthew Flatt 2011-07-23 19:52:42 -06:00
parent 42f41d868a
commit c9d4e0fb8c
2 changed files with 38 additions and 11 deletions

View File

@ -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;
}
}
}

View File

@ -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;
}