Commit 38572bba authored by Georg Brandl's avatar Georg Brandl

Closes #15161: add support for giving path as a fd for truncate() and pathconf().

parent e124fa6d
......@@ -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
......
......@@ -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
......
......@@ -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):
......
......@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment