]> granicus.if.org Git - python/commitdiff
Issue #23668: Adds support for os.truncate and os.ftruncate on Windows
authorSteve Dower <steve.dower@microsoft.com>
Sat, 21 Mar 2015 02:50:46 +0000 (19:50 -0700)
committerSteve Dower <steve.dower@microsoft.com>
Sat, 21 Mar 2015 02:50:46 +0000 (19:50 -0700)
Doc/library/io.rst
Doc/library/os.rst
Misc/NEWS
Modules/_io/fileio.c
Modules/posixmodule.c

index 634bf5865452dddfbae99bbdfbbb117173eb1d6c..f009c65cf0a0b6a54e4bc35bf0ea115e9fa75fc6 100644 (file)
@@ -339,8 +339,11 @@ I/O Base Classes
       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
       extension, the contents of the new file area depend on the platform
-      (on most systems, additional bytes are zero-filled, on Windows they're
-      undetermined).  The new file size is returned.
+      (on most systems, additional bytes are zero-filled).  The new file size
+      is returned.
+
+   .. versionchanged:: 3.5
+      Windows will now zero-fill files when extending.
 
    .. method:: writable()
 
index eb10db6b8a9d76e80c54776904f5f386139354ce..bd09937aebcdaad26f486d4f737e10620b68d03e 100644 (file)
@@ -805,8 +805,10 @@ as internal buffering of data.
    most *length* bytes in size.  As of Python 3.3, this is equivalent to
    ``os.truncate(fd, length)``.
 
-   Availability: Unix.
+   Availability: Unix, Windows.
 
+   .. versionchanged:: 3.5
+      Added support for Windows
 
 .. function:: get_blocking(fd)
 
@@ -2492,10 +2494,12 @@ features:
 
    This function can support :ref:`specifying a file descriptor <path_fd>`.
 
-   Availability: Unix.
+   Availability: Unix, Windows.
 
    .. versionadded:: 3.3
 
+   .. versionchanged:: 3.5
+      Added support for Windows
 
 .. function:: unlink(path, *, dir_fd=None)
 
index ad287373f6987ab2e40b395f531da0b444beaa0b..f6ae315888ff72e7e3620bfee63d38485c80e347 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -286,6 +286,8 @@ Library
 
 - 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.
   Patch by Demian Brecht.
 
index 5108fc759c7081045cf266ddad242359698852c4..bb3e9b9f94a2c4775b356871622af1584bc6926a 100644 (file)
@@ -839,9 +839,7 @@ static PyObject *
 fileio_truncate(fileio *self, PyObject *args)
 {
     PyObject *posobj = NULL; /* the new size wanted by the user */
-#ifndef MS_WINDOWS
     Py_off_t pos;
-#endif
     int ret;
     int fd;
 
@@ -864,52 +862,6 @@ fileio_truncate(fileio *self, PyObject *args)
         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)
     pos = PyLong_AsLongLong(posobj);
 #else
@@ -922,11 +874,13 @@ fileio_truncate(fileio *self, PyObject *args)
 
     Py_BEGIN_ALLOW_THREADS
     errno = 0;
+#ifdef MS_WINDOWS
+    ret = _chsize_s(fd, pos);
+#else
     ret = ftruncate(fd, pos);
+#endif
     Py_END_ALLOW_THREADS
 
-#endif /* !MS_WINDOWS */
-
     if (ret != 0) {
         Py_DECREF(posobj);
         PyErr_SetFromErrno(PyExc_IOError);
index 7da1ab0eb8982947062bc738534a7386e71a1cfe..724acc63d112726eda744d28128378ae957b08ec 100644 (file)
@@ -2315,6 +2315,10 @@ FTRUNCATE
 #endif
 /*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
 
+#ifdef MS_WINDOWS
+    #undef PATH_HAVE_FTRUNCATE
+    #define PATH_HAVE_FTRUNCATE 1
+#endif
 
 /*[python input]
 
@@ -8753,7 +8757,7 @@ os_makedev_impl(PyModuleDef *module, int major, int minor)
 #endif /* HAVE_DEVICE_MACROS */
 
 
-#ifdef HAVE_FTRUNCATE
+#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
 /*[clinic input]
 os.ftruncate
 
@@ -8771,9 +8775,16 @@ os_ftruncate_impl(PyModuleDef *module, int fd, Py_off_t length)
     int result;
     int async_err = 0;
 
+    if (!_PyVerify_fd(fd))
+        return posix_error();
+
     do {
         Py_BEGIN_ALLOW_THREADS
+#ifdef MS_WINDOWS
+        result = _chsize_s(fd, length);
+#else
         result = ftruncate(fd, length);
+#endif
         Py_END_ALLOW_THREADS
     } while (result != 0 && errno == EINTR &&
              !(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;
     Py_RETURN_NONE;
 }
-#endif /* HAVE_FTRUNCATE */
+#endif /* HAVE_FTRUNCATE || MS_WINDOWS */
 
 
-#ifdef HAVE_TRUNCATE
+#if defined HAVE_TRUNCATE || defined MS_WINDOWS
 /*[clinic input]
 os.truncate
     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]*/
 {
     int result;
+#ifdef MS_WINDOWS
+    int fd;
+#endif
 
-    Py_BEGIN_ALLOW_THREADS
-#ifdef HAVE_FTRUNCATE
     if (path->fd != -1)
-        result = ftruncate(path->fd, length);
+        return os_ftruncate_impl(module, path->fd, length);
+
+    Py_BEGIN_ALLOW_THREADS
+#ifdef MS_WINDOWS
+    if (path->wide)
+        fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
     else
+        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);
 #endif
-        result = truncate(path->narrow, length);
     Py_END_ALLOW_THREADS
     if (result < 0)
         return path_error(path);
 
     Py_RETURN_NONE;
 }
-#endif /* HAVE_TRUNCATE */
+#endif /* HAVE_TRUNCATE || MS_WINDOWS */
 
 
 /* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
@@ -12771,7 +12798,7 @@ static char *have_functions[] = {
     "HAVE_FSTATVFS",
 #endif
 
-#ifdef HAVE_FTRUNCATE
+#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
     "HAVE_FTRUNCATE",
 #endif