fcntlmodule.c 8.65 KB
Newer Older
1 2 3

/* fcntl module */

Roger E. Masse's avatar
Roger E. Masse committed
4
#include "Python.h"
5

Guido van Rossum's avatar
Guido van Rossum committed
6 7 8 9 10 11 12 13
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
#endif

14
#include <sys/ioctl.h>
15 16
#include <fcntl.h>

17 18 19

/* fcntl(fd, opt, [arg]) */

Roger E. Masse's avatar
Roger E. Masse committed
20
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
21
fcntl_fcntl(PyObject *self, PyObject *args)
22 23 24 25 26 27 28 29 30
{
	int fd;
	int code;
	int arg;
	int ret;
	char *str;
	int len;
	char buf[1024];

31
	if (PyArg_ParseTuple(args, "iis#:fcntl", &fd, &code, &str, &len)) {
32
		if (len > sizeof buf) {
Roger E. Masse's avatar
Roger E. Masse committed
33 34
			PyErr_SetString(PyExc_ValueError,
					"fcntl string arg too long");
35 36 37
			return NULL;
		}
		memcpy(buf, str, len);
Roger E. Masse's avatar
Roger E. Masse committed
38
		Py_BEGIN_ALLOW_THREADS
39
		ret = fcntl(fd, code, buf);
Roger E. Masse's avatar
Roger E. Masse committed
40
		Py_END_ALLOW_THREADS
41
		if (ret < 0) {
Roger E. Masse's avatar
Roger E. Masse committed
42
			PyErr_SetFromErrno(PyExc_IOError);
43 44
			return NULL;
		}
Roger E. Masse's avatar
Roger E. Masse committed
45
		return PyString_FromStringAndSize(buf, len);
46 47
	}

Roger E. Masse's avatar
Roger E. Masse committed
48
	PyErr_Clear();
49 50 51 52
	arg = 0;
	if (!PyArg_ParseTuple(args, "ii|i;fcntl requires 2 integers and optionally a third integer or a string", 
			      &fd, &code, &arg)) {
	  return NULL;
53
	}
Roger E. Masse's avatar
Roger E. Masse committed
54
	Py_BEGIN_ALLOW_THREADS
55
	ret = fcntl(fd, code, arg);
Roger E. Masse's avatar
Roger E. Masse committed
56
	Py_END_ALLOW_THREADS
57
	if (ret < 0) {
Roger E. Masse's avatar
Roger E. Masse committed
58
		PyErr_SetFromErrno(PyExc_IOError);
59 60
		return NULL;
	}
Roger E. Masse's avatar
Roger E. Masse committed
61
	return PyInt_FromLong((long)ret);
62 63
}

64 65 66 67 68 69 70
static char fcntl_doc [] =

"fcntl(fd, opt, [arg])\n\
\n\
Perform the requested operation on file descriptor fd.  The operation\n\
is defined by op and is operating system dependent.  Typically these\n\
codes can be retrieved from the library module FCNTL.  The argument arg\n\
71 72 73 74 75 76
is optional, and defaults to 0; it may be an int or a string. If arg is\n\
given as a string, the return value of fcntl is a string of that length,\n\
containing the resulting value put in the arg buffer by the operating system.\n\
The length of the arg string is not allowed to exceed 1024 bytes. If the arg\n\
given is an integer or if none is specified, the result value is an integer\n\
corresponding to the return value of the fcntl call in the C code.";
77

78 79 80

/* ioctl(fd, opt, [arg]) */

Roger E. Masse's avatar
Roger E. Masse committed
81
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
82
fcntl_ioctl(PyObject *self, PyObject *args)
83 84 85 86 87 88 89 90 91
{
	int fd;
	int code;
	int arg;
	int ret;
	char *str;
	int len;
	char buf[1024];

92
	if (PyArg_ParseTuple(args, "iis#:ioctl", &fd, &code, &str, &len)) {
93
		if (len > sizeof buf) {
Roger E. Masse's avatar
Roger E. Masse committed
94 95
			PyErr_SetString(PyExc_ValueError,
					"ioctl string arg too long");
96 97 98
			return NULL;
		}
		memcpy(buf, str, len);
Roger E. Masse's avatar
Roger E. Masse committed
99
		Py_BEGIN_ALLOW_THREADS
100
		ret = ioctl(fd, code, buf);
Roger E. Masse's avatar
Roger E. Masse committed
101
		Py_END_ALLOW_THREADS
102
		if (ret < 0) {
Roger E. Masse's avatar
Roger E. Masse committed
103
			PyErr_SetFromErrno(PyExc_IOError);
104 105
			return NULL;
		}
Roger E. Masse's avatar
Roger E. Masse committed
106
		return PyString_FromStringAndSize(buf, len);
107 108
	}

Roger E. Masse's avatar
Roger E. Masse committed
109
	PyErr_Clear();
110 111 112 113
	arg = 0;
	if (!PyArg_ParseTuple(args, "ii|i;ioctl requires 2 integers and optionally a third integer or a string", 
			      &fd, &code, &arg)) {
	  return NULL;
114
	}
Roger E. Masse's avatar
Roger E. Masse committed
115
	Py_BEGIN_ALLOW_THREADS
116
	ret = ioctl(fd, code, arg);
Roger E. Masse's avatar
Roger E. Masse committed
117
	Py_END_ALLOW_THREADS
118
	if (ret < 0) {
Roger E. Masse's avatar
Roger E. Masse committed
119
		PyErr_SetFromErrno(PyExc_IOError);
120 121
		return NULL;
	}
Roger E. Masse's avatar
Roger E. Masse committed
122
	return PyInt_FromLong((long)ret);
123 124
}

125 126 127 128 129 130
static char ioctl_doc [] =
"ioctl(fd, opt, [arg])\n\
\n\
Perform the requested operation on file descriptor fd.  The operation\n\
is defined by op and is operating system dependent.  Typically these\n\
codes can be retrieved from the library module IOCTL.  The argument arg\n\
131 132 133 134 135 136
is optional, and defaults to 0; it may be an int or a string. If arg is\n\
given as a string, the return value of ioctl is a string of that length,\n\
containing the resulting value put in the arg buffer by the operating system.\n\
The length of the arg string is not allowed to exceed 1024 bytes. If the arg\n\
given is an integer or if none is specified, the result value is an integer\n\
corresponding to the return value of the ioctl call in the C code.";
137

138

Guido van Rossum's avatar
Guido van Rossum committed
139 140
/* flock(fd, operation) */

Roger E. Masse's avatar
Roger E. Masse committed
141
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
142
fcntl_flock(PyObject *self, PyObject *args)
Guido van Rossum's avatar
Guido van Rossum committed
143 144 145 146 147
{
	int fd;
	int code;
	int ret;

148
	if (!PyArg_ParseTuple(args, "ii:flock", &fd, &code))
Guido van Rossum's avatar
Guido van Rossum committed
149 150
		return NULL;

151
#ifdef HAVE_FLOCK
152
	Py_BEGIN_ALLOW_THREADS
Guido van Rossum's avatar
Guido van Rossum committed
153
	ret = flock(fd, code);
154
	Py_END_ALLOW_THREADS
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
#else

#ifndef LOCK_SH
#define LOCK_SH		1	/* shared lock */
#define LOCK_EX		2	/* exclusive lock */
#define LOCK_NB		4	/* don't block when locking */
#define LOCK_UN		8	/* unlock */
#endif
	{
		struct flock l;
		if (code == LOCK_UN)
			l.l_type = F_UNLCK;
		else if (code & LOCK_SH)
			l.l_type = F_RDLCK;
		else if (code & LOCK_EX)
			l.l_type = F_WRLCK;
		else {
Roger E. Masse's avatar
Roger E. Masse committed
172 173
			PyErr_SetString(PyExc_ValueError,
					"unrecognized flock argument");
174 175 176
			return NULL;
		}
		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
180 181
	}
#endif /* HAVE_FLOCK */
Guido van Rossum's avatar
Guido van Rossum committed
182
	if (ret < 0) {
Roger E. Masse's avatar
Roger E. Masse committed
183
		PyErr_SetFromErrno(PyExc_IOError);
Guido van Rossum's avatar
Guido van Rossum committed
184 185
		return NULL;
	}
Roger E. Masse's avatar
Roger E. Masse committed
186 187
	Py_INCREF(Py_None);
	return Py_None;
Guido van Rossum's avatar
Guido van Rossum committed
188 189
}

190 191 192 193 194 195 196 197
static char flock_doc [] =
"flock(fd, operation)\n\
\n\
Perform the lock operation op on file descriptor fd.  See the Unix \n\
manual flock(3) for details.  (On some systems, this function is\n\
emulated using fcntl().)";


Guido van Rossum's avatar
Guido van Rossum committed
198
/* lockf(fd, operation) */
Roger E. Masse's avatar
Roger E. Masse committed
199
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
200
fcntl_lockf(PyObject *self, PyObject *args)
Guido van Rossum's avatar
Guido van Rossum committed
201
{
202 203
	int fd, code, ret, whence = 0;
	PyObject *lenobj = NULL, *startobj = NULL;
Guido van Rossum's avatar
Guido van Rossum committed
204

205
	if (!PyArg_ParseTuple(args, "ii|OOi:lockf", &fd, &code,
206
			      &lenobj, &startobj, &whence))
Guido van Rossum's avatar
Guido van Rossum committed
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
	    return NULL;

#ifndef LOCK_SH
#define LOCK_SH		1	/* shared lock */
#define LOCK_EX		2	/* exclusive lock */
#define LOCK_NB		4	/* don't block when locking */
#define LOCK_UN		8	/* unlock */
#endif
	{
		struct flock l;
		if (code == LOCK_UN)
			l.l_type = F_UNLCK;
		else if (code & LOCK_SH)
			l.l_type = F_RDLCK;
		else if (code & LOCK_EX)
			l.l_type = F_WRLCK;
		else {
Roger E. Masse's avatar
Roger E. Masse committed
224 225
			PyErr_SetString(PyExc_ValueError,
					"unrecognized flock argument");
Guido van Rossum's avatar
Guido van Rossum committed
226 227
			return NULL;
		}
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
		l.l_start = l.l_len = 0;
		if (startobj != NULL) {
#if !defined(HAVE_LARGEFILE_SUPPORT)
			l.l_start = PyInt_AsLong(startobj);
#else
			l.l_start = PyLong_Check(startobj) ?
					PyLong_AsLongLong(startobj) :
					PyInt_AsLong(startobj);
#endif
			if (PyErr_Occurred())
				return NULL;
		}
		if (lenobj != NULL) {
#if !defined(HAVE_LARGEFILE_SUPPORT)
			l.l_len = PyInt_AsLong(lenobj);
#else
			l.l_len = PyLong_Check(lenobj) ?
					PyLong_AsLongLong(lenobj) :
					PyInt_AsLong(lenobj);
#endif
			if (PyErr_Occurred())
				return NULL;
		}
Guido van Rossum's avatar
Guido van Rossum committed
251
		l.l_whence = whence;
252
		Py_BEGIN_ALLOW_THREADS
Guido van Rossum's avatar
Guido van Rossum committed
253
		ret = fcntl(fd, (code & LOCK_NB) ? F_SETLK : F_SETLKW, &l);
254
		Py_END_ALLOW_THREADS
Guido van Rossum's avatar
Guido van Rossum committed
255 256
	}
	if (ret < 0) {
Roger E. Masse's avatar
Roger E. Masse committed
257
		PyErr_SetFromErrno(PyExc_IOError);
Guido van Rossum's avatar
Guido van Rossum committed
258 259
		return NULL;
	}
Roger E. Masse's avatar
Roger E. Masse committed
260 261
	Py_INCREF(Py_None);
	return Py_None;
Guido van Rossum's avatar
Guido van Rossum committed
262
}
Guido van Rossum's avatar
Guido van Rossum committed
263

264
static char lockf_doc [] =
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
"lockf (fd, operation, length=0, start=0, whence=0)\n\
\n\
This is essentially a wrapper around the fcntl() locking calls.  fd is the\n\
file descriptor of the file to lock or unlock, and operation is one of the\n\
following values:\n\
\n\
    LOCK_UN - unlock\n\
    LOCK_SH - acquire a shared lock\n\
    LOCK_EX - acquire an exclusive lock\n\
\n\
When operation is LOCK_SH or LOCK_EX, it can also be bit-wise OR'd with\n\
LOCK_NB to avoid blocking on lock acquisition.  If LOCK_NB is used and the\n\
lock cannot be acquired, an IOError will be raised and the exception will\n\
have an errno attribute set to EACCES or EAGAIN (depending on the operating\n\
system -- for portability, check for either value).\n\
\n\
length is the number of bytes to lock, with the default meaning to lock to\n\
EOF.  start is the byte offset, relative to whence, to that the lock\n\
starts.  whence is as with fileobj.seek(), specifically:\n\
\n\
    0 - relative to the start of the file (SEEK_SET)\n\
    1 - relative to the current buffer position (SEEK_CUR)\n\
287
    2 - relative to the end of the file (SEEK_END)";
288

289 290
/* List of functions */

Roger E. Masse's avatar
Roger E. Masse committed
291
static PyMethodDef fcntl_methods[] = {
292 293 294 295
	{"fcntl",	fcntl_fcntl, METH_VARARGS, fcntl_doc},
	{"ioctl",	fcntl_ioctl, METH_VARARGS, ioctl_doc},
	{"flock",	fcntl_flock, METH_VARARGS, flock_doc},
	{"lockf",       fcntl_lockf, METH_VARARGS, lockf_doc},
296 297 298 299
	{NULL,		NULL}		/* sentinel */
};


300 301 302 303 304 305 306
static char module_doc [] =

"This module performs file control and I/O control on file \n\
descriptors.  It is an interface to the fcntl() and ioctl() Unix\n\
routines.  File descriptors can be obtained with the fileno() method of\n\
a file or socket object.";

307 308
/* Module initialisation */

309
static int
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
310
ins(PyObject* d, char* symbol, long value)
311 312 313 314 315 316 317 318 319 320
{
        PyObject* v = PyInt_FromLong(value);
        if (!v || PyDict_SetItemString(d, symbol, v) < 0)
                return -1;

        Py_DECREF(v);
        return 0;
}

static int
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
321
all_ins(PyObject* d)
322 323 324 325 326
{
        if (ins(d, "LOCK_SH", (long)LOCK_SH)) return -1;
        if (ins(d, "LOCK_EX", (long)LOCK_EX)) return -1;
        if (ins(d, "LOCK_NB", (long)LOCK_NB)) return -1;
        if (ins(d, "LOCK_UN", (long)LOCK_UN)) return -1;
Guido van Rossum's avatar
Guido van Rossum committed
327
	return 0;
328 329
}

330
DL_EXPORT(void)
331
initfcntl(void)
332
{
Roger E. Masse's avatar
Roger E. Masse committed
333
	PyObject *m, *d;
334

335 336
	/* Create the module and add the functions and documentation */
	m = Py_InitModule3("fcntl", fcntl_methods, module_doc);
337 338

	/* Add some symbolic constants to the module */
Roger E. Masse's avatar
Roger E. Masse committed
339
	d = PyModule_GetDict(m);
340
	all_ins(d);
341
}