ia64/xen-unstable

view tools/python/xen/lowlevel/xs/xs.c @ 6676:639a36483fee

Fix and cleanup error handling.
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Wed Sep 07 13:40:06 2005 +0000 (2005-09-07)
parents a75b08af8d19
children cdfa7dd00c44 cdfa7dd00c44
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 None 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 if (!xsval) {
386 val = PyErr_SetFromErrno(PyExc_RuntimeError);
387 Py_DECREF(token);
388 goto exit;
389 }
391 for (i = 0; i < PyList_Size(xsh->watches); i++) {
392 if (PyList_GetItem(xsh->watches, i) == Py_None) {
393 PyList_SetItem(xsh->watches, i, token);
394 break;
395 }
396 }
397 if (i == PyList_Size(xsh->watches))
398 PyList_Append(xsh->watches, token);
399 Py_INCREF(Py_None);
400 val = Py_None;
401 exit:
402 return val;
403 }
405 #define xspy_read_watch_doc "\n" \
406 "Read a watch notification.\n" \
407 "The notification must be acknowledged by passing\n" \
408 "the token to acknowledge_watch().\n" \
409 " path [string]: xenstore path.\n" \
410 "\n" \
411 "Returns: [tuple] (path, token).\n" \
412 "Raises RuntimeError on error.\n" \
413 "\n"
415 static PyObject *xspy_read_watch(PyObject *self, PyObject *args,
416 PyObject *kwds)
417 {
418 static char *kwd_spec[] = { NULL };
419 static char *arg_spec = "";
421 XsHandle *xsh = (XsHandle *)self;
422 struct xs_handle *xh = xshandle(self);
423 PyObject *val = NULL;
424 char **xsval = NULL;
425 PyObject *token;
426 int i;
428 if (!xh)
429 goto exit;
430 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
431 goto exit;
432 xsval = xs_read_watch(xh);
433 if (!xsval) {
434 val = PyErr_SetFromErrno(PyExc_RuntimeError);
435 goto exit;
436 }
437 if (sscanf(xsval[1], "%li", (unsigned long *)&token) != 1) {
438 PyErr_SetString(PyExc_RuntimeError, "invalid token");
439 goto exit;
440 }
441 for (i = 0; i < PyList_Size(xsh->watches); i++) {
442 if (token == PyList_GetItem(xsh->watches, i))
443 break;
444 }
445 if (i == PyList_Size(xsh->watches)) {
446 PyErr_SetString(PyExc_RuntimeError, "invalid token");
447 goto exit;
448 }
449 /* Create tuple (path, token). */
450 val = Py_BuildValue("(sO)", xsval[0], token);
451 exit:
452 if (xsval)
453 free(xsval);
454 return val;
455 }
457 #define xspy_acknowledge_watch_doc "\n" \
458 "Acknowledge a watch notification that has been read.\n" \
459 " token [string] : from the watch notification\n" \
460 "\n" \
461 "Returns None on success.\n" \
462 "Raises RuntimeError on error.\n" \
463 "\n"
465 static PyObject *xspy_acknowledge_watch(PyObject *self, PyObject *args,
466 PyObject *kwds)
467 {
468 static char *kwd_spec[] = { "token", NULL };
469 static char *arg_spec = "O";
470 PyObject *token;
471 char token_str[MAX_STRLEN(unsigned long) + 1];
473 struct xs_handle *xh = xshandle(self);
474 PyObject *val = NULL;
475 int xsval = 0;
477 if (!xh)
478 goto exit;
479 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &token))
480 goto exit;
481 sprintf(token_str, "%li", (unsigned long)token);
482 xsval = xs_acknowledge_watch(xh, token_str);
483 if (!xsval) {
484 val = PyErr_SetFromErrno(PyExc_RuntimeError);
485 goto exit;
486 }
487 Py_INCREF(Py_None);
488 val = Py_None;
489 exit:
490 return val;
491 }
493 #define xspy_unwatch_doc "\n" \
494 "Stop watching a path.\n" \
495 " path [string] : xenstore path.\n" \
496 " token [string] : token from the watch.\n" \
497 "\n" \
498 "Returns None on success.\n" \
499 "Raises RuntimeError on error.\n" \
500 "\n"
502 static PyObject *xspy_unwatch(PyObject *self, PyObject *args, PyObject *kwds)
503 {
504 static char *kwd_spec[] = { "path", "token", NULL };
505 static char *arg_spec = "sO";
506 char *path = NULL;
507 PyObject *token;
508 char token_str[MAX_STRLEN(unsigned long) + 1];
509 int i;
511 XsHandle *xsh = (XsHandle *)self;
512 struct xs_handle *xh = xshandle(self);
513 PyObject *val = NULL;
514 int xsval = 0;
516 if (!xh)
517 goto exit;
518 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path,
519 &token))
520 goto exit;
521 sprintf(token_str, "%li", (unsigned long)token);
522 xsval = xs_unwatch(xh, path, token_str);
523 if (!xsval)
524 val = PyErr_SetFromErrno(PyExc_RuntimeError);
525 else {
526 Py_INCREF(Py_None);
527 val = Py_None;
528 }
529 for (i = 0; i < PyList_Size(xsh->watches); i++) {
530 if (token == PyList_GetItem(xsh->watches, i)) {
531 Py_INCREF(Py_None);
532 PyList_SetItem(xsh->watches, i, Py_None);
533 break;
534 }
535 }
536 exit:
537 return val;
538 }
540 #define xspy_transaction_start_doc "\n" \
541 "Start a transaction on a path.\n" \
542 "Only one transaction can be active at a time.\n" \
543 " path [string]: xenstore path.\n" \
544 "\n" \
545 "Returns: [int] 0 on success.\n" \
546 "Raises RuntimeError on error.\n" \
547 "\n"
549 static PyObject *xspy_transaction_start(PyObject *self, PyObject *args,
550 PyObject *kwds)
551 {
552 static char *kwd_spec[] = { "path", NULL };
553 static char *arg_spec = "s|";
554 char *path = NULL;
556 struct xs_handle *xh = xshandle(self);
557 PyObject *val = NULL;
558 int xsval = 0;
560 if (!xh)
561 goto exit;
562 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
563 goto exit;
564 xsval = xs_transaction_start(xh, path);
565 val = pyvalue_int(xsval);
566 exit:
567 return val;
568 }
570 #define xspy_transaction_end_doc "\n" \
571 "End the current transaction.\n" \
572 "Attempts to commit the transaction unless abort is true.\n" \
573 " abort [int]: abort flag (default 0).\n" \
574 "\n" \
575 "Returns: [int] 0 on success.\n" \
576 "Raises RuntimeError on error.\n" \
577 "\n"
579 static PyObject *xspy_transaction_end(PyObject *self, PyObject *args,
580 PyObject *kwds)
581 {
582 static char *kwd_spec[] = { "abort", NULL };
583 static char *arg_spec = "|i";
584 int abort = 0;
586 struct xs_handle *xh = xshandle(self);
587 PyObject *val = NULL;
588 int xsval = 0;
590 if (!xh)
591 goto exit;
592 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &abort))
593 goto exit;
594 xsval = xs_transaction_end(xh, abort);
595 val = pyvalue_int(xsval);
596 exit:
597 return val;
598 }
600 #define xspy_introduce_domain_doc "\n" \
601 "Tell xenstore about a domain so it can talk to it.\n" \
602 " dom [int] : domain id\n" \
603 " page [long] : address of domain's xenstore page\n" \
604 " port [int] : port the domain is using for xenstore\n" \
605 " path [string]: path to the domain's data in xenstore\n" \
606 "\n" \
607 "Returns: [int] 0 on success.\n" \
608 "Raises RuntimeError on error.\n" \
609 "\n"
611 static PyObject *xspy_introduce_domain(PyObject *self, PyObject *args,
612 PyObject *kwds)
613 {
614 static char *kwd_spec[] = { "dom", "page", "port", "path", NULL };
615 static char *arg_spec = "iiis|";
616 domid_t dom = 0;
617 unsigned long page = 0;
618 unsigned int port = 0;
619 char *path = NULL;
621 struct xs_handle *xh = xshandle(self);
622 PyObject *val = NULL;
623 int xsval = 0;
625 if (!xh)
626 goto exit;
627 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
628 &dom, &page, &port, &path))
629 goto exit;
630 xsval = xs_introduce_domain(xh, dom, page, port, path);
631 val = pyvalue_int(xsval);
632 exit:
633 return val;
634 }
636 #define xspy_release_domain_doc "\n" \
637 "Tell xenstore to release its channel to a domain.\n" \
638 "Unless this is done the domain will not be released.\n" \
639 " dom [int]: domain id\n" \
640 "\n" \
641 "Returns: [int] 0 on success.\n" \
642 "Raises RuntimeError on error.\n" \
643 "\n"
645 static PyObject *xspy_release_domain(PyObject *self, PyObject *args,
646 PyObject *kwds)
647 {
648 static char *kwd_spec[] = { "dom", NULL };
649 static char *arg_spec = "i|";
650 domid_t dom;
652 struct xs_handle *xh = xshandle(self);
653 PyObject *val = NULL;
654 int xsval = 0;
656 if (!xh)
657 goto exit;
658 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
659 &dom))
660 goto exit;
661 xsval = xs_release_domain(xh, dom);
662 val = pyvalue_int(xsval);
663 exit:
664 return val;
665 }
667 #define xspy_close_doc "\n" \
668 "Close the connection to xenstore.\n" \
669 "\n" \
670 "Returns: [int] 0 on success.\n" \
671 "Raises RuntimeError on error.\n" \
672 "\n"
674 static PyObject *xspy_close(PyObject *self, PyObject *args, PyObject *kwds)
675 {
676 static char *kwd_spec[] = { NULL };
677 static char *arg_spec = "";
678 int i;
680 XsHandle *xsh = (XsHandle *)self;
681 struct xs_handle *xh = xshandle(self);
682 PyObject *val = NULL;
683 int xsval = 1;
685 if (!xh)
686 goto exit;
687 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
688 goto exit;
689 for (i = 0; i < PyList_Size(xsh->watches); i++) {
690 /* TODO: xs_unwatch watches */
691 Py_INCREF(Py_None);
692 PyList_SetItem(xsh->watches, i, Py_None);
693 }
694 xs_daemon_close(xh);
695 xsh->xh = NULL;
696 val = pyvalue_int(xsval);
697 exit:
698 return val;
699 }
701 #define xspy_shutdown_doc "\n" \
702 "Shutdown the xenstore daemon.\n" \
703 "\n" \
704 "Returns: [int] 0 on success.\n" \
705 "Raises RuntimeError on error.\n" \
706 "\n"
708 static PyObject *xspy_shutdown(PyObject *self, PyObject *args, PyObject *kwds)
709 {
710 static char *kwd_spec[] = { NULL };
711 static char *arg_spec = "";
713 struct xs_handle *xh = xshandle(self);
714 PyObject *val = NULL;
715 int xsval = 0;
717 if (!xh)
718 goto exit;
719 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
720 goto exit;
721 xsval = xs_shutdown(xh);
722 val = pyvalue_int(xsval);
723 exit:
724 return val;
725 }
727 #define xspy_fileno_doc "\n" \
728 "Get the file descriptor of the xenstore socket.\n" \
729 "Allows an xs object to be passed to select().\n" \
730 "\n" \
731 "Returns: [int] file descriptor.\n" \
732 "\n"
734 static PyObject *xspy_fileno(PyObject *self, PyObject *args, PyObject *kwds)
735 {
736 static char *kwd_spec[] = { NULL };
737 static char *arg_spec = "";
739 struct xs_handle *xh = xshandle(self);
740 PyObject *val = NULL;
742 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
743 goto exit;
744 val = PyInt_FromLong((xh ? xs_fileno(xh) : -1));
745 exit:
746 return val;
747 }
749 #define XSPY_METH(_name) { \
750 .ml_name = #_name, \
751 .ml_meth = (PyCFunction) xspy_ ## _name, \
752 .ml_flags = (METH_VARARGS | METH_KEYWORDS), \
753 .ml_doc = xspy_ ## _name ## _doc }
755 static PyMethodDef xshandle_methods[] = {
756 XSPY_METH(read),
757 XSPY_METH(write),
758 XSPY_METH(ls),
759 XSPY_METH(mkdir),
760 XSPY_METH(rm),
761 XSPY_METH(get_permissions),
762 XSPY_METH(set_permissions),
763 XSPY_METH(watch),
764 XSPY_METH(read_watch),
765 XSPY_METH(acknowledge_watch),
766 XSPY_METH(unwatch),
767 XSPY_METH(transaction_start),
768 XSPY_METH(transaction_end),
769 XSPY_METH(introduce_domain),
770 XSPY_METH(release_domain),
771 XSPY_METH(close),
772 XSPY_METH(shutdown),
773 XSPY_METH(fileno),
774 { /* Terminator. */ },
775 };
777 static PyObject *xshandle_getattr(PyObject *self, char *name)
778 {
779 PyObject *val = NULL;
780 val = Py_FindMethod(xshandle_methods, self, name);
781 return val;
782 }
784 static void xshandle_dealloc(PyObject *self)
785 {
786 XsHandle *xh = (XsHandle*)self;
787 if (xh->xh) {
788 xs_daemon_close(xh->xh);
789 xh->xh = NULL;
790 }
791 PyObject_Del(self);
792 }
794 static PyTypeObject xshandle_type = {
795 PyObject_HEAD_INIT(&PyType_Type)
796 0,
797 "xshandle",
798 sizeof(XsHandle),
799 0,
800 xshandle_dealloc, /* tp_dealloc */
801 NULL, /* tp_print */
802 xshandle_getattr, /* tp_getattr */
803 NULL, /* tp_setattr */
804 NULL, /* tp_compare */
805 NULL, /* tp_repr */
806 NULL, /* tp_as_number */
807 NULL, /* tp_as_sequence */
808 NULL, /* tp_as_mapping */
809 NULL /* tp_hash */
810 };
812 static PyObject *xshandle_open(PyObject *self, PyObject *args, PyObject *kwds)
813 {
814 static char *kwd_spec[] = { "readonly", NULL };
815 static char *arg_spec = "|i";
816 int readonly = 0;
818 XsHandle *xsh = NULL;
819 PyObject *val = NULL;
821 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
822 &readonly))
823 return NULL;
825 xsh = PyObject_New(XsHandle, &xshandle_type);
826 if (!xsh)
827 return NULL;
828 xsh->watches = PyList_New(0);
829 if (!xsh->watches)
830 goto exit;
831 xsh->xh = (readonly ? xs_daemon_open_readonly() : xs_daemon_open());
832 if (!xsh->xh) {
833 Py_DECREF(xsh->watches);
834 goto exit;
835 }
836 val = (PyObject *)xsh;
837 return val;
838 exit:
839 PyObject_Del(xsh);
840 return NULL;
841 }
843 static PyMethodDef xs_methods[] = {
844 { .ml_name = "open",
845 .ml_meth = (PyCFunction)xshandle_open,
846 .ml_flags = (METH_VARARGS | METH_KEYWORDS),
847 .ml_doc = "\n"
848 "Open a connection to the xenstore daemon.\n"
849 "Returns: xs connection object.\n"
850 "Raises RuntimeError on error.\n"
851 "\n"
852 },
853 { /* Terminator. */ }
854 };
856 PyMODINIT_FUNC initxs (void)
857 {
858 PyObject *module;
860 module = Py_InitModule(PYPKG, xs_methods);
861 }