fcntlmodule.c revision 3886bb6997f8f7b0b64eed19045161e697f415fe
1/***********************************************************
2Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
4
5                        All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
16
17While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
29
30******************************************************************/
31
32/* fcntl module */
33
34#include "Python.h"
35
36#ifdef HAVE_UNISTD_H
37#include <unistd.h>
38#endif
39
40#ifdef HAVE_SYS_FILE_H
41#include <sys/file.h>
42#endif
43
44#include <sys/ioctl.h>
45#include <fcntl.h>
46
47
48/* fcntl(fd, opt, [arg]) */
49
50static PyObject *
51fcntl_fcntl(self, args)
52	PyObject *self; /* Not used */
53	PyObject *args;
54{
55	int fd;
56	int code;
57	int arg;
58	int ret;
59	char *str;
60	int len;
61	char buf[1024];
62
63	if (PyArg_Parse(args, "(iis#)", &fd, &code, &str, &len)) {
64		if (len > sizeof buf) {
65			PyErr_SetString(PyExc_ValueError,
66					"fcntl string arg too long");
67			return NULL;
68		}
69		memcpy(buf, str, len);
70		Py_BEGIN_ALLOW_THREADS
71		ret = fcntl(fd, code, buf);
72		Py_END_ALLOW_THREADS
73		if (ret < 0) {
74			PyErr_SetFromErrno(PyExc_IOError);
75			return NULL;
76		}
77		return PyString_FromStringAndSize(buf, len);
78	}
79
80	PyErr_Clear();
81	if (PyArg_Parse(args, "(ii)", &fd, &code))
82		arg = 0;
83	else {
84		PyErr_Clear();
85		if (!PyArg_Parse(args, "(iii)", &fd, &code, &arg))
86			return NULL;
87	}
88	Py_BEGIN_ALLOW_THREADS
89	ret = fcntl(fd, code, arg);
90	Py_END_ALLOW_THREADS
91	if (ret < 0) {
92		PyErr_SetFromErrno(PyExc_IOError);
93		return NULL;
94	}
95	return PyInt_FromLong((long)ret);
96}
97
98static char fcntl_doc [] =
99
100"fcntl(fd, opt, [arg])\n\
101\n\
102Perform the requested operation on file descriptor fd.  The operation\n\
103is defined by op and is operating system dependent.  Typically these\n\
104codes can be retrieved from the library module FCNTL.  The argument arg\n\
105is optional, and defaults to 0; it may be an int or a string.";
106
107
108/* ioctl(fd, opt, [arg]) */
109
110static PyObject *
111fcntl_ioctl(self, args)
112	PyObject *self; /* Not used */
113	PyObject *args;
114{
115	int fd;
116	int code;
117	int arg;
118	int ret;
119	char *str;
120	int len;
121	char buf[1024];
122
123	if (PyArg_Parse(args, "(iis#)", &fd, &code, &str, &len)) {
124		if (len > sizeof buf) {
125			PyErr_SetString(PyExc_ValueError,
126					"ioctl string arg too long");
127			return NULL;
128		}
129		memcpy(buf, str, len);
130		Py_BEGIN_ALLOW_THREADS
131		ret = ioctl(fd, code, buf);
132		Py_END_ALLOW_THREADS
133		if (ret < 0) {
134			PyErr_SetFromErrno(PyExc_IOError);
135			return NULL;
136		}
137		return PyString_FromStringAndSize(buf, len);
138	}
139
140	PyErr_Clear();
141	if (PyArg_Parse(args, "(ii)", &fd, &code))
142		arg = 0;
143	else {
144		PyErr_Clear();
145		if (!PyArg_Parse(args, "(iii)", &fd, &code, &arg))
146			return NULL;
147	}
148	Py_BEGIN_ALLOW_THREADS
149	ret = ioctl(fd, code, arg);
150	Py_END_ALLOW_THREADS
151	if (ret < 0) {
152		PyErr_SetFromErrno(PyExc_IOError);
153		return NULL;
154	}
155	return PyInt_FromLong((long)ret);
156}
157
158static char ioctl_doc [] =
159"ioctl(fd, opt, [arg])\n\
160\n\
161Perform the requested operation on file descriptor fd.  The operation\n\
162is defined by op and is operating system dependent.  Typically these\n\
163codes can be retrieved from the library module IOCTL.  The argument arg\n\
164is optional, and defaults to 0; it may be an int or a string.";
165
166
167/* flock(fd, operation) */
168
169static PyObject *
170fcntl_flock(self, args)
171	PyObject *self; /* Not used */
172	PyObject *args;
173{
174	int fd;
175	int code;
176	int ret;
177
178	if (!PyArg_Parse(args, "(ii)", &fd, &code))
179		return NULL;
180
181	Py_BEGIN_ALLOW_THREADS
182#ifdef HAVE_FLOCK
183	ret = flock(fd, code);
184#else
185
186#ifndef LOCK_SH
187#define LOCK_SH		1	/* shared lock */
188#define LOCK_EX		2	/* exclusive lock */
189#define LOCK_NB		4	/* don't block when locking */
190#define LOCK_UN		8	/* unlock */
191#endif
192	{
193		struct flock l;
194		if (code == LOCK_UN)
195			l.l_type = F_UNLCK;
196		else if (code & LOCK_SH)
197			l.l_type = F_RDLCK;
198		else if (code & LOCK_EX)
199			l.l_type = F_WRLCK;
200		else {
201			PyErr_SetString(PyExc_ValueError,
202					"unrecognized flock argument");
203			return NULL;
204		}
205		l.l_whence = l.l_start = l.l_len = 0;
206		ret = fcntl(fd, (code & LOCK_NB) ? F_SETLK : F_SETLKW, &l);
207	}
208#endif /* HAVE_FLOCK */
209	Py_END_ALLOW_THREADS
210	if (ret < 0) {
211		PyErr_SetFromErrno(PyExc_IOError);
212		return NULL;
213	}
214	Py_INCREF(Py_None);
215	return Py_None;
216}
217
218static char flock_doc [] =
219"flock(fd, operation)\n\
220\n\
221Perform the lock operation op on file descriptor fd.  See the Unix \n\
222manual flock(3) for details.  (On some systems, this function is\n\
223emulated using fcntl().)";
224
225
226/* lockf(fd, operation) */
227static PyObject *
228fcntl_lockf(self, args)
229	PyObject *self; /* Not used */
230	PyObject *args;
231{
232	int fd, code, len = 0, start = 0, whence = 0, ret;
233
234	if (!PyArg_ParseTuple(args, "ii|iii", &fd, &code, &len,
235			       &start, &whence))
236	    return NULL;
237
238	Py_BEGIN_ALLOW_THREADS
239#ifndef LOCK_SH
240#define LOCK_SH		1	/* shared lock */
241#define LOCK_EX		2	/* exclusive lock */
242#define LOCK_NB		4	/* don't block when locking */
243#define LOCK_UN		8	/* unlock */
244#endif
245	{
246		struct flock l;
247		if (code == LOCK_UN)
248			l.l_type = F_UNLCK;
249		else if (code & LOCK_SH)
250			l.l_type = F_RDLCK;
251		else if (code & LOCK_EX)
252			l.l_type = F_WRLCK;
253		else {
254			PyErr_SetString(PyExc_ValueError,
255					"unrecognized flock argument");
256			return NULL;
257		}
258		l.l_len = len;
259		l.l_start = start;
260		l.l_whence = whence;
261		ret = fcntl(fd, (code & LOCK_NB) ? F_SETLK : F_SETLKW, &l);
262	}
263	Py_END_ALLOW_THREADS
264	if (ret < 0) {
265		PyErr_SetFromErrno(PyExc_IOError);
266		return NULL;
267	}
268	Py_INCREF(Py_None);
269	return Py_None;
270}
271
272static char lockf_doc [] =
273"lockf (fd, operation)\n\
274\n\
275This is a wrapper around the FCNTL.F_SETLK and FCNTL.F_SETLKW fcntl()\n\
276calls.  See the Unix manual for details.";
277
278/* List of functions */
279
280static PyMethodDef fcntl_methods[] = {
281	{"fcntl",	fcntl_fcntl, 0, fcntl_doc},
282	{"ioctl",	fcntl_ioctl, 0, ioctl_doc},
283	{"flock",	fcntl_flock, 0, flock_doc},
284	{"lockf",       fcntl_lockf, 1, lockf_doc},
285	{NULL,		NULL}		/* sentinel */
286};
287
288
289static char module_doc [] =
290
291"This module performs file control and I/O control on file \n\
292descriptors.  It is an interface to the fcntl() and ioctl() Unix\n\
293routines.  File descriptors can be obtained with the fileno() method of\n\
294a file or socket object.";
295
296/* Module initialisation */
297
298static int
299ins(d, symbol, value)
300        PyObject* d;
301        char* symbol;
302        long value;
303{
304        PyObject* v = PyInt_FromLong(value);
305        if (!v || PyDict_SetItemString(d, symbol, v) < 0)
306                return -1;
307
308        Py_DECREF(v);
309        return 0;
310}
311
312static int
313all_ins(d)
314        PyObject* d;
315{
316        if (ins(d, "LOCK_SH", (long)LOCK_SH)) return -1;
317        if (ins(d, "LOCK_EX", (long)LOCK_EX)) return -1;
318        if (ins(d, "LOCK_NB", (long)LOCK_NB)) return -1;
319        if (ins(d, "LOCK_UN", (long)LOCK_UN)) return -1;
320	return 0;
321}
322
323DL_EXPORT(void)
324initfcntl()
325{
326	PyObject *m, *d;
327
328	/* Create the module and add the functions and documentation */
329	m = Py_InitModule3("fcntl", fcntl_methods, module_doc);
330
331	/* Add some symbolic constants to the module */
332	d = PyModule_GetDict(m);
333	all_ins(d);
334
335	/* Check for errors */
336	if (PyErr_Occurred())
337		Py_FatalError("can't initialize module fcntl");
338}
339