Skip to content
Open
8 changes: 8 additions & 0 deletions Lib/test/test_os/test_os.py
Original file line number Diff line number Diff line change
Expand Up @@ -2788,6 +2788,14 @@ def test_ftruncate(self):
def test_lseek(self):
self.check(os.lseek, 0, 0)

@unittest.skipUnless(hasattr(os, 'lseek'), 'test needs os.lseek()')
@unittest.skipUnless(hasattr(os, 'pipe'), "need os.pipe()")
def test_lseek_on_pipe(self):
rfd, wfd = os.pipe()
self.addCleanup(os.close, rfd)
self.addCleanup(os.close, wfd)
self.assertRaises(OSError, os.lseek, rfd, 123, os.SEEK_END)

@unittest.skipUnless(hasattr(os, 'read'), 'test needs os.read()')
def test_read(self):
self.check(os.read, 1)
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_winapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ def test_namedpipe(self):
# Pipe instance is available, so this passes
_winapi.WaitNamedPipe(pipe_name, 0)

with open(pipe_name, 'w+b') as pipe2:
with open(pipe_name, 'w+b', buffering=0) as pipe2:
# No instances available, so this times out
# (WinError 121 does not get mapped to TimeoutError)
with self.assertRaises(OSError):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
:exc:`OSError` will be raised if call :func:`os.lseek` with non seekable
object on Windows.
9 changes: 8 additions & 1 deletion Modules/_io/fileio.c
Original file line number Diff line number Diff line change
Expand Up @@ -989,7 +989,14 @@ portable_lseek(fileio *self, PyObject *posobj, int whence, bool suppress_pipe_er
Py_BEGIN_ALLOW_THREADS
_Py_BEGIN_SUPPRESS_IPH
#ifdef MS_WINDOWS
res = _lseeki64(fd, pos, whence);
HANDLE h = (HANDLE)_get_osfhandle(fd);
if (h != INVALID_HANDLE_VALUE && GetFileType(h) == FILE_TYPE_PIPE) {
res = -1;
errno = ESPIPE;
}
else {
res = _lseeki64(fd, pos, whence);
}
#else
res = lseek(fd, pos, whence);
#endif
Expand Down
13 changes: 10 additions & 3 deletions Modules/posixmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -11915,7 +11915,7 @@ static Py_off_t
os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
/*[clinic end generated code: output=971e1efb6b30bd2f input=4a3de549f07e1c40]*/
{
Py_off_t result;
Py_off_t result = -1;

#ifdef SEEK_SET
/* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
Expand All @@ -11929,14 +11929,21 @@ os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
Py_BEGIN_ALLOW_THREADS
_Py_BEGIN_SUPPRESS_IPH
#ifdef MS_WINDOWS
result = _lseeki64(fd, position, how);
HANDLE h = (HANDLE)_get_osfhandle(fd);
if (h != INVALID_HANDLE_VALUE && GetFileType(h) == FILE_TYPE_PIPE) {
errno = ESPIPE;
}
else {
result = _lseeki64(fd, position, how);
}
#else
result = lseek(fd, position, how);
#endif
_Py_END_SUPPRESS_IPH
Py_END_ALLOW_THREADS
if (result < 0)
if (result < 0) {
posix_error();
}

return result;
}
Expand Down
Loading