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:
parent
42f41d868a
commit
c9d4e0fb8c
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user