From 316d2425f76f1c24dc1423f7e1c6737d982da08d Mon Sep 17 00:00:00 2001 From: Hristo Venev Date: Mon, 7 Mar 2016 14:07:43 +0200 Subject: [PATCH] fcntl: support F_OFD_* Also fix start/len conversion to off{,64}_t --- Lib/test/test_fcntl.py | 19 +++++++++++++++++++ Modules/clinic/fcntlmodule.c.h | 19 +++++++++++-------- Modules/fcntlmodule.c | 35 +++++++++++++++++++++++++---------- 3 files changed, 55 insertions(+), 18 deletions(-) diff --git a/Lib/test/test_fcntl.py b/Lib/test/test_fcntl.py index e3b7ed2..c54b5cd 100644 --- a/Lib/test/test_fcntl.py +++ b/Lib/test/test_fcntl.py @@ -11,6 +11,11 @@ from test.support import (verbose, TESTFN, unlink, run_unittest, import_module, # Skip test if no fcntl module. fcntl = import_module('fcntl') +class NotInt: + def __init__(self, a): + self.a=a + def __int__(self): + return self.a # TODO - Write tests for flock() and lockf(). @@ -134,6 +139,20 @@ class TestFcntl(unittest.TestCase): fcntl.flock(self.f, fcntl.LOCK_UN) fcntl.flock(fileno, fcntl.LOCK_EX) fcntl.flock(fileno, fcntl.LOCK_UN) + fcntl.lockf(fileno, fcntl.LOCK_EX, 2**31-1) + fcntl.lockf(fileno, fcntl.LOCK_EX, 2**31) + fcntl.lockf(fileno, fcntl.LOCK_EX, NotInt(2**31-1)) + fcntl.lockf(fileno, fcntl.LOCK_EX, NotInt(2**31)) + self.assertRaises(BlockingIOError, fcntl.lockf, fileno, fcntl.LOCK_EX | fcntl.LOCK_NB, open_file_descriptor=True) + fcntl.lockf(fileno, fcntl.LOCK_UN) + fcntl.lockf(fileno, fcntl.LOCK_SH) + fcntl.lockf(fileno, fcntl.LOCK_SH | fcntl.LOCK_NB) + fcntl.lockf(fileno, fcntl.LOCK_SH | fcntl.LOCK_NB, open_file_descriptor=True) + fcntl.lockf(fileno, fcntl.LOCK_SH | fcntl.LOCK_NB, open_file_descriptor=True) + self.assertRaises(BlockingIOError, fcntl.lockf, fileno, fcntl.LOCK_EX | fcntl.LOCK_NB, open_file_descriptor=True) + fcntl.lockf(fileno, fcntl.LOCK_UN) + fcntl.lockf(fileno, fcntl.LOCK_EX | fcntl.LOCK_NB, open_file_descriptor=True) + fcntl.lockf(fileno, fcntl.LOCK_UN, open_file_descriptor=True) self.assertRaises(ValueError, fcntl.flock, -1, fcntl.LOCK_SH) self.assertRaises(TypeError, fcntl.flock, 'spam', fcntl.LOCK_SH) diff --git a/Modules/clinic/fcntlmodule.c.h b/Modules/clinic/fcntlmodule.c.h index 5e3b1c0..8cecf8f 100644 --- a/Modules/clinic/fcntlmodule.c.h +++ b/Modules/clinic/fcntlmodule.c.h @@ -131,7 +131,8 @@ exit: } PyDoc_STRVAR(fcntl_lockf__doc__, -"lockf($module, fd, cmd, len=0, start=0, whence=0, /)\n" +"lockf($module, /, fd, cmd, len=0, start=0, whence=0,\n" +" open_file_descriptor=False)\n" "--\n" "\n" "A wrapper around the fcntl() locking calls.\n" @@ -158,28 +159,30 @@ PyDoc_STRVAR(fcntl_lockf__doc__, " 2 - relative to the end of the file (SEEK_END)"); #define FCNTL_LOCKF_METHODDEF \ - {"lockf", (PyCFunction)fcntl_lockf, METH_VARARGS, fcntl_lockf__doc__}, + {"lockf", (PyCFunction)fcntl_lockf, METH_VARARGS|METH_KEYWORDS, fcntl_lockf__doc__}, static PyObject * fcntl_lockf_impl(PyModuleDef *module, int fd, int code, PyObject *lenobj, - PyObject *startobj, int whence); + PyObject *startobj, int whence, int open_file_descriptor); static PyObject * -fcntl_lockf(PyModuleDef *module, PyObject *args) +fcntl_lockf(PyModuleDef *module, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; + static char *_keywords[] = {"fd", "cmd", "len", "start", "whence", "open_file_descriptor", NULL}; int fd; int code; PyObject *lenobj = NULL; PyObject *startobj = NULL; int whence = 0; + int open_file_descriptor = 0; - if (!PyArg_ParseTuple(args, "O&i|OOi:lockf", - conv_descriptor, &fd, &code, &lenobj, &startobj, &whence)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&i|OOip:lockf", _keywords, + conv_descriptor, &fd, &code, &lenobj, &startobj, &whence, &open_file_descriptor)) goto exit; - return_value = fcntl_lockf_impl(module, fd, code, lenobj, startobj, whence); + return_value = fcntl_lockf_impl(module, fd, code, lenobj, startobj, whence, open_file_descriptor); exit: return return_value; } -/*[clinic end generated code: output=92963b631d00f0fe input=a9049054013a1b77]*/ +/*[clinic end generated code: output=782df12c4b8098ad input=a9049054013a1b77]*/ diff --git a/Modules/fcntlmodule.c b/Modules/fcntlmodule.c index 97ff07c..b100498 100644 --- a/Modules/fcntlmodule.c +++ b/Modules/fcntlmodule.c @@ -331,7 +331,7 @@ fcntl.lockf len as lenobj: object(c_default='NULL') = 0 start as startobj: object(c_default='NULL') = 0 whence: int = 0 - / + open_file_descriptor: bool = False A wrapper around the fcntl() locking calls. @@ -359,8 +359,8 @@ starts. `whence` is as with fileobj.seek(), specifically: static PyObject * fcntl_lockf_impl(PyModuleDef *module, int fd, int code, PyObject *lenobj, - PyObject *startobj, int whence) -/*[clinic end generated code: output=31af35eba08b9af7 input=9c594391de821f24]*/ + PyObject *startobj, int whence, int open_file_descriptor) +/*[clinic end generated code: output=35b767f635507cd4 input=57433c68e144e94b]*/ { int ret; @@ -388,9 +388,7 @@ fcntl_lockf_impl(PyModuleDef *module, int fd, int code, PyObject *lenobj, #if !defined(HAVE_LARGEFILE_SUPPORT) l.l_start = PyLong_AsLong(startobj); #else - l.l_start = PyLong_Check(startobj) ? - PyLong_AsLongLong(startobj) : - PyLong_AsLong(startobj); + l.l_start = PyLong_AsLongLong(startobj); #endif if (PyErr_Occurred()) return NULL; @@ -399,16 +397,24 @@ fcntl_lockf_impl(PyModuleDef *module, int fd, int code, PyObject *lenobj, #if !defined(HAVE_LARGEFILE_SUPPORT) l.l_len = PyLong_AsLong(lenobj); #else - l.l_len = PyLong_Check(lenobj) ? - PyLong_AsLongLong(lenobj) : - PyLong_AsLong(lenobj); + l.l_len = PyLong_AsLongLong(lenobj); #endif if (PyErr_Occurred()) return NULL; } l.l_whence = whence; + l.l_pid = 0; Py_BEGIN_ALLOW_THREADS - ret = fcntl(fd, (code & LOCK_NB) ? F_SETLK : F_SETLKW, &l); + if (open_file_descriptor) { +#ifdef F_OFD_SETLK + ret = fcntl(fd, (code & LOCK_NB) ? F_OFD_SETLK : F_OFD_SETLKW, &l); +#else + PyErr_SetString(PyExc_NotImplementedError, + "lockf: open_file_descriptor not supported on this platform"); + return NULL; +#endif + } else + ret = fcntl(fd, (code & LOCK_NB) ? F_SETLK : F_SETLKW, &l); Py_END_ALLOW_THREADS } if (ret < 0) { @@ -486,6 +492,15 @@ all_ins(PyObject* m) #ifdef F_SETLKW if (PyModule_AddIntMacro(m, F_SETLKW)) return -1; #endif +#ifdef F_OFD_GETLK + if (PyModule_AddIntMacro(m, F_OFD_GETLK)) return -1; +#endif +#ifdef F_OFD_SETLK + if (PyModule_AddIntMacro(m, F_OFD_SETLK)) return -1; +#endif +#ifdef F_OFD_SETLKW + if (PyModule_AddIntMacro(m, F_OFD_SETLKW)) return -1; +#endif #ifdef F_GETOWN if (PyModule_AddIntMacro(m, F_GETOWN)) return -1; #endif -- 2.7.2