summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeorg Brandl <georg@python.org>2012-06-24 10:55:33 (GMT)
committerGeorg Brandl <georg@python.org>2012-06-24 10:55:33 (GMT)
commit306336bcdaf886c10df9c1b46886d5f0cddcaa69 (patch)
tree2f866c5adddc259acf2fb27fe8fc5d589f9d5d7a
parent8ccadaafe637d265a1e286e0261e3231ebcc678d (diff)
downloadcpython-306336bcdaf886c10df9c1b46886d5f0cddcaa69.zip
cpython-306336bcdaf886c10df9c1b46886d5f0cddcaa69.tar.gz
cpython-306336bcdaf886c10df9c1b46886d5f0cddcaa69.tar.bz2
Closes #15161: add support for giving path as a fd for truncate() and pathconf().
-rw-r--r--Doc/library/os.rst12
-rw-r--r--Lib/os.py2
-rw-r--r--Lib/test/test_os.py2
-rw-r--r--Modules/posixmodule.c82
4 files changed, 76 insertions, 22 deletions
diff --git a/Doc/library/os.rst b/Doc/library/os.rst
index a1e174d..0729a94 100644
--- a/Doc/library/os.rst
+++ b/Doc/library/os.rst
@@ -724,6 +724,8 @@ as internal buffering of data.
included in ``pathconf_names``, an :exc:`OSError` is raised with
:const:`errno.EINVAL` for the error number.
+ From Python 3.3, this is equivalent to ``os.pathconf(fd, name)``.
+
Availability: Unix.
@@ -758,8 +760,9 @@ as internal buffering of data.
.. function:: ftruncate(fd, length)
- Truncate the file corresponding to file descriptor *fd*, so that it is at most
- *length* bytes in size.
+ Truncate the file corresponding to file descriptor *fd*, so that it is at
+ most *length* bytes in size. From Python 3.3, this is equivalent to
+ ``os.truncate(fd, length)``.
Availability: Unix.
@@ -1622,6 +1625,9 @@ features:
included in ``pathconf_names``, an :exc:`OSError` is raised with
:const:`errno.EINVAL` for the error number.
+ This function can support :ref:`specifying an open file descriptor
+ <path_fd>`.
+
Availability: Unix.
@@ -2054,6 +2060,8 @@ features:
Truncate the file corresponding to *path*, so that it is at most
*length* bytes in size.
+ This function can support :ref:`specifying a file descriptor <path_fd>`.
+
Availability: Unix.
.. versionadded:: 3.3
diff --git a/Lib/os.py b/Lib/os.py
index 4a40cfe..f990627 100644
--- a/Lib/os.py
+++ b/Lib/os.py
@@ -172,8 +172,10 @@ if _exists("_have_functions"):
_add("HAVE_FDOPENDIR", "listdir")
_add("HAVE_FEXECVE", "execve")
_set.add(stat) # fstat always works
+ _add("HAVE_FTRUNCATE", "truncate")
_add("HAVE_FUTIMENS", "utime")
_add("HAVE_FUTIMES", "utime")
+ _add("HAVE_FPATHCONF", "pathconf")
if _exists("statvfs") and _exists("fstatvfs"): # mac os x10.3
_add("HAVE_FSTATVFS", "statvfs")
supports_fd = _set
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
index 654dd23..62a7dad 100644
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -1084,10 +1084,12 @@ class TestInvalidFD(unittest.TestCase):
def test_fpathconf(self):
if hasattr(os, "fpathconf"):
+ self.check(os.pathconf, "PC_NAME_MAX")
self.check(os.fpathconf, "PC_NAME_MAX")
def test_ftruncate(self):
if hasattr(os, "ftruncate"):
+ self.check(os.truncate, 0)
self.check(os.ftruncate, 0)
def test_lseek(self):
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index bfe32b8..6da030a 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -8482,28 +8482,44 @@ posix_ftruncate(PyObject *self, PyObject *args)
#ifdef HAVE_TRUNCATE
PyDoc_STRVAR(posix_truncate__doc__,
"truncate(path, length)\n\n\
-Truncate the file given by path to length bytes.");
+Truncate the file given by path to length bytes.\n\
+On some platforms, path may also be specified as an open file descriptor.\n\
+ If this functionality is unavailable, using it raises an exception.");
static PyObject *
-posix_truncate(PyObject *self, PyObject *args)
+posix_truncate(PyObject *self, PyObject *args, PyObject *kwargs)
{
- PyObject *opath;
- const char *path;
+ path_t path;
off_t length;
int res;
+ PyObject *result = NULL;
+ static char *keywords[] = {"path", "length", NULL};
- if (!PyArg_ParseTuple(args, "O&O&:truncate",
- PyUnicode_FSConverter, &opath, _parse_off_t, &length))
+ memset(&path, 0, sizeof(path));
+#ifdef HAVE_FTRUNCATE
+ path.allow_fd = 1;
+#endif
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&:truncate", keywords,
+ path_converter, &path,
+ _parse_off_t, &length))
return NULL;
- path = PyBytes_AsString(opath);
Py_BEGIN_ALLOW_THREADS
- res = truncate(path, length);
+#ifdef HAVE_FTRUNCATE
+ if (path.fd != -1)
+ res = ftruncate(path.fd, length);
+ else
+#endif
+ res = truncate(path.narrow, length);
Py_END_ALLOW_THREADS
- Py_DECREF(opath);
if (res < 0)
- return posix_error();
- Py_RETURN_NONE;
+ result = path_posix_error("truncate", &path);
+ else {
+ Py_INCREF(Py_None);
+ result = Py_None;
+ }
+ path_cleanup(&path);
+ return result;
}
#endif
@@ -9219,31 +9235,45 @@ posix_fpathconf(PyObject *self, PyObject *args)
PyDoc_STRVAR(posix_pathconf__doc__,
"pathconf(path, name) -> integer\n\n\
Return the configuration limit name for the file or directory path.\n\
-If there is no limit, return -1.");
+If there is no limit, return -1.\n\
+On some platforms, path may also be specified as an open file descriptor.\n\
+ If this functionality is unavailable, using it raises an exception.");
static PyObject *
-posix_pathconf(PyObject *self, PyObject *args)
+posix_pathconf(PyObject *self, PyObject *args, PyObject *kwargs)
{
+ path_t path;
PyObject *result = NULL;
int name;
- char *path;
+ static char *keywords[] = {"path", "name", NULL};
- if (PyArg_ParseTuple(args, "sO&:pathconf", &path,
- conv_path_confname, &name)) {
+ memset(&path, 0, sizeof(path));
+#ifdef HAVE_FPATHCONF
+ path.allow_fd = 1;
+#endif
+ if (PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&:pathconf", keywords,
+ path_converter, &path,
+ conv_path_confname, &name)) {
long limit;
errno = 0;
- limit = pathconf(path, name);
+#ifdef HAVE_FPATHCONF
+ if (path.fd != -1)
+ limit = fpathconf(path.fd, name);
+ else
+#endif
+ limit = pathconf(path.narrow, name);
if (limit == -1 && errno != 0) {
if (errno == EINVAL)
/* could be a path or name problem */
posix_error();
else
- posix_error_with_filename(path);
+ result = path_posix_error("pathconf", &path);
}
else
result = PyLong_FromLong(limit);
}
+ path_cleanup(&path);
return result;
}
#endif
@@ -11078,7 +11108,9 @@ static PyMethodDef posix_methods[] = {
{"ftruncate", posix_ftruncate, METH_VARARGS, posix_ftruncate__doc__},
#endif
#ifdef HAVE_TRUNCATE
- {"truncate", posix_truncate, METH_VARARGS, posix_truncate__doc__},
+ {"truncate", (PyCFunction)posix_truncate,
+ METH_VARARGS | METH_KEYWORDS,
+ posix_truncate__doc__},
#endif
#ifdef HAVE_POSIX_FALLOCATE
{"posix_fallocate", posix_posix_fallocate, METH_VARARGS, posix_posix_fallocate__doc__},
@@ -11149,7 +11181,9 @@ static PyMethodDef posix_methods[] = {
{"fpathconf", posix_fpathconf, METH_VARARGS, posix_fpathconf__doc__},
#endif
#ifdef HAVE_PATHCONF
- {"pathconf", posix_pathconf, METH_VARARGS, posix_pathconf__doc__},
+ {"pathconf", (PyCFunction)posix_pathconf,
+ METH_VARARGS | METH_KEYWORDS,
+ posix_pathconf__doc__},
#endif
{"abort", posix_abort, METH_NOARGS, posix_abort__doc__},
#ifdef MS_WINDOWS
@@ -11741,6 +11775,10 @@ static char *have_functions[] = {
"HAVE_FDOPENDIR",
#endif
+#ifdef HAVE_FPATHCONF
+ "HAVE_FPATHCONF",
+#endif
+
#ifdef HAVE_FSTATAT
"HAVE_FSTATAT",
#endif
@@ -11749,6 +11787,10 @@ static char *have_functions[] = {
"HAVE_FSTATVFS",
#endif
+#ifdef HAVE_FTRUNCATE
+ "HAVE_FTRUNCATE",
+#endif
+
#ifdef HAVE_FUTIMENS
"HAVE_FUTIMENS",
#endif