diff -r 9725ddcd37e6 Doc/library/os.rst --- a/Doc/library/os.rst Sun Jun 24 11:57:07 2012 +0200 +++ b/Doc/library/os.rst Sun Jun 24 12:29:50 2012 +0200 @@ -753,7 +753,7 @@ 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. + *length* bytes in size. Equivalent to ``os.truncate(fd, length)``. Availability: Unix. @@ -2057,6 +2057,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 `. + Availability: Unix. .. versionadded:: 3.3 diff -r 9725ddcd37e6 Lib/os.py --- a/Lib/os.py Sun Jun 24 11:57:07 2012 +0200 +++ b/Lib/os.py Sun Jun 24 12:29:50 2012 +0200 @@ -172,6 +172,7 @@ 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") if _exists("statvfs") and _exists("fstatvfs"): # mac os x10.3 diff -r 9725ddcd37e6 Modules/posixmodule.c --- a/Modules/posixmodule.c Sun Jun 24 11:57:07 2012 +0200 +++ b/Modules/posixmodule.c Sun Jun 24 12:29:50 2012 +0200 @@ -8482,28 +8482,44 @@ posix_ftruncate(PyObject *self, PyObject #ifdef HAVE_TRUNCATE PyDoc_STRVAR(posix_truncate__doc__, "truncate(path, length)\n\n\ -Truncate the file given by path to length bytes."); - -static PyObject * -posix_truncate(PyObject *self, PyObject *args) -{ - PyObject *opath; - const char *path; +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, PyObject *kwargs) +{ + path_t path; off_t length; int res; - - if (!PyArg_ParseTuple(args, "O&O&:truncate", - PyUnicode_FSConverter, &opath, _parse_off_t, &length)) - return NULL; - path = PyBytes_AsString(opath); + PyObject *result = NULL; + static char *keywords[] = {"path", "length", NULL}; + + 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; 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_error("truncate", &path); + else { + Py_INCREF(Py_None); + result = Py_None; + } + path_cleanup(&path); + return result; } #endif @@ -11078,7 +11094,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__}, @@ -11749,6 +11767,10 @@ static char *have_functions[] = { "HAVE_FSTATVFS", #endif +#ifdef HAVE_FTRUNCATE + "HAVE_FTRUNCATE", +#endif + #ifdef HAVE_FUTIMENS "HAVE_FUTIMENS", #endif