Skip to content

Commit b7299dd

Browse files
committed
Issue 20152, 22821: Port the fcntl module to Argument Clinic.
Along the way, fix an argumrnt to fcntl.fcntl to be an int instead of a long. Thanks to Serhiy Storchaka for reviewing my Clinic patch and for writing the patch to fix the long/int issue.
1 parent df1b699 commit b7299dd

2 files changed

Lines changed: 416 additions & 210 deletions

File tree

‎Modules/clinic/fcntlmodule.c.h‎

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
/*[clinic input]
2+
preserve
3+
[clinic start generated code]*/
4+
5+
PyDoc_STRVAR(fcntl_fcntl__doc__,
6+
"fcntl($module, fd, code, arg=None, /)\n"
7+
"--\n"
8+
"\n"
9+
"Perform the operation `code` on file descriptor fd.\n"
10+
"\n"
11+
"The values used for `code` are operating system dependent, and are available\n"
12+
"as constants in the fcntl module, using the same names as used in\n"
13+
"the relevant C header files. The argument arg is optional, and\n"
14+
"defaults to 0; it may be an int or a string. If arg is given as a string,\n"
15+
"the return value of fcntl is a string of that length, containing the\n"
16+
"resulting value put in the arg buffer by the operating system. The length\n"
17+
"of the arg string is not allowed to exceed 1024 bytes. If the arg given\n"
18+
"is an integer or if none is specified, the result value is an integer\n"
19+
"corresponding to the return value of the fcntl call in the C code.");
20+
21+
#define FCNTL_FCNTL_METHODDEF \
22+
{"fcntl", (PyCFunction)fcntl_fcntl, METH_VARARGS, fcntl_fcntl__doc__},
23+
24+
static PyObject *
25+
fcntl_fcntl_impl(PyModuleDef *module, int fd, int code, PyObject *arg);
26+
27+
static PyObject *
28+
fcntl_fcntl(PyModuleDef *module, PyObject *args)
29+
{
30+
PyObject *return_value = NULL;
31+
int fd;
32+
int code;
33+
PyObject *arg = NULL;
34+
35+
if (!PyArg_ParseTuple(args,
36+
"O&i|O:fcntl",
37+
conv_descriptor, &fd, &code, &arg))
38+
goto exit;
39+
return_value = fcntl_fcntl_impl(module, fd, code, arg);
40+
41+
exit:
42+
return return_value;
43+
}
44+
45+
PyDoc_STRVAR(fcntl_ioctl__doc__,
46+
"ioctl($module, fd, op, arg=None, mutate_flag=True, /)\n"
47+
"--\n"
48+
"\n"
49+
"Perform the operation op on file descriptor fd.\n"
50+
"\n"
51+
"The values used for op are operating system dependent, and are available as\n"
52+
"constants in the fcntl or termios library modules, using the same names as\n"
53+
"used in the relevant C header files.\n"
54+
"\n"
55+
"The argument `arg` is optional, and defaults to 0; it may be an int or a\n"
56+
"buffer containing character data (most likely a string or an array).\n"
57+
"\n"
58+
"If the argument is a mutable buffer (such as an array) and if the\n"
59+
"mutate_flag argument (which is only allowed in this case) is true then the\n"
60+
"buffer is (in effect) passed to the operating system and changes made by\n"
61+
"the OS will be reflected in the contents of the buffer after the call has\n"
62+
"returned. The return value is the integer returned by the ioctl system\n"
63+
"call.\n"
64+
"\n"
65+
"If the argument is a mutable buffer and the mutable_flag argument is not\n"
66+
"passed or is false, the behavior is as if a string had been passed. This\n"
67+
"behavior will change in future releases of Python.\n"
68+
"\n"
69+
"If the argument is an immutable buffer (most likely a string) then a copy\n"
70+
"of the buffer is passed to the operating system and the return value is a\n"
71+
"string of the same length containing whatever the operating system put in\n"
72+
"the buffer. The length of the arg buffer in this case is not allowed to\n"
73+
"exceed 1024 bytes.\n"
74+
"\n"
75+
"If the arg given is an integer or if none is specified, the result value is\n"
76+
"an integer corresponding to the return value of the ioctl call in the C\n"
77+
"code.");
78+
79+
#define FCNTL_IOCTL_METHODDEF \
80+
{"ioctl", (PyCFunction)fcntl_ioctl, METH_VARARGS, fcntl_ioctl__doc__},
81+
82+
static PyObject *
83+
fcntl_ioctl_impl(PyModuleDef *module, int fd, unsigned int code, PyObject *ob_arg, int mutate_arg);
84+
85+
static PyObject *
86+
fcntl_ioctl(PyModuleDef *module, PyObject *args)
87+
{
88+
PyObject *return_value = NULL;
89+
int fd;
90+
unsigned int code;
91+
PyObject *ob_arg = NULL;
92+
int mutate_arg = 1;
93+
94+
if (!PyArg_ParseTuple(args,
95+
"O&I|Op:ioctl",
96+
conv_descriptor, &fd, &code, &ob_arg, &mutate_arg))
97+
goto exit;
98+
return_value = fcntl_ioctl_impl(module, fd, code, ob_arg, mutate_arg);
99+
100+
exit:
101+
return return_value;
102+
}
103+
104+
PyDoc_STRVAR(fcntl_flock__doc__,
105+
"flock($module, fd, code, /)\n"
106+
"--\n"
107+
"\n"
108+
"Perform the lock operation op on file descriptor fd.\n"
109+
"\n"
110+
"See the Unix manual page for flock(2) for details (On some systems, this\n"
111+
"function is emulated using fcntl()).");
112+
113+
#define FCNTL_FLOCK_METHODDEF \
114+
{"flock", (PyCFunction)fcntl_flock, METH_VARARGS, fcntl_flock__doc__},
115+
116+
static PyObject *
117+
fcntl_flock_impl(PyModuleDef *module, int fd, int code);
118+
119+
static PyObject *
120+
fcntl_flock(PyModuleDef *module, PyObject *args)
121+
{
122+
PyObject *return_value = NULL;
123+
int fd;
124+
int code;
125+
126+
if (!PyArg_ParseTuple(args,
127+
"O&i:flock",
128+
conv_descriptor, &fd, &code))
129+
goto exit;
130+
return_value = fcntl_flock_impl(module, fd, code);
131+
132+
exit:
133+
return return_value;
134+
}
135+
136+
PyDoc_STRVAR(fcntl_lockf__doc__,
137+
"lockf($module, fd, code, lenobj=None, startobj=None, whence=0, /)\n"
138+
"--\n"
139+
"\n"
140+
"A wrapper around the fcntl() locking calls.\n"
141+
"\n"
142+
"fd is the file descriptor of the file to lock or unlock, and operation is one\n"
143+
"of the following values:\n"
144+
"\n"
145+
" LOCK_UN - unlock\n"
146+
" LOCK_SH - acquire a shared lock\n"
147+
" LOCK_EX - acquire an exclusive lock\n"
148+
"\n"
149+
"When operation is LOCK_SH or LOCK_EX, it can also be bitwise ORed with\n"
150+
"LOCK_NB to avoid blocking on lock acquisition. If LOCK_NB is used and the\n"
151+
"lock cannot be acquired, an IOError will be raised and the exception will\n"
152+
"have an errno attribute set to EACCES or EAGAIN (depending on the operating\n"
153+
"system -- for portability, check for either value).\n"
154+
"\n"
155+
"length is the number of bytes to lock, with the default meaning to lock to\n"
156+
"EOF. start is the byte offset, relative to whence, to that the lock\n"
157+
"starts. whence is as with fileobj.seek(), specifically:\n"
158+
"\n"
159+
" 0 - relative to the start of the file (SEEK_SET)\n"
160+
" 1 - relative to the current buffer position (SEEK_CUR)\n"
161+
" 2 - relative to the end of the file (SEEK_END)");
162+
163+
#define FCNTL_LOCKF_METHODDEF \
164+
{"lockf", (PyCFunction)fcntl_lockf, METH_VARARGS, fcntl_lockf__doc__},
165+
166+
static PyObject *
167+
fcntl_lockf_impl(PyModuleDef *module, int fd, int code, PyObject *lenobj, PyObject *startobj, int whence);
168+
169+
static PyObject *
170+
fcntl_lockf(PyModuleDef *module, PyObject *args)
171+
{
172+
PyObject *return_value = NULL;
173+
int fd;
174+
int code;
175+
PyObject *lenobj = NULL;
176+
PyObject *startobj = NULL;
177+
int whence = 0;
178+
179+
if (!PyArg_ParseTuple(args,
180+
"O&i|OOi:lockf",
181+
conv_descriptor, &fd, &code, &lenobj, &startobj, &whence))
182+
goto exit;
183+
return_value = fcntl_lockf_impl(module, fd, code, lenobj, startobj, whence);
184+
185+
exit:
186+
return return_value;
187+
}
188+
/*[clinic end generated code: output=84bdde73a92f7c61 input=a9049054013a1b77]*/

0 commit comments

Comments
 (0)