debuggers.hg

view tools/xenstore/xs.c @ 6641:f27205ea60ef

merge?
author cl349@firebug.cl.cam.ac.uk
date Sat Sep 03 16:58:50 2005 +0000 (2005-09-03)
parents 8a228cbb69fe dd668f7527cb
children 29808fef9148 b6c98fe62e1a
line source
1 /*
2 Xen Store Daemon interface providing simple tree-like database.
3 Copyright (C) 2005 Rusty Russell IBM Corporation
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <fcntl.h>
23 #include <sys/socket.h>
24 #include <sys/un.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <stdbool.h>
28 #include <stdlib.h>
29 #include <assert.h>
30 #include <stdio.h>
31 #include <signal.h>
32 #include <stdint.h>
33 #include <errno.h>
34 #include <sys/ioctl.h>
35 #include "xs.h"
36 #include "xenstored.h"
37 #include "xs_lib.h"
38 #include "utils.h"
39 #include "xenbus_dev.h"
41 struct xs_handle
42 {
43 int fd;
44 enum { SOCK, DEV } type;
45 };
47 /* Get the socket from the store daemon handle.
48 */
49 int xs_fileno(struct xs_handle *h)
50 {
51 return h->fd;
52 }
54 static struct xs_handle *get_socket(const char *connect_to)
55 {
56 struct sockaddr_un addr;
57 int sock, saved_errno;
58 struct xs_handle *h = NULL;
60 sock = socket(PF_UNIX, SOCK_STREAM, 0);
61 if (sock < 0)
62 return NULL;
64 addr.sun_family = AF_UNIX;
65 strcpy(addr.sun_path, connect_to);
67 if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) {
68 h = malloc(sizeof(*h));
69 if (h) {
70 h->fd = sock;
71 h->type = SOCK;
72 return h;
73 }
74 }
76 saved_errno = errno;
77 close(sock);
78 errno = saved_errno;
79 return NULL;
80 }
82 static struct xs_handle *get_dev(const char *connect_to)
83 {
84 int fd, saved_errno;
85 struct xs_handle *h = NULL;
87 fd = open(connect_to, O_RDONLY);
88 if (fd < 0)
89 return NULL;
91 h = malloc(sizeof(*h));
92 if (h) {
93 h->fd = fd;
94 h->type = DEV;
95 return h;
96 }
98 saved_errno = errno;
99 close(fd);
100 errno = saved_errno;
101 return NULL;
102 }
104 struct xs_handle *xs_daemon_open(void)
105 {
106 return get_socket(xs_daemon_socket());
107 }
109 struct xs_handle *xs_daemon_open_readonly(void)
110 {
111 return get_socket(xs_daemon_socket_ro());
112 }
114 struct xs_handle *xs_domain_open(void)
115 {
116 return get_dev(xs_domain_dev());
117 }
119 void xs_daemon_close(struct xs_handle *h)
120 {
121 if (h->fd >= 0)
122 close(h->fd);
123 free(h);
124 }
126 static bool read_all(int fd, void *data, unsigned int len)
127 {
128 while (len) {
129 int done;
131 done = read(fd, data, len);
132 if (done < 0) {
133 if (errno == EINTR)
134 continue;
135 return false;
136 }
137 if (done == 0) {
138 /* It closed fd on us? EBADF is appropriate. */
139 errno = EBADF;
140 return false;
141 }
142 data += done;
143 len -= done;
144 }
146 return true;
147 }
149 #ifdef XSTEST
150 #define read_all read_all_choice
151 #define xs_write_all write_all_choice
152 #endif
154 static int get_error(const char *errorstring)
155 {
156 unsigned int i;
158 for (i = 0; !streq(errorstring, xsd_errors[i].errstring); i++)
159 if (i == ARRAY_SIZE(xsd_errors) - 1)
160 return EINVAL;
161 return xsd_errors[i].errnum;
162 }
164 /* Adds extra nul terminator, because we generally (always?) hold strings. */
165 static void *read_reply(int fd, enum xsd_sockmsg_type *type, unsigned int *len)
166 {
167 struct xsd_sockmsg msg;
168 void *ret;
169 int saved_errno;
171 if (!read_all(fd, &msg, sizeof(msg)))
172 return NULL;
174 ret = malloc(msg.len + 1);
175 if (!ret)
176 return NULL;
178 if (!read_all(fd, ret, msg.len)) {
179 saved_errno = errno;
180 free(ret);
181 errno = saved_errno;
182 return NULL;
183 }
185 *type = msg.type;
186 if (len)
187 *len = msg.len;
188 ((char *)ret)[msg.len] = '\0';
189 return ret;
190 }
192 /* Send message to xs, get malloc'ed reply. NULL and set errno on error. */
193 static void *xs_talkv_sock(struct xs_handle *h, enum xsd_sockmsg_type type,
194 const struct iovec *iovec, unsigned int num_vecs,
195 unsigned int *len)
196 {
197 struct xsd_sockmsg msg;
198 void *ret = NULL;
199 int saved_errno;
200 unsigned int i;
201 struct sigaction ignorepipe, oldact;
203 msg.type = type;
204 msg.len = 0;
205 for (i = 0; i < num_vecs; i++)
206 msg.len += iovec[i].iov_len;
208 ignorepipe.sa_handler = SIG_IGN;
209 sigemptyset(&ignorepipe.sa_mask);
210 ignorepipe.sa_flags = 0;
211 sigaction(SIGPIPE, &ignorepipe, &oldact);
213 if (!xs_write_all(h->fd, &msg, sizeof(msg)))
214 goto fail;
216 for (i = 0; i < num_vecs; i++)
217 if (!xs_write_all(h->fd, iovec[i].iov_base, iovec[i].iov_len))
218 goto fail;
220 /* Watches can have fired before reply comes: daemon detects
221 * and re-transmits, so we can ignore this. */
222 do {
223 free(ret);
224 ret = read_reply(h->fd, &msg.type, len);
225 if (!ret)
226 goto fail;
227 } while (msg.type == XS_WATCH_EVENT);
229 sigaction(SIGPIPE, &oldact, NULL);
230 if (msg.type == XS_ERROR) {
231 saved_errno = get_error(ret);
232 free(ret);
233 errno = saved_errno;
234 return NULL;
235 }
237 if (msg.type != type) {
238 free(ret);
239 saved_errno = EBADF;
240 goto close_fd;
242 }
243 return ret;
245 fail:
246 /* We're in a bad state, so close fd. */
247 saved_errno = errno;
248 sigaction(SIGPIPE, &oldact, NULL);
249 close_fd:
250 close(h->fd);
251 h->fd = -1;
252 errno = saved_errno;
253 return NULL;
254 }
256 /* Send message to xs, get malloc'ed reply. NULL and set errno on error. */
257 static void *xs_talkv_dev(struct xs_handle *h, enum xsd_sockmsg_type type,
258 const struct iovec *iovec, unsigned int num_vecs,
259 unsigned int *len)
260 {
261 struct xenbus_dev_talkv dt;
262 char *buf;
263 int err, buflen = 1024;
265 again:
266 buf = malloc(buflen);
267 if (buf == NULL) {
268 errno = ENOMEM;
269 return NULL;
270 }
271 dt.type = type;
272 dt.iovec = (struct kvec *)iovec;
273 dt.num_vecs = num_vecs;
274 dt.buf = buf;
275 dt.len = buflen;
276 err = ioctl(h->fd, IOCTL_XENBUS_DEV_TALKV, &dt);
277 if (err < 0) {
278 free(buf);
279 errno = err;
280 return NULL;
281 }
282 if (err > buflen) {
283 free(buf);
284 buflen = err;
285 goto again;
286 }
287 if (len)
288 *len = err;
289 return buf;
290 }
292 /* Send message to xs, get malloc'ed reply. NULL and set errno on error. */
293 static void *xs_talkv(struct xs_handle *h, enum xsd_sockmsg_type type,
294 const struct iovec *iovec, unsigned int num_vecs,
295 unsigned int *len)
296 {
297 if (h->type == SOCK)
298 return xs_talkv_sock(h, type, iovec, num_vecs, len);
299 if (h->type == DEV)
300 return xs_talkv_dev(h, type, iovec, num_vecs, len);
301 return NULL;
302 }
304 /* free(), but don't change errno. */
305 static void free_no_errno(void *p)
306 {
307 int saved_errno = errno;
308 free(p);
309 errno = saved_errno;
310 }
312 /* Simplified version of xs_talkv: single message. */
313 static void *xs_single(struct xs_handle *h, enum xsd_sockmsg_type type,
314 const char *string, unsigned int *len)
315 {
316 struct iovec iovec;
318 iovec.iov_base = (void *)string;
319 iovec.iov_len = strlen(string) + 1;
320 return xs_talkv(h, type, &iovec, 1, len);
321 }
323 static bool xs_bool(char *reply)
324 {
325 if (!reply)
326 return false;
327 free(reply);
328 return true;
329 }
331 char **xs_directory(struct xs_handle *h, const char *path, unsigned int *num)
332 {
333 char *strings, *p, **ret;
334 unsigned int len;
336 strings = xs_single(h, XS_DIRECTORY, path, &len);
337 if (!strings)
338 return NULL;
340 /* Count the strings. */
341 *num = xs_count_strings(strings, len);
343 /* Transfer to one big alloc for easy freeing. */
344 ret = malloc(*num * sizeof(char *) + len);
345 if (!ret) {
346 free_no_errno(strings);
347 return NULL;
348 }
349 memcpy(&ret[*num], strings, len);
350 free_no_errno(strings);
352 strings = (char *)&ret[*num];
353 for (p = strings, *num = 0; p < strings + len; p += strlen(p) + 1)
354 ret[(*num)++] = p;
355 return ret;
356 }
358 /* Get the value of a single file, nul terminated.
359 * Returns a malloced value: call free() on it after use.
360 * len indicates length in bytes, not including the nul.
361 */
362 void *xs_read(struct xs_handle *h, const char *path, unsigned int *len)
363 {
364 return xs_single(h, XS_READ, path, len);
365 }
367 /* Write the value of a single file.
368 * Returns false on failure. createflags can be 0, O_CREAT, or O_CREAT|O_EXCL.
369 */
370 bool xs_write(struct xs_handle *h, const char *path,
371 const void *data, unsigned int len, int createflags)
372 {
373 const char *flags;
374 struct iovec iovec[3];
376 /* Format: Flags (as string), path, data. */
377 if (createflags == 0)
378 flags = XS_WRITE_NONE;
379 else if (createflags == O_CREAT)
380 flags = XS_WRITE_CREATE;
381 else if (createflags == (O_CREAT|O_EXCL))
382 flags = XS_WRITE_CREATE_EXCL;
383 else {
384 errno = EINVAL;
385 return false;
386 }
388 iovec[0].iov_base = (void *)path;
389 iovec[0].iov_len = strlen(path) + 1;
390 iovec[1].iov_base = (void *)flags;
391 iovec[1].iov_len = strlen(flags) + 1;
392 iovec[2].iov_base = (void *)data;
393 iovec[2].iov_len = len;
395 return xs_bool(xs_talkv(h, XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL));
396 }
398 /* Create a new directory.
399 * Returns false on failure.
400 */
401 bool xs_mkdir(struct xs_handle *h, const char *path)
402 {
403 return xs_bool(xs_single(h, XS_MKDIR, path, NULL));
404 }
406 /* Destroy a file or directory (directories must be empty).
407 * Returns false on failure.
408 */
409 bool xs_rm(struct xs_handle *h, const char *path)
410 {
411 return xs_bool(xs_single(h, XS_RM, path, NULL));
412 }
414 /* Get permissions of node (first element is owner).
415 * Returns malloced array, or NULL: call free() after use.
416 */
417 struct xs_permissions *xs_get_permissions(struct xs_handle *h,
418 const char *path, unsigned int *num)
419 {
420 char *strings;
421 unsigned int len;
422 struct xs_permissions *ret;
424 strings = xs_single(h, XS_GET_PERMS, path, &len);
425 if (!strings)
426 return NULL;
428 /* Count the strings: each one perms then domid. */
429 *num = xs_count_strings(strings, len);
431 /* Transfer to one big alloc for easy freeing. */
432 ret = malloc(*num * sizeof(struct xs_permissions));
433 if (!ret) {
434 free_no_errno(strings);
435 return NULL;
436 }
438 if (!xs_strings_to_perms(ret, *num, strings)) {
439 free_no_errno(ret);
440 ret = NULL;
441 }
443 free(strings);
444 return ret;
445 }
447 /* Set permissions of node (must be owner).
448 * Returns false on failure.
449 */
450 bool xs_set_permissions(struct xs_handle *h, const char *path,
451 struct xs_permissions *perms,
452 unsigned int num_perms)
453 {
454 unsigned int i;
455 struct iovec iov[1+num_perms];
457 iov[0].iov_base = (void *)path;
458 iov[0].iov_len = strlen(path) + 1;
460 for (i = 0; i < num_perms; i++) {
461 char buffer[MAX_STRLEN(domid_t)+1];
463 if (!xs_perm_to_string(&perms[i], buffer))
464 goto unwind;
466 iov[i+1].iov_base = strdup(buffer);
467 iov[i+1].iov_len = strlen(buffer) + 1;
468 if (!iov[i+1].iov_base)
469 goto unwind;
470 }
472 if (!xs_bool(xs_talkv(h, XS_SET_PERMS, iov, 1+num_perms, NULL)))
473 goto unwind;
474 for (i = 0; i < num_perms; i++)
475 free(iov[i+1].iov_base);
476 return true;
478 unwind:
479 num_perms = i;
480 for (i = 0; i < num_perms; i++)
481 free_no_errno(iov[i+1].iov_base);
482 return false;
483 }
485 /* Watch a node for changes (poll on fd to detect, or call read_watch()).
486 * When the node (or any child) changes, fd will become readable.
487 * Token is returned when watch is read, to allow matching.
488 * Returns false on failure.
489 */
490 bool xs_watch(struct xs_handle *h, const char *path, const char *token)
491 {
492 struct iovec iov[2];
494 iov[0].iov_base = (void *)path;
495 iov[0].iov_len = strlen(path) + 1;
496 iov[1].iov_base = (void *)token;
497 iov[1].iov_len = strlen(token) + 1;
499 return xs_bool(xs_talkv(h, XS_WATCH, iov, ARRAY_SIZE(iov), NULL));
500 }
502 /* Find out what node change was on (will block if nothing pending).
503 * Returns array of two pointers: path and token, or NULL.
504 * Call free() after use.
505 */
506 char **xs_read_watch(struct xs_handle *h)
507 {
508 struct xsd_sockmsg msg;
509 char **ret;
511 if (!read_all(h->fd, &msg, sizeof(msg)))
512 return NULL;
514 assert(msg.type == XS_WATCH_EVENT);
515 ret = malloc(sizeof(char *)*2 + msg.len);
516 if (!ret)
517 return NULL;
519 ret[0] = (char *)(ret + 2);
520 if (!read_all(h->fd, ret[0], msg.len)) {
521 free_no_errno(ret);
522 return NULL;
523 }
524 ret[1] = ret[0] + strlen(ret[0]) + 1;
525 return ret;
526 }
528 /* Acknowledge watch on node. Watches must be acknowledged before
529 * any other watches can be read.
530 * Returns false on failure.
531 */
532 bool xs_acknowledge_watch(struct xs_handle *h, const char *token)
533 {
534 return xs_bool(xs_single(h, XS_WATCH_ACK, token, NULL));
535 }
537 /* Remove a watch on a node.
538 * Returns false on failure (no watch on that node).
539 */
540 bool xs_unwatch(struct xs_handle *h, const char *path, const char *token)
541 {
542 struct iovec iov[2];
544 iov[0].iov_base = (char *)path;
545 iov[0].iov_len = strlen(path) + 1;
546 iov[1].iov_base = (char *)token;
547 iov[1].iov_len = strlen(token) + 1;
549 return xs_bool(xs_talkv(h, XS_UNWATCH, iov, ARRAY_SIZE(iov), NULL));
550 }
552 /* Start a transaction: changes by others will not be seen during this
553 * transaction, and changes will not be visible to others until end.
554 * Transaction only applies to the given subtree.
555 * You can only have one transaction at any time.
556 * Returns false on failure.
557 */
558 bool xs_transaction_start(struct xs_handle *h, const char *subtree)
559 {
560 return xs_bool(xs_single(h, XS_TRANSACTION_START, subtree, NULL));
561 }
563 /* End a transaction.
564 * If abandon is true, transaction is discarded instead of committed.
565 * Returns false on failure, which indicates an error: transactions will
566 * not fail spuriously.
567 */
568 bool xs_transaction_end(struct xs_handle *h, bool abort)
569 {
570 char abortstr[2];
572 if (abort)
573 strcpy(abortstr, "F");
574 else
575 strcpy(abortstr, "T");
576 return xs_bool(xs_single(h, XS_TRANSACTION_END, abortstr, NULL));
577 }
579 /* Introduce a new domain.
580 * This tells the store daemon about a shared memory page and event channel
581 * associated with a domain: the domain uses these to communicate.
582 */
583 bool xs_introduce_domain(struct xs_handle *h, domid_t domid, unsigned long mfn,
584 unsigned int eventchn, const char *path)
585 {
586 char domid_str[MAX_STRLEN(domid)];
587 char mfn_str[MAX_STRLEN(mfn)];
588 char eventchn_str[MAX_STRLEN(eventchn)];
589 struct iovec iov[4];
591 sprintf(domid_str, "%u", domid);
592 sprintf(mfn_str, "%lu", mfn);
593 sprintf(eventchn_str, "%u", eventchn);
595 iov[0].iov_base = domid_str;
596 iov[0].iov_len = strlen(domid_str) + 1;
597 iov[1].iov_base = mfn_str;
598 iov[1].iov_len = strlen(mfn_str) + 1;
599 iov[2].iov_base = eventchn_str;
600 iov[2].iov_len = strlen(eventchn_str) + 1;
601 iov[3].iov_base = (char *)path;
602 iov[3].iov_len = strlen(path) + 1;
604 return xs_bool(xs_talkv(h, XS_INTRODUCE, iov, ARRAY_SIZE(iov), NULL));
605 }
607 bool xs_release_domain(struct xs_handle *h, domid_t domid)
608 {
609 char domid_str[MAX_STRLEN(domid)];
611 sprintf(domid_str, "%u", domid);
613 return xs_bool(xs_single(h, XS_RELEASE, domid_str, NULL));
614 }
616 bool xs_shutdown(struct xs_handle *h)
617 {
618 bool ret = xs_bool(xs_single(h, XS_SHUTDOWN, "", NULL));
619 if (ret) {
620 char c;
621 /* Wait for it to actually shutdown. */
622 read(h->fd, &c, 1);
623 }
624 return ret;
625 }
627 /* Only useful for DEBUG versions */
628 char *xs_debug_command(struct xs_handle *h, const char *cmd,
629 void *data, unsigned int len)
630 {
631 struct iovec iov[2];
633 iov[0].iov_base = (void *)cmd;
634 iov[0].iov_len = strlen(cmd) + 1;
635 iov[1].iov_base = data;
636 iov[1].iov_len = len;
638 return xs_talkv(h, XS_DEBUG, iov, ARRAY_SIZE(iov), NULL);
639 }