ia64/xen-unstable

view tools/xenstore/xs.c @ 7238:971e7c7411b3

Raise an exception if an error appears on the pipes to our children, and make
sure that the child's pipes are closed even under that exception. Move the
handling of POLLHUP to the end of the loop, so that we guarantee to read any
remaining data from the child if POLLHUP and POLLIN appear at the same time.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@ewan
date Thu Oct 06 10:13:11 2005 +0100 (2005-10-06)
parents ef9591d03fdd
children 93e27f7ca8a8 61b3b357d827 402b5eb85905
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.
330 */
331 bool xs_write(struct xs_handle *h, const char *path,
332 const void *data, unsigned int len)
333 {
334 struct iovec iovec[2];
336 iovec[0].iov_base = (void *)path;
337 iovec[0].iov_len = strlen(path) + 1;
338 iovec[1].iov_base = (void *)data;
339 iovec[1].iov_len = len;
341 return xs_bool(xs_talkv(h, XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL));
342 }
344 /* Create a new directory.
345 * Returns false on failure, or success if it already exists.
346 */
347 bool xs_mkdir(struct xs_handle *h, const char *path)
348 {
349 return xs_bool(xs_single(h, XS_MKDIR, path, NULL));
350 }
352 /* Destroy a file or directory (directories must be empty).
353 * Returns false on failure, or success if it doesn't exist.
354 */
355 bool xs_rm(struct xs_handle *h, const char *path)
356 {
357 return xs_bool(xs_single(h, XS_RM, path, NULL));
358 }
360 /* Get permissions of node (first element is owner).
361 * Returns malloced array, or NULL: call free() after use.
362 */
363 struct xs_permissions *xs_get_permissions(struct xs_handle *h,
364 const char *path, unsigned int *num)
365 {
366 char *strings;
367 unsigned int len;
368 struct xs_permissions *ret;
370 strings = xs_single(h, XS_GET_PERMS, path, &len);
371 if (!strings)
372 return NULL;
374 /* Count the strings: each one perms then domid. */
375 *num = xs_count_strings(strings, len);
377 /* Transfer to one big alloc for easy freeing. */
378 ret = malloc(*num * sizeof(struct xs_permissions));
379 if (!ret) {
380 free_no_errno(strings);
381 return NULL;
382 }
384 if (!xs_strings_to_perms(ret, *num, strings)) {
385 free_no_errno(ret);
386 ret = NULL;
387 }
389 free(strings);
390 return ret;
391 }
393 /* Set permissions of node (must be owner).
394 * Returns false on failure.
395 */
396 bool xs_set_permissions(struct xs_handle *h, const char *path,
397 struct xs_permissions *perms,
398 unsigned int num_perms)
399 {
400 unsigned int i;
401 struct iovec iov[1+num_perms];
403 iov[0].iov_base = (void *)path;
404 iov[0].iov_len = strlen(path) + 1;
406 for (i = 0; i < num_perms; i++) {
407 char buffer[MAX_STRLEN(domid_t)+1];
409 if (!xs_perm_to_string(&perms[i], buffer))
410 goto unwind;
412 iov[i+1].iov_base = strdup(buffer);
413 iov[i+1].iov_len = strlen(buffer) + 1;
414 if (!iov[i+1].iov_base)
415 goto unwind;
416 }
418 if (!xs_bool(xs_talkv(h, XS_SET_PERMS, iov, 1+num_perms, NULL)))
419 goto unwind;
420 for (i = 0; i < num_perms; i++)
421 free(iov[i+1].iov_base);
422 return true;
424 unwind:
425 num_perms = i;
426 for (i = 0; i < num_perms; i++)
427 free_no_errno(iov[i+1].iov_base);
428 return false;
429 }
431 /* Watch a node for changes (poll on fd to detect, or call read_watch()).
432 * When the node (or any child) changes, fd will become readable.
433 * Token is returned when watch is read, to allow matching.
434 * Returns false on failure.
435 */
436 bool xs_watch(struct xs_handle *h, const char *path, const char *token)
437 {
438 struct iovec iov[2];
440 iov[0].iov_base = (void *)path;
441 iov[0].iov_len = strlen(path) + 1;
442 iov[1].iov_base = (void *)token;
443 iov[1].iov_len = strlen(token) + 1;
445 return xs_bool(xs_talkv(h, XS_WATCH, iov, ARRAY_SIZE(iov), NULL));
446 }
448 /* Find out what node change was on (will block if nothing pending).
449 * Returns array of two pointers: path and token, or NULL.
450 * Call free() after use.
451 */
452 char **xs_read_watch(struct xs_handle *h)
453 {
454 struct xsd_sockmsg msg;
455 char **ret;
457 if (!read_all(h->fd, &msg, sizeof(msg)))
458 return NULL;
460 assert(msg.type == XS_WATCH_EVENT);
461 ret = malloc(sizeof(char *)*2 + msg.len);
462 if (!ret)
463 return NULL;
465 ret[0] = (char *)(ret + 2);
466 if (!read_all(h->fd, ret[0], msg.len)) {
467 free_no_errno(ret);
468 return NULL;
469 }
470 ret[1] = ret[0] + strlen(ret[0]) + 1;
471 return ret;
472 }
474 /* Acknowledge watch on node. Watches must be acknowledged before
475 * any other watches can be read.
476 * Returns false on failure.
477 */
478 bool xs_acknowledge_watch(struct xs_handle *h, const char *token)
479 {
480 return xs_bool(xs_single(h, XS_WATCH_ACK, token, NULL));
481 }
483 /* Remove a watch on a node.
484 * Returns false on failure (no watch on that node).
485 */
486 bool xs_unwatch(struct xs_handle *h, const char *path, const char *token)
487 {
488 struct iovec iov[2];
490 iov[0].iov_base = (char *)path;
491 iov[0].iov_len = strlen(path) + 1;
492 iov[1].iov_base = (char *)token;
493 iov[1].iov_len = strlen(token) + 1;
495 return xs_bool(xs_talkv(h, XS_UNWATCH, iov, ARRAY_SIZE(iov), NULL));
496 }
498 /* Start a transaction: changes by others will not be seen during this
499 * transaction, and changes will not be visible to others until end.
500 * You can only have one transaction at any time.
501 * Returns false on failure.
502 */
503 bool xs_transaction_start(struct xs_handle *h)
504 {
505 return xs_bool(xs_single(h, XS_TRANSACTION_START, "", NULL));
506 }
508 /* End a transaction.
509 * If abandon is true, transaction is discarded instead of committed.
510 * Returns false on failure, which indicates an error: transactions will
511 * not fail spuriously.
512 */
513 bool xs_transaction_end(struct xs_handle *h, bool abort)
514 {
515 char abortstr[2];
517 if (abort)
518 strcpy(abortstr, "F");
519 else
520 strcpy(abortstr, "T");
521 return xs_bool(xs_single(h, XS_TRANSACTION_END, abortstr, NULL));
522 }
524 /* Introduce a new domain.
525 * This tells the store daemon about a shared memory page and event channel
526 * associated with a domain: the domain uses these to communicate.
527 */
528 bool xs_introduce_domain(struct xs_handle *h, domid_t domid, unsigned long mfn,
529 unsigned int eventchn, const char *path)
530 {
531 char domid_str[MAX_STRLEN(domid)];
532 char mfn_str[MAX_STRLEN(mfn)];
533 char eventchn_str[MAX_STRLEN(eventchn)];
534 struct iovec iov[4];
536 sprintf(domid_str, "%u", domid);
537 sprintf(mfn_str, "%lu", mfn);
538 sprintf(eventchn_str, "%u", eventchn);
540 iov[0].iov_base = domid_str;
541 iov[0].iov_len = strlen(domid_str) + 1;
542 iov[1].iov_base = mfn_str;
543 iov[1].iov_len = strlen(mfn_str) + 1;
544 iov[2].iov_base = eventchn_str;
545 iov[2].iov_len = strlen(eventchn_str) + 1;
546 iov[3].iov_base = (char *)path;
547 iov[3].iov_len = strlen(path) + 1;
549 return xs_bool(xs_talkv(h, XS_INTRODUCE, iov, ARRAY_SIZE(iov), NULL));
550 }
552 bool xs_release_domain(struct xs_handle *h, domid_t domid)
553 {
554 char domid_str[MAX_STRLEN(domid)];
556 sprintf(domid_str, "%u", domid);
558 return xs_bool(xs_single(h, XS_RELEASE, domid_str, NULL));
559 }
561 char *xs_get_domain_path(struct xs_handle *h, domid_t domid)
562 {
563 char domid_str[MAX_STRLEN(domid)];
565 sprintf(domid_str, "%u", domid);
567 return xs_single(h, XS_GET_DOMAIN_PATH, domid_str, NULL);
568 }
570 bool xs_shutdown(struct xs_handle *h)
571 {
572 bool ret = xs_bool(xs_single(h, XS_SHUTDOWN, "", NULL));
573 if (ret) {
574 char c;
575 /* Wait for it to actually shutdown. */
576 while ((read(h->fd, &c, 1) < 0) && (errno == EINTR))
577 continue;
578 }
579 return ret;
580 }
582 /* Only useful for DEBUG versions */
583 char *xs_debug_command(struct xs_handle *h, const char *cmd,
584 void *data, unsigned int len)
585 {
586 struct iovec iov[2];
588 iov[0].iov_base = (void *)cmd;
589 iov[0].iov_len = strlen(cmd) + 1;
590 iov[1].iov_base = data;
591 iov[1].iov_len = len;
593 return xs_talkv(h, XS_DEBUG, iov, ARRAY_SIZE(iov), NULL);
594 }