[Jython-checkins] jython: Ensure os.fstat() returns a valid st_mode on Windows. Addresses #2320.
jeff.allen
jython-checkins at python.org
Tue Nov 10 14:07:25 EST 2015
https://hg.python.org/jython/rev/0381d60ca611
changeset: 7798:0381d60ca611
user: Jeff Allen <ja.py at farowl.co.uk>
date: Tue Nov 10 07:27:49 2015 +0000
summary:
Ensure os.fstat() returns a valid st_mode on Windows. Addresses #2320.
Compensate for (probable) bug in jnr-posix whereby fstat st_mode is
always zero. We provide a custom stat-object able to synthesize a mode
from DOS-ish file attributes. Also we suppress os.closerange on Windows
until real integer file descriptors are available.
files:
Lib/test/regrtest.py | 1 -
src/org/python/modules/posix/PosixModule.java | 66 ++++++++-
2 files changed, 59 insertions(+), 8 deletions(-)
diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py
--- a/Lib/test/regrtest.py
+++ b/Lib/test/regrtest.py
@@ -1358,7 +1358,6 @@
'java.nt': # Expected to fail on Windows
"""
- test_fileinput # issue 2320 (because fstat().st_mode is zero)
test_mailbox # fails miserably and ruins other tests
test_os_jy # Locale tests run and fail on Cygwin
test_popen # http://bugs.python.org/issue1559298
diff --git a/src/org/python/modules/posix/PosixModule.java b/src/org/python/modules/posix/PosixModule.java
--- a/src/org/python/modules/posix/PosixModule.java
+++ b/src/org/python/modules/posix/PosixModule.java
@@ -15,8 +15,8 @@
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.LinkOption;
+import java.nio.file.NoSuchFileException;
import java.nio.file.NotLinkException;
-import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributeView;
@@ -34,9 +34,11 @@
import jnr.posix.FileStat;
import jnr.posix.POSIX;
import jnr.posix.POSIXFactory;
+import jnr.posix.POSIXHandler;
import jnr.posix.Times;
+import jnr.posix.WindowsRawFileStat;
import jnr.posix.util.FieldAccess;
-import jnr.posix.util.Platform;
+import jnr.posix.windows.CommonFileInformation;
import org.python.core.BufferProtocol;
import org.python.core.ClassDictInit;
@@ -53,8 +55,8 @@
import org.python.core.PyString;
import org.python.core.PySystemState;
import org.python.core.PyTuple;
+import org.python.core.Untraversable;
import org.python.core.imp;
-import org.python.core.Untraversable;
import org.python.core.io.FileIO;
import org.python.core.io.IOBase;
import org.python.core.io.RawIOBase;
@@ -75,7 +77,8 @@
private static final OS os = OS.getOS();
/** Platform specific POSIX services. */
- private static final POSIX posix = POSIXFactory.getPOSIX(new PythonPOSIXHandler(), true);
+ private static final POSIXHandler posixHandler = new PythonPOSIXHandler();
+ private static final POSIX posix = POSIXFactory.getPOSIX(posixHandler, true);
/** os.open flags. */
private static final int O_RDONLY = 0x0;
@@ -354,6 +357,7 @@
}
}
+ @Hide(OS.NT)
public static void closerange(PyObject fd_lowObj, PyObject fd_highObj) {
int fd_low = getFD(fd_lowObj).getIntFD(false);
int fd_high = getFD(fd_highObj).getIntFD(false);
@@ -1365,10 +1369,18 @@
try {
FDUnion fd = getFD(fdObj);
FileStat stat;
- if (fd.isIntFD()) {
- stat = posix.fstat(fd.intFD);
+ if (os != OS.NT) {
+ if (fd.isIntFD()) {
+ stat = posix.fstat(fd.intFD);
+ } else {
+ stat = posix.fstat(fd.javaFD);
+ }
} else {
- stat = posix.fstat(fd.javaFD);
+ // FIXME: jnr-posix fstat work-around. See issue #2320.
+ stat = new WindowsRawFileStat2(posix, posixHandler);
+ if (posix.fstat(fd.javaFD, stat) < 0) {
+ throw Py.OSError(Errno.EBADF);
+ }
}
return PyStatResult.fromFileStat(stat);
} catch (PyException ex) {
@@ -1376,4 +1388,44 @@
}
}
}
+
+ /*
+ * Extend the Windows stat object defined by jnr.posix, which in jnr-posix 2.0.4 is buggy to the
+ * extent that st_mode is always zero. Remarkably, it is possible to fix this by defining a
+ * cunning replacement.
+ */
+ private static class WindowsRawFileStat2 extends WindowsRawFileStat {
+
+ public WindowsRawFileStat2(POSIX posix, POSIXHandler handler) {
+ super(posix, handler);
+ }
+
+ private int mode; // Replaces st_mode
+
+ @Override
+ public void setup(CommonFileInformation fileInfo) {
+ super.setup(fileInfo);
+ // CommonFileInformation gives us (DOS-style) file attributes, not access rights.
+ int attr = fileInfo.getFileAttributes();
+ int mode = ALL_READ;
+ if ((attr & CommonFileInformation.FILE_ATTRIBUTE_READONLY) == 0) {
+ // Writable: assume by all
+ mode |= ALL_WRITE;
+ }
+ if ((attr & CommonFileInformation.FILE_ATTRIBUTE_DIRECTORY) != 0) {
+ // Directory: assume by all can look things up in it.
+ mode |= S_IFDIR | S_IXUGO;
+ } else {
+ // Regular file
+ mode |= S_IFREG;
+ }
+ this.mode = mode;
+ }
+
+ @Override
+ public int mode() {
+ return mode;
+ }
+ }
+
}
--
Repository URL: https://hg.python.org/jython
More information about the Jython-checkins
mailing list