From: <pj...@us...> - 2009-10-27 23:55:02
|
Revision: 6920 http://jython.svn.sourceforge.net/jython/?rev=6920&view=rev Author: pjenvey Date: 2009-10-27 23:54:38 +0000 (Tue, 27 Oct 2009) Log Message: ----------- o move chmod/mkdir to PosixModule and add chown, using the newer jna-posix errno() for accurate error messages fixes #1470, 1493 o attempt to figure out listdir failure errnos fixes #1496 o guard against null paths in PosixModule refs #1369 Modified Paths: -------------- trunk/jython/Lib/posix.py trunk/jython/src/org/python/modules/posix/PosixModule.java Modified: trunk/jython/Lib/posix.py =================================================================== --- trunk/jython/Lib/posix.py 2009-10-27 23:49:37 UTC (rev 6919) +++ trunk/jython/Lib/posix.py 2009-10-27 23:54:38 UTC (rev 6920) @@ -14,9 +14,9 @@ import sys __all__ = [name for name in _posix.__all__ if not name.startswith('__doc__')] -__all__.extend(['chmod', 'fsync', 'getenv', 'getpid', 'isatty', 'mkdir', - 'popen', 'putenv', 'remove', 'rename', 'rmdir', 'system', - 'umask', 'unlink', 'unsetenv', 'urandom', 'utime']) +__all__.extend(['fsync', 'getenv', 'getpid', 'isatty', 'popen', 'putenv', + 'remove', 'rename', 'rmdir', 'system', 'umask', 'unlink', + 'unsetenv', 'urandom', 'utime']) _name = _posix.__name__[1:] @@ -26,37 +26,6 @@ # For urandom urandom_source = None -def chmod(path, mode): - """chmod(path, mode) - - Change the access permissions of a file. - """ - # XXX no error handling for chmod in jna-posix - # catch not found errors explicitly here, for now - from java.io import File - abs_path = sys.getPath(path) - if not File(abs_path).exists(): - raise OSError(errno.ENOENT, strerror(errno.ENOENT), path) - _posix_impl.chmod(abs_path, mode) - -def mkdir(path, mode='ignored'): - """mkdir(path [, mode=0777]) - - Create a directory. - - The optional parameter is currently ignored. - """ - # XXX: use _posix_impl.mkdir when we can get the real errno upon failure - from java.io import File - fp = File(sys.getPath(path)) - if not fp.mkdir(): - if fp.isDirectory() or fp.isFile(): - err = errno.EEXIST - else: - err = 0 - msg = strerror(err) if err else "couldn't make directory" - raise OSError(err, msg, path) - def remove(path): """remove(path) @@ -369,6 +338,8 @@ """getpid() -> pid Return the current process id.""" + # XXX: getpid and umask should really be hidden from __all__ when + # not _native_posix return _posix_impl.getpid() def isatty(fileno): Modified: trunk/jython/src/org/python/modules/posix/PosixModule.java =================================================================== --- trunk/jython/src/org/python/modules/posix/PosixModule.java 2009-10-27 23:49:37 UTC (rev 6919) +++ trunk/jython/src/org/python/modules/posix/PosixModule.java 2009-10-27 23:54:38 UTC (rev 6920) @@ -11,6 +11,7 @@ import java.nio.ByteBuffer; import java.util.Map; +import org.jruby.ext.posix.FileStat; import org.jruby.ext.posix.JavaPOSIX; import org.jruby.ext.posix.POSIX; import org.jruby.ext.posix.POSIXFactory; @@ -128,6 +129,7 @@ "specified access to the path. The mode argument can be F_OK to test\n" + "existence, or the inclusive-OR of R_OK, W_OK, and X_OK."); public static boolean access(String path, int mode) { + ensurePath(path); boolean result = true; File file = new RelativeFile(path); @@ -166,7 +168,7 @@ String path = pathObj.toString(); // stat raises ENOENT for us if path doesn't exist - if (!posix.stat(new RelativeFile(path).getPath()).isDirectory()) { + if (!posix.stat(absolutePath(path)).isDirectory()) { throw Py.OSError(Errno.ENOTDIR, path); } @@ -176,6 +178,24 @@ Py.getSystemState().setCurrentWorkingDir(realpath.__call__(pathObj).toString()); } + public static PyString __doc__chmod = new PyString( + "chmod(path, mode)\n\n" + + "Change the access permissions of a file."); + public static void chmod(String path, int mode) { + if (posix.chmod(absolutePath(path), mode) < 0) { + throw errorFromErrno(path); + } + } + + public static PyString __doc__chown = new PyString( + "chown(path, uid, gid)\n\n" + + "Change the owner and group id of path to the numeric uid and gid."); + public static void chown(String path, int uid, int gid) { + if (posix.chown(absolutePath(path), uid, gid) < 0) { + throw errorFromErrno(path); + } + } + public static PyString __doc__close = new PyString( "close(fd)\n\n" + "Close a file descriptor (for low level IO)."); @@ -183,7 +203,7 @@ try { FileDescriptors.get(fd).close(); } catch (PyException pye) { - badFD(); + throw badFD(); } } @@ -205,7 +225,7 @@ } RawIOBase rawIO = FileDescriptors.get(fd); if (rawIO.closed()) { - badFD(); + throw badFD(); } try { @@ -250,14 +270,27 @@ "The list is in arbitrary order. It does not include the special\n" + "entries '.' and '..' even if they are present in the directory."); public static PyList listdir(String path) { + ensurePath(path); PyList list = new PyList(); - String[] files = new RelativeFile(path).list(); + File file = new RelativeFile(path); + String[] names = file.list(); - if (files == null) { - throw Py.OSError("No such directory: " + path); + if (names == null) { + // Can't read the path for some reason. stat will throw an error if it can't + // read it either + FileStat stat = posix.stat(file.getPath()); + // It exists, maybe not a dir, or we don't have permission? + if (!stat.isDirectory()) { + throw Py.OSError(Errno.ENOTDIR, path); + } + if (!file.canRead()) { + throw Py.OSError(Errno.EACCES, path); + } + // + throw Py.OSError("listdir(): an unknown error occured: " + path); } - for (String file : files) { - list.append(new PyString(file)); + for (String name : names) { + list.append(new PyString(name)); } return list; } @@ -269,8 +302,7 @@ try { return FileDescriptors.get(fd).seek(pos, how); } catch (PyException pye) { - badFD(); - return -1; + throw badFD(); } } @@ -278,9 +310,22 @@ "lstat(path) -> stat result\n\n" + "Like stat(path), but do not follow symbolic links."); public static PyObject lstat(String path) { - return PyStatResult.fromFileStat(posix.lstat(new RelativeFile(path).getPath())); + return PyStatResult.fromFileStat(posix.lstat(absolutePath(path))); } + public static PyString __doc__mkdir = new PyString( + "mkdir(path [, mode=0777])\n\n" + + "Create a directory."); + public static void mkdir(String path) { + mkdir(path, 0777); + } + + public static void mkdir(String path, int mode) { + if (posix.mkdir(absolutePath(path), mode) < 0) { + throw errorFromErrno(path); + } + } + public static PyString __doc__open = new PyString( "open(filename, flag [, mode=0777]) -> fd\n\n" + "Open a file (for low level IO).\n\n" + @@ -290,6 +335,7 @@ } public static FileIO open(String path, int flag, int mode) { + ensurePath(path); boolean reading = (flag & O_RDONLY) != 0; boolean writing = (flag & O_WRONLY) != 0; boolean updating = (flag & O_RDWR) != 0; @@ -349,8 +395,7 @@ try { return StringUtil.fromBytes(FileDescriptors.get(fd).read(buffersize)); } catch (PyException pye) { - badFD(); - return null; + throw badFD(); } } @@ -360,7 +405,7 @@ "Note that some platforms may return only a small subset of the\n" + "standard fields"); public static PyObject stat(String path) { - return PyStatResult.fromFileStat(posix.stat(new RelativeFile(path).getPath())); + return PyStatResult.fromFileStat(posix.stat(absolutePath(path))); } public static PyString __doc__strerror = new PyString( @@ -387,8 +432,7 @@ try { return FileDescriptors.get(fd).write(ByteBuffer.wrap(StringUtil.toBytes(string))); } catch (PyException pye) { - badFD(); - return -1; + throw badFD(); } } @@ -430,10 +474,31 @@ return environ; } - private static void badFD() { - throw Py.OSError(Errno.EBADF); + /** + * Return the absolute form of path. + * + * @param path a path String, raising a TypeError when null + * @return an absolute path String + */ + private static String absolutePath(String path) { + ensurePath(path); + return new RelativeFile(path).getPath(); } + private static void ensurePath(String path) { + if (path == null) { + throw Py.TypeError("coercing to Unicode: need string or buffer, NoneType found"); + } + } + + private static PyException badFD() { + return Py.OSError(Errno.EBADF); + } + + private static PyException errorFromErrno(String path) { + return Py.OSError(Errno.valueOf(posix.errno()), path); + } + public static POSIX getPOSIX() { return posix; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |