|
Packit |
130fc8 |
/* Simple D-Bus types: Unix FD type.
|
|
Packit |
130fc8 |
*
|
|
Packit |
130fc8 |
* Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
|
|
Packit |
130fc8 |
* Copyright (C) 2010 Signove <http://www.signove.com>
|
|
Packit |
130fc8 |
*
|
|
Packit |
130fc8 |
* Permission is hereby granted, free of charge, to any person
|
|
Packit |
130fc8 |
* obtaining a copy of this software and associated documentation
|
|
Packit |
130fc8 |
* files (the "Software"), to deal in the Software without
|
|
Packit |
130fc8 |
* restriction, including without limitation the rights to use, copy,
|
|
Packit |
130fc8 |
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
Packit |
130fc8 |
* of the Software, and to permit persons to whom the Software is
|
|
Packit |
130fc8 |
* furnished to do so, subject to the following conditions:
|
|
Packit |
130fc8 |
*
|
|
Packit |
130fc8 |
* The above copyright notice and this permission notice shall be
|
|
Packit |
130fc8 |
* included in all copies or substantial portions of the Software.
|
|
Packit |
130fc8 |
*
|
|
Packit |
130fc8 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
Packit |
130fc8 |
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
Packit |
130fc8 |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
Packit |
130fc8 |
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
Packit |
130fc8 |
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
Packit |
130fc8 |
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
Packit |
130fc8 |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
Packit |
130fc8 |
* DEALINGS IN THE SOFTWARE.
|
|
Packit |
130fc8 |
*/
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
#include "dbus_bindings-internal.h"
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
#include "types-internal.h"
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
PyDoc_STRVAR(UnixFd_tp_doc,
|
|
Packit |
130fc8 |
"An Unix Fd.\n"
|
|
Packit |
130fc8 |
"\n"
|
|
Packit |
130fc8 |
"Constructor::\n"
|
|
Packit |
130fc8 |
"\n"
|
|
Packit |
130fc8 |
" dbus.UnixFd(value: int or file object[, variant_level: int]) -> UnixFd\n"
|
|
Packit |
130fc8 |
"\n"
|
|
Packit |
130fc8 |
"``value`` must be the integer value of a file descriptor, or an object that\n"
|
|
Packit |
130fc8 |
"implements the fileno() method. Otherwise, `ValueError` will be\n"
|
|
Packit |
130fc8 |
"raised.\n"
|
|
Packit |
130fc8 |
"\n"
|
|
Packit |
130fc8 |
"UnixFd keeps a dup() (duplicate) of the supplied file descriptor. The\n"
|
|
Packit |
130fc8 |
"caller remains responsible for closing the original fd.\n"
|
|
Packit |
130fc8 |
"\n"
|
|
Packit |
130fc8 |
"``variant_level`` must be non-negative; the default is 0.\n"
|
|
Packit |
130fc8 |
"\n"
|
|
Packit |
130fc8 |
":IVariables:\n"
|
|
Packit |
130fc8 |
" `variant_level` : int\n"
|
|
Packit |
130fc8 |
" Indicates how many nested Variant containers this object\n"
|
|
Packit |
130fc8 |
" is contained in: if a message's wire format has a variant containing a\n"
|
|
Packit |
130fc8 |
" variant containing an Unix Fd, this is represented in Python by an\n"
|
|
Packit |
130fc8 |
" Unix Fd with variant_level==2.\n"
|
|
Packit |
130fc8 |
);
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
typedef struct {
|
|
Packit |
130fc8 |
PyObject_HEAD
|
|
Packit |
130fc8 |
int fd;
|
|
Packit |
130fc8 |
} UnixFdObject;
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
/* Return values:
|
|
Packit |
130fc8 |
* -2 - the long value overflows an int
|
|
Packit |
130fc8 |
* -1 - Python failed producing a long (or in Python 2 an int)
|
|
Packit |
130fc8 |
* 0 - success
|
|
Packit |
130fc8 |
* 1 - arg is not a long (or in Python 2 an int)
|
|
Packit |
130fc8 |
*
|
|
Packit |
130fc8 |
* Or to summarize:
|
|
Packit |
130fc8 |
* status < 0 - an error occurred, and a Python exception is set.
|
|
Packit |
130fc8 |
* status == 0 - all is okay, output argument *fd is set.
|
|
Packit |
130fc8 |
* status > 0 - try something else
|
|
Packit |
130fc8 |
*/
|
|
Packit |
130fc8 |
static int
|
|
Packit |
130fc8 |
make_fd(PyObject *arg, int *fd)
|
|
Packit |
130fc8 |
{
|
|
Packit |
130fc8 |
long fd_arg;
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
if (INTORLONG_CHECK(arg))
|
|
Packit |
130fc8 |
{
|
|
Packit |
130fc8 |
/* on Python 2 this accepts either int or long */
|
|
Packit |
130fc8 |
fd_arg = PyLong_AsLong(arg);
|
|
Packit |
130fc8 |
if (fd_arg == -1 && PyErr_Occurred()) {
|
|
Packit |
130fc8 |
return -1;
|
|
Packit |
130fc8 |
}
|
|
Packit |
130fc8 |
}
|
|
Packit |
130fc8 |
else {
|
|
Packit |
130fc8 |
return 1;
|
|
Packit |
130fc8 |
}
|
|
Packit |
130fc8 |
/* Check for int overflow. */
|
|
Packit |
130fc8 |
if (fd_arg < INT_MIN || fd_arg > INT_MAX) {
|
|
Packit |
130fc8 |
PyErr_Format(PyExc_ValueError, "int is outside fd range");
|
|
Packit |
130fc8 |
return -2;
|
|
Packit |
130fc8 |
}
|
|
Packit |
130fc8 |
*fd = (int)fd_arg;
|
|
Packit |
130fc8 |
return 0;
|
|
Packit |
130fc8 |
}
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
static PyObject *
|
|
Packit |
130fc8 |
UnixFd_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs UNUSED)
|
|
Packit |
130fc8 |
{
|
|
Packit |
130fc8 |
UnixFdObject *self = NULL;
|
|
Packit |
130fc8 |
PyObject *arg;
|
|
Packit |
130fc8 |
int status, fd, fd_original = -1;
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
if (!PyArg_ParseTuple(args, "O", &arg, NULL)) {
|
|
Packit |
130fc8 |
return NULL;
|
|
Packit |
130fc8 |
}
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
status = make_fd(arg, &fd_original);
|
|
Packit |
130fc8 |
if (status < 0)
|
|
Packit |
130fc8 |
return NULL;
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
if (status > 0) {
|
|
Packit |
130fc8 |
if (PyObject_HasAttrString(arg, "fileno")) {
|
|
Packit |
130fc8 |
PyObject *fd_number = PyObject_CallMethod(arg, "fileno", NULL);
|
|
Packit |
130fc8 |
if (!fd_number)
|
|
Packit |
130fc8 |
return NULL;
|
|
Packit |
130fc8 |
status = make_fd(fd_number, &fd_original);
|
|
Packit |
130fc8 |
Py_CLEAR(fd_number);
|
|
Packit |
130fc8 |
if (status < 0)
|
|
Packit |
130fc8 |
return NULL;
|
|
Packit |
130fc8 |
if (status > 0) {
|
|
Packit |
130fc8 |
PyErr_Format(PyExc_ValueError, "Argument's fileno() method "
|
|
Packit |
130fc8 |
"returned a non-int value");
|
|
Packit |
130fc8 |
return NULL;
|
|
Packit |
130fc8 |
}
|
|
Packit |
130fc8 |
/* fd_original is all good. */
|
|
Packit |
130fc8 |
}
|
|
Packit |
130fc8 |
else {
|
|
Packit |
130fc8 |
PyErr_Format(PyExc_ValueError, "Argument is not int and does not "
|
|
Packit |
130fc8 |
"implement fileno() method");
|
|
Packit |
130fc8 |
return NULL;
|
|
Packit |
130fc8 |
}
|
|
Packit |
130fc8 |
}
|
|
Packit |
130fc8 |
assert(fd_original >= 0);
|
|
Packit |
130fc8 |
fd = dup(fd_original);
|
|
Packit |
130fc8 |
if (fd < 0) {
|
|
Packit |
130fc8 |
PyErr_Format(PyExc_ValueError, "Invalid file descriptor");
|
|
Packit |
130fc8 |
return NULL;
|
|
Packit |
130fc8 |
}
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
self = (UnixFdObject *) cls->tp_alloc(cls, 0);
|
|
Packit |
130fc8 |
if (!self)
|
|
Packit |
130fc8 |
return NULL;
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
self->fd = fd;
|
|
Packit |
130fc8 |
return (PyObject *)self;
|
|
Packit |
130fc8 |
}
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
static void
|
|
Packit |
130fc8 |
UnixFd_dealloc(UnixFdObject *self)
|
|
Packit |
130fc8 |
{
|
|
Packit |
130fc8 |
if (self->fd >= 0) {
|
|
Packit |
130fc8 |
close(self->fd);
|
|
Packit |
130fc8 |
self->fd = -1;
|
|
Packit |
130fc8 |
}
|
|
Packit |
130fc8 |
}
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
PyDoc_STRVAR(UnixFd_take__doc__,
|
|
Packit |
130fc8 |
"take() -> int\n"
|
|
Packit |
130fc8 |
"\n"
|
|
Packit |
130fc8 |
"This method returns the file descriptor owned by UnixFd object.\n"
|
|
Packit |
130fc8 |
"Note that, once this method is called, closing the file descriptor is\n"
|
|
Packit |
130fc8 |
"the caller's responsibility.\n"
|
|
Packit |
130fc8 |
"\n"
|
|
Packit |
130fc8 |
"This method may be called at most once; UnixFd 'forgets' the file\n"
|
|
Packit |
130fc8 |
"descriptor after it is taken.\n"
|
|
Packit |
130fc8 |
"\n"
|
|
Packit |
130fc8 |
":Raises ValueError: if this method has already been called\n"
|
|
Packit |
130fc8 |
);
|
|
Packit |
130fc8 |
static PyObject *
|
|
Packit |
130fc8 |
UnixFd_take(UnixFdObject *self)
|
|
Packit |
130fc8 |
{
|
|
Packit |
130fc8 |
PyObject *fdnumber;
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
if (self->fd < 0) {
|
|
Packit |
130fc8 |
PyErr_SetString(PyExc_ValueError, "File descriptor already taken");
|
|
Packit |
130fc8 |
return NULL;
|
|
Packit |
130fc8 |
}
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
fdnumber = Py_BuildValue("i", self->fd);
|
|
Packit |
130fc8 |
self->fd = -1;
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
return fdnumber;
|
|
Packit |
130fc8 |
}
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
int
|
|
Packit |
130fc8 |
dbus_py_unix_fd_get_fd(PyObject *self)
|
|
Packit |
130fc8 |
{
|
|
Packit |
130fc8 |
return ((UnixFdObject *) self)->fd;
|
|
Packit |
130fc8 |
}
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
static PyMethodDef UnixFd_methods[] = {
|
|
Packit |
130fc8 |
{"take", (PyCFunction) UnixFd_take, METH_NOARGS, UnixFd_take__doc__ },
|
|
Packit |
130fc8 |
{NULL}
|
|
Packit |
130fc8 |
};
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
PyTypeObject DBusPyUnixFd_Type = {
|
|
Packit |
130fc8 |
PyVarObject_HEAD_INIT(NULL, 0)
|
|
Packit |
130fc8 |
"dbus.UnixFd",
|
|
Packit |
130fc8 |
sizeof(UnixFdObject),
|
|
Packit |
130fc8 |
0,
|
|
Packit |
130fc8 |
(destructor) UnixFd_dealloc, /* tp_dealloc */
|
|
Packit |
130fc8 |
0, /* tp_print */
|
|
Packit |
130fc8 |
0, /* tp_getattr */
|
|
Packit |
130fc8 |
0, /* tp_setattr */
|
|
Packit |
130fc8 |
0, /* tp_compare */
|
|
Packit |
130fc8 |
0, /* tp_repr */
|
|
Packit |
130fc8 |
0, /* tp_as_number */
|
|
Packit |
130fc8 |
0, /* tp_as_sequence */
|
|
Packit |
130fc8 |
0, /* tp_as_mapping */
|
|
Packit |
130fc8 |
0, /* tp_hash */
|
|
Packit |
130fc8 |
0, /* tp_call */
|
|
Packit |
130fc8 |
0, /* tp_str */
|
|
Packit |
130fc8 |
0, /* tp_getattro */
|
|
Packit |
130fc8 |
0, /* tp_setattro */
|
|
Packit |
130fc8 |
0, /* tp_as_buffer */
|
|
Packit |
130fc8 |
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
|
Packit |
130fc8 |
UnixFd_tp_doc, /* tp_doc */
|
|
Packit |
130fc8 |
0, /* tp_traverse */
|
|
Packit |
130fc8 |
0, /* tp_clear */
|
|
Packit |
130fc8 |
0, /* tp_richcompare */
|
|
Packit |
130fc8 |
0, /* tp_weaklistoffset */
|
|
Packit |
130fc8 |
0, /* tp_iter */
|
|
Packit |
130fc8 |
0, /* tp_iternext */
|
|
Packit |
130fc8 |
UnixFd_methods, /* tp_methods */
|
|
Packit |
130fc8 |
0, /* tp_members */
|
|
Packit |
130fc8 |
0, /* tp_getset */
|
|
Packit |
130fc8 |
0, /* tp_base */
|
|
Packit |
130fc8 |
0, /* tp_dict */
|
|
Packit |
130fc8 |
0, /* tp_descr_get */
|
|
Packit |
130fc8 |
0, /* tp_descr_set */
|
|
Packit |
130fc8 |
0, /* tp_dictoffset */
|
|
Packit |
130fc8 |
0, /* tp_init */
|
|
Packit |
130fc8 |
0, /* tp_alloc */
|
|
Packit |
130fc8 |
UnixFd_tp_new, /* tp_new */
|
|
Packit |
130fc8 |
};
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
dbus_bool_t
|
|
Packit |
130fc8 |
dbus_py_init_unixfd_type(void)
|
|
Packit |
130fc8 |
{
|
|
Packit |
130fc8 |
if (PyType_Ready(&DBusPyUnixFd_Type) < 0) return 0;
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
return 1;
|
|
Packit |
130fc8 |
}
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
dbus_bool_t
|
|
Packit |
130fc8 |
dbus_py_insert_unixfd_type(PyObject *this_module)
|
|
Packit |
130fc8 |
{
|
|
Packit |
130fc8 |
Py_INCREF(&DBusPyUnixFd_Type);
|
|
Packit |
130fc8 |
if (PyModule_AddObject(this_module, "UnixFd",
|
|
Packit |
130fc8 |
(PyObject *)&DBusPyUnixFd_Type) < 0) return 0;
|
|
Packit |
130fc8 |
return 1;
|
|
Packit |
130fc8 |
}
|
|
Packit |
130fc8 |
|
|
Packit |
130fc8 |
/* vim:set ft=c cino< sw=4 sts=4 et: */
|