ia64/xen-unstable

view tools/python/xen/lowlevel/xs/xs.c @ 6674:a75b08af8d19

merge?
author cl349@firebug.cl.cam.ac.uk
date Wed Sep 07 12:48:11 2005 +0000 (2005-09-07)
parents 63e226a5e272 dd668f7527cb
children 639a36483fee
line source
1 /*
2 * Python interface to the Xen Store Daemon.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of version 2.1 of the GNU Lesser General Public
6 * License as published by the Free Software Foundation.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Copyright (C) 2005 Mike Wray Hewlett-Packard
18 * Copyright (C) 2005 Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
19 *
20 */
22 #include <Python.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
31 #include "xs.h"
33 /** @file
34 * Python interface to the Xen Store Daemon (xs).
35 */
37 /* Needed for Python versions earlier than 2.3. */
38 #ifndef PyMODINIT_FUNC
39 #define PyMODINIT_FUNC DL_EXPORT(void)
40 #endif
42 #define PYPKG "xen.lowlevel.xs"
44 /** Python wrapper round an xs handle.
45 */
46 typedef struct XsHandle {
47 PyObject_HEAD;
48 struct xs_handle *xh;
49 PyObject *watches;
50 } XsHandle;
52 static inline struct xs_handle *xshandle(PyObject *self)
53 {
54 struct xs_handle *xh = ((XsHandle*)self)->xh;
55 if (!xh)
56 PyErr_SetString(PyExc_RuntimeError, "invalid xenstore daemon handle");
57 return xh;
58 }
60 static inline PyObject *pyvalue_int(int val) {
61 return (val
62 ? PyInt_FromLong(val)
63 : PyErr_SetFromErrno(PyExc_RuntimeError));
64 }
66 static inline PyObject *pyvalue_str(char *val) {
67 return (val
68 ? PyString_FromString(val)
69 : PyErr_SetFromErrno(PyExc_RuntimeError));
70 }
72 #define xspy_read_doc "\n" \
73 "Read data from a path.\n" \
74 " path [string]: xenstore path\n" \
75 "\n" \
76 "Returns: [string] data read.\n" \
77 "Raises RuntimeError on error.\n" \
78 "\n"
80 static PyObject *xspy_read(PyObject *self, PyObject *args, PyObject *kwds)
81 {
82 static char *kwd_spec[] = { "path", NULL };
83 static char *arg_spec = "s|";
84 char *path = NULL;
86 struct xs_handle *xh = xshandle(self);
87 char *xsval = NULL;
88 unsigned int xsval_n = 0;
89 PyObject *val = NULL;
91 if (!xh)
92 goto exit;
93 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
94 &path))
95 goto exit;
96 xsval = xs_read(xh, path, &xsval_n);
97 if (!xsval) {
98 val = pyvalue_int(0);
99 goto exit;
100 }
101 val = PyString_FromStringAndSize(xsval, xsval_n);
102 exit:
103 if (xsval)
104 free(xsval);
105 return val;
106 }
108 #define xspy_write_doc "\n" \
109 "Write data to a path.\n" \
110 " path [string] : xenstore path to write to\n." \
111 " data [string] : data to write.\n" \
112 " create [int] : create flag, default 0.\n" \
113 " excl [int] : exclusive flag, default 0.\n" \
114 "\n" \
115 "Returns: [int] 0 on success.\n" \
116 "Raises RuntimeError on error.\n" \
117 "\n"
119 static PyObject *xspy_write(PyObject *self, PyObject *args, PyObject *kwds)
120 {
121 static char *kwd_spec[] = { "path", "data", "create", "excl", NULL };
122 static char *arg_spec = "ss#|ii";
123 char *path = NULL;
124 char *data = NULL;
125 int data_n = 0;
126 int create = 0;
127 int excl = 0;
129 struct xs_handle *xh = xshandle(self);
130 PyObject *val = NULL;
131 int flags = 0;
132 int xsval = 0;
134 if (!xh)
135 goto exit;
136 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
137 &path, &data, &data_n, &create, &excl))
138 goto exit;
139 if (create)
140 flags |= O_CREAT;
141 if (excl)
142 flags |= O_EXCL;
143 xsval = xs_write(xh, path, data, data_n, flags);
144 val = pyvalue_int(xsval);
145 exit:
146 return val;
147 }
149 #define xspy_ls_doc "\n" \
150 "List a directory.\n" \
151 " path [string]: path to list.\n" \
152 "\n" \
153 "Returns: [string array] list of subdirectory names.\n" \
154 "Raises RuntimeError on error.\n" \
155 "\n"
157 static PyObject *xspy_ls(PyObject *self, PyObject *args, PyObject *kwds)
158 {
159 static char *kwd_spec[] = { "path", NULL };
160 static char *arg_spec = "s|";
161 char *path = NULL;
163 struct xs_handle *xh = xshandle(self);
164 PyObject *val = NULL;
165 char **xsval = NULL;
166 unsigned int xsval_n = 0;
167 int i;
169 if (!xh)
170 goto exit;
171 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
172 goto exit;
173 xsval = xs_directory(xh, path, &xsval_n);
174 if (!xsval) {
175 val = pyvalue_int(0);
176 goto exit;
177 }
178 val = PyList_New(xsval_n);
179 for (i = 0; i < xsval_n; i++)
180 PyList_SetItem(val, i, PyString_FromString(xsval[i]));
181 exit:
182 return val;
183 }
185 #define xspy_mkdir_doc "\n" \
186 "Make a directory.\n" \
187 " path [string]: path to directory to create.\n" \
188 "\n" \
189 "Returns: [int] 0 on success.\n" \
190 "Raises RuntimeError on error.\n" \
191 "\n"
193 static PyObject *xspy_mkdir(PyObject *self, PyObject *args, PyObject *kwds)
194 {
195 static char *kwd_spec[] = { "path", NULL };
196 static char *arg_spec = "s|";
197 char *path = NULL;
199 struct xs_handle *xh = xshandle(self);
200 PyObject *val = NULL;
201 int xsval = 0;
203 if (!xh)
204 goto exit;
205 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
206 goto exit;
207 xsval = xs_mkdir(xh, path);
208 val = pyvalue_int(xsval);
209 exit:
210 return val;
211 }
213 #define xspy_rm_doc "\n" \
214 "Remove a path.\n" \
215 " path [string] : path to remove\n" \
216 "\n" \
217 "Returns: [int] 0 on success.\n" \
218 "Raises RuntimeError on error.\n" \
219 "\n"
221 static PyObject *xspy_rm(PyObject *self, PyObject *args, PyObject *kwds)
222 {
223 static char *kwd_spec[] = { "path", NULL };
224 static char *arg_spec = "s|";
225 char *path = NULL;
227 struct xs_handle *xh = xshandle(self);
228 PyObject *val = NULL;
229 int xsval = 0;
231 if (!xh)
232 goto exit;
233 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
234 goto exit;
235 xsval = xs_rm(xh, path);
236 val = pyvalue_int(xsval);
237 exit:
238 return val;
239 }
241 #define xspy_get_permissions_doc "\n" \
242 "Get the permissions for a path\n" \
243 " path [string]: xenstore path.\n" \
244 "\n" \
245 "Returns: permissions array.\n" \
246 "Raises RuntimeError on error.\n" \
247 "\n"
249 static PyObject *xspy_get_permissions(PyObject *self, PyObject *args,
250 PyObject *kwds)
251 {
252 static char *kwd_spec[] = { "path", NULL };
253 static char *arg_spec = "s|";
254 char *path = NULL;
256 struct xs_handle *xh = xshandle(self);
257 PyObject *val = NULL;
258 struct xs_permissions *perms;
259 unsigned int perms_n = 0;
260 int i;
262 if (!xh)
263 goto exit;
264 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
265 goto exit;
266 perms = xs_get_permissions(xh, path, &perms_n);
267 if (!perms) {
268 PyErr_SetFromErrno(PyExc_RuntimeError);
269 goto exit;
270 }
271 val = PyList_New(perms_n);
272 for (i = 0; i < perms_n; i++, perms++) {
273 PyObject *p = Py_BuildValue("{s:i,s:i,s:i}",
274 "dom", perms->id,
275 "read", (perms->perms & XS_PERM_READ),
276 "write", (perms->perms & XS_PERM_WRITE));
277 PyList_SetItem(val, i, p);
278 }
279 exit:
280 return val;
281 }
283 #define xspy_set_permissions_doc "\n" \
284 "Set the permissions for a path\n" \
285 " path [string] : xenstore path.\n" \
286 " perms : permissions.\n" \
287 "\n" \
288 "Returns: [int] 0 on success.\n" \
289 "Raises RuntimeError on error.\n" \
290 "\n"
292 static PyObject *xspy_set_permissions(PyObject *self, PyObject *args,
293 PyObject *kwds)
294 {
295 static char *kwd_spec[] = { "path", "perms", NULL };
296 static char *arg_spec = "sO";
297 char *path = NULL;
298 PyObject *perms = NULL;
299 static char *perm_names[] = { "dom", "read", "write", NULL };
300 static char *perm_spec = "i|iiii";
302 struct xs_handle *xh = xshandle(self);
303 int i, xsval;
304 struct xs_permissions *xsperms = NULL;
305 int xsperms_n = 0;
306 PyObject *tuple0 = NULL;
307 PyObject *val = NULL;
309 if (!xh)
310 goto exit;
311 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
312 &path, &perms))
313 goto exit;
314 if (!PyList_Check(perms)) {
315 PyErr_SetString(PyExc_RuntimeError, "perms must be a list");
316 goto exit;
317 }
318 xsperms_n = PyList_Size(perms);
319 xsperms = calloc(xsperms_n, sizeof(struct xs_permissions));
320 if (!xsperms) {
321 PyErr_SetString(PyExc_RuntimeError, "out of memory");
322 goto exit;
323 }
324 tuple0 = PyTuple_New(0);
325 if (!tuple0)
326 goto exit;
327 for (i = 0; i < xsperms_n; i++) {
328 /* Domain the permissions apply to. */
329 int dom = 0;
330 /* Read/write perms. Set these. */
331 int p_read = 0, p_write = 0;
332 PyObject *p = PyList_GetItem(perms, i);
333 if (!PyArg_ParseTupleAndKeywords(tuple0, p, perm_spec, perm_names,
334 &dom, &p_read, &p_write))
335 goto exit;
336 xsperms[i].id = dom;
337 if (p_read)
338 xsperms[i].perms |= XS_PERM_READ;
339 if (p_write)
340 xsperms[i].perms |= XS_PERM_WRITE;
341 }
342 xsval = xs_set_permissions(xh, path, xsperms, xsperms_n);
343 val = pyvalue_int(xsval);
344 exit:
345 Py_XDECREF(tuple0);
346 if (xsperms)
347 free(xsperms);
348 return val;
349 }
351 #define xspy_watch_doc "\n" \
352 "Watch a path, get notifications when it changes.\n" \
353 " path [string] : xenstore path.\n" \
354 " token [string] : returned in watch notification.\n" \
355 "\n" \
356 "Returns: [int] 0 on success.\n" \
357 "Raises RuntimeError on error.\n" \
358 "\n"
360 /* Each 10 bits takes ~ 3 digits, plus one, plus one for nul terminator. */
361 #define MAX_STRLEN(x) ((sizeof(x) * CHAR_BIT + CHAR_BIT-1) / 10 * 3 + 2)
363 static PyObject *xspy_watch(PyObject *self, PyObject *args, PyObject *kwds)
364 {
365 static char *kwd_spec[] = { "path", "token", NULL };
366 static char *arg_spec = "sO";
367 char *path = NULL;
368 PyObject *token;
369 char token_str[MAX_STRLEN(unsigned long) + 1];
370 int i;
372 XsHandle *xsh = (XsHandle *)self;
373 struct xs_handle *xh = xshandle(self);
374 PyObject *val = NULL;
375 int xsval = 0;
377 if (!xh)
378 goto exit;
379 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
380 &path, &token))
381 goto exit;
382 Py_INCREF(token);
383 sprintf(token_str, "%li", (unsigned long)token);
384 xsval = xs_watch(xh, path, token_str);
385 val = pyvalue_int(xsval);
386 if (xsval) {
387 for (i = 0; i < PyList_Size(xsh->watches); i++) {
388 if (PyList_GetItem(xsh->watches, i) == Py_None) {
389 PyList_SetItem(xsh->watches, i, token);
390 break;
391 }
392 }
393 if (i == PyList_Size(xsh->watches))
394 PyList_Append(xsh->watches, token);
395 } else
396 Py_DECREF(token);
397 exit:
398 return val;
399 }
401 #define xspy_read_watch_doc "\n" \
402 "Read a watch notification.\n" \
403 "The notification must be acknowledged by passing\n" \
404 "the token to acknowledge_watch().\n" \
405 " path [string]: xenstore path.\n" \
406 "\n" \
407 "Returns: [tuple] (path, token).\n" \
408 "Raises RuntimeError on error.\n" \
409 "\n"
411 static PyObject *xspy_read_watch(PyObject *self, PyObject *args,
412 PyObject *kwds)
413 {
414 static char *kwd_spec[] = { NULL };
415 static char *arg_spec = "";
417 XsHandle *xsh = (XsHandle *)self;
418 struct xs_handle *xh = xshandle(self);
419 PyObject *val = NULL;
420 char **xsval = NULL;
421 PyObject *token;
422 int i;
424 if (!xh)
425 goto exit;
426 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
427 goto exit;
428 xsval = xs_read_watch(xh);
429 if (!xsval) {
430 val = PyErr_SetFromErrno(PyExc_RuntimeError);
431 goto exit;
432 }
433 if (sscanf(xsval[1], "%li", (unsigned long *)&token) != 1) {
434 PyErr_SetString(PyExc_RuntimeError, "invalid token");
435 goto exit;
436 }
437 for (i = 0; i < PyList_Size(xsh->watches); i++) {
438 if (token == PyList_GetItem(xsh->watches, i))
439 break;
440 }
441 if (i == PyList_Size(xsh->watches)) {
442 PyErr_SetString(PyExc_RuntimeError, "invalid token");
443 goto exit;
444 }
445 /* Create tuple (path, token). */
446 val = Py_BuildValue("(sO)", xsval[0], token);
447 exit:
448 if (xsval)
449 free(xsval);
450 return val;
451 }
453 #define xspy_acknowledge_watch_doc "\n" \
454 "Acknowledge a watch notification that has been read.\n" \
455 " token [string] : from the watch notification\n" \
456 "\n" \
457 "Returns: [int] 0 on success.\n" \
458 "Raises RuntimeError on error.\n" \
459 "\n"
461 static PyObject *xspy_acknowledge_watch(PyObject *self, PyObject *args,
462 PyObject *kwds)
463 {
464 static char *kwd_spec[] = { "token", NULL };
465 static char *arg_spec = "O";
466 PyObject *token;
467 char token_str[MAX_STRLEN(unsigned long) + 1];
469 struct xs_handle *xh = xshandle(self);
470 PyObject *val = NULL;
471 int xsval = 0;
473 if (!xh)
474 goto exit;
475 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &token))
476 goto exit;
477 sprintf(token_str, "%li", (unsigned long)token);
478 xsval = xs_acknowledge_watch(xh, token_str);
479 val = pyvalue_int(xsval);
480 exit:
481 return val;
482 }
484 #define xspy_unwatch_doc "\n" \
485 "Stop watching a path.\n" \
486 " path [string] : xenstore path.\n" \
487 " token [string] : token from the watch.\n" \
488 "\n" \
489 "Returns: [int] 0 on success.\n" \
490 "Raises RuntimeError on error.\n" \
491 "\n"
493 static PyObject *xspy_unwatch(PyObject *self, PyObject *args, PyObject *kwds)
494 {
495 static char *kwd_spec[] = { "path", "token", NULL };
496 static char *arg_spec = "sO";
497 char *path = NULL;
498 PyObject *token;
499 char token_str[MAX_STRLEN(unsigned long) + 1];
500 int i;
502 XsHandle *xsh = (XsHandle *)self;
503 struct xs_handle *xh = xshandle(self);
504 PyObject *val = NULL;
505 int xsval = 0;
507 if (!xh)
508 goto exit;
509 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path,
510 &token))
511 goto exit;
512 sprintf(token_str, "%li", (unsigned long)token);
513 xsval = xs_unwatch(xh, path, token_str);
514 val = pyvalue_int(xsval);
515 for (i = 0; i < PyList_Size(xsh->watches); i++) {
516 if (token == PyList_GetItem(xsh->watches, i)) {
517 Py_INCREF(Py_None);
518 PyList_SetItem(xsh->watches, i, Py_None);
519 break;
520 }
521 }
522 exit:
523 return val;
524 }
526 #define xspy_transaction_start_doc "\n" \
527 "Start a transaction on a path.\n" \
528 "Only one transaction can be active at a time.\n" \
529 " path [string]: xenstore path.\n" \
530 "\n" \
531 "Returns: [int] 0 on success.\n" \
532 "Raises RuntimeError on error.\n" \
533 "\n"
535 static PyObject *xspy_transaction_start(PyObject *self, PyObject *args,
536 PyObject *kwds)
537 {
538 static char *kwd_spec[] = { "path", NULL };
539 static char *arg_spec = "s|";
540 char *path = NULL;
542 struct xs_handle *xh = xshandle(self);
543 PyObject *val = NULL;
544 int xsval = 0;
546 if (!xh)
547 goto exit;
548 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
549 goto exit;
550 xsval = xs_transaction_start(xh, path);
551 val = pyvalue_int(xsval);
552 exit:
553 return val;
554 }
556 #define xspy_transaction_end_doc "\n" \
557 "End the current transaction.\n" \
558 "Attempts to commit the transaction unless abort is true.\n" \
559 " abort [int]: abort flag (default 0).\n" \
560 "\n" \
561 "Returns: [int] 0 on success.\n" \
562 "Raises RuntimeError on error.\n" \
563 "\n"
565 static PyObject *xspy_transaction_end(PyObject *self, PyObject *args,
566 PyObject *kwds)
567 {
568 static char *kwd_spec[] = { "abort", NULL };
569 static char *arg_spec = "|i";
570 int abort = 0;
572 struct xs_handle *xh = xshandle(self);
573 PyObject *val = NULL;
574 int xsval = 0;
576 if (!xh)
577 goto exit;
578 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &abort))
579 goto exit;
580 xsval = xs_transaction_end(xh, abort);
581 val = pyvalue_int(xsval);
582 exit:
583 return val;
584 }
586 #define xspy_introduce_domain_doc "\n" \
587 "Tell xenstore about a domain so it can talk to it.\n" \
588 " dom [int] : domain id\n" \
589 " page [long] : address of domain's xenstore page\n" \
590 " port [int] : port the domain is using for xenstore\n" \
591 " path [string]: path to the domain's data in xenstore\n" \
592 "\n" \
593 "Returns: [int] 0 on success.\n" \
594 "Raises RuntimeError on error.\n" \
595 "\n"
597 static PyObject *xspy_introduce_domain(PyObject *self, PyObject *args,
598 PyObject *kwds)
599 {
600 static char *kwd_spec[] = { "dom", "page", "port", "path", NULL };
601 static char *arg_spec = "iiis|";
602 domid_t dom = 0;
603 unsigned long page = 0;
604 unsigned int port = 0;
605 char *path = NULL;
607 struct xs_handle *xh = xshandle(self);
608 PyObject *val = NULL;
609 int xsval = 0;
611 if (!xh)
612 goto exit;
613 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
614 &dom, &page, &port, &path))
615 goto exit;
616 xsval = xs_introduce_domain(xh, dom, page, port, path);
617 val = pyvalue_int(xsval);
618 exit:
619 return val;
620 }
622 #define xspy_release_domain_doc "\n" \
623 "Tell xenstore to release its channel to a domain.\n" \
624 "Unless this is done the domain will not be released.\n" \
625 " dom [int]: domain id\n" \
626 "\n" \
627 "Returns: [int] 0 on success.\n" \
628 "Raises RuntimeError on error.\n" \
629 "\n"
631 static PyObject *xspy_release_domain(PyObject *self, PyObject *args,
632 PyObject *kwds)
633 {
634 static char *kwd_spec[] = { "dom", NULL };
635 static char *arg_spec = "i|";
636 domid_t dom;
638 struct xs_handle *xh = xshandle(self);
639 PyObject *val = NULL;
640 int xsval = 0;
642 if (!xh)
643 goto exit;
644 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
645 &dom))
646 goto exit;
647 xsval = xs_release_domain(xh, dom);
648 val = pyvalue_int(xsval);
649 exit:
650 return val;
651 }
653 #define xspy_close_doc "\n" \
654 "Close the connection to xenstore.\n" \
655 "\n" \
656 "Returns: [int] 0 on success.\n" \
657 "Raises RuntimeError on error.\n" \
658 "\n"
660 static PyObject *xspy_close(PyObject *self, PyObject *args, PyObject *kwds)
661 {
662 static char *kwd_spec[] = { NULL };
663 static char *arg_spec = "";
664 int i;
666 XsHandle *xsh = (XsHandle *)self;
667 struct xs_handle *xh = xshandle(self);
668 PyObject *val = NULL;
669 int xsval = 1;
671 if (!xh)
672 goto exit;
673 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
674 goto exit;
675 for (i = 0; i < PyList_Size(xsh->watches); i++) {
676 /* TODO: xs_unwatch watches */
677 Py_INCREF(Py_None);
678 PyList_SetItem(xsh->watches, i, Py_None);
679 }
680 xs_daemon_close(xh);
681 xsh->xh = NULL;
682 val = pyvalue_int(xsval);
683 exit:
684 return val;
685 }
687 #define xspy_shutdown_doc "\n" \
688 "Shutdown the xenstore daemon.\n" \
689 "\n" \
690 "Returns: [int] 0 on success.\n" \
691 "Raises RuntimeError on error.\n" \
692 "\n"
694 static PyObject *xspy_shutdown(PyObject *self, PyObject *args, PyObject *kwds)
695 {
696 static char *kwd_spec[] = { NULL };
697 static char *arg_spec = "";
699 struct xs_handle *xh = xshandle(self);
700 PyObject *val = NULL;
701 int xsval = 0;
703 if (!xh)
704 goto exit;
705 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
706 goto exit;
707 xsval = xs_shutdown(xh);
708 val = pyvalue_int(xsval);
709 exit:
710 return val;
711 }
713 #define xspy_fileno_doc "\n" \
714 "Get the file descriptor of the xenstore socket.\n" \
715 "Allows an xs object to be passed to select().\n" \
716 "\n" \
717 "Returns: [int] file descriptor.\n" \
718 "\n"
720 static PyObject *xspy_fileno(PyObject *self, PyObject *args, PyObject *kwds)
721 {
722 static char *kwd_spec[] = { NULL };
723 static char *arg_spec = "";
725 struct xs_handle *xh = xshandle(self);
726 PyObject *val = NULL;
728 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
729 goto exit;
730 val = PyInt_FromLong((xh ? xs_fileno(xh) : -1));
731 exit:
732 return val;
733 }
735 #define XSPY_METH(_name) { \
736 .ml_name = #_name, \
737 .ml_meth = (PyCFunction) xspy_ ## _name, \
738 .ml_flags = (METH_VARARGS | METH_KEYWORDS), \
739 .ml_doc = xspy_ ## _name ## _doc }
741 static PyMethodDef xshandle_methods[] = {
742 XSPY_METH(read),
743 XSPY_METH(write),
744 XSPY_METH(ls),
745 XSPY_METH(mkdir),
746 XSPY_METH(rm),
747 XSPY_METH(get_permissions),
748 XSPY_METH(set_permissions),
749 XSPY_METH(watch),
750 XSPY_METH(read_watch),
751 XSPY_METH(acknowledge_watch),
752 XSPY_METH(unwatch),
753 XSPY_METH(transaction_start),
754 XSPY_METH(transaction_end),
755 XSPY_METH(introduce_domain),
756 XSPY_METH(release_domain),
757 XSPY_METH(close),
758 XSPY_METH(shutdown),
759 XSPY_METH(fileno),
760 { /* Terminator. */ },
761 };
763 static PyObject *xshandle_getattr(PyObject *self, char *name)
764 {
765 PyObject *val = NULL;
766 val = Py_FindMethod(xshandle_methods, self, name);
767 return val;
768 }
770 static void xshandle_dealloc(PyObject *self)
771 {
772 XsHandle *xh = (XsHandle*)self;
773 if (xh->xh) {
774 xs_daemon_close(xh->xh);
775 xh->xh = NULL;
776 }
777 PyObject_Del(self);
778 }
780 static PyTypeObject xshandle_type = {
781 PyObject_HEAD_INIT(&PyType_Type)
782 0,
783 "xshandle",
784 sizeof(XsHandle),
785 0,
786 xshandle_dealloc, /* tp_dealloc */
787 NULL, /* tp_print */
788 xshandle_getattr, /* tp_getattr */
789 NULL, /* tp_setattr */
790 NULL, /* tp_compare */
791 NULL, /* tp_repr */
792 NULL, /* tp_as_number */
793 NULL, /* tp_as_sequence */
794 NULL, /* tp_as_mapping */
795 NULL /* tp_hash */
796 };
798 static PyObject *xshandle_open(PyObject *self, PyObject *args, PyObject *kwds)
799 {
800 static char *kwd_spec[] = { "readonly", NULL };
801 static char *arg_spec = "|i";
802 int readonly = 0;
804 XsHandle *xsh = NULL;
805 PyObject *val = NULL;
807 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
808 &readonly))
809 return NULL;
811 xsh = PyObject_New(XsHandle, &xshandle_type);
812 if (!xsh)
813 return NULL;
814 xsh->watches = PyList_New(0);
815 if (!xsh->watches)
816 goto exit;
817 xsh->xh = (readonly ? xs_daemon_open_readonly() : xs_daemon_open());
818 if (!xsh->xh) {
819 Py_DECREF(xsh->watches);
820 goto exit;
821 }
822 val = (PyObject *)xsh;
823 return val;
824 exit:
825 PyObject_Del(xsh);
826 return NULL;
827 }
829 static PyMethodDef xs_methods[] = {
830 { .ml_name = "open",
831 .ml_meth = (PyCFunction)xshandle_open,
832 .ml_flags = (METH_VARARGS | METH_KEYWORDS),
833 .ml_doc = "\n"
834 "Open a connection to the xenstore daemon.\n"
835 "Returns: xs connection object.\n"
836 "Raises RuntimeError on error.\n"
837 "\n"
838 },
839 { /* Terminator. */ }
840 };
842 PyMODINIT_FUNC initxs (void)
843 {
844 PyObject *module;
846 module = Py_InitModule(PYPKG, xs_methods);
847 }