ia64/xen-unstable

view tools/xenstore/xs.c @ 6946:e703abaf6e3d

Add behaviour to the remove methods to remove the transaction's path itself. This allows us to write Remove(path) to remove the specified path rather than having to slice the path ourselves.
author emellor@ewan
date Sun Sep 18 14:42:13 2005 +0100 (2005-09-18)
parents 3233e7ecfa9f
children a5d67e3fbff1 872cf6ee0594
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"
40 struct xs_handle
41 {
42 int fd;
43 };
45 /* Get the socket from the store daemon handle.
46 */
47 int xs_fileno(struct xs_handle *h)
48 {
49 return h->fd;
50 }
52 static struct xs_handle *get_socket(const char *connect_to)
53 {
54 struct sockaddr_un addr;
55 int sock, saved_errno;
56 struct xs_handle *h = NULL;
58 sock = socket(PF_UNIX, SOCK_STREAM, 0);
59 if (sock < 0)
60 return NULL;
62 addr.sun_family = AF_UNIX;
63 strcpy(addr.sun_path, connect_to);
65 if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) {
66 h = malloc(sizeof(*h));
67 if (h) {
68 h->fd = sock;
69 return h;
70 }
71 }
73 saved_errno = errno;
74 close(sock);
75 errno = saved_errno;
76 return NULL;
77 }
79 static struct xs_handle *get_dev(const char *connect_to)
80 {
81 int fd, saved_errno;
82 struct xs_handle *h;
84 fd = open(connect_to, O_RDWR);
85 if (fd < 0)
86 return NULL;
88 h = malloc(sizeof(*h));
89 if (h) {
90 h->fd = fd;
91 return h;
92 }
94 saved_errno = errno;
95 close(fd);
96 errno = saved_errno;
97 return NULL;
98 }
100 static struct xs_handle *get_handle(const char *connect_to)
101 {
102 struct stat buf;
104 if (stat(connect_to, &buf) != 0)
105 return NULL;
107 if (S_ISSOCK(buf.st_mode))
108 return get_socket(connect_to);
109 else
110 return get_dev(connect_to);
111 }
113 struct xs_handle *xs_daemon_open(void)
114 {
115 return get_handle(xs_daemon_socket());
116 }
118 struct xs_handle *xs_daemon_open_readonly(void)
119 {
120 return get_handle(xs_daemon_socket_ro());
121 }
123 struct xs_handle *xs_domain_open(void)
124 {
125 return get_handle(xs_domain_dev());
126 }
128 void xs_daemon_close(struct xs_handle *h)
129 {
130 if (h->fd >= 0)
131 close(h->fd);
132 free(h);
133 }
135 static bool read_all(int fd, void *data, unsigned int len)
136 {
137 while (len) {
138 int done;
140 done = read(fd, data, len);
141 if (done < 0) {
142 if (errno == EINTR)
143 continue;
144 return false;
145 }
146 if (done == 0) {
147 /* It closed fd on us? EBADF is appropriate. */
148 errno = EBADF;
149 return false;
150 }
151 data += done;
152 len -= done;
153 }
155 return true;
156 }
158 #ifdef XSTEST
159 #define read_all read_all_choice
160 #define xs_write_all write_all_choice
161 #endif
163 static int get_error(const char *errorstring)
164 {
165 unsigned int i;
167 for (i = 0; !streq(errorstring, xsd_errors[i].errstring); i++)
168 if (i == ARRAY_SIZE(xsd_errors) - 1)
169 return EINVAL;
170 return xsd_errors[i].errnum;
171 }
173 /* Adds extra nul terminator, because we generally (always?) hold strings. */
174 static void *read_reply(int fd, enum xsd_sockmsg_type *type, unsigned int *len)
175 {
176 struct xsd_sockmsg msg;
177 void *ret;
178 int saved_errno;
180 if (!read_all(fd, &msg, sizeof(msg)))
181 return NULL;
183 ret = malloc(msg.len + 1);
184 if (!ret)
185 return NULL;
187 if (!read_all(fd, ret, msg.len)) {
188 saved_errno = errno;
189 free(ret);
190 errno = saved_errno;
191 return NULL;
192 }
194 *type = msg.type;
195 if (len)
196 *len = msg.len;
197 ((char *)ret)[msg.len] = '\0';
198 return ret;
199 }
201 /* Send message to xs, get malloc'ed reply. NULL and set errno on error. */
202 static void *xs_talkv(struct xs_handle *h, enum xsd_sockmsg_type type,
203 const struct iovec *iovec, unsigned int num_vecs,
204 unsigned int *len)
205 {
206 struct xsd_sockmsg msg;
207 void *ret = NULL;
208 int saved_errno;
209 unsigned int i;
210 struct sigaction ignorepipe, oldact;
212 msg.type = type;
213 msg.len = 0;
214 for (i = 0; i < num_vecs; i++)
215 msg.len += iovec[i].iov_len;
217 ignorepipe.sa_handler = SIG_IGN;
218 sigemptyset(&ignorepipe.sa_mask);
219 ignorepipe.sa_flags = 0;
220 sigaction(SIGPIPE, &ignorepipe, &oldact);
222 if (!xs_write_all(h->fd, &msg, sizeof(msg)))
223 goto fail;
225 for (i = 0; i < num_vecs; i++)
226 if (!xs_write_all(h->fd, iovec[i].iov_base, iovec[i].iov_len))
227 goto fail;
229 /* Watches can have fired before reply comes: daemon detects
230 * and re-transmits, so we can ignore this. */
231 do {
232 free(ret);
233 ret = read_reply(h->fd, &msg.type, len);
234 if (!ret)
235 goto fail;
236 } while (msg.type == XS_WATCH_EVENT);
238 sigaction(SIGPIPE, &oldact, NULL);
239 if (msg.type == XS_ERROR) {
240 saved_errno = get_error(ret);
241 free(ret);
242 errno = saved_errno;
243 return NULL;
244 }
246 if (msg.type != type) {
247 free(ret);
248 saved_errno = EBADF;
249 goto close_fd;
251 }
252 return ret;
254 fail:
255 /* We're in a bad state, so close fd. */
256 saved_errno = errno;
257 sigaction(SIGPIPE, &oldact, NULL);
258 close_fd:
259 close(h->fd);
260 h->fd = -1;
261 errno = saved_errno;
262 return NULL;
263 }
265 /* free(), but don't change errno. */
266 static void free_no_errno(void *p)
267 {
268 int saved_errno = errno;
269 free(p);
270 errno = saved_errno;
271 }
273 /* Simplified version of xs_talkv: single message. */
274 static void *xs_single(struct xs_handle *h, enum xsd_sockmsg_type type,
275 const char *string, unsigned int *len)
276 {
277 struct iovec iovec;
279 iovec.iov_base = (void *)string;
280 iovec.iov_len = strlen(string) + 1;
281 return xs_talkv(h, type, &iovec, 1, len);
282 }
284 static bool xs_bool(char *reply)
285 {
286 if (!reply)
287 return false;
288 free(reply);
289 return true;
290 }
292 char **xs_directory(struct xs_handle *h, const char *path, unsigned int *num)
293 {
294 char *strings, *p, **ret;
295 unsigned int len;
297 strings = xs_single(h, XS_DIRECTORY, path, &len);
298 if (!strings)
299 return NULL;
301 /* Count the strings. */
302 *num = xs_count_strings(strings, len);
304 /* Transfer to one big alloc for easy freeing. */
305 ret = malloc(*num * sizeof(char *) + len);
306 if (!ret) {
307 free_no_errno(strings);
308 return NULL;
309 }
310 memcpy(&ret[*num], strings, len);
311 free_no_errno(strings);
313 strings = (char *)&ret[*num];
314 for (p = strings, *num = 0; p < strings + len; p += strlen(p) + 1)
315 ret[(*num)++] = p;
316 return ret;
317 }
319 /* Get the value of a single file, nul terminated.
320 * Returns a malloced value: call free() on it after use.
321 * len indicates length in bytes, not including the nul.
322 */
323 void *xs_read(struct xs_handle *h, const char *path, unsigned int *len)
324 {
325 return xs_single(h, XS_READ, path, len);
326 }
328 /* Write the value of a single file.
329 * Returns false on failure. createflags can be 0, O_CREAT, or O_CREAT|O_EXCL.
330 */
331 bool xs_write(struct xs_handle *h, const char *path,
332 const void *data, unsigned int len, int createflags)
333 {
334 const char *flags;
335 struct iovec iovec[3];
337 /* Format: Flags (as string), path, data. */
338 if (createflags == 0)
339 flags = XS_WRITE_NONE;
340 else if (createflags == O_CREAT)
341 flags = XS_WRITE_CREATE;
342 else if (createflags == (O_CREAT|O_EXCL))
343 flags = XS_WRITE_CREATE_EXCL;
344 else {
345 errno = EINVAL;
346 return false;
347 }
349 iovec[0].iov_base = (void *)path;
350 iovec[0].iov_len = strlen(path) + 1;
351 iovec[1].iov_base = (void *)flags;
352 iovec[1].iov_len = strlen(flags) + 1;
353 iovec[2].iov_base = (void *)data;
354 iovec[2].iov_len = len;
356 return xs_bool(xs_talkv(h, XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL));
357 }
359 /* Create a new directory.
360 * Returns false on failure.
361 */
362 bool xs_mkdir(struct xs_handle *h, const char *path)
363 {
364 return xs_bool(xs_single(h, XS_MKDIR, path, NULL));
365 }
367 /* Destroy a file or directory (directories must be empty).
368 * Returns false on failure.
369 */
370 bool xs_rm(struct xs_handle *h, const char *path)
371 {
372 return xs_bool(xs_single(h, XS_RM, path, NULL));
373 }
375 /* Get permissions of node (first element is owner).
376 * Returns malloced array, or NULL: call free() after use.
377 */
378 struct xs_permissions *xs_get_permissions(struct xs_handle *h,
379 const char *path, unsigned int *num)
380 {
381 char *strings;
382 unsigned int len;
383 struct xs_permissions *ret;
385 strings = xs_single(h, XS_GET_PERMS, path, &len);
386 if (!strings)
387 return NULL;
389 /* Count the strings: each one perms then domid. */
390 *num = xs_count_strings(strings, len);
392 /* Transfer to one big alloc for easy freeing. */
393 ret = malloc(*num * sizeof(struct xs_permissions));
394 if (!ret) {
395 free_no_errno(strings);
396 return NULL;
397 }
399 if (!xs_strings_to_perms(ret, *num, strings)) {
400 free_no_errno(ret);
401 ret = NULL;
402 }
404 free(strings);
405 return ret;
406 }
408 /* Set permissions of node (must be owner).
409 * Returns false on failure.
410 */
411 bool xs_set_permissions(struct xs_handle *h, const char *path,
412 struct xs_permissions *perms,
413 unsigned int num_perms)
414 {
415 unsigned int i;
416 struct iovec iov[1+num_perms];
418 iov[0].iov_base = (void *)path;
419 iov[0].iov_len = strlen(path) + 1;
421 for (i = 0; i < num_perms; i++) {
422 char buffer[MAX_STRLEN(domid_t)+1];
424 if (!xs_perm_to_string(&perms[i], buffer))
425 goto unwind;
427 iov[i+1].iov_base = strdup(buffer);
428 iov[i+1].iov_len = strlen(buffer) + 1;
429 if (!iov[i+1].iov_base)
430 goto unwind;
431 }
433 if (!xs_bool(xs_talkv(h, XS_SET_PERMS, iov, 1+num_perms, NULL)))
434 goto unwind;
435 for (i = 0; i < num_perms; i++)
436 free(iov[i+1].iov_base);
437 return true;
439 unwind:
440 num_perms = i;
441 for (i = 0; i < num_perms; i++)
442 free_no_errno(iov[i+1].iov_base);
443 return false;
444 }
446 /* Watch a node for changes (poll on fd to detect, or call read_watch()).
447 * When the node (or any child) changes, fd will become readable.
448 * Token is returned when watch is read, to allow matching.
449 * Returns false on failure.
450 */
451 bool xs_watch(struct xs_handle *h, const char *path, const char *token)
452 {
453 struct iovec iov[2];
455 iov[0].iov_base = (void *)path;
456 iov[0].iov_len = strlen(path) + 1;
457 iov[1].iov_base = (void *)token;
458 iov[1].iov_len = strlen(token) + 1;
460 return xs_bool(xs_talkv(h, XS_WATCH, iov, ARRAY_SIZE(iov), NULL));
461 }
463 /* Find out what node change was on (will block if nothing pending).
464 * Returns array of two pointers: path and token, or NULL.
465 * Call free() after use.
466 */
467 char **xs_read_watch(struct xs_handle *h)
468 {
469 struct xsd_sockmsg msg;
470 char **ret;
472 if (!read_all(h->fd, &msg, sizeof(msg)))
473 return NULL;
475 assert(msg.type == XS_WATCH_EVENT);
476 ret = malloc(sizeof(char *)*2 + msg.len);
477 if (!ret)
478 return NULL;
480 ret[0] = (char *)(ret + 2);
481 if (!read_all(h->fd, ret[0], msg.len)) {
482 free_no_errno(ret);
483 return NULL;
484 }
485 ret[1] = ret[0] + strlen(ret[0]) + 1;
486 return ret;
487 }
489 /* Acknowledge watch on node. Watches must be acknowledged before
490 * any other watches can be read.
491 * Returns false on failure.
492 */
493 bool xs_acknowledge_watch(struct xs_handle *h, const char *token)
494 {
495 return xs_bool(xs_single(h, XS_WATCH_ACK, token, NULL));
496 }
498 /* Remove a watch on a node.
499 * Returns false on failure (no watch on that node).
500 */
501 bool xs_unwatch(struct xs_handle *h, const char *path, const char *token)
502 {
503 struct iovec iov[2];
505 iov[0].iov_base = (char *)path;
506 iov[0].iov_len = strlen(path) + 1;
507 iov[1].iov_base = (char *)token;
508 iov[1].iov_len = strlen(token) + 1;
510 return xs_bool(xs_talkv(h, XS_UNWATCH, iov, ARRAY_SIZE(iov), NULL));
511 }
513 /* Start a transaction: changes by others will not be seen during this
514 * transaction, and changes will not be visible to others until end.
515 * Transaction only applies to the given subtree.
516 * You can only have one transaction at any time.
517 * Returns false on failure.
518 */
519 bool xs_transaction_start(struct xs_handle *h, const char *subtree)
520 {
521 return xs_bool(xs_single(h, XS_TRANSACTION_START, subtree, NULL));
522 }
524 /* End a transaction.
525 * If abandon is true, transaction is discarded instead of committed.
526 * Returns false on failure, which indicates an error: transactions will
527 * not fail spuriously.
528 */
529 bool xs_transaction_end(struct xs_handle *h, bool abort)
530 {
531 char abortstr[2];
533 if (abort)
534 strcpy(abortstr, "F");
535 else
536 strcpy(abortstr, "T");
537 return xs_bool(xs_single(h, XS_TRANSACTION_END, abortstr, NULL));
538 }
540 /* Introduce a new domain.
541 * This tells the store daemon about a shared memory page and event channel
542 * associated with a domain: the domain uses these to communicate.
543 */
544 bool xs_introduce_domain(struct xs_handle *h, domid_t domid, unsigned long mfn,
545 unsigned int eventchn, const char *path)
546 {
547 char domid_str[MAX_STRLEN(domid)];
548 char mfn_str[MAX_STRLEN(mfn)];
549 char eventchn_str[MAX_STRLEN(eventchn)];
550 struct iovec iov[4];
552 sprintf(domid_str, "%u", domid);
553 sprintf(mfn_str, "%lu", mfn);
554 sprintf(eventchn_str, "%u", eventchn);
556 iov[0].iov_base = domid_str;
557 iov[0].iov_len = strlen(domid_str) + 1;
558 iov[1].iov_base = mfn_str;
559 iov[1].iov_len = strlen(mfn_str) + 1;
560 iov[2].iov_base = eventchn_str;
561 iov[2].iov_len = strlen(eventchn_str) + 1;
562 iov[3].iov_base = (char *)path;
563 iov[3].iov_len = strlen(path) + 1;
565 return xs_bool(xs_talkv(h, XS_INTRODUCE, iov, ARRAY_SIZE(iov), NULL));
566 }
568 bool xs_release_domain(struct xs_handle *h, domid_t domid)
569 {
570 char domid_str[MAX_STRLEN(domid)];
572 sprintf(domid_str, "%u", domid);
574 return xs_bool(xs_single(h, XS_RELEASE, domid_str, NULL));
575 }
577 char *xs_get_domain_path(struct xs_handle *h, domid_t domid)
578 {
579 char domid_str[MAX_STRLEN(domid)];
581 sprintf(domid_str, "%u", domid);
583 return xs_single(h, XS_GET_DOMAIN_PATH, domid_str, NULL);
584 }
586 bool xs_shutdown(struct xs_handle *h)
587 {
588 bool ret = xs_bool(xs_single(h, XS_SHUTDOWN, "", NULL));
589 if (ret) {
590 char c;
591 /* Wait for it to actually shutdown. */
592 while ((read(h->fd, &c, 1) < 0) && (errno == EINTR))
593 continue;
594 }
595 return ret;
596 }
598 /* Only useful for DEBUG versions */
599 char *xs_debug_command(struct xs_handle *h, const char *cmd,
600 void *data, unsigned int len)
601 {
602 struct iovec iov[2];
604 iov[0].iov_base = (void *)cmd;
605 iov[0].iov_len = strlen(cmd) + 1;
606 iov[1].iov_base = data;
607 iov[1].iov_len = len;
609 return xs_talkv(h, XS_DEBUG, iov, ARRAY_SIZE(iov), NULL);
610 }