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
|
%- = skip int
|
||||||
|
|
||||||
%L = line number as intptr_t, -1 means no line
|
%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
|
%E = error number for platform-specific error string
|
||||||
%Z = potential platform-specific error number; additional char*
|
%Z = potential platform-specific error number; additional char*
|
||||||
is either NULL or a specific error message
|
is either NULL or a specific error message
|
||||||
%N = boolean then error number like %E (if boolean is 0)
|
%N = boolean then error number like %E (if boolean is 0)
|
||||||
or error number for scheme_hostname_error()
|
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)
|
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);
|
ints[ip++] = mzVA_ARG(args, int);
|
||||||
break;
|
break;
|
||||||
case 'N':
|
case 'N':
|
||||||
|
case 'm':
|
||||||
ints[ip++] = mzVA_ARG(args, int);
|
ints[ip++] = mzVA_ARG(args, int);
|
||||||
ints[ip++] = mzVA_ARG(args, int);
|
ints[ip++] = mzVA_ARG(args, int);
|
||||||
break;
|
break;
|
||||||
|
@ -389,14 +392,19 @@ static intptr_t sch_vsprintf(char *s, intptr_t maxlen, const char *msg, va_list
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
|
case 'm':
|
||||||
case 'E':
|
case 'E':
|
||||||
case 'Z':
|
case 'Z':
|
||||||
case 'N':
|
case 'N':
|
||||||
{
|
{
|
||||||
int en, he;
|
int en, he, none = 0;
|
||||||
char *es;
|
char *es;
|
||||||
|
|
||||||
if (type == 'N') {
|
if (type == 'm') {
|
||||||
|
none = !ints[ip++];
|
||||||
|
type = 'e';
|
||||||
|
he = 0;
|
||||||
|
} else if (type == 'N') {
|
||||||
he = ints[ip++];
|
he = ints[ip++];
|
||||||
type = 'E';
|
type = 'E';
|
||||||
} else
|
} else
|
||||||
|
@ -412,7 +420,7 @@ static intptr_t sch_vsprintf(char *s, intptr_t maxlen, const char *msg, va_list
|
||||||
if (he)
|
if (he)
|
||||||
es = (char *)scheme_hostname_error(en);
|
es = (char *)scheme_hostname_error(en);
|
||||||
|
|
||||||
if (en || es) {
|
if ((en || es) && !none) {
|
||||||
#ifdef NO_STRERROR_AVAILABLE
|
#ifdef NO_STRERROR_AVAILABLE
|
||||||
if (!es)
|
if (!es)
|
||||||
es = "Unknown error";
|
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);
|
sprintf((char *)t, "%s; errno=%d", es, en);
|
||||||
tlen = strlen(t);
|
tlen = strlen(t);
|
||||||
} else {
|
} else {
|
||||||
t = "errno=?";
|
if (none) {
|
||||||
tlen = 7;
|
t = "";
|
||||||
|
tlen = 0;
|
||||||
|
} else {
|
||||||
|
t = "errno=?";
|
||||||
|
tlen = 7;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3835,7 +3835,7 @@ failed:
|
||||||
static Scheme_Object *copy_file(int argc, Scheme_Object **argv)
|
static Scheme_Object *copy_file(int argc, Scheme_Object **argv)
|
||||||
{
|
{
|
||||||
char *src, *dest, *reason = NULL;
|
char *src, *dest, *reason = NULL;
|
||||||
int pre_exists = 0;
|
int pre_exists = 0, has_err_val = 0, err_val = 0;
|
||||||
Scheme_Object *bss, *bsd;
|
Scheme_Object *bss, *bsd;
|
||||||
|
|
||||||
if (!SCHEME_PATH_STRINGP(argv[0]))
|
if (!SCHEME_PATH_STRINGP(argv[0]))
|
||||||
|
@ -3886,12 +3886,16 @@ static Scheme_Object *copy_file(int argc, Scheme_Object **argv)
|
||||||
|
|
||||||
s = fopen(src, "rb");
|
s = fopen(src, "rb");
|
||||||
if (!s) {
|
if (!s) {
|
||||||
|
err_val = errno;
|
||||||
|
has_err_val = 1;
|
||||||
reason = "cannot open source file";
|
reason = "cannot open source file";
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
d = fopen(dest, "wb");
|
d = fopen(dest, "wb");
|
||||||
if (!d) {
|
if (!d) {
|
||||||
|
err_val = errno;
|
||||||
|
has_err_val = 1;
|
||||||
fclose(s);
|
fclose(s);
|
||||||
reason = "cannot open destination file";
|
reason = "cannot open destination file";
|
||||||
goto failed;
|
goto failed;
|
||||||
|
@ -3917,6 +3921,8 @@ static Scheme_Object *copy_file(int argc, Scheme_Object **argv)
|
||||||
else if (errno != EINTR)
|
else if (errno != EINTR)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
err_val = errno;
|
||||||
|
has_err_val = 0;
|
||||||
reason = "cannot set destination's mode";
|
reason = "cannot set destination's mode";
|
||||||
} else
|
} else
|
||||||
reason = "read or write failed";
|
reason = "read or write failed";
|
||||||
|
@ -3928,15 +3934,23 @@ static Scheme_Object *copy_file(int argc, Scheme_Object **argv)
|
||||||
return scheme_void;
|
return scheme_void;
|
||||||
|
|
||||||
reason = "copy failed";
|
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;
|
pre_exists = 1;
|
||||||
|
has_err_val = 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
scheme_raise_exn(pre_exists ? MZEXN_FAIL_FILESYSTEM_EXISTS : MZEXN_FAIL_FILESYSTEM,
|
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,
|
reason,
|
||||||
filename_for_error(argv[0]),
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user