windows: avoid SetFilePointer() on unsupported file-stream types

Closes PR 12339
This commit is contained in:
Matthew Flatt 2011-11-26 18:08:28 -07:00
parent 5adc74fdf0
commit 291a18b045

View File

@ -4992,12 +4992,22 @@ Scheme_Object *scheme_open_output_file_with_mode(const char *name, const char *w
return scheme_do_open_output_file((char *)who, 0, 3, a, 0, 0, NULL, NULL); return scheme_do_open_output_file((char *)who, 0, 3, a, 0, 0, NULL, NULL);
} }
#ifdef WINDOWS_FILE_HANDLES
static int win_seekable(int fd)
{
/* SetFilePointer() requires " a file stored on a seeking device".
I'm not sure how to test that, so we approximate as "regular
file". */
return GetFileType((HANDLE)fd) == FILE_TYPE_DISK;
}
#endif
Scheme_Object * Scheme_Object *
scheme_file_position(int argc, Scheme_Object *argv[]) scheme_file_position(int argc, Scheme_Object *argv[])
{ {
FILE *f; FILE *f;
Scheme_Indexed_String *is; Scheme_Indexed_String *is;
int fd; intptr_t fd;
#ifdef MZ_FDS #ifdef MZ_FDS
int had_fd; int had_fd;
#endif #endif
@ -5118,13 +5128,14 @@ scheme_file_position(int argc, Scheme_Object *argv[])
#ifdef MZ_FDS #ifdef MZ_FDS
} else if (had_fd) { } else if (had_fd) {
intptr_t lv; intptr_t lv;
int errid = 0;
if (!SCHEME_INPUT_PORTP(argv[0])) { if (!SCHEME_INPUT_PORTP(argv[0])) {
flush_fd(scheme_output_port_record(argv[0]), NULL, 0, 0, 0, 0); flush_fd(scheme_output_port_record(argv[0]), NULL, 0, 0, 0, 0);
} }
# ifdef WINDOWS_FILE_HANDLES # ifdef WINDOWS_FILE_HANDLES
{ if (win_seekable(fd)) {
DWORD r; DWORD r;
LONG lo_w, hi_w; LONG lo_w, hi_w;
lo_w = (LONG)(nll & 0xFFFFFFFF); lo_w = (LONG)(nll & 0xFFFFFFFF);
@ -5132,24 +5143,24 @@ scheme_file_position(int argc, Scheme_Object *argv[])
r = SetFilePointer((HANDLE)fd, lo_w, &hi_w, r = SetFilePointer((HANDLE)fd, lo_w, &hi_w,
((whence == SEEK_SET) ? FILE_BEGIN : FILE_END)); ((whence == SEEK_SET) ? FILE_BEGIN : FILE_END));
if ((r == INVALID_SET_FILE_POINTER) if ((r == INVALID_SET_FILE_POINTER)
&& GetLastError() != NO_ERROR) && GetLastError() != NO_ERROR) {
errid = GetLastError();
lv = -1; lv = -1;
else } else
lv = 0; lv = 0;
} else {
lv = -1;
errid = ERROR_UNSUPPORTED_TYPE;
} }
# else # else
lv = BIG_OFF_T_IZE(lseek)(fd, nll, whence); lv = BIG_OFF_T_IZE(lseek)(fd, nll, whence);
if (lv < 0) errid = errno;
# endif # endif
if (lv < 0) { if (lv < 0) {
# ifdef WINDOWS_FILE_HANDLES
int errid;
errid = GetLastError();
errno = errid;
# endif
scheme_raise_exn(MZEXN_FAIL_FILESYSTEM, scheme_raise_exn(MZEXN_FAIL_FILESYSTEM,
"file-position: position change failed on stream (" FILENAME_EXN_E ")", "file-position: position change failed on stream (" FILENAME_EXN_E ")",
errno); errid);
} }
if (SCHEME_INPUT_PORTP(argv[0])) { if (SCHEME_INPUT_PORTP(argv[0])) {
@ -5231,7 +5242,7 @@ scheme_file_position(int argc, Scheme_Object *argv[])
#ifdef MZ_FDS #ifdef MZ_FDS
} else if (had_fd) { } else if (had_fd) {
# ifdef WINDOWS_FILE_HANDLES # ifdef WINDOWS_FILE_HANDLES
{ if (win_seekable(fd)) {
DWORD lo_w, hi_w; DWORD lo_w, hi_w;
hi_w = 0; hi_w = 0;
lo_w = SetFilePointer((HANDLE)fd, 0, &hi_w, FILE_CURRENT); lo_w = SetFilePointer((HANDLE)fd, 0, &hi_w, FILE_CURRENT);
@ -5240,7 +5251,8 @@ scheme_file_position(int argc, Scheme_Object *argv[])
pll = -1; pll = -1;
else else
pll = ((mzlonglong)hi_w << 32) | lo_w; pll = ((mzlonglong)hi_w << 32) | lo_w;
} } else
pll = -1;
# else # else
pll = BIG_OFF_T_IZE(lseek)(fd, 0, 1); pll = BIG_OFF_T_IZE(lseek)(fd, 0, 1);
# endif # endif