~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
cvs/emstar/fusd/python/fusdmodule.c


  1 /*
  2  *
  3  * Copyright (c) 2003 The Regents of the University of California.  All 
  4  * rights reserved.
  5  *
  6  * Redistribution and use in source and binary forms, with or without
  7  * modification, are permitted provided that the following conditions
  8  * are met:
  9  *
 10  * - Redistributions of source code must retain the above copyright
 11  *   notice, this list of conditions and the following disclaimer.
 12  *
 13  * - Neither the name of the University nor the names of its
 14  *   contributors may be used to endorse or promote products derived
 15  *   from this software without specific prior written permission.
 16  *
 17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
 18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 19  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 20  * PARTICULAR  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
 21  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 25  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 27  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28  *
 29  */
 30  
 31 
 32 /*
 33     Copyright (C) 2003  Brian Warner  <warner-fusd@lothar.com>
 34 
 35     This program is free software, and can be distributed under the same
 36     terms as the rest of FUSD (the BSD 3-clause license). See the file
 37     ../LICENSE for details.
 38 */
 39 
 40 
 41 
 42 #include <stdio.h>
 43 #include <Python.h>
 44 
 45 #include <sys/types.h>
 46 #include <sys/ioctl.h>
 47 #include <errno.h>
 48 
 49 #include "fusd.h"
 50 
 51 typedef struct {
 52     PyObject_HEAD
 53     struct fusd_file_info *file;
 54     int active;
 55     PyObject *fp;
 56 } RequestObject;
 57 
 58 staticforward PyTypeObject ReadRequest_Type;
 59 staticforward PyTypeObject WriteRequest_Type;
 60 staticforward PyTypeObject IoctlRequest_Type;
 61 staticforward PyTypeObject PollDiffRequest_Type;
 62 
 63 #define ReadRequestObject_Check(v) ((v)->ob_type == &ReadRequest_Type)
 64 #define WriteRequestObject_Check(v) ((v)->ob_type == &WriteRequest_Type)
 65 #define IoctlRequestObject_Check(v) ((v)->ob_type == &IoctlRequest_Type)
 66 #define PollDiffRequestObject_Check(v) ((v)->ob_type == &PollDiffRequest_Type)
 67 
 68 static RequestObject *
 69 newReadRequestObject(struct fusd_file_info *file, PyObject *fp)
 70 {
 71     RequestObject *self;
 72     self = PyObject_New(RequestObject, &ReadRequest_Type);
 73     if (self == NULL)
 74         return NULL;
 75     self->file = file;
 76     self->active = 1;
 77     self->fp = fp;
 78     return self;
 79 }
 80 
 81 static RequestObject *
 82 newWriteRequestObject(struct fusd_file_info *file, PyObject *fp)
 83 {
 84     RequestObject *self;
 85     self = PyObject_New(RequestObject, &WriteRequest_Type);
 86     if (self == NULL)
 87         return NULL;
 88     self->file = file;
 89     self->active = 1;
 90     self->fp = fp;
 91     return self;
 92 }
 93 
 94 static RequestObject *
 95 newIoctlRequestObject(struct fusd_file_info *file, PyObject *fp)
 96 {
 97     RequestObject *self;
 98     self = PyObject_New(RequestObject, &IoctlRequest_Type);
 99     if (self == NULL)
100         return NULL;
101     self->file = file;
102     self->active = 1;
103     self->fp = fp;
104     return self;
105 }
106 
107 static RequestObject *
108 newPollDiffRequestObject(struct fusd_file_info *file, PyObject *fp)
109 {
110     RequestObject *self;
111     self = PyObject_New(RequestObject, &PollDiffRequest_Type);
112     if (self == NULL)
113         return NULL;
114     self->file = file;
115     self->active = 1;
116     self->fp = fp;
117     return self;
118 }
119 
120 static void
121 Request_dealloc(RequestObject *self)
122 {
123     if (self->active) {
124         /* the python code should not let active requests fall out of scope.
125            They should all be explicitly .finish()ed or .destroy()ed */
126         fprintf(stderr, "Warning: Active Request <%s> being destroyed\n",
127                 self->ob_type->tp_name);
128         self->active = 0;
129         fusd_destroy(self->file);
130     }
131     PyObject_Del(self);
132 }
133 
134 static PyObject *
135 Request_finish(RequestObject *self, PyObject *args)
136 {
137     int retval; /* really ssize_t */
138     int rc;
139 
140     if (!PyArg_ParseTuple(args, "i:finish", &retval))
141         return NULL;
142     if (!self->active) {
143         PyErr_SetString(PyExc_RuntimeError, "duplicate request->return");
144         return NULL;
145     }
146     rc = fusd_return(self->file, retval);
147     self->active = 0;
148     return PyInt_FromLong(rc);
149 }
150 
151 static PyObject *
152 Request_destroy(RequestObject *self, PyObject *args)
153 {
154     if (!PyArg_ParseTuple(args, ":destroy"))
155         return NULL;
156     if (!self->active) {
157         PyErr_SetString(PyExc_RuntimeError,
158                         "can only destroy active requests");
159         return NULL;
160     }
161     fusd_destroy(self->file);
162     self->active = 0;
163 
164     Py_INCREF(Py_None);
165     return Py_None;
166 }
167 
168 static PyObject *
169 ReadRequest_setdata(RequestObject *self, PyObject *args)
170 {
171     int offset;
172     char *data;
173     int datalen;
174 
175     if (!self->active) {
176         PyErr_SetString(PyExc_RuntimeError, "setdata on inactive request");
177         return NULL;
178     }
179 
180     if (!PyArg_ParseTuple(args, "is#:setdata", &offset, &data, &datalen))
181         return NULL;
182 
183     if ((offset < 0) || (offset+datalen > fusd_get_length(self->file))) {
184         PyErr_SetString(PyExc_IndexError, "writing beyond buffer");
185         return NULL;
186     }
187 
188     memcpy(fusd_get_read_buffer(self->file), data, datalen);
189 
190     Py_INCREF(Py_None);
191     return Py_None;
192 }
193 
194 static PyObject *
195 WriteRequest_getdata(RequestObject *self, PyObject *args)
196 {
197     int offset = 0;
198     int datalen = fusd_get_length(self->file);
199     int reqlen = datalen;
200     PyObject *ret;
201 
202     if (!self->active) {
203         PyErr_SetString(PyExc_RuntimeError, "getdata on inactive request");
204         return NULL;
205     }
206     if (!PyArg_ParseTuple(args, "|ii:getdata", &offset, &reqlen))
207         return NULL;
208 
209     if ((offset < 0) || (reqlen < 0 ) || (offset+reqlen > datalen)) {
210         PyErr_SetString(PyExc_IndexError, "reading beyond buffer");
211         return NULL;
212     }
213 
214     ret = Py_BuildValue("s#", fusd_get_write_buffer(self->file) + offset,
215                         reqlen);
216     return ret;
217 }
218 
219 static PyObject *
220 IoctlRequest_getdata(RequestObject *self, PyObject *args)
221 {
222 
223     if (!self->active) {
224         PyErr_SetString(PyExc_RuntimeError, "getdata on inactive request");
225         return NULL;
226     }
227 
228     // IO_W or IO_WR will have a data pointer
229     if (fusd_get_ioctl_buffer(self->file)) {
230         return Py_BuildValue("s#", fusd_get_ioctl_buffer(self->file),
231                              fusd_get_length(self->file));
232     }
233     // IO will have an int, IO_R will probably have a zero
234     return PyInt_FromLong(fusd_get_ioctl_arg(self->file));
235 }
236 
237 static PyObject *
238 IoctlRequest_setdata(RequestObject *self, PyObject *args)
239 {
240     char *data;
241     int datalen;
242     int cmd = fusd_get_ioctl_request(self->file);
243 
244     if (!self->active) {
245         PyErr_SetString(PyExc_RuntimeError, "getdata on inactive request");
246         return NULL;
247     }
248 
249     // IO_R will have a data pointer. IO_W will to, but it isn't used
250     if ((_IOC_DIR(cmd) & _IOC_READ) && fusd_get_ioctl_buffer(self->file))
251     {
252         if (!PyArg_ParseTuple(args, "s#:setdata", &data, &datalen))
253             return NULL;
254         if (datalen > fusd_get_length(self->file)) {
255             PyErr_Format(PyExc_IndexError,
256                          "too much data: ioctl accepts %d bytes, given %d",
257                          fusd_get_length(self->file), datalen);
258             return NULL;
259         }
260         memcpy(fusd_get_ioctl_buffer(self->file), data, datalen);
261         Py_INCREF(Py_None);
262         return Py_None;
263     }
264 
265     PyErr_SetString(PyExc_TypeError, "this ioctl is read only");
266     return NULL;
267 }
268 
269 
270 static PyMethodDef ReadRequest_methods[] = {
271     {"setdata", (PyCFunction)ReadRequest_setdata, METH_VARARGS},
272     {"destroy", (PyCFunction)Request_destroy, METH_VARARGS},
273     {"finish", (PyCFunction)Request_finish, METH_VARARGS},
274     {NULL, NULL} /* sentinel */
275 };
276 
277 static PyMethodDef WriteRequest_methods[] = {
278     {"getdata", (PyCFunction)WriteRequest_getdata, METH_VARARGS},
279     {"destroy", (PyCFunction)Request_destroy, METH_VARARGS},
280     {"finish", (PyCFunction)Request_finish, METH_VARARGS},
281     {NULL, NULL} /* sentinel */
282 };
283 
284 static PyMethodDef IoctlRequest_methods[] = {
285     {"getdata", (PyCFunction)IoctlRequest_getdata, METH_VARARGS},
286     {"setdata", (PyCFunction)IoctlRequest_setdata, METH_VARARGS},
287     {"destroy", (PyCFunction)Request_destroy, METH_VARARGS},
288     {"finish", (PyCFunction)Request_finish, METH_VARARGS},
289     {NULL, NULL} /* sentinel */
290 };
291 
292 static PyMethodDef PollDiffRequest_methods[] = {
293     {"destroy", (PyCFunction)Request_destroy, METH_VARARGS},
294     {"finish", (PyCFunction)Request_finish, METH_VARARGS},
295     {NULL, NULL} /* sentinel */
296 };
297 
298 static int
299 Request_getparm(RequestObject *self, char *name, int *valid)
300 {
301     *valid = 1;
302     if (strcmp(name, "length") == 0)
303         return fusd_get_length(self->file);
304     if (strcmp(name, "fd") == 0)
305         return self->file->fd;
306     if (strcmp(name, "flags") == 0)
307         return self->file->flags;
308     if (strcmp(name, "pid") == 0)
309         return self->file->pid;
310     if (strcmp(name, "uid") == 0)
311         return self->file->uid;
312     if (strcmp(name, "gid") == 0)
313         return self->file->gid;
314     if (strcmp(name, "offset") == 0) {
315         int offset = *(fusd_get_offset(self->file)); /* loff_t */
316         return offset;
317     }
318             
319     *valid = 0;
320     return 0;
321 }
322 
323 static PyObject *
324 ReadRequest_getattr(RequestObject *self, char *name)
325 {
326     int parm, valid;
327 
328     parm = Request_getparm(self, name, &valid);
329     if (valid)
330         return PyInt_FromLong(parm);
331     return Py_FindMethod(ReadRequest_methods, (PyObject *)self, name);
332 }
333 
334 static PyObject *
335 WriteRequest_getattr(RequestObject *self, char *name)
336 {
337     int parm, valid;
338 
339     parm = Request_getparm(self, name, &valid);
340     if (valid)
341         return PyInt_FromLong(parm);
342     return Py_FindMethod(WriteRequest_methods, (PyObject *)self, name);
343 }
344 
345 static PyObject *
346 IoctlRequest_getattr(RequestObject *self, char *name)
347 {
348     int parm, valid;
349     int cmd = fusd_get_ioctl_request(self->file);
350 
351     parm = Request_getparm(self, name, &valid);
352     if (valid)
353         return PyInt_FromLong(parm);
354     if (strcmp(name, "cmd") == 0)
355         return PyInt_FromLong(cmd);
356     if (strcmp(name, "nr") == 0)
357         return PyInt_FromLong(_IOC_NR(cmd));
358     if (strcmp(name, "type") == 0)
359         return PyInt_FromLong(_IOC_TYPE(cmd));
360     if (strcmp(name, "size") == 0)
361         return PyInt_FromLong(_IOC_SIZE(cmd));
362     if (strcmp(name, "direction") == 0)
363         return PyInt_FromLong(_IOC_DIR(cmd));
364     if (strcmp(name, "dir_string") == 0) {
365         int dir = _IOC_DIR(cmd);
366         switch (dir) {
367           case _IOC_NONE:
368             return PyString_FromString("none");
369           case _IOC_WRITE:
370             return PyString_FromString("write");
371           case _IOC_READ:
372             return PyString_FromString("read");
373           case (_IOC_READ | _IOC_WRITE):
374             return PyString_FromString("readwrite");
375         }
376     }
377 
378     return Py_FindMethod(IoctlRequest_methods, (PyObject *)self, name);
379 }
380 
381 static PyObject *
382 PollDiffRequest_getattr(RequestObject *self, char *name)
383 {
384     return Py_FindMethod(PollDiffRequest_methods, (PyObject *)self, name);
385 }
386 
387 
388 static int
389 Request_setattr(RequestObject *self, char *name, PyObject *v)
390 {
391     if (strcmp(name, "offset") == 0) {
392         int offset;
393         offset = PyInt_AsLong(v);
394         if (PyErr_Occurred())
395             return -1;
396         *(fusd_get_offset(self->file)) = offset; /* loff_t */
397         return 0;
398     }
399     if (strcmp(name, "flags") == 0) {
400         int flags;
401         flags = PyInt_AsLong(v);
402         if (PyErr_Occurred())
403             return -1;
404         self->file->flags = flags;
405         return 0;
406     }
407 
408     PyErr_Format(PyExc_AttributeError,
409                  "cannot set Request attribute '%s'", name);
410     return -1;
411 }
412 
413 statichere PyTypeObject ReadRequest_Type = {
414     /* The ob_type field must be initialized in the module init function
415      * to be portable to Windows without using C++. */
416     PyObject_HEAD_INIT(NULL)
417     0,                              /*ob_size*/
418     "fusdmodule.ReadRequest",       /*tp_name*/
419     sizeof(RequestObject),          /*tp_basicsize*/
420     0,                              /*tp_itemsize*/
421     /* methods */
422     (destructor)Request_dealloc,    /*tp_dealloc*/
423     0,                                     /*tp_print*/
424     (getattrfunc)ReadRequest_getattr,      /*tp_getattr*/
425     (setattrfunc)Request_setattr,          /*tp_setattr*/
426 };
427 
428 statichere PyTypeObject WriteRequest_Type = {
429     /* The ob_type field must be initialized in the module init function
430      * to be portable to Windows without using C++. */
431     PyObject_HEAD_INIT(NULL)
432     0,                              /*ob_size*/
433     "fusdmodule.WriteRequest",      /*tp_name*/
434     sizeof(RequestObject),          /*tp_basicsize*/
435     0,                              /*tp_itemsize*/
436     /* methods */
437     (destructor)Request_dealloc,    /*tp_dealloc*/
438     0,                                     /*tp_print*/
439     (getattrfunc)WriteRequest_getattr,     /*tp_getattr*/
440     (setattrfunc)Request_setattr,          /*tp_setattr*/
441 };
442 
443 statichere PyTypeObject IoctlRequest_Type = {
444     /* The ob_type field must be initialized in the module init function
445      * to be portable to Windows without using C++. */
446     PyObject_HEAD_INIT(NULL)
447     0,                              /*ob_size*/
448     "fusdmodule.IoctlRequest",      /*tp_name*/
449     sizeof(RequestObject),          /*tp_basicsize*/
450     0,                              /*tp_itemsize*/
451     /* methods */
452     (destructor)Request_dealloc,    /*tp_dealloc*/
453     0,                                     /*tp_print*/
454     (getattrfunc)IoctlRequest_getattr,     /*tp_getattr*/
455     (setattrfunc)Request_setattr,          /*tp_setattr*/
456 };
457 
458 statichere PyTypeObject PollDiffRequest_Type = {
459     /* The ob_type field must be initialized in the module init function
460      * to be portable to Windows without using C++. */
461     PyObject_HEAD_INIT(NULL)
462     0,                              /*ob_size*/
463     "fusdmodule.PollDiffRequest",   /*tp_name*/
464     sizeof(RequestObject),          /*tp_basicsize*/
465     0,                              /*tp_itemsize*/
466     /* methods */
467     (destructor)Request_dealloc,    /*tp_dealloc*/
468     0,                                     /*tp_print*/
469     (getattrfunc)PollDiffRequest_getattr,  /*tp_getattr*/
470     0,                                     /*tp_setattr*/
471 };
472 
473 
474 static int
475 client_open(struct fusd_file_info *file)
476 {
477     PyObject *ret, *device;
478     int retval;
479     unsigned int flags;
480     PyObject *fp;
481 
482     device = file->device_info;
483     ret = PyObject_CallMethod(device, "do_open",
484                               "iiii", file->flags, file->pid,
485                               file->uid, file->gid);
486     if (!ret) {
487         /* print and clear the exception */
488         PyErr_Print();
489         return -EIO;
490     }
491     if (!PyArg_ParseTuple(ret, "iiO", &retval, &flags, &fp))
492     {
493         PyErr_Print();
494         return -EIO;
495     }
496     file->flags = flags;
497     file->private_data = fp;
498     return retval;
499 }
500 
501 static int
502 client_close(struct fusd_file_info *file)
503 {
504     PyObject *ret, *device, *fp;
505     int retval;
506 
507     device = file->device_info;
508     fp = file->private_data;
509     ret = PyObject_CallMethod(device, "do_close", "Oiiii",
510                               fp, file->flags, file->pid,
511                               file->uid, file->gid);
512     if (!ret) {
513         /* print and clear the exception */
514         PyErr_Print();
515         return -EIO;
516     }
517     if (!PyArg_ParseTuple(ret, "i", &retval))
518     {
519         PyErr_Print();
520         return -EIO;
521     }
522     return retval;
523 }
524 
525 static ssize_t
526 client_read(struct fusd_file_info *file, char *buffer, size_t length,
527             loff_t *offset)
528 {
529     PyObject *ret, *fp;
530     RequestObject *req;
531     int newoffset;
532 
533     fp = file->private_data;
534 
535     newoffset = *offset; /* loff_t */
536     if (newoffset != *offset) {
537         fprintf(stderr, "Ack! offset is too large, loff_t is too big\n");
538         fprintf(stderr, "client_read() failing..\n");
539         return -EIO;
540     }
541 
542     req = newReadRequestObject(file, fp);
543     if (!req) {
544         fprintf(stderr, "client_read: unable to allocate RequestObject\n");
545         return -EIO;
546     }
547 
548     ret = PyObject_CallMethod(fp, "do_read", "O", req);
549 
550     if (ret == Py_None) {
551         /* this is the normal case. They might have called req.finish, or
552            they may defer it until later. */
553         Py_DECREF(req);
554         return -FUSD_NOREPLY;
555     }
556 
557     /* something went wrong */
558 
559     if (ret) {
560         fprintf(stderr,
561                 "do_read should not return anything (returned <%s>)\n",
562                 ret->ob_type->tp_name);
563     } else {
564         /* print and clear the exception */
565         PyErr_Print();
566     }
567 
568     if (req->active) {
569         /* they didn't do .finish, so free the Request (preserving the .file
570            struct) and return an error. */
571         req->active = 0;
572         Py_DECREF(req);
573         return -EIO;
574     }
575     /* they did do .finish, so an error code was already sent */
576     Py_DECREF(req);
577     return -FUSD_NOREPLY;
578 }
579 
580 static ssize_t
581 client_write(struct fusd_file_info *file, const char *buffer,
582              size_t length, loff_t *offset)
583 {
584     PyObject *ret, *fp;
585     int newoffset;
586     RequestObject *req;
587 
588     /* N.B.: loff_t is larger than an int, so you can't pass *offset to a
589      varargs function because everything after that argument will be taken
590      from the wrong place. Downgrade it to an int before handing it to
591      Py_BuildValue. This also means we can't deal with >2GB files yet. */
592 
593     fp = file->private_data;
594     newoffset = *offset;
595 
596     if (newoffset != *offset) {
597         fprintf(stderr, "Ack! offset is too large, loff_t is too big\n");
598         fprintf(stderr, "client_write() failing..\n");
599         return -EIO;
600     }
601 
602     req = newWriteRequestObject(file, fp);
603     if (!req) {
604         fprintf(stderr, "client_write: unable to allocate RequestObject\n");
605         return -EIO;
606     }
607     
608     ret = PyObject_CallMethod(fp, "do_write", "O", req);
609 
610     if (ret == Py_None) {
611         /* this is the normal case. They might have called req.finish, or
612            they may defer it until later. */
613         Py_DECREF(req);
614         return -FUSD_NOREPLY;
615     }
616 
617     /* something went wrong */
618 
619     if (ret) {
620         fprintf(stderr,
621                 "do_write should not return anything (returned <%s>)\n",
622                 ret->ob_type->tp_name);
623     } else {
624         /* print and clear the exception */
625         PyErr_Print();
626     }
627 
628     if (req->active) {
629         /* they didn't do .finish, so free the Request (preserving the .file
630            struct) and return an error. */
631         req->active = 0;
632         Py_DECREF(req);
633         return -EIO;
634     }
635     /* they did do .finish, so an error code was already sent */
636     Py_DECREF(req);
637     return -FUSD_NOREPLY;
638 }
639 
640 static int
641 client_ioctl(struct fusd_file_info *file, int request, void *data)
642 {
643     PyObject *ret, *fp;
644     RequestObject *req;
645 
646     fp = file->private_data;
647 
648     req = newIoctlRequestObject(file, fp);
649     if (!req) {
650         fprintf(stderr, "client_ioctl: unable to allocate RequestObject\n");
651         return -EIO;
652     }
653 
654     ret = PyObject_CallMethod(fp, "do_ioctl", "O", req);
655 
656     if (ret == Py_None) {
657         /* this is the normal case. They might have called req.finish, or
658            they may defer it until later. */
659         Py_DECREF(req);
660         return -FUSD_NOREPLY;
661     }
662 
663     /* something went wrong */
664 
665     if (ret) {
666         fprintf(stderr,
667                 "do_ioctl should not return anything (returned <%s>)\n",
668                 ret->ob_type->tp_name);
669     } else {
670         /* print and clear the exception */
671         PyErr_Print();
672     }
673 
674     if (req->active) {
675         /* they didn't do .finish, so free the Request (preserving the .file
676            struct) and return an error. */
677         req->active = 0;
678         Py_DECREF(req);
679         return -EIO;
680     }
681     /* they did do .finish, so an error code was already sent */
682     Py_DECREF(req);
683     return -FUSD_NOREPLY;
684 }
685 
686 static int
687 client_poll_diff(struct fusd_file_info *file, unsigned int cached_state)
688 {
689     PyObject *ret, *fp;
690     RequestObject *req;
691 
692     fp = file->private_data;
693 
694     req = newPollDiffRequestObject(file, fp);
695     if (!req) {
696         fprintf(stderr,
697                 "client_poll_diff: unable to allocate RequestObject\n");
698         return -EIO;
699     }
700 
701     ret = PyObject_CallMethod(fp, "do_poll_diff", "Oi", req, cached_state);
702 
703     if (ret == Py_None) {
704         /* this is the normal case. They might have called req.finish, or
705            they may defer it until later. */
706         Py_DECREF(req);
707         return -FUSD_NOREPLY;
708     }
709 
710     /* something went wrong */
711 
712     if (ret) {
713         fprintf(stderr,
714                 "do_poll_diff should not return anything (returned <%s>)\n",
715                 ret->ob_type->tp_name);
716     } else {
717         /* print and clear the exception */
718         PyErr_Print();
719     }
720 
721     if (req->active) {
722         /* they didn't do .finish, so free the Request (preserving the .file
723            struct) and return an error. */
724         req->active = 0;
725         Py_DECREF(req);
726         return -EIO;
727     }
728     /* they did do .finish, so an error code was already sent */
729     Py_DECREF(req);
730     return -FUSD_NOREPLY;
731 }
732 
733 static struct fusd_file_operations fops = {
734     open: client_open,
735     close: client_close,
736     read: client_read,
737     write: client_write,
738     ioctl: client_ioctl,
739     poll_diff: client_poll_diff,
740 };
741 
742 
743 static PyObject *
744 do_register(PyObject *self, PyObject *args)
745 {
746     const char *name;
747     PyObject *device_info;
748     int mode; /* permissions for the /dev/NAME device, like 0666 */
749     mode_t realmode;
750     int handle;
751 
752     if (!PyArg_ParseTuple(args, "siO", &name, &mode, &device_info))
753         return NULL;
754 
755     realmode = mode;
756     handle = fusd_register(name, realmode, device_info, &fops);
757     if (handle < 0) {
758         /* errno will be ENOPKG if the kernel module isn't installed */
759         return PyErr_SetFromErrno(PyExc_RuntimeError);
760     }
761     Py_INCREF(device_info);
762     return PyInt_FromLong(handle);
763 }
764 
765 static PyObject *
766 do_unregister(PyObject *self, PyObject *args)
767 {
768     PyObject *device_info;
769     int rc, fd;
770 
771     if (!PyArg_ParseTuple(args, "iO", &fd, &device_info))
772         return NULL;
773 
774     rc = fusd_unregister(fd);
775     Py_DECREF(device_info);
776     if (rc < 0) {
777         return PyErr_SetFromErrno(PyExc_RuntimeError);
778     }
779     return PyInt_FromLong(rc);
780 }
781 
782 static PyObject *
783 do_dispatch(PyObject *self, PyObject *args)
784 {
785     int fd;
786 
787     if (!PyArg_ParseTuple(args, "i", &fd))
788         return NULL;
789 
790     fusd_dispatch(fd);
791 
792     Py_INCREF(Py_None);
793     return Py_None;
794 }
795 
796 static PyObject *
797 do_run(PyObject *self, PyObject *args)
798 {
799     if (!PyArg_ParseTuple(args, ""))
800         return NULL;
801 
802     fusd_run(); /* runs forever */
803 
804     Py_INCREF(Py_None);
805     return Py_None; /* but just in case */
806 }
807 
808 static
809 struct PyMethodDef Methods[] =
810 {
811     {"register",  do_register, METH_VARARGS },
812     {"unregister",  do_unregister, METH_VARARGS },
813     {"dispatch",  do_dispatch, METH_VARARGS },
814     {"run",  do_run, METH_VARARGS },
815     {NULL, NULL },
816 };
817 
818 DL_EXPORT(void)
819 init_fusd(void)
820 {
821     PyObject *module, *d;
822 
823     ReadRequest_Type.ob_type = &PyType_Type;
824     WriteRequest_Type.ob_type = &PyType_Type;
825     IoctlRequest_Type.ob_type = &PyType_Type;
826 
827     module = Py_InitModule("_fusd", Methods);
828 
829     /* constants */
830     d = PyModule_GetDict(module);
831     PyDict_SetItemString(d, "NOREPLY", PyInt_FromLong(FUSD_NOREPLY));
832     PyDict_SetItemString(d, "NOTIFY_INPUT",
833                          PyInt_FromLong(FUSD_NOTIFY_INPUT));
834     PyDict_SetItemString(d, "NOTIFY_OUTPUT",
835                          PyInt_FromLong(FUSD_NOTIFY_OUTPUT));
836     PyDict_SetItemString(d, "NOTIFY_EXCEPT",
837                          PyInt_FromLong(FUSD_NOTIFY_EXCEPT));
838 }
839 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.