Kaydet (Commit) 98305a0d authored tarafından Michael W. Hudson's avatar Michael W. Hudson

Take Tim's work on file.truncate out of 2.2.1 again.

üst eae11ba4
......@@ -1152,15 +1152,11 @@ Files have the following methods:
\end{methoddesc}
\begin{methoddesc}[file]{truncate}{\optional{size}}
Truncate the file's size. If the optional \var{size} argument is
Truncate the file's size. If the optional \var{size} argument
present, the file is truncated to (at most) that size. The size
defaults to the current position. The current file position is
not changed. Note that if a specified size exceeds the file's
current size, the result is platform-dependent: possibilities
include that file may remain unchanged, increase to the specified
size as if zero-filled, or increase to the specified size with
undefined new content.
Availability: Windows, many \UNIX variants.
defaults to the current position. Availability of this function
depends on the operating system version (for example, not all
\UNIX{} versions support this operation).
\end{methoddesc}
\begin{methoddesc}[file]{write}{str}
......
......@@ -128,35 +128,20 @@ expect(os.lseek(f.fileno(), size, 0), size)
expect(f.read(1), 'a') # the 'a' that was written at the end of the file above
f.close()
if hasattr(f, 'truncate'):
if test_support.verbose:
print 'try truncate'
f = open(name, 'r+b')
f.seek(0, 2)
expect(f.tell(), size+1) # else we've lost track of the true size
# Cut it back via seek + truncate with no argument.
newsize = size - 10
f.seek(newsize)
f.truncate()
expect(f.tell(), newsize) # else pointer moved
f.seek(0, 2)
expect(f.tell(), newsize) # else wasn't truncated
# Ensure that truncate(smaller than true size) shrinks the file.
newsize -= 1
f.seek(42)
f.truncate(newsize)
expect(f.tell(), 42) # else pointer moved
f.seek(0, 2)
expect(f.tell(), newsize) # else wasn't truncated
# XXX truncate(larger than true size) is ill-defined across platforms
# cut it waaaaay back
f.seek(0)
f.truncate(1)
expect(f.tell(), 0) # else pointer moved
expect(len(f.read()), 1) # else wasn't truncated
f.close()
# XXX add tests for truncate if it exists
# XXX has truncate ever worked on Windows? specifically on WinNT I get:
# "IOError: [Errno 13] Permission denied"
##try:
## newsize = size - 10
## f.seek(newsize)
## f.truncate()
## expect(f.tell(), newsize)
## newsize = newsize - 1
## f.seek(0)
## f.truncate(newsize)
## expect(f.tell(), newsize)
##except AttributeError:
## pass
os.unlink(name)
......@@ -27,11 +27,6 @@ Library
arbitrary shell code can't be executed because a bogus URL was
passed in.
Windows
- file.truncate([newsize]) now works on Windows for all newsize values.
It used to fail if newsize didn't fit in 32 bits, reflecting a
limitation of MS _chsize (which is no longer used).
What's New in Python 2.2 final?
Release date: 21-Dec-2001
......
......@@ -10,10 +10,8 @@
#ifdef MS_WIN32
#define fileno _fileno
/* can simulate truncate with Win32 API functions; see file_truncate */
/* can (almost fully) duplicate with _chsize, see file_truncate */
#define HAVE_FTRUNCATE
#define WINDOWS_LEAN_AND_MEAN
#include <windows.h>
#endif
#ifdef macintosh
......@@ -377,9 +375,6 @@ file_truncate(PyFileObject *f, PyObject *args)
newsizeobj = NULL;
if (!PyArg_ParseTuple(args, "|O:truncate", &newsizeobj))
return NULL;
/* Set newsize to current postion if newsizeobj NULL, else to the
specified value. */
if (newsizeobj != NULL) {
#if !defined(HAVE_LARGEFILE_SUPPORT)
newsize = PyInt_AsLong(newsizeobj);
......@@ -390,80 +385,37 @@ file_truncate(PyFileObject *f, PyObject *args)
#endif
if (PyErr_Occurred())
return NULL;
}
else {
/* Default to current position. */
} else {
/* Default to current position*/
Py_BEGIN_ALLOW_THREADS
errno = 0;
newsize = _portable_ftell(f->f_fp);
Py_END_ALLOW_THREADS
if (newsize == -1)
goto onioerror;
if (newsize == -1) {
PyErr_SetFromErrno(PyExc_IOError);
clearerr(f->f_fp);
return NULL;
}
}
/* Flush the file. */
Py_BEGIN_ALLOW_THREADS
errno = 0;
ret = fflush(f->f_fp);
Py_END_ALLOW_THREADS
if (ret != 0)
goto onioerror;
if (ret != 0) goto onioerror;
#ifdef MS_WIN32
/* MS _chsize doesn't work if newsize doesn't fit in 32 bits,
so don't even try using it. */
{
Py_off_t current; /* current file position */
HANDLE hFile;
int error;
/* current <- current file postion. */
if (newsizeobj == NULL)
current = newsize;
else {
Py_BEGIN_ALLOW_THREADS
errno = 0;
current = _portable_ftell(f->f_fp);
Py_END_ALLOW_THREADS
if (current == -1)
goto onioerror;
}
/* Move to newsize. */
if (current != newsize) {
Py_BEGIN_ALLOW_THREADS
errno = 0;
error = _portable_fseek(f->f_fp, newsize, SEEK_SET)
!= 0;
Py_END_ALLOW_THREADS
if (error)
goto onioerror;
}
/* Truncate. Note that this may grow the file! */
Py_BEGIN_ALLOW_THREADS
errno = 0;
hFile = (HANDLE)_get_osfhandle(fileno(f->f_fp));
error = hFile == (HANDLE)-1;
if (!error) {
error = SetEndOfFile(hFile) == 0;
if (error)
errno = EACCES;
}
Py_END_ALLOW_THREADS
if (error)
goto onioerror;
/* Restore original file position. */
if (current != newsize) {
/* can use _chsize; if, however, the newsize overflows 32-bits then
_chsize is *not* adequate; in this case, an OverflowError is raised */
if (newsize > LONG_MAX) {
PyErr_SetString(PyExc_OverflowError,
"the new size is too long for _chsize (it is limited to 32-bit values)");
return NULL;
} else {
Py_BEGIN_ALLOW_THREADS
errno = 0;
error = _portable_fseek(f->f_fp, current, SEEK_SET)
!= 0;
ret = _chsize(fileno(f->f_fp), (long)newsize);
Py_END_ALLOW_THREADS
if (error)
goto onioerror;
}
if (ret != 0) goto onioerror;
}
#else
Py_BEGIN_ALLOW_THREADS
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment