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