Files for 2.1b1 distribution.
[python/dscho.git] / Modules / fcntlmodule.c
blob5aa5516055fb4f319b3c00362f89bfbe6fdf9011
2 /* fcntl module */
4 #include "Python.h"
6 #ifdef HAVE_UNISTD_H
7 #include <unistd.h>
8 #endif
10 #ifdef HAVE_SYS_FILE_H
11 #include <sys/file.h>
12 #endif
14 #include <sys/ioctl.h>
15 #include <fcntl.h>
18 /* fcntl(fd, opt, [arg]) */
20 static PyObject *
21 fcntl_fcntl(PyObject *self, PyObject *args)
23 int fd;
24 int code;
25 int arg;
26 int ret;
27 char *str;
28 int len;
29 char buf[1024];
31 if (PyArg_ParseTuple(args, "iis#:fcntl", &fd, &code, &str, &len)) {
32 if (len > sizeof buf) {
33 PyErr_SetString(PyExc_ValueError,
34 "fcntl string arg too long");
35 return NULL;
37 memcpy(buf, str, len);
38 Py_BEGIN_ALLOW_THREADS
39 ret = fcntl(fd, code, buf);
40 Py_END_ALLOW_THREADS
41 if (ret < 0) {
42 PyErr_SetFromErrno(PyExc_IOError);
43 return NULL;
45 return PyString_FromStringAndSize(buf, len);
48 PyErr_Clear();
49 arg = 0;
50 if (!PyArg_ParseTuple(args, "ii|i;fcntl requires 2 integers and optionally a third integer or a string",
51 &fd, &code, &arg)) {
52 return NULL;
54 Py_BEGIN_ALLOW_THREADS
55 ret = fcntl(fd, code, arg);
56 Py_END_ALLOW_THREADS
57 if (ret < 0) {
58 PyErr_SetFromErrno(PyExc_IOError);
59 return NULL;
61 return PyInt_FromLong((long)ret);
64 static char fcntl_doc [] =
66 "fcntl(fd, opt, [arg])\n\
67 \n\
68 Perform the requested operation on file descriptor fd. The operation\n\
69 is defined by op and is operating system dependent. Typically these\n\
70 codes can be retrieved from the library module FCNTL. The argument arg\n\
71 is optional, and defaults to 0; it may be an int or a string. If arg is\n\
72 given as a string, the return value of fcntl is a string of that length,\n\
73 containing the resulting value put in the arg buffer by the operating system.\n\
74 The length of the arg string is not allowed to exceed 1024 bytes. If the arg\n\
75 given is an integer or if none is specified, the result value is an integer\n\
76 corresponding to the return value of the fcntl call in the C code.";
79 /* ioctl(fd, opt, [arg]) */
81 static PyObject *
82 fcntl_ioctl(PyObject *self, PyObject *args)
84 int fd;
85 int code;
86 int arg;
87 int ret;
88 char *str;
89 int len;
90 char buf[1024];
92 if (PyArg_ParseTuple(args, "iis#:ioctl", &fd, &code, &str, &len)) {
93 if (len > sizeof buf) {
94 PyErr_SetString(PyExc_ValueError,
95 "ioctl string arg too long");
96 return NULL;
98 memcpy(buf, str, len);
99 Py_BEGIN_ALLOW_THREADS
100 ret = ioctl(fd, code, buf);
101 Py_END_ALLOW_THREADS
102 if (ret < 0) {
103 PyErr_SetFromErrno(PyExc_IOError);
104 return NULL;
106 return PyString_FromStringAndSize(buf, len);
109 PyErr_Clear();
110 arg = 0;
111 if (!PyArg_ParseTuple(args, "ii|i;ioctl requires 2 integers and optionally a third integer or a string",
112 &fd, &code, &arg)) {
113 return NULL;
115 Py_BEGIN_ALLOW_THREADS
116 ret = ioctl(fd, code, arg);
117 Py_END_ALLOW_THREADS
118 if (ret < 0) {
119 PyErr_SetFromErrno(PyExc_IOError);
120 return NULL;
122 return PyInt_FromLong((long)ret);
125 static char ioctl_doc [] =
126 "ioctl(fd, opt, [arg])\n\
128 Perform the requested operation on file descriptor fd. The operation\n\
129 is defined by op and is operating system dependent. Typically these\n\
130 codes can be retrieved from the library module IOCTL. The argument arg\n\
131 is optional, and defaults to 0; it may be an int or a string. If arg is\n\
132 given as a string, the return value of ioctl is a string of that length,\n\
133 containing the resulting value put in the arg buffer by the operating system.\n\
134 The length of the arg string is not allowed to exceed 1024 bytes. If the arg\n\
135 given is an integer or if none is specified, the result value is an integer\n\
136 corresponding to the return value of the ioctl call in the C code.";
139 /* flock(fd, operation) */
141 static PyObject *
142 fcntl_flock(PyObject *self, PyObject *args)
144 int fd;
145 int code;
146 int ret;
148 if (!PyArg_ParseTuple(args, "ii:flock", &fd, &code))
149 return NULL;
151 #ifdef HAVE_FLOCK
152 Py_BEGIN_ALLOW_THREADS
153 ret = flock(fd, code);
154 Py_END_ALLOW_THREADS
155 #else
157 #ifndef LOCK_SH
158 #define LOCK_SH 1 /* shared lock */
159 #define LOCK_EX 2 /* exclusive lock */
160 #define LOCK_NB 4 /* don't block when locking */
161 #define LOCK_UN 8 /* unlock */
162 #endif
164 struct flock l;
165 if (code == LOCK_UN)
166 l.l_type = F_UNLCK;
167 else if (code & LOCK_SH)
168 l.l_type = F_RDLCK;
169 else if (code & LOCK_EX)
170 l.l_type = F_WRLCK;
171 else {
172 PyErr_SetString(PyExc_ValueError,
173 "unrecognized flock argument");
174 return NULL;
176 l.l_whence = l.l_start = l.l_len = 0;
177 Py_BEGIN_ALLOW_THREADS
178 ret = fcntl(fd, (code & LOCK_NB) ? F_SETLK : F_SETLKW, &l);
179 Py_END_ALLOW_THREADS
181 #endif /* HAVE_FLOCK */
182 if (ret < 0) {
183 PyErr_SetFromErrno(PyExc_IOError);
184 return NULL;
186 Py_INCREF(Py_None);
187 return Py_None;
190 static char flock_doc [] =
191 "flock(fd, operation)\n\
193 Perform the lock operation op on file descriptor fd. See the Unix \n\
194 manual flock(3) for details. (On some systems, this function is\n\
195 emulated using fcntl().)";
198 /* lockf(fd, operation) */
199 static PyObject *
200 fcntl_lockf(PyObject *self, PyObject *args)
202 int fd, code, ret, whence = 0;
203 PyObject *lenobj = NULL, *startobj = NULL;
205 if (!PyArg_ParseTuple(args, "ii|OOi:lockf", &fd, &code,
206 &lenobj, &startobj, &whence))
207 return NULL;
209 #ifndef LOCK_SH
210 #define LOCK_SH 1 /* shared lock */
211 #define LOCK_EX 2 /* exclusive lock */
212 #define LOCK_NB 4 /* don't block when locking */
213 #define LOCK_UN 8 /* unlock */
214 #endif
216 struct flock l;
217 if (code == LOCK_UN)
218 l.l_type = F_UNLCK;
219 else if (code & LOCK_SH)
220 l.l_type = F_RDLCK;
221 else if (code & LOCK_EX)
222 l.l_type = F_WRLCK;
223 else {
224 PyErr_SetString(PyExc_ValueError,
225 "unrecognized flock argument");
226 return NULL;
228 l.l_start = l.l_len = 0;
229 if (startobj != NULL) {
230 #if !defined(HAVE_LARGEFILE_SUPPORT)
231 l.l_start = PyInt_AsLong(startobj);
232 #else
233 l.l_start = PyLong_Check(startobj) ?
234 PyLong_AsLongLong(startobj) :
235 PyInt_AsLong(startobj);
236 #endif
237 if (PyErr_Occurred())
238 return NULL;
240 if (lenobj != NULL) {
241 #if !defined(HAVE_LARGEFILE_SUPPORT)
242 l.l_len = PyInt_AsLong(lenobj);
243 #else
244 l.l_len = PyLong_Check(lenobj) ?
245 PyLong_AsLongLong(lenobj) :
246 PyInt_AsLong(lenobj);
247 #endif
248 if (PyErr_Occurred())
249 return NULL;
251 l.l_whence = whence;
252 Py_BEGIN_ALLOW_THREADS
253 ret = fcntl(fd, (code & LOCK_NB) ? F_SETLK : F_SETLKW, &l);
254 Py_END_ALLOW_THREADS
256 if (ret < 0) {
257 PyErr_SetFromErrno(PyExc_IOError);
258 return NULL;
260 Py_INCREF(Py_None);
261 return Py_None;
264 static char lockf_doc [] =
265 "lockf (fd, operation, length=0, start=0, whence=0)\n\
267 This is essentially a wrapper around the fcntl() locking calls. fd is the\n\
268 file descriptor of the file to lock or unlock, and operation is one of the\n\
269 following values:\n\
271 LOCK_UN - unlock\n\
272 LOCK_SH - acquire a shared lock\n\
273 LOCK_EX - acquire an exclusive lock\n\
275 When operation is LOCK_SH or LOCK_EX, it can also be bit-wise OR'd with\n\
276 LOCK_NB to avoid blocking on lock acquisition. If LOCK_NB is used and the\n\
277 lock cannot be acquired, an IOError will be raised and the exception will\n\
278 have an errno attribute set to EACCES or EAGAIN (depending on the operating\n\
279 system -- for portability, check for either value).\n\
281 length is the number of bytes to lock, with the default meaning to lock to\n\
282 EOF. start is the byte offset, relative to whence, to that the lock\n\
283 starts. whence is as with fileobj.seek(), specifically:\n\
285 0 - relative to the start of the file (SEEK_SET)\n\
286 1 - relative to the current buffer position (SEEK_CUR)\n\
287 2 - relative to the end of the file (SEEK_END)";
289 /* List of functions */
291 static PyMethodDef fcntl_methods[] = {
292 {"fcntl", fcntl_fcntl, METH_VARARGS, fcntl_doc},
293 {"ioctl", fcntl_ioctl, METH_VARARGS, ioctl_doc},
294 {"flock", fcntl_flock, METH_VARARGS, flock_doc},
295 {"lockf", fcntl_lockf, METH_VARARGS, lockf_doc},
296 {NULL, NULL} /* sentinel */
300 static char module_doc [] =
302 "This module performs file control and I/O control on file \n\
303 descriptors. It is an interface to the fcntl() and ioctl() Unix\n\
304 routines. File descriptors can be obtained with the fileno() method of\n\
305 a file or socket object.";
307 /* Module initialisation */
309 static int
310 ins(PyObject* d, char* symbol, long value)
312 PyObject* v = PyInt_FromLong(value);
313 if (!v || PyDict_SetItemString(d, symbol, v) < 0)
314 return -1;
316 Py_DECREF(v);
317 return 0;
320 static int
321 all_ins(PyObject* d)
323 if (ins(d, "LOCK_SH", (long)LOCK_SH)) return -1;
324 if (ins(d, "LOCK_EX", (long)LOCK_EX)) return -1;
325 if (ins(d, "LOCK_NB", (long)LOCK_NB)) return -1;
326 if (ins(d, "LOCK_UN", (long)LOCK_UN)) return -1;
327 return 0;
330 DL_EXPORT(void)
331 initfcntl(void)
333 PyObject *m, *d;
335 /* Create the module and add the functions and documentation */
336 m = Py_InitModule3("fcntl", fcntl_methods, module_doc);
338 /* Add some symbolic constants to the module */
339 d = PyModule_GetDict(m);
340 all_ins(d);