diff --git Doc/library/os.rst Doc/library/os.rst index 0547154..5c34cb3 100644 --- Doc/library/os.rst +++ Doc/library/os.rst @@ -437,6 +437,9 @@ process will then be assigned 3, 4, 5, and so forth. The name "file descriptor" is slightly deceptive; on Unix platforms, sockets and pipes are also referenced by file descriptors. +For these functions, the file descriptor can either be an integer, or an object +with a fileno() method which returns the actual file descriptor. + .. function:: close(fd) @@ -552,7 +555,6 @@ by file descriptors. Return ``True`` if the file descriptor *fd* is open and connected to a tty(-like) device, else ``False``. Availability: Unix. - .. function:: lseek(fd, pos, how) Set the current position of file descriptor *fd* to position *pos*, modified @@ -561,7 +563,6 @@ by file descriptors. current position; :const:`os.SEEK_END` or ``2`` to set it relative to the end of the file. Availability: Unix, Windows. - .. function:: open(file, flags[, mode]) Open the file *file* and set various flags according to *flags* and possibly @@ -617,7 +618,6 @@ by file descriptors. Return the process group associated with the terminal given by *fd* (an open file descriptor as returned by :func:`os.open`). Availability: Unix. - .. function:: tcsetpgrp(fd, pg) Set the process group associated with the terminal given by *fd* (an open file diff --git Lib/test/test_posix.py Lib/test/test_posix.py index fa1abe3..c60af24 100644 --- Lib/test/test_posix.py +++ Lib/test/test_posix.py @@ -116,6 +116,7 @@ class PosixTester(unittest.TestCase): fp = open(support.TESTFN) try: self.assertTrue(posix.fstatvfs(fp.fileno())) + self.assertTrue(posix.fstatvfs(fp)) finally: fp.close() @@ -129,6 +130,14 @@ class PosixTester(unittest.TestCase): posix.ftruncate(fp.fileno(), 0) finally: fp.close() + fp = open(support.TESTFN, 'w+') + try: + fp.write('test') + fp.flush() + posix.ftruncate(fp, 0) + finally: + fp.close() + def test_dup(self): if hasattr(posix, 'dup'): @@ -139,6 +148,14 @@ class PosixTester(unittest.TestCase): os.close(fd) finally: fp.close() + fp = open(support.TESTFN) + try: + fd = posix.dup(fp) + self.assert_(isinstance(fd, int)) + os.close(fd) + finally: + fp.close() + def test_confstr(self): if hasattr(posix, 'confstr'): @@ -191,6 +208,7 @@ class PosixTester(unittest.TestCase): fp = open(support.TESTFN) try: self.assertTrue(posix.fstat(fp.fileno())) + self.assertTrue(posix.fstat(fp)) finally: fp.close() diff --git Modules/posixmodule.c Modules/posixmodule.c index 5076d3b..e1c8587 100644 --- Modules/posixmodule.c +++ Modules/posixmodule.c @@ -1796,9 +1796,13 @@ descriptor fd."); static PyObject * posix_fchmod(PyObject *self, PyObject *args) { + PyObject *fdobj; int fd, mode, res; - if (!PyArg_ParseTuple(args, "ii:fchmod", &fd, &mode)) + if (!PyArg_ParseTuple(args, "Oi:fchmod", &fdobj, &mode)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj); + if (fd == -1) + return NULL; /* Rely on AsFileDescriptor's error handling */ Py_BEGIN_ALLOW_THREADS res = fchmod(fd, mode); Py_END_ALLOW_THREADS @@ -1971,11 +1975,15 @@ fd to the numeric uid and gid."); static PyObject * posix_fchown(PyObject *self, PyObject *args) { + PyObject *fdobj; int fd; long uid, gid; int res; - if (!PyArg_ParseTuple(args, "ill:chown", &fd, &uid, &gid)) + if (!PyArg_ParseTuple(args, "Oll:chown", &fdobj, &uid, &gid)) return NULL; + if (fd == -1) + return NULL; /* Rely on AsFileDescriptor's error handling */ + fd = PyObject_AsFileDescriptor(fdobj); Py_BEGIN_ALLOW_THREADS res = fchown(fd, (uid_t) uid, (gid_t) gid); Py_END_ALLOW_THREADS @@ -4836,10 +4844,14 @@ Return the process group associated with the terminal given by a fd."); static PyObject * posix_tcgetpgrp(PyObject *self, PyObject *args) { + PyObject *fdobj; int fd; pid_t pgid; - if (!PyArg_ParseTuple(args, "i:tcgetpgrp", &fd)) + if (!PyArg_ParseTuple(args, "O:tcgetpgrp", &fdobj)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj); + if (fd == -1) + return NULL; /* Rely on AsFileDescriptor's error handling */ pgid = tcgetpgrp(fd); if (pgid < 0) return posix_error(); @@ -4856,10 +4868,14 @@ Set the process group associated with the terminal given by a fd."); static PyObject * posix_tcsetpgrp(PyObject *self, PyObject *args) { + PyObject *fdobj; int fd; pid_t pgid; - if (!PyArg_ParseTuple(args, "i" _Py_PARSE_PID ":tcsetpgrp", &fd, &pgid)) + if (!PyArg_ParseTuple(args, "O" _Py_PARSE_PID ":tcsetpgrp", &fdobj, &pgid)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj); + if (fd == -1) + return NULL; /* Rely on AsFileDescriptor's error handling */ if (tcsetpgrp(fd, pgid) < 0) return posix_error(); Py_INCREF(Py_None); @@ -4921,9 +4937,12 @@ Close a file descriptor (for low level IO)."); static PyObject * posix_close(PyObject *self, PyObject *args) { + PyObject *fdobj; int fd, res; - if (!PyArg_ParseTuple(args, "i:close", &fd)) + if (!PyArg_ParseTuple(args, "O:close", &fdobj)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj); + /* Rely on PyVerify to detect error cases */ if (!_PyVerify_fd(fd)) return posix_error(); Py_BEGIN_ALLOW_THREADS @@ -4962,9 +4981,12 @@ Return a duplicate of a file descriptor."); static PyObject * posix_dup(PyObject *self, PyObject *args) { + PyObject *fdobj; int fd; - if (!PyArg_ParseTuple(args, "i:dup", &fd)) + if (!PyArg_ParseTuple(args, "O:dup", &fdobj)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj); + /* Rely on PyVerify to detect error cases */ if (!_PyVerify_fd(fd)) return posix_error(); Py_BEGIN_ALLOW_THREADS @@ -4983,9 +5005,12 @@ Duplicate file descriptor."); static PyObject * posix_dup2(PyObject *self, PyObject *args) { + PyObject *fdobj1, *fdobj2; int fd, fd2, res; - if (!PyArg_ParseTuple(args, "ii:dup2", &fd, &fd2)) + if (!PyArg_ParseTuple(args, "OO:dup2", &fdobj1, &fdobj2)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj1); + fd2 = PyObject_AsFileDescriptor(fdobj2); if (!_PyVerify_fd_dup2(fd, fd2)) return posix_error(); Py_BEGIN_ALLOW_THREADS @@ -5011,9 +5036,13 @@ posix_lseek(PyObject *self, PyObject *args) #else off_t pos, res; #endif + PyObject *fdobj; PyObject *posobj; - if (!PyArg_ParseTuple(args, "iOi:lseek", &fd, &posobj, &how)) + if (!PyArg_ParseTuple(args, "OOi:lseek", &fdobj, &posobj, &how)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj); + if (fd == -1) + return NULL; /* Rely on AsFileDescriptor's error handling */ #ifdef SEEK_SET /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */ switch (how) { @@ -5059,11 +5088,15 @@ Read a file descriptor."); static PyObject * posix_read(PyObject *self, PyObject *args) { + PyObject *fdobj; int fd, size; Py_ssize_t n; PyObject *buffer; - if (!PyArg_ParseTuple(args, "ii:read", &fd, &size)) + if (!PyArg_ParseTuple(args, "Oi:read", &fdobj, &size)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj); + if (fd == -1) + return NULL; /* Rely on AsFileDescriptor's error handling */ if (size < 0) { errno = EINVAL; return posix_error(); @@ -5093,12 +5126,15 @@ Write a string to a file descriptor."); static PyObject * posix_write(PyObject *self, PyObject *args) { + PyObject *fdobj; Py_buffer pbuf; int fd; Py_ssize_t size; - if (!PyArg_ParseTuple(args, "iy*:write", &fd, &pbuf)) + if (!PyArg_ParseTuple(args, "Oy*:write", &fdobj, &pbuf)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj); + /* Rely on PyVerify to detect error cases */ if (!_PyVerify_fd(fd)) return posix_error(); Py_BEGIN_ALLOW_THREADS @@ -5118,11 +5154,15 @@ Like stat(), but for an open file descriptor."); static PyObject * posix_fstat(PyObject *self, PyObject *args) { - int fd; + PyObject *fdobj; STRUCT_STAT st; int res; - if (!PyArg_ParseTuple(args, "i:fstat", &fd)) + int fd; + if (!PyArg_ParseTuple(args, "O:fstat", &fdobj)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj); + if (fd == -1) + return NULL; /* Rely on AsFileDescriptor's error handling */ #ifdef __VMS /* on OpenVMS we must ensure that all bytes are written to the file */ fsync(fd); @@ -5151,9 +5191,12 @@ connected to the slave end of a terminal."); static PyObject * posix_isatty(PyObject *self, PyObject *args) { + PyObject *fdobj; int fd; - if (!PyArg_ParseTuple(args, "i:isatty", &fd)) + if (!PyArg_ParseTuple(args, "O:isatty", &fdobj)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj); + /* Rely on PyVerify to detect error cases */ if (!_PyVerify_fd(fd)) return PyBool_FromLong(0); return PyBool_FromLong(isatty(fd)); @@ -5310,13 +5353,17 @@ Truncate a file to a specified length."); static PyObject * posix_ftruncate(PyObject *self, PyObject *args) { + PyObject *fdobj; int fd; off_t length; int res; PyObject *lenobj; - if (!PyArg_ParseTuple(args, "iO:ftruncate", &fd, &lenobj)) + if (!PyArg_ParseTuple(args, "OO:ftruncate", &fdobj, &lenobj)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj); + if (fd == -1) + return NULL; /* Rely on AsFileDescriptor's error handling */ #if !defined(HAVE_LARGEFILE_SUPPORT) length = PyLong_AsLong(lenobj); @@ -5706,11 +5753,15 @@ Perform an fstatvfs system call on the given fd."); static PyObject * posix_fstatvfs(PyObject *self, PyObject *args) { + PyObject *fdobj; int fd, res; struct statvfs st; - if (!PyArg_ParseTuple(args, "i:fstatvfs", &fd)) + if (!PyArg_ParseTuple(args, "O:fstatvfs", &fdobj)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj); + if (fd == -1) + return NULL; /* Rely on AsFileDescriptor's error handling */ Py_BEGIN_ALLOW_THREADS res = fstatvfs(fd, &st); Py_END_ALLOW_THREADS @@ -5878,10 +5929,15 @@ static PyObject * posix_fpathconf(PyObject *self, PyObject *args) { PyObject *result = NULL; + PyObject *fdobj; int name, fd; - if (PyArg_ParseTuple(args, "iO&:fpathconf", &fd, + if (PyArg_ParseTuple(args, "OO&:fpathconf", &fdobj, conv_path_confname, &name)) { + + fd = PyObject_AsFileDescriptor(fdobj); + if (fd == -1) + return NULL; /* Rely on AsFileDescriptor's error handling */ long limit; errno = 0;