Index: Lib/_pyio.py =================================================================== --- Lib/_pyio.py (revision 77317) +++ Lib/_pyio.py (working copy) @@ -867,7 +867,7 @@ elif pos < 0: raise ValueError("negative truncate position %r" % (pos,)) del self._buffer[pos:] - return self.seek(pos) + return pos # we do NOT move the file pointer def readable(self): return True @@ -1226,8 +1226,8 @@ if pos is None: pos = self.tell() # Use seek to flush the read buffer. - self.seek(pos) - return BufferedWriter.truncate(self) + self.seek(0, os.SEEK_CUR) + return BufferedWriter.truncate(self, pos) def read(self, n=None): if n is None: Index: Lib/test/test_io.py =================================================================== --- Lib/test/test_io.py (revision 77317) +++ Lib/test/test_io.py (working copy) @@ -233,7 +233,13 @@ support.unlink(support.TESTFN) def write_ops(self, f): + self.assertEqual(f.write(b"blah."), 5) + f.truncate(0) + self.assertEqual(f.tell(), 5) + f.seek(0) + + self.assertEqual(f.write(b"blah."), 5) self.assertEqual(f.seek(0), 0) self.assertEqual(f.write(b"Hello."), 6) self.assertEqual(f.tell(), 6) @@ -244,8 +250,9 @@ self.assertEqual(f.write(b"h"), 1) self.assertEqual(f.seek(-1, 2), 13) self.assertEqual(f.tell(), 13) + self.assertEqual(f.truncate(12), 12) - self.assertEqual(f.tell(), 12) + self.assertEqual(f.tell(), 13) self.assertRaises(TypeError, f.seek, 0.0) def read_ops(self, f, buffered=False): @@ -988,7 +995,7 @@ bufio = self.tp(raw, 8) bufio.write(b"abcdef") self.assertEqual(bufio.truncate(3), 3) - self.assertEqual(bufio.tell(), 3) + self.assertEqual(bufio.tell(), 6) with self.open(support.TESTFN, "rb", buffering=0) as f: self.assertEqual(f.read(), b"abc") Index: Modules/_io/bytesio.c =================================================================== --- Modules/_io/bytesio.c (revision 77317) +++ Modules/_io/bytesio.c (working copy) @@ -453,7 +453,6 @@ if (resize_buffer(self, size) < 0) return NULL; } - self->pos = size; return PyLong_FromSsize_t(size); } Index: Modules/_io/fileio.c =================================================================== --- Modules/_io/fileio.c (revision 77317) +++ Modules/_io/fileio.c (working copy) @@ -759,6 +759,7 @@ fileio_truncate(fileio *self, PyObject *args) { PyObject *posobj = NULL; + PyObject *oldposobj = NULL; Py_off_t pos; int ret; int fd; @@ -778,27 +779,21 @@ if (posobj == NULL) return NULL; } - else { - /* Move to the position to be truncated. */ - posobj = portable_lseek(fd, posobj, 0); - } - if (posobj == NULL) - return NULL; -#if defined(HAVE_LARGEFILE_SUPPORT) - pos = PyLong_AsLongLong(posobj); -#else - pos = PyLong_AsLong(posobj); -#endif - if (pos == -1 && PyErr_Occurred()) - return NULL; +#ifdef MS_WINDOWS -#ifdef MS_WINDOWS /* MS _chsize doesn't work if newsize doesn't fit in 32 bits, so don't even try using it. */ { HANDLE hFile; + oldposobj = portable_lseek(fd, NULL, 1); // we save the file pointer position + if (oldposobj == NULL) + return NULL; + posobj = portable_lseek(fd, posobj, 0); // we must move to the truncation position + if (posobj == NULL) + return NULL; + /* Truncate. Note that this may grow the file! */ Py_BEGIN_ALLOW_THREADS errno = 0; @@ -810,12 +805,26 @@ errno = EACCES; } Py_END_ALLOW_THREADS + + oldposobj = portable_lseek(fd, oldposobj, 0); // we restore the file pointer position + if (oldposobj == NULL) + return NULL; } #else + +#if defined(HAVE_LARGEFILE_SUPPORT) + pos = PyLong_AsLongLong(posobj); +#else + pos = PyLong_AsLong(posobj); +#endif + if (PyErr_Occurred()) + return NULL; + Py_BEGIN_ALLOW_THREADS errno = 0; ret = ftruncate(fd, pos); Py_END_ALLOW_THREADS + #endif /* !MS_WINDOWS */ if (ret != 0) {