Issue #23668: Adds support for os.truncate and os.ftruncate on Windows
This commit is contained in:
parent
c7d979f022
commit
fe0a41aae4
|
@ -339,8 +339,11 @@ I/O Base Classes
|
||||||
if *size* is not specified). The current stream position isn't changed.
|
if *size* is not specified). The current stream position isn't changed.
|
||||||
This resizing can extend or reduce the current file size. In case of
|
This resizing can extend or reduce the current file size. In case of
|
||||||
extension, the contents of the new file area depend on the platform
|
extension, the contents of the new file area depend on the platform
|
||||||
(on most systems, additional bytes are zero-filled, on Windows they're
|
(on most systems, additional bytes are zero-filled). The new file size
|
||||||
undetermined). The new file size is returned.
|
is returned.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.5
|
||||||
|
Windows will now zero-fill files when extending.
|
||||||
|
|
||||||
.. method:: writable()
|
.. method:: writable()
|
||||||
|
|
||||||
|
|
|
@ -805,8 +805,10 @@ as internal buffering of data.
|
||||||
most *length* bytes in size. As of Python 3.3, this is equivalent to
|
most *length* bytes in size. As of Python 3.3, this is equivalent to
|
||||||
``os.truncate(fd, length)``.
|
``os.truncate(fd, length)``.
|
||||||
|
|
||||||
Availability: Unix.
|
Availability: Unix, Windows.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.5
|
||||||
|
Added support for Windows
|
||||||
|
|
||||||
.. function:: get_blocking(fd)
|
.. function:: get_blocking(fd)
|
||||||
|
|
||||||
|
@ -2492,10 +2494,12 @@ features:
|
||||||
|
|
||||||
This function can support :ref:`specifying a file descriptor <path_fd>`.
|
This function can support :ref:`specifying a file descriptor <path_fd>`.
|
||||||
|
|
||||||
Availability: Unix.
|
Availability: Unix, Windows.
|
||||||
|
|
||||||
.. versionadded:: 3.3
|
.. versionadded:: 3.3
|
||||||
|
|
||||||
|
.. versionchanged:: 3.5
|
||||||
|
Added support for Windows
|
||||||
|
|
||||||
.. function:: unlink(path, *, dir_fd=None)
|
.. function:: unlink(path, *, dir_fd=None)
|
||||||
|
|
||||||
|
|
|
@ -286,6 +286,8 @@ Library
|
||||||
|
|
||||||
- Issue #2052: Add charset parameter to HtmlDiff.make_file().
|
- Issue #2052: Add charset parameter to HtmlDiff.make_file().
|
||||||
|
|
||||||
|
- Issue #23668: Support os.truncate and os.ftruncate on Windows.
|
||||||
|
|
||||||
- Issue #23138: Fixed parsing cookies with absent keys or values in cookiejar.
|
- Issue #23138: Fixed parsing cookies with absent keys or values in cookiejar.
|
||||||
Patch by Demian Brecht.
|
Patch by Demian Brecht.
|
||||||
|
|
||||||
|
|
|
@ -839,9 +839,7 @@ static PyObject *
|
||||||
fileio_truncate(fileio *self, PyObject *args)
|
fileio_truncate(fileio *self, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject *posobj = NULL; /* the new size wanted by the user */
|
PyObject *posobj = NULL; /* the new size wanted by the user */
|
||||||
#ifndef MS_WINDOWS
|
|
||||||
Py_off_t pos;
|
Py_off_t pos;
|
||||||
#endif
|
|
||||||
int ret;
|
int ret;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
|
@ -864,52 +862,6 @@ fileio_truncate(fileio *self, PyObject *args)
|
||||||
Py_INCREF(posobj);
|
Py_INCREF(posobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
|
||||||
/* MS _chsize doesn't work if newsize doesn't fit in 32 bits,
|
|
||||||
so don't even try using it. */
|
|
||||||
{
|
|
||||||
PyObject *oldposobj, *tempposobj;
|
|
||||||
HANDLE hFile;
|
|
||||||
|
|
||||||
/* we save the file pointer position */
|
|
||||||
oldposobj = portable_lseek(fd, NULL, 1);
|
|
||||||
if (oldposobj == NULL) {
|
|
||||||
Py_DECREF(posobj);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we then move to the truncation position */
|
|
||||||
tempposobj = portable_lseek(fd, posobj, 0);
|
|
||||||
if (tempposobj == NULL) {
|
|
||||||
Py_DECREF(oldposobj);
|
|
||||||
Py_DECREF(posobj);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
Py_DECREF(tempposobj);
|
|
||||||
|
|
||||||
/* Truncate. Note that this may grow the file! */
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
|
||||||
errno = 0;
|
|
||||||
hFile = (HANDLE)_get_osfhandle(fd);
|
|
||||||
ret = hFile == (HANDLE)-1; /* testing for INVALID_HANDLE value */
|
|
||||||
if (ret == 0) {
|
|
||||||
ret = SetEndOfFile(hFile) == 0;
|
|
||||||
if (ret)
|
|
||||||
errno = EACCES;
|
|
||||||
}
|
|
||||||
Py_END_ALLOW_THREADS
|
|
||||||
|
|
||||||
/* we restore the file pointer position in any case */
|
|
||||||
tempposobj = portable_lseek(fd, oldposobj, 0);
|
|
||||||
Py_DECREF(oldposobj);
|
|
||||||
if (tempposobj == NULL) {
|
|
||||||
Py_DECREF(posobj);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
Py_DECREF(tempposobj);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
|
|
||||||
#if defined(HAVE_LARGEFILE_SUPPORT)
|
#if defined(HAVE_LARGEFILE_SUPPORT)
|
||||||
pos = PyLong_AsLongLong(posobj);
|
pos = PyLong_AsLongLong(posobj);
|
||||||
#else
|
#else
|
||||||
|
@ -922,11 +874,13 @@ fileio_truncate(fileio *self, PyObject *args)
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
#ifdef MS_WINDOWS
|
||||||
|
ret = _chsize_s(fd, pos);
|
||||||
|
#else
|
||||||
ret = ftruncate(fd, pos);
|
ret = ftruncate(fd, pos);
|
||||||
|
#endif
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
#endif /* !MS_WINDOWS */
|
|
||||||
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
Py_DECREF(posobj);
|
Py_DECREF(posobj);
|
||||||
PyErr_SetFromErrno(PyExc_IOError);
|
PyErr_SetFromErrno(PyExc_IOError);
|
||||||
|
|
|
@ -2315,6 +2315,10 @@ FTRUNCATE
|
||||||
#endif
|
#endif
|
||||||
/*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
|
/*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
|
||||||
|
|
||||||
|
#ifdef MS_WINDOWS
|
||||||
|
#undef PATH_HAVE_FTRUNCATE
|
||||||
|
#define PATH_HAVE_FTRUNCATE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/*[python input]
|
/*[python input]
|
||||||
|
|
||||||
|
@ -8753,7 +8757,7 @@ os_makedev_impl(PyModuleDef *module, int major, int minor)
|
||||||
#endif /* HAVE_DEVICE_MACROS */
|
#endif /* HAVE_DEVICE_MACROS */
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_FTRUNCATE
|
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
os.ftruncate
|
os.ftruncate
|
||||||
|
|
||||||
|
@ -8771,9 +8775,16 @@ os_ftruncate_impl(PyModuleDef *module, int fd, Py_off_t length)
|
||||||
int result;
|
int result;
|
||||||
int async_err = 0;
|
int async_err = 0;
|
||||||
|
|
||||||
|
if (!_PyVerify_fd(fd))
|
||||||
|
return posix_error();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
|
#ifdef MS_WINDOWS
|
||||||
|
result = _chsize_s(fd, length);
|
||||||
|
#else
|
||||||
result = ftruncate(fd, length);
|
result = ftruncate(fd, length);
|
||||||
|
#endif
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
} while (result != 0 && errno == EINTR &&
|
} while (result != 0 && errno == EINTR &&
|
||||||
!(async_err = PyErr_CheckSignals()));
|
!(async_err = PyErr_CheckSignals()));
|
||||||
|
@ -8781,10 +8792,10 @@ os_ftruncate_impl(PyModuleDef *module, int fd, Py_off_t length)
|
||||||
return (!async_err) ? posix_error() : NULL;
|
return (!async_err) ? posix_error() : NULL;
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
#endif /* HAVE_FTRUNCATE */
|
#endif /* HAVE_FTRUNCATE || MS_WINDOWS */
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_TRUNCATE
|
#if defined HAVE_TRUNCATE || defined MS_WINDOWS
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
os.truncate
|
os.truncate
|
||||||
path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
|
path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
|
||||||
|
@ -8801,21 +8812,37 @@ os_truncate_impl(PyModuleDef *module, path_t *path, Py_off_t length)
|
||||||
/*[clinic end generated code: output=f60a9e08370e9e2e input=77229cf0b50a9b77]*/
|
/*[clinic end generated code: output=f60a9e08370e9e2e input=77229cf0b50a9b77]*/
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
#ifdef MS_WINDOWS
|
||||||
|
int fd;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (path->fd != -1)
|
||||||
|
return os_ftruncate_impl(module, path->fd, length);
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
#ifdef HAVE_FTRUNCATE
|
#ifdef MS_WINDOWS
|
||||||
if (path->fd != -1)
|
if (path->wide)
|
||||||
result = ftruncate(path->fd, length);
|
fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
|
||||||
else
|
else
|
||||||
#endif
|
fd = _open(path->narrow, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
|
||||||
|
if (fd < 0)
|
||||||
|
result = -1;
|
||||||
|
else {
|
||||||
|
result = _chsize_s(fd, length);
|
||||||
|
close(fd);
|
||||||
|
if (result < 0)
|
||||||
|
errno = result;
|
||||||
|
}
|
||||||
|
#else
|
||||||
result = truncate(path->narrow, length);
|
result = truncate(path->narrow, length);
|
||||||
|
#endif
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
return path_error(path);
|
return path_error(path);
|
||||||
|
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
#endif /* HAVE_TRUNCATE */
|
#endif /* HAVE_TRUNCATE || MS_WINDOWS */
|
||||||
|
|
||||||
|
|
||||||
/* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
|
/* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
|
||||||
|
@ -12771,7 +12798,7 @@ static char *have_functions[] = {
|
||||||
"HAVE_FSTATVFS",
|
"HAVE_FSTATVFS",
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_FTRUNCATE
|
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
|
||||||
"HAVE_FTRUNCATE",
|
"HAVE_FTRUNCATE",
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue