1992-08-17 05:55:12 -03:00
|
|
|
|
|
|
|
/* fcntl module */
|
|
|
|
|
1996-12-17 13:42:22 -04:00
|
|
|
#include "Python.h"
|
1992-08-17 05:55:12 -03:00
|
|
|
|
1996-12-05 19:43:35 -04:00
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_SYS_FILE_H
|
|
|
|
#include <sys/file.h>
|
|
|
|
#endif
|
|
|
|
|
1996-12-09 14:49:14 -04:00
|
|
|
#include <sys/ioctl.h>
|
1996-06-11 12:11:34 -03:00
|
|
|
#include <fcntl.h>
|
|
|
|
|
1992-08-17 05:55:12 -03:00
|
|
|
|
|
|
|
/* fcntl(fd, opt, [arg]) */
|
|
|
|
|
1996-12-17 13:42:22 -04:00
|
|
|
static PyObject *
|
2000-07-10 14:15:07 -03:00
|
|
|
fcntl_fcntl(PyObject *self, PyObject *args)
|
1992-08-17 05:55:12 -03:00
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
int code;
|
|
|
|
int arg;
|
|
|
|
int ret;
|
|
|
|
char *str;
|
|
|
|
int len;
|
|
|
|
char buf[1024];
|
|
|
|
|
2000-08-02 17:46:51 -03:00
|
|
|
if (PyArg_ParseTuple(args, "iis#:fcntl", &fd, &code, &str, &len)) {
|
1992-08-17 05:55:12 -03:00
|
|
|
if (len > sizeof buf) {
|
1996-12-17 13:42:22 -04:00
|
|
|
PyErr_SetString(PyExc_ValueError,
|
|
|
|
"fcntl string arg too long");
|
1992-08-17 05:55:12 -03:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
memcpy(buf, str, len);
|
1996-12-17 13:42:22 -04:00
|
|
|
Py_BEGIN_ALLOW_THREADS
|
1995-10-07 16:18:22 -03:00
|
|
|
ret = fcntl(fd, code, buf);
|
1996-12-17 13:42:22 -04:00
|
|
|
Py_END_ALLOW_THREADS
|
1995-10-07 16:18:22 -03:00
|
|
|
if (ret < 0) {
|
1996-12-17 13:42:22 -04:00
|
|
|
PyErr_SetFromErrno(PyExc_IOError);
|
1992-08-17 05:55:12 -03:00
|
|
|
return NULL;
|
|
|
|
}
|
1996-12-17 13:42:22 -04:00
|
|
|
return PyString_FromStringAndSize(buf, len);
|
1992-08-17 05:55:12 -03:00
|
|
|
}
|
|
|
|
|
1996-12-17 13:42:22 -04:00
|
|
|
PyErr_Clear();
|
2000-08-02 17:46:51 -03:00
|
|
|
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;
|
1992-08-17 05:55:12 -03:00
|
|
|
}
|
1996-12-17 13:42:22 -04:00
|
|
|
Py_BEGIN_ALLOW_THREADS
|
1992-08-17 05:55:12 -03:00
|
|
|
ret = fcntl(fd, code, arg);
|
1996-12-17 13:42:22 -04:00
|
|
|
Py_END_ALLOW_THREADS
|
1992-08-17 05:55:12 -03:00
|
|
|
if (ret < 0) {
|
1996-12-17 13:42:22 -04:00
|
|
|
PyErr_SetFromErrno(PyExc_IOError);
|
1992-08-17 05:55:12 -03:00
|
|
|
return NULL;
|
|
|
|
}
|
1996-12-17 13:42:22 -04:00
|
|
|
return PyInt_FromLong((long)ret);
|
1992-08-17 05:55:12 -03:00
|
|
|
}
|
|
|
|
|
1998-11-23 11:32:55 -04:00
|
|
|
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\
|
2000-08-02 17:46:51 -03:00
|
|
|
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.";
|
1998-11-23 11:32:55 -04:00
|
|
|
|
1992-08-17 05:55:12 -03:00
|
|
|
|
|
|
|
/* ioctl(fd, opt, [arg]) */
|
|
|
|
|
1996-12-17 13:42:22 -04:00
|
|
|
static PyObject *
|
2000-07-10 14:15:07 -03:00
|
|
|
fcntl_ioctl(PyObject *self, PyObject *args)
|
1992-08-17 05:55:12 -03:00
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
int code;
|
|
|
|
int arg;
|
|
|
|
int ret;
|
|
|
|
char *str;
|
|
|
|
int len;
|
|
|
|
char buf[1024];
|
|
|
|
|
2000-08-02 17:46:51 -03:00
|
|
|
if (PyArg_ParseTuple(args, "iis#:ioctl", &fd, &code, &str, &len)) {
|
1992-08-17 05:55:12 -03:00
|
|
|
if (len > sizeof buf) {
|
1996-12-17 13:42:22 -04:00
|
|
|
PyErr_SetString(PyExc_ValueError,
|
|
|
|
"ioctl string arg too long");
|
1992-08-17 05:55:12 -03:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
memcpy(buf, str, len);
|
1996-12-17 13:42:22 -04:00
|
|
|
Py_BEGIN_ALLOW_THREADS
|
1995-10-07 16:18:22 -03:00
|
|
|
ret = ioctl(fd, code, buf);
|
1996-12-17 13:42:22 -04:00
|
|
|
Py_END_ALLOW_THREADS
|
1995-10-07 16:18:22 -03:00
|
|
|
if (ret < 0) {
|
1996-12-17 13:42:22 -04:00
|
|
|
PyErr_SetFromErrno(PyExc_IOError);
|
1992-08-17 05:55:12 -03:00
|
|
|
return NULL;
|
|
|
|
}
|
1996-12-17 13:42:22 -04:00
|
|
|
return PyString_FromStringAndSize(buf, len);
|
1992-08-17 05:55:12 -03:00
|
|
|
}
|
|
|
|
|
1996-12-17 13:42:22 -04:00
|
|
|
PyErr_Clear();
|
2000-08-02 17:46:51 -03:00
|
|
|
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;
|
1992-08-17 05:55:12 -03:00
|
|
|
}
|
1996-12-17 13:42:22 -04:00
|
|
|
Py_BEGIN_ALLOW_THREADS
|
1992-08-17 05:55:12 -03:00
|
|
|
ret = ioctl(fd, code, arg);
|
1996-12-17 13:42:22 -04:00
|
|
|
Py_END_ALLOW_THREADS
|
1992-08-17 05:55:12 -03:00
|
|
|
if (ret < 0) {
|
1996-12-17 13:42:22 -04:00
|
|
|
PyErr_SetFromErrno(PyExc_IOError);
|
1992-08-17 05:55:12 -03:00
|
|
|
return NULL;
|
|
|
|
}
|
1996-12-17 13:42:22 -04:00
|
|
|
return PyInt_FromLong((long)ret);
|
1992-08-17 05:55:12 -03:00
|
|
|
}
|
|
|
|
|
1998-11-23 11:32:55 -04:00
|
|
|
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\
|
2000-08-02 17:46:51 -03:00
|
|
|
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.";
|
1998-11-23 11:32:55 -04:00
|
|
|
|
1992-08-17 05:55:12 -03:00
|
|
|
|
1996-05-23 19:56:38 -03:00
|
|
|
/* flock(fd, operation) */
|
|
|
|
|
1996-12-17 13:42:22 -04:00
|
|
|
static PyObject *
|
2000-07-10 14:15:07 -03:00
|
|
|
fcntl_flock(PyObject *self, PyObject *args)
|
1996-05-23 19:56:38 -03:00
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
int code;
|
|
|
|
int ret;
|
|
|
|
|
2000-08-02 17:46:51 -03:00
|
|
|
if (!PyArg_ParseTuple(args, "ii:flock", &fd, &code))
|
1996-05-23 19:56:38 -03:00
|
|
|
return NULL;
|
|
|
|
|
1996-06-11 12:11:34 -03:00
|
|
|
#ifdef HAVE_FLOCK
|
1999-01-06 14:44:23 -04:00
|
|
|
Py_BEGIN_ALLOW_THREADS
|
1996-05-23 19:56:38 -03:00
|
|
|
ret = flock(fd, code);
|
1999-01-06 14:44:23 -04:00
|
|
|
Py_END_ALLOW_THREADS
|
1996-06-11 12:11:34 -03:00
|
|
|
#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 {
|
1996-12-17 13:42:22 -04:00
|
|
|
PyErr_SetString(PyExc_ValueError,
|
|
|
|
"unrecognized flock argument");
|
1996-06-11 12:11:34 -03:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
l.l_whence = l.l_start = l.l_len = 0;
|
1999-01-06 14:44:23 -04:00
|
|
|
Py_BEGIN_ALLOW_THREADS
|
1996-06-11 12:11:34 -03:00
|
|
|
ret = fcntl(fd, (code & LOCK_NB) ? F_SETLK : F_SETLKW, &l);
|
1999-01-06 14:44:23 -04:00
|
|
|
Py_END_ALLOW_THREADS
|
1996-06-11 12:11:34 -03:00
|
|
|
}
|
|
|
|
#endif /* HAVE_FLOCK */
|
1996-05-23 19:56:38 -03:00
|
|
|
if (ret < 0) {
|
1996-12-17 13:42:22 -04:00
|
|
|
PyErr_SetFromErrno(PyExc_IOError);
|
1996-05-23 19:56:38 -03:00
|
|
|
return NULL;
|
|
|
|
}
|
1996-12-17 13:42:22 -04:00
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
1996-05-23 19:56:38 -03:00
|
|
|
}
|
|
|
|
|
1998-11-23 11:32:55 -04:00
|
|
|
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().)";
|
|
|
|
|
|
|
|
|
1996-09-11 20:17:20 -03:00
|
|
|
/* lockf(fd, operation) */
|
1996-12-17 13:42:22 -04:00
|
|
|
static PyObject *
|
2000-07-10 14:15:07 -03:00
|
|
|
fcntl_lockf(PyObject *self, PyObject *args)
|
1996-09-11 20:17:20 -03:00
|
|
|
{
|
1999-01-06 14:44:23 -04:00
|
|
|
int fd, code, ret, whence = 0;
|
|
|
|
PyObject *lenobj = NULL, *startobj = NULL;
|
1996-05-23 19:56:38 -03:00
|
|
|
|
2000-02-29 09:59:29 -04:00
|
|
|
if (!PyArg_ParseTuple(args, "ii|OOi:lockf", &fd, &code,
|
1999-01-06 14:44:23 -04:00
|
|
|
&lenobj, &startobj, &whence))
|
1996-09-11 20:17:20 -03:00
|
|
|
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 {
|
1996-12-17 13:42:22 -04:00
|
|
|
PyErr_SetString(PyExc_ValueError,
|
|
|
|
"unrecognized flock argument");
|
1996-09-11 20:17:20 -03:00
|
|
|
return NULL;
|
|
|
|
}
|
1999-01-06 14:44:23 -04:00
|
|
|
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;
|
|
|
|
}
|
1996-09-11 20:17:20 -03:00
|
|
|
l.l_whence = whence;
|
1999-01-06 14:44:23 -04:00
|
|
|
Py_BEGIN_ALLOW_THREADS
|
1996-09-11 20:17:20 -03:00
|
|
|
ret = fcntl(fd, (code & LOCK_NB) ? F_SETLK : F_SETLKW, &l);
|
1999-01-06 14:44:23 -04:00
|
|
|
Py_END_ALLOW_THREADS
|
1996-09-11 20:17:20 -03:00
|
|
|
}
|
|
|
|
if (ret < 0) {
|
1996-12-17 13:42:22 -04:00
|
|
|
PyErr_SetFromErrno(PyExc_IOError);
|
1996-09-11 20:17:20 -03:00
|
|
|
return NULL;
|
|
|
|
}
|
1996-12-17 13:42:22 -04:00
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
1996-09-11 20:17:20 -03:00
|
|
|
}
|
1996-05-23 19:56:38 -03:00
|
|
|
|
1998-11-23 11:32:55 -04:00
|
|
|
static char lockf_doc [] =
|
2001-01-24 20:20:13 -04:00
|
|
|
"lockf (fd, operation, length=0, start=0, whence=0)
|
|
|
|
|
|
|
|
This is essentially a wrapper around the fcntl() locking calls. fd is the
|
|
|
|
file descriptor of the file to lock or unlock, and operation is one of the
|
|
|
|
following values:
|
|
|
|
|
|
|
|
LOCK_UN - unlock
|
|
|
|
LOCK_SH - acquire a shared lock
|
|
|
|
LOCK_EX - acquire an exclusive lock
|
|
|
|
|
|
|
|
When operation is LOCK_SH or LOCK_EX, it can also be bit-wise OR'd with
|
|
|
|
LOCK_NB to avoid blocking on lock acquisition. If LOCK_NB is used and the
|
|
|
|
lock cannot be acquired, an IOError will be raised and the exception will
|
|
|
|
have an errno attribute set to EACCES or EAGAIN (depending on the operating
|
|
|
|
system -- for portability, check for either value).
|
|
|
|
|
|
|
|
length is the number of bytes to lock, with the default meaning to lock to
|
|
|
|
EOF. start is the byte offset, relative to whence, to that the lock
|
|
|
|
starts. whence is as with fileobj.seek(), specifically:
|
|
|
|
|
|
|
|
0 - relative to the start of the file (SEEK_SET)
|
|
|
|
1 - relative to the current buffer position (SEEK_CUR)
|
|
|
|
2 - relative to the end of the file (SEEK_END)";
|
1998-11-23 11:32:55 -04:00
|
|
|
|
1992-08-17 05:55:12 -03:00
|
|
|
/* List of functions */
|
|
|
|
|
1996-12-17 13:42:22 -04:00
|
|
|
static PyMethodDef fcntl_methods[] = {
|
2000-08-02 17:46:51 -03:00
|
|
|
{"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},
|
1992-08-17 05:55:12 -03:00
|
|
|
{NULL, NULL} /* sentinel */
|
|
|
|
};
|
|
|
|
|
|
|
|
|
1998-11-23 11:32:55 -04:00
|
|
|
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.";
|
|
|
|
|
1992-08-17 05:55:12 -03:00
|
|
|
/* Module initialisation */
|
|
|
|
|
1997-07-31 16:39:54 -03:00
|
|
|
static int
|
2000-07-10 14:15:07 -03:00
|
|
|
ins(PyObject* d, char* symbol, long value)
|
1997-07-31 16:39:54 -03:00
|
|
|
{
|
|
|
|
PyObject* v = PyInt_FromLong(value);
|
|
|
|
if (!v || PyDict_SetItemString(d, symbol, v) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
Py_DECREF(v);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2000-07-10 14:15:07 -03:00
|
|
|
all_ins(PyObject* d)
|
1997-07-31 16:39:54 -03:00
|
|
|
{
|
|
|
|
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;
|
1997-08-14 23:52:08 -03:00
|
|
|
return 0;
|
1997-07-31 16:39:54 -03:00
|
|
|
}
|
|
|
|
|
1998-12-04 14:50:17 -04:00
|
|
|
DL_EXPORT(void)
|
2000-07-21 03:00:07 -03:00
|
|
|
initfcntl(void)
|
1992-08-17 05:55:12 -03:00
|
|
|
{
|
1996-12-17 13:42:22 -04:00
|
|
|
PyObject *m, *d;
|
1992-08-17 05:55:12 -03:00
|
|
|
|
1998-11-23 11:32:55 -04:00
|
|
|
/* Create the module and add the functions and documentation */
|
|
|
|
m = Py_InitModule3("fcntl", fcntl_methods, module_doc);
|
1992-08-17 05:55:12 -03:00
|
|
|
|
|
|
|
/* Add some symbolic constants to the module */
|
1996-12-17 13:42:22 -04:00
|
|
|
d = PyModule_GetDict(m);
|
1997-07-31 16:39:54 -03:00
|
|
|
all_ins(d);
|
1992-08-17 05:55:12 -03:00
|
|
|
}
|