fcntlmodule.c revision 9bfd2bf5ede8e5d58775180d6867d81ddcdd3594
1/*********************************************************** 2Copyright (c) 2000, BeOpen.com. 3Copyright (c) 1995-2000, Corporation for National Research Initiatives. 4Copyright (c) 1990-1995, Stichting Mathematisch Centrum. 5All rights reserved. 6 7See the file "Misc/COPYRIGHT" for information on usage and 8redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. 9******************************************************************/ 10 11/* fcntl module */ 12 13#include "Python.h" 14 15#ifdef HAVE_UNISTD_H 16#include <unistd.h> 17#endif 18 19#ifdef HAVE_SYS_FILE_H 20#include <sys/file.h> 21#endif 22 23#include <sys/ioctl.h> 24#include <fcntl.h> 25 26 27/* fcntl(fd, opt, [arg]) */ 28 29static PyObject * 30fcntl_fcntl(PyObject *self, PyObject *args) 31{ 32 int fd; 33 int code; 34 int arg; 35 int ret; 36 char *str; 37 int len; 38 char buf[1024]; 39 40 if (PyArg_ParseTuple(args, "iis#:fcntl", &fd, &code, &str, &len)) { 41 if (len > sizeof buf) { 42 PyErr_SetString(PyExc_ValueError, 43 "fcntl string arg too long"); 44 return NULL; 45 } 46 memcpy(buf, str, len); 47 Py_BEGIN_ALLOW_THREADS 48 ret = fcntl(fd, code, buf); 49 Py_END_ALLOW_THREADS 50 if (ret < 0) { 51 PyErr_SetFromErrno(PyExc_IOError); 52 return NULL; 53 } 54 return PyString_FromStringAndSize(buf, len); 55 } 56 57 PyErr_Clear(); 58 arg = 0; 59 if (!PyArg_ParseTuple(args, "ii|i;fcntl requires 2 integers and optionally a third integer or a string", 60 &fd, &code, &arg)) { 61 return NULL; 62 } 63 Py_BEGIN_ALLOW_THREADS 64 ret = fcntl(fd, code, arg); 65 Py_END_ALLOW_THREADS 66 if (ret < 0) { 67 PyErr_SetFromErrno(PyExc_IOError); 68 return NULL; 69 } 70 return PyInt_FromLong((long)ret); 71} 72 73static char fcntl_doc [] = 74 75"fcntl(fd, opt, [arg])\n\ 76\n\ 77Perform the requested operation on file descriptor fd. The operation\n\ 78is defined by op and is operating system dependent. Typically these\n\ 79codes can be retrieved from the library module FCNTL. The argument arg\n\ 80is optional, and defaults to 0; it may be an int or a string. If arg is\n\ 81given as a string, the return value of fcntl is a string of that length,\n\ 82containing the resulting value put in the arg buffer by the operating system.\n\ 83The length of the arg string is not allowed to exceed 1024 bytes. If the arg\n\ 84given is an integer or if none is specified, the result value is an integer\n\ 85corresponding to the return value of the fcntl call in the C code."; 86 87 88/* ioctl(fd, opt, [arg]) */ 89 90static PyObject * 91fcntl_ioctl(PyObject *self, PyObject *args) 92{ 93 int fd; 94 int code; 95 int arg; 96 int ret; 97 char *str; 98 int len; 99 char buf[1024]; 100 101 if (PyArg_ParseTuple(args, "iis#:ioctl", &fd, &code, &str, &len)) { 102 if (len > sizeof buf) { 103 PyErr_SetString(PyExc_ValueError, 104 "ioctl string arg too long"); 105 return NULL; 106 } 107 memcpy(buf, str, len); 108 Py_BEGIN_ALLOW_THREADS 109 ret = ioctl(fd, code, buf); 110 Py_END_ALLOW_THREADS 111 if (ret < 0) { 112 PyErr_SetFromErrno(PyExc_IOError); 113 return NULL; 114 } 115 return PyString_FromStringAndSize(buf, len); 116 } 117 118 PyErr_Clear(); 119 arg = 0; 120 if (!PyArg_ParseTuple(args, "ii|i;ioctl requires 2 integers and optionally a third integer or a string", 121 &fd, &code, &arg)) { 122 return NULL; 123 } 124 Py_BEGIN_ALLOW_THREADS 125 ret = ioctl(fd, code, arg); 126 Py_END_ALLOW_THREADS 127 if (ret < 0) { 128 PyErr_SetFromErrno(PyExc_IOError); 129 return NULL; 130 } 131 return PyInt_FromLong((long)ret); 132} 133 134static char ioctl_doc [] = 135"ioctl(fd, opt, [arg])\n\ 136\n\ 137Perform the requested operation on file descriptor fd. The operation\n\ 138is defined by op and is operating system dependent. Typically these\n\ 139codes can be retrieved from the library module IOCTL. The argument arg\n\ 140is optional, and defaults to 0; it may be an int or a string. If arg is\n\ 141given as a string, the return value of ioctl is a string of that length,\n\ 142containing the resulting value put in the arg buffer by the operating system.\n\ 143The length of the arg string is not allowed to exceed 1024 bytes. If the arg\n\ 144given is an integer or if none is specified, the result value is an integer\n\ 145corresponding to the return value of the ioctl call in the C code."; 146 147 148/* flock(fd, operation) */ 149 150static PyObject * 151fcntl_flock(PyObject *self, PyObject *args) 152{ 153 int fd; 154 int code; 155 int ret; 156 157 if (!PyArg_ParseTuple(args, "ii:flock", &fd, &code)) 158 return NULL; 159 160#ifdef HAVE_FLOCK 161 Py_BEGIN_ALLOW_THREADS 162 ret = flock(fd, code); 163 Py_END_ALLOW_THREADS 164#else 165 166#ifndef LOCK_SH 167#define LOCK_SH 1 /* shared lock */ 168#define LOCK_EX 2 /* exclusive lock */ 169#define LOCK_NB 4 /* don't block when locking */ 170#define LOCK_UN 8 /* unlock */ 171#endif 172 { 173 struct flock l; 174 if (code == LOCK_UN) 175 l.l_type = F_UNLCK; 176 else if (code & LOCK_SH) 177 l.l_type = F_RDLCK; 178 else if (code & LOCK_EX) 179 l.l_type = F_WRLCK; 180 else { 181 PyErr_SetString(PyExc_ValueError, 182 "unrecognized flock argument"); 183 return NULL; 184 } 185 l.l_whence = l.l_start = l.l_len = 0; 186 Py_BEGIN_ALLOW_THREADS 187 ret = fcntl(fd, (code & LOCK_NB) ? F_SETLK : F_SETLKW, &l); 188 Py_END_ALLOW_THREADS 189 } 190#endif /* HAVE_FLOCK */ 191 if (ret < 0) { 192 PyErr_SetFromErrno(PyExc_IOError); 193 return NULL; 194 } 195 Py_INCREF(Py_None); 196 return Py_None; 197} 198 199static char flock_doc [] = 200"flock(fd, operation)\n\ 201\n\ 202Perform the lock operation op on file descriptor fd. See the Unix \n\ 203manual flock(3) for details. (On some systems, this function is\n\ 204emulated using fcntl().)"; 205 206 207/* lockf(fd, operation) */ 208static PyObject * 209fcntl_lockf(PyObject *self, PyObject *args) 210{ 211 int fd, code, ret, whence = 0; 212 PyObject *lenobj = NULL, *startobj = NULL; 213 214 if (!PyArg_ParseTuple(args, "ii|OOi:lockf", &fd, &code, 215 &lenobj, &startobj, &whence)) 216 return NULL; 217 218#ifndef LOCK_SH 219#define LOCK_SH 1 /* shared lock */ 220#define LOCK_EX 2 /* exclusive lock */ 221#define LOCK_NB 4 /* don't block when locking */ 222#define LOCK_UN 8 /* unlock */ 223#endif 224 { 225 struct flock l; 226 if (code == LOCK_UN) 227 l.l_type = F_UNLCK; 228 else if (code & LOCK_SH) 229 l.l_type = F_RDLCK; 230 else if (code & LOCK_EX) 231 l.l_type = F_WRLCK; 232 else { 233 PyErr_SetString(PyExc_ValueError, 234 "unrecognized flock argument"); 235 return NULL; 236 } 237 l.l_start = l.l_len = 0; 238 if (startobj != NULL) { 239#if !defined(HAVE_LARGEFILE_SUPPORT) 240 l.l_start = PyInt_AsLong(startobj); 241#else 242 l.l_start = PyLong_Check(startobj) ? 243 PyLong_AsLongLong(startobj) : 244 PyInt_AsLong(startobj); 245#endif 246 if (PyErr_Occurred()) 247 return NULL; 248 } 249 if (lenobj != NULL) { 250#if !defined(HAVE_LARGEFILE_SUPPORT) 251 l.l_len = PyInt_AsLong(lenobj); 252#else 253 l.l_len = PyLong_Check(lenobj) ? 254 PyLong_AsLongLong(lenobj) : 255 PyInt_AsLong(lenobj); 256#endif 257 if (PyErr_Occurred()) 258 return NULL; 259 } 260 l.l_whence = whence; 261 Py_BEGIN_ALLOW_THREADS 262 ret = fcntl(fd, (code & LOCK_NB) ? F_SETLK : F_SETLKW, &l); 263 Py_END_ALLOW_THREADS 264 } 265 if (ret < 0) { 266 PyErr_SetFromErrno(PyExc_IOError); 267 return NULL; 268 } 269 Py_INCREF(Py_None); 270 return Py_None; 271} 272 273static char lockf_doc [] = 274"lockf (fd, operation)\n\ 275\n\ 276This is a wrapper around the FCNTL.F_SETLK and FCNTL.F_SETLKW fcntl()\n\ 277calls. See the Unix manual for details."; 278 279/* List of functions */ 280 281static PyMethodDef fcntl_methods[] = { 282 {"fcntl", fcntl_fcntl, METH_VARARGS, fcntl_doc}, 283 {"ioctl", fcntl_ioctl, METH_VARARGS, ioctl_doc}, 284 {"flock", fcntl_flock, METH_VARARGS, flock_doc}, 285 {"lockf", fcntl_lockf, METH_VARARGS, lockf_doc}, 286 {NULL, NULL} /* sentinel */ 287}; 288 289 290static char module_doc [] = 291 292"This module performs file control and I/O control on file \n\ 293descriptors. It is an interface to the fcntl() and ioctl() Unix\n\ 294routines. File descriptors can be obtained with the fileno() method of\n\ 295a file or socket object."; 296 297/* Module initialisation */ 298 299static int 300ins(PyObject* d, char* symbol, long value) 301{ 302 PyObject* v = PyInt_FromLong(value); 303 if (!v || PyDict_SetItemString(d, symbol, v) < 0) 304 return -1; 305 306 Py_DECREF(v); 307 return 0; 308} 309 310static int 311all_ins(PyObject* d) 312{ 313 if (ins(d, "LOCK_SH", (long)LOCK_SH)) return -1; 314 if (ins(d, "LOCK_EX", (long)LOCK_EX)) return -1; 315 if (ins(d, "LOCK_NB", (long)LOCK_NB)) return -1; 316 if (ins(d, "LOCK_UN", (long)LOCK_UN)) return -1; 317 return 0; 318} 319 320DL_EXPORT(void) 321initfcntl(void) 322{ 323 PyObject *m, *d; 324 325 /* Create the module and add the functions and documentation */ 326 m = Py_InitModule3("fcntl", fcntl_methods, module_doc); 327 328 /* Add some symbolic constants to the module */ 329 d = PyModule_GetDict(m); 330 all_ins(d); 331} 332