direct-io.hg

view tools/xenstore/xenstored_core.c @ 8335:c8378d3c3af8

Make sure to fork again after setsid() so that child cannot regain CTTY.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
author Anthony Liguori <anthony@codemonkey.ws>
date Mon Dec 12 15:11:13 2005 +0000 (2005-12-12)
parents ac3ceb2d37d1
children c70109e64c9e
line source
1 /*
2 Simple prototype Xen Store Daemon providing simple tree-like database.
3 Copyright (C) 2005 Rusty Russell IBM Corporation
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program 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
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <sys/socket.h>
23 #include <sys/select.h>
24 #include <sys/un.h>
25 #include <sys/time.h>
26 #include <time.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <stdbool.h>
30 #include <stdio.h>
31 #include <stdarg.h>
32 #include <stdlib.h>
33 #include <syslog.h>
34 #include <string.h>
35 #include <errno.h>
36 #include <dirent.h>
37 #include <getopt.h>
38 #include <signal.h>
39 #include <assert.h>
40 #include <setjmp.h>
42 //#define DEBUG
43 #include "utils.h"
44 #include "list.h"
45 #include "talloc.h"
46 #include "xs_lib.h"
47 #include "xenstored_core.h"
48 #include "xenstored_watch.h"
49 #include "xenstored_transaction.h"
50 #include "xenstored_domain.h"
51 #include "xenctrl.h"
52 #include "tdb.h"
54 extern int eventchn_fd; /* in xenstored_domain.c */
56 static bool verbose;
57 LIST_HEAD(connections);
58 static int tracefd = -1;
59 static int reopen_log_pipe[2];
60 static char *tracefile = NULL;
61 static TDB_CONTEXT *tdb_ctx;
63 #ifdef TESTING
64 static bool failtest = false;
66 /* We override talloc's malloc. */
67 void *test_malloc(size_t size)
68 {
69 /* 1 in 20 means only about 50% of connections establish. */
70 if (failtest && (random() % 32) == 0)
71 return NULL;
72 return malloc(size);
73 }
75 static void stop_failtest(int signum __attribute__((unused)))
76 {
77 failtest = false;
78 }
80 /* Need these before we #define away write_all/mkdir in testing.h */
81 bool test_write_all(int fd, void *contents, unsigned int len);
82 bool test_write_all(int fd, void *contents, unsigned int len)
83 {
84 if (failtest && (random() % 8) == 0) {
85 if (len)
86 len = random() % len;
87 write(fd, contents, len);
88 errno = ENOSPC;
89 return false;
90 }
91 return xs_write_all(fd, contents, len);
92 }
94 int test_mkdir(const char *dir, int perms);
95 int test_mkdir(const char *dir, int perms)
96 {
97 if (failtest && (random() % 8) == 0) {
98 errno = ENOSPC;
99 return -1;
100 }
101 return mkdir(dir, perms);
102 }
103 #endif /* TESTING */
105 #include "xenstored_test.h"
107 /* FIXME: Ideally, this should never be called. Some can be eliminated. */
108 /* Something is horribly wrong: shutdown immediately. */
109 void __attribute__((noreturn)) corrupt(struct connection *conn,
110 const char *fmt, ...)
111 {
112 va_list arglist;
113 char *str;
114 int saved_errno = errno;
116 va_start(arglist, fmt);
117 str = talloc_vasprintf(NULL, fmt, arglist);
118 va_end(arglist);
120 trace("xenstored corruption: connection id %i: err %s: %s",
121 conn ? (int)conn->id : -1, strerror(saved_errno), str);
122 eprintf("xenstored corruption: connection id %i: err %s: %s",
123 conn ? (int)conn->id : -1, strerror(saved_errno), str);
124 #ifdef TESTING
125 /* Allow them to attach debugger. */
126 sleep(30);
127 #endif
128 syslog(LOG_DAEMON,
129 "xenstored corruption: connection id %i: err %s: %s",
130 conn ? (int)conn->id : -1, strerror(saved_errno), str);
131 _exit(2);
132 }
134 TDB_CONTEXT *tdb_context(struct connection *conn)
135 {
136 /* conn = NULL used in manual_node at setup. */
137 if (!conn || !conn->transaction)
138 return tdb_ctx;
139 return tdb_transaction_context(conn->transaction);
140 }
142 bool replace_tdb(const char *newname, TDB_CONTEXT *newtdb)
143 {
144 if (rename(newname, xs_daemon_tdb()) != 0)
145 return false;
146 tdb_close(tdb_ctx);
147 tdb_ctx = talloc_steal(talloc_autofree_context(), newtdb);
148 return true;
149 }
151 static char *sockmsg_string(enum xsd_sockmsg_type type)
152 {
153 switch (type) {
154 case XS_DEBUG: return "DEBUG";
155 case XS_DIRECTORY: return "DIRECTORY";
156 case XS_READ: return "READ";
157 case XS_GET_PERMS: return "GET_PERMS";
158 case XS_WATCH: return "WATCH";
159 case XS_UNWATCH: return "UNWATCH";
160 case XS_TRANSACTION_START: return "TRANSACTION_START";
161 case XS_TRANSACTION_END: return "TRANSACTION_END";
162 case XS_INTRODUCE: return "INTRODUCE";
163 case XS_RELEASE: return "RELEASE";
164 case XS_GET_DOMAIN_PATH: return "GET_DOMAIN_PATH";
165 case XS_WRITE: return "WRITE";
166 case XS_MKDIR: return "MKDIR";
167 case XS_RM: return "RM";
168 case XS_SET_PERMS: return "SET_PERMS";
169 case XS_WATCH_EVENT: return "WATCH_EVENT";
170 case XS_ERROR: return "ERROR";
171 case XS_IS_DOMAIN_INTRODUCED: return "XS_IS_DOMAIN_INTRODUCED";
172 default:
173 return "**UNKNOWN**";
174 }
175 }
177 static void trace_io(const struct connection *conn,
178 const char *prefix,
179 const struct buffered_data *data)
180 {
181 char string[64];
182 unsigned int i;
183 time_t now;
184 struct tm *tm;
186 if (tracefd < 0)
187 return;
189 now = time(NULL);
190 tm = localtime(&now);
192 write(tracefd, prefix, strlen(prefix));
193 sprintf(string, " %p %02d:%02d:%02d ", conn, tm->tm_hour, tm->tm_min,
194 tm->tm_sec);
195 write(tracefd, string, strlen(string));
196 write(tracefd, sockmsg_string(data->hdr.msg.type),
197 strlen(sockmsg_string(data->hdr.msg.type)));
198 write(tracefd, " (", 2);
199 for (i = 0; i < data->hdr.msg.len; i++) {
200 if (data->buffer[i] == '\0')
201 write(tracefd, " ", 1);
202 else
203 write(tracefd, data->buffer + i, 1);
204 }
205 write(tracefd, ")\n", 2);
206 }
208 void trace_create(const void *data, const char *type)
209 {
210 char string[64];
211 if (tracefd < 0)
212 return;
214 write(tracefd, "CREATE ", strlen("CREATE "));
215 write(tracefd, type, strlen(type));
216 sprintf(string, " %p\n", data);
217 write(tracefd, string, strlen(string));
218 }
220 void trace_destroy(const void *data, const char *type)
221 {
222 char string[64];
223 if (tracefd < 0)
224 return;
226 write(tracefd, "DESTROY ", strlen("DESTROY "));
227 write(tracefd, type, strlen(type));
228 sprintf(string, " %p\n", data);
229 write(tracefd, string, strlen(string));
230 }
232 void trace(const char *fmt, ...)
233 {
234 va_list arglist;
235 char *str;
237 if (tracefd < 0)
238 return;
240 va_start(arglist, fmt);
241 str = talloc_vasprintf(NULL, fmt, arglist);
242 va_end(arglist);
243 write(tracefd, str, strlen(str));
244 talloc_free(str);
245 }
248 /**
249 * Signal handler for SIGHUP, which requests that the trace log is reopened
250 * (in the main loop). A single byte is written to reopen_log_pipe, to awaken
251 * the select() in the main loop.
252 */
253 static void trigger_reopen_log(int signal __attribute__((unused)))
254 {
255 char c = 'A';
256 write(reopen_log_pipe[1], &c, 1);
257 }
260 static void reopen_log()
261 {
262 if (tracefile) {
263 if (tracefd > 0)
264 close(tracefd);
266 tracefd = open(tracefile, O_WRONLY|O_CREAT|O_APPEND, 0600);
268 if (tracefd < 0)
269 perror("Could not open tracefile");
270 else
271 write(tracefd, "\n***\n", strlen("\n***\n"));
272 }
273 }
276 static bool write_messages(struct connection *conn)
277 {
278 int ret;
279 struct buffered_data *out;
281 out = list_top(&conn->out_list, struct buffered_data, list);
282 if (out == NULL)
283 return true;
285 if (out->inhdr) {
286 if (verbose)
287 xprintf("Writing msg %s (%.*s) out to %p\n",
288 sockmsg_string(out->hdr.msg.type),
289 out->hdr.msg.len,
290 out->buffer, conn);
291 ret = conn->write(conn, out->hdr.raw + out->used,
292 sizeof(out->hdr) - out->used);
293 if (ret < 0)
294 return false;
296 out->used += ret;
297 if (out->used < sizeof(out->hdr))
298 return true;
300 out->inhdr = false;
301 out->used = 0;
303 /* Second write might block if non-zero. */
304 if (out->hdr.msg.len && !conn->domain)
305 return true;
306 }
308 ret = conn->write(conn, out->buffer + out->used,
309 out->hdr.msg.len - out->used);
310 if (ret < 0)
311 return false;
313 out->used += ret;
314 if (out->used != out->hdr.msg.len)
315 return true;
317 trace_io(conn, "OUT", out);
319 list_del(&out->list);
320 talloc_free(out);
322 return true;
323 }
325 static int destroy_conn(void *_conn)
326 {
327 struct connection *conn = _conn;
329 /* Flush outgoing if possible, but don't block. */
330 if (!conn->domain) {
331 fd_set set;
332 struct timeval none;
334 FD_ZERO(&set);
335 FD_SET(conn->fd, &set);
336 none.tv_sec = none.tv_usec = 0;
338 while (!list_empty(&conn->out_list)
339 && select(conn->fd+1, NULL, &set, NULL, &none) == 1)
340 if (!write_messages(conn))
341 break;
342 close(conn->fd);
343 }
344 list_del(&conn->list);
345 trace_destroy(conn, "connection");
346 return 0;
347 }
350 static void set_fd(int fd, fd_set *set, int *max)
351 {
352 FD_SET(fd, set);
353 if (fd > *max)
354 *max = fd;
355 }
358 static int initialize_set(fd_set *inset, fd_set *outset, int sock, int ro_sock)
359 {
360 struct connection *i;
361 int max = -1;
363 FD_ZERO(inset);
364 FD_ZERO(outset);
366 set_fd(sock, inset, &max);
367 set_fd(ro_sock, inset, &max);
368 set_fd(eventchn_fd, inset, &max);
369 set_fd(reopen_log_pipe[0], inset, &max);
370 list_for_each_entry(i, &connections, list) {
371 if (i->domain)
372 continue;
373 set_fd(i->fd, inset, &max);
374 if (!list_empty(&i->out_list))
375 FD_SET(i->fd, outset);
376 }
377 return max;
378 }
380 static int destroy_fd(void *_fd)
381 {
382 int *fd = _fd;
383 close(*fd);
384 return 0;
385 }
387 /* Return a pointer to an fd, self-closing and attached to this pathname. */
388 int *talloc_open(const char *pathname, int flags, int mode)
389 {
390 int *fd;
392 fd = talloc(pathname, int);
393 *fd = open(pathname, flags, mode);
394 if (*fd < 0) {
395 int saved_errno = errno;
396 talloc_free(fd);
397 errno = saved_errno;
398 return NULL;
399 }
400 talloc_set_destructor(fd, destroy_fd);
401 return fd;
402 }
404 /* Is child a subnode of parent, or equal? */
405 bool is_child(const char *child, const char *parent)
406 {
407 unsigned int len = strlen(parent);
409 /* / should really be "" for this algorithm to work, but that's a
410 * usability nightmare. */
411 if (streq(parent, "/"))
412 return true;
414 if (strncmp(child, parent, len) != 0)
415 return false;
417 return child[len] == '/' || child[len] == '\0';
418 }
420 /* If it fails, returns NULL and sets errno. */
421 static struct node *read_node(struct connection *conn, const char *name)
422 {
423 TDB_DATA key, data;
424 uint32_t *p;
425 struct node *node;
427 key.dptr = (void *)name;
428 key.dsize = strlen(name);
429 data = tdb_fetch(tdb_context(conn), key);
431 if (data.dptr == NULL) {
432 if (tdb_error(tdb_context(conn)) == TDB_ERR_NOEXIST)
433 errno = ENOENT;
434 else
435 errno = EIO;
436 return NULL;
437 }
439 node = talloc(name, struct node);
440 node->name = talloc_strdup(node, name);
441 node->parent = NULL;
442 node->tdb = tdb_context(conn);
443 talloc_steal(node, data.dptr);
445 /* Datalen, childlen, number of permissions */
446 p = (uint32_t *)data.dptr;
447 node->num_perms = p[0];
448 node->datalen = p[1];
449 node->childlen = p[2];
451 /* Permissions are struct xs_permissions. */
452 node->perms = (void *)&p[3];
453 /* Data is binary blob (usually ascii, no nul). */
454 node->data = node->perms + node->num_perms;
455 /* Children is strings, nul separated. */
456 node->children = node->data + node->datalen;
458 return node;
459 }
461 static bool write_node(struct connection *conn, const struct node *node)
462 {
463 TDB_DATA key, data;
464 void *p;
466 key.dptr = (void *)node->name;
467 key.dsize = strlen(node->name);
469 data.dsize = 3*sizeof(uint32_t)
470 + node->num_perms*sizeof(node->perms[0])
471 + node->datalen + node->childlen;
472 data.dptr = talloc_size(node, data.dsize);
473 ((uint32_t *)data.dptr)[0] = node->num_perms;
474 ((uint32_t *)data.dptr)[1] = node->datalen;
475 ((uint32_t *)data.dptr)[2] = node->childlen;
476 p = data.dptr + 3 * sizeof(uint32_t);
478 memcpy(p, node->perms, node->num_perms*sizeof(node->perms[0]));
479 p += node->num_perms*sizeof(node->perms[0]);
480 memcpy(p, node->data, node->datalen);
481 p += node->datalen;
482 memcpy(p, node->children, node->childlen);
484 /* TDB should set errno, but doesn't even set ecode AFAICT. */
485 if (tdb_store(tdb_context(conn), key, data, TDB_REPLACE) != 0) {
486 errno = ENOSPC;
487 return false;
488 }
489 return true;
490 }
492 static enum xs_perm_type perm_for_conn(struct connection *conn,
493 struct xs_permissions *perms,
494 unsigned int num)
495 {
496 unsigned int i;
497 enum xs_perm_type mask = XS_PERM_READ|XS_PERM_WRITE|XS_PERM_OWNER;
499 if (!conn->can_write)
500 mask &= ~XS_PERM_WRITE;
502 /* Owners and tools get it all... */
503 if (!conn->id || perms[0].id == conn->id)
504 return (XS_PERM_READ|XS_PERM_WRITE|XS_PERM_OWNER) & mask;
506 for (i = 1; i < num; i++)
507 if (perms[i].id == conn->id)
508 return perms[i].perms & mask;
510 return perms[0].perms & mask;
511 }
513 static char *get_parent(const char *node)
514 {
515 char *slash = strrchr(node + 1, '/');
516 if (!slash)
517 return talloc_strdup(node, "/");
518 return talloc_asprintf(node, "%.*s", (int)(slash - node), node);
519 }
521 /* What do parents say? */
522 static enum xs_perm_type ask_parents(struct connection *conn, const char *name)
523 {
524 struct node *node;
526 do {
527 name = get_parent(name);
528 node = read_node(conn, name);
529 if (node)
530 break;
531 } while (!streq(name, "/"));
533 /* No permission at root? We're in trouble. */
534 if (!node)
535 corrupt(conn, "No permissions file at root");
537 return perm_for_conn(conn, node->perms, node->num_perms);
538 }
540 /* We have a weird permissions system. You can allow someone into a
541 * specific node without allowing it in the parents. If it's going to
542 * fail, however, we don't want the errno to indicate any information
543 * about the node. */
544 static int errno_from_parents(struct connection *conn, const char *node,
545 int errnum, enum xs_perm_type perm)
546 {
547 /* We always tell them about memory failures. */
548 if (errnum == ENOMEM)
549 return errnum;
551 if (ask_parents(conn, node) & perm)
552 return errnum;
553 return EACCES;
554 }
556 /* If it fails, returns NULL and sets errno. */
557 struct node *get_node(struct connection *conn,
558 const char *name,
559 enum xs_perm_type perm)
560 {
561 struct node *node;
563 if (!name || !is_valid_nodename(name)) {
564 errno = EINVAL;
565 return NULL;
566 }
567 node = read_node(conn, name);
568 /* If we don't have permission, we don't have node. */
569 if (node) {
570 if ((perm_for_conn(conn, node->perms, node->num_perms) & perm)
571 != perm)
572 node = NULL;
573 }
574 /* Clean up errno if they weren't supposed to know. */
575 if (!node)
576 errno = errno_from_parents(conn, name, errno, perm);
577 return node;
578 }
580 static struct buffered_data *new_buffer(void *ctx)
581 {
582 struct buffered_data *data;
584 data = talloc(ctx, struct buffered_data);
585 if (data == NULL)
586 return NULL;
588 data->inhdr = true;
589 data->used = 0;
590 data->buffer = NULL;
592 return data;
593 }
595 /* Return length of string (including nul) at this offset. */
596 static unsigned int get_string(const struct buffered_data *data,
597 unsigned int offset)
598 {
599 const char *nul;
601 if (offset >= data->used)
602 return 0;
604 nul = memchr(data->buffer + offset, 0, data->used - offset);
605 if (!nul)
606 return 0;
608 return nul - (data->buffer + offset) + 1;
609 }
611 /* Break input into vectors, return the number, fill in up to num of them. */
612 unsigned int get_strings(struct buffered_data *data,
613 char *vec[], unsigned int num)
614 {
615 unsigned int off, i, len;
617 off = i = 0;
618 while ((len = get_string(data, off)) != 0) {
619 if (i < num)
620 vec[i] = data->buffer + off;
621 i++;
622 off += len;
623 }
624 return i;
625 }
627 void send_reply(struct connection *conn, enum xsd_sockmsg_type type,
628 const void *data, unsigned int len)
629 {
630 struct buffered_data *bdata;
632 /* Message is a child of the connection context for auto-cleanup. */
633 bdata = new_buffer(conn);
634 bdata->buffer = talloc_array(bdata, char, len);
636 /* Echo request header in reply unless this is an async watch event. */
637 if (type != XS_WATCH_EVENT) {
638 memcpy(&bdata->hdr.msg, &conn->in->hdr.msg,
639 sizeof(struct xsd_sockmsg));
640 } else {
641 memset(&bdata->hdr.msg, 0, sizeof(struct xsd_sockmsg));
642 }
644 /* Update relevant header fields and fill in the message body. */
645 bdata->hdr.msg.type = type;
646 bdata->hdr.msg.len = len;
647 memcpy(bdata->buffer, data, len);
649 /* Queue for later transmission. */
650 list_add_tail(&bdata->list, &conn->out_list);
651 }
653 /* Some routines (write, mkdir, etc) just need a non-error return */
654 void send_ack(struct connection *conn, enum xsd_sockmsg_type type)
655 {
656 send_reply(conn, type, "OK", sizeof("OK"));
657 }
659 void send_error(struct connection *conn, int error)
660 {
661 unsigned int i;
663 for (i = 0; error != xsd_errors[i].errnum; i++) {
664 if (i == ARRAY_SIZE(xsd_errors) - 1) {
665 eprintf("xenstored: error %i untranslatable", error);
666 i = 0; /* EINVAL */
667 break;
668 }
669 }
670 send_reply(conn, XS_ERROR, xsd_errors[i].errstring,
671 strlen(xsd_errors[i].errstring) + 1);
672 }
674 static bool valid_chars(const char *node)
675 {
676 /* Nodes can have lots of crap. */
677 return (strspn(node,
678 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
679 "abcdefghijklmnopqrstuvwxyz"
680 "0123456789-/_@") == strlen(node));
681 }
683 bool is_valid_nodename(const char *node)
684 {
685 /* Must start in /. */
686 if (!strstarts(node, "/"))
687 return false;
689 /* Cannot end in / (unless it's just "/"). */
690 if (strends(node, "/") && !streq(node, "/"))
691 return false;
693 /* No double //. */
694 if (strstr(node, "//"))
695 return false;
697 return valid_chars(node);
698 }
700 /* We expect one arg in the input: return NULL otherwise. */
701 static const char *onearg(struct buffered_data *in)
702 {
703 if (!in->used || get_string(in, 0) != in->used)
704 return NULL;
705 return in->buffer;
706 }
708 static char *perms_to_strings(const void *ctx,
709 struct xs_permissions *perms, unsigned int num,
710 unsigned int *len)
711 {
712 unsigned int i;
713 char *strings = NULL;
714 char buffer[MAX_STRLEN(unsigned int) + 1];
716 for (*len = 0, i = 0; i < num; i++) {
717 if (!xs_perm_to_string(&perms[i], buffer))
718 return NULL;
720 strings = talloc_realloc(ctx, strings, char,
721 *len + strlen(buffer) + 1);
722 strcpy(strings + *len, buffer);
723 *len += strlen(buffer) + 1;
724 }
725 return strings;
726 }
728 char *canonicalize(struct connection *conn, const char *node)
729 {
730 const char *prefix;
732 if (!node || strstarts(node, "/"))
733 return (char *)node;
734 prefix = get_implicit_path(conn);
735 if (prefix)
736 return talloc_asprintf(node, "%s/%s", prefix, node);
737 return (char *)node;
738 }
740 bool check_event_node(const char *node)
741 {
742 if (!node || !strstarts(node, "@")) {
743 errno = EINVAL;
744 return false;
745 }
746 return true;
747 }
749 static void send_directory(struct connection *conn, const char *name)
750 {
751 struct node *node;
753 name = canonicalize(conn, name);
754 node = get_node(conn, name, XS_PERM_READ);
755 if (!node) {
756 send_error(conn, errno);
757 return;
758 }
760 send_reply(conn, XS_DIRECTORY, node->children, node->childlen);
761 }
763 static void do_read(struct connection *conn, const char *name)
764 {
765 struct node *node;
767 name = canonicalize(conn, name);
768 node = get_node(conn, name, XS_PERM_READ);
769 if (!node) {
770 send_error(conn, errno);
771 return;
772 }
774 send_reply(conn, XS_READ, node->data, node->datalen);
775 }
777 static void delete_node_single(struct connection *conn, struct node *node)
778 {
779 TDB_DATA key;
781 key.dptr = (void *)node->name;
782 key.dsize = strlen(node->name);
784 if (tdb_delete(tdb_context(conn), key) != 0)
785 corrupt(conn, "Could not delete '%s'", node->name);
786 }
788 /* Must not be / */
789 static char *basename(const char *name)
790 {
791 return strrchr(name, '/') + 1;
792 }
794 static struct node *construct_node(struct connection *conn, const char *name)
795 {
796 const char *base;
797 unsigned int baselen;
798 struct node *parent, *node;
799 char *children, *parentname = get_parent(name);
801 /* If parent doesn't exist, create it. */
802 parent = read_node(conn, parentname);
803 if (!parent)
804 parent = construct_node(conn, parentname);
805 if (!parent)
806 return NULL;
808 /* Add child to parent. */
809 base = basename(name);
810 baselen = strlen(base) + 1;
811 children = talloc_array(name, char, parent->childlen + baselen);
812 memcpy(children, parent->children, parent->childlen);
813 memcpy(children + parent->childlen, base, baselen);
814 parent->children = children;
815 parent->childlen += baselen;
817 /* Allocate node */
818 node = talloc(name, struct node);
819 node->tdb = tdb_context(conn);
820 node->name = talloc_strdup(node, name);
822 /* Inherit permissions, except domains own what they create */
823 node->num_perms = parent->num_perms;
824 node->perms = talloc_memdup(node, parent->perms,
825 node->num_perms * sizeof(node->perms[0]));
826 if (conn && conn->id)
827 node->perms[0].id = conn->id;
829 /* No children, no data */
830 node->children = node->data = NULL;
831 node->childlen = node->datalen = 0;
832 node->parent = parent;
833 return node;
834 }
836 static int destroy_node(void *_node)
837 {
838 struct node *node = _node;
839 TDB_DATA key;
841 if (streq(node->name, "/"))
842 corrupt(NULL, "Destroying root node!");
844 key.dptr = (void *)node->name;
845 key.dsize = strlen(node->name);
847 tdb_delete(node->tdb, key);
848 return 0;
849 }
851 /* Be careful: create heirarchy, put entry in existing parent *last*.
852 * This helps fsck if we die during this. */
853 static struct node *create_node(struct connection *conn,
854 const char *name,
855 void *data, unsigned int datalen)
856 {
857 struct node *node, *i;
859 node = construct_node(conn, name);
860 if (!node)
861 return NULL;
863 node->data = data;
864 node->datalen = datalen;
866 /* We write out the nodes down, setting destructor in case
867 * something goes wrong. */
868 for (i = node; i; i = i->parent) {
869 if (!write_node(conn, i))
870 return NULL;
871 talloc_set_destructor(i, destroy_node);
872 }
874 /* OK, now remove destructors so they stay around */
875 for (i = node; i; i = i->parent)
876 talloc_set_destructor(i, NULL);
877 return node;
878 }
880 /* path, data... */
881 static void do_write(struct connection *conn, struct buffered_data *in)
882 {
883 unsigned int offset, datalen;
884 struct node *node;
885 char *vec[1] = { NULL }; /* gcc4 + -W + -Werror fucks code. */
886 char *name;
888 /* Extra "strings" can be created by binary data. */
889 if (get_strings(in, vec, ARRAY_SIZE(vec)) < ARRAY_SIZE(vec)) {
890 send_error(conn, EINVAL);
891 return;
892 }
894 offset = strlen(vec[0]) + 1;
895 datalen = in->used - offset;
897 name = canonicalize(conn, vec[0]);
898 node = get_node(conn, name, XS_PERM_WRITE);
899 if (!node) {
900 /* No permissions, invalid input? */
901 if (errno != ENOENT) {
902 send_error(conn, errno);
903 return;
904 }
905 node = create_node(conn, name, in->buffer + offset, datalen);
906 if (!node) {
907 send_error(conn, errno);
908 return;
909 }
910 } else {
911 node->data = in->buffer + offset;
912 node->datalen = datalen;
913 if (!write_node(conn, node)){
914 send_error(conn, errno);
915 return;
916 }
917 }
919 add_change_node(conn->transaction, name, false);
920 fire_watches(conn, name, false);
921 send_ack(conn, XS_WRITE);
922 }
924 static void do_mkdir(struct connection *conn, const char *name)
925 {
926 struct node *node;
928 name = canonicalize(conn, name);
929 node = get_node(conn, name, XS_PERM_WRITE);
931 /* If it already exists, fine. */
932 if (!node) {
933 /* No permissions? */
934 if (errno != ENOENT) {
935 send_error(conn, errno);
936 return;
937 }
938 node = create_node(conn, name, NULL, 0);
939 if (!node) {
940 send_error(conn, errno);
941 return;
942 }
943 add_change_node(conn->transaction, name, false);
944 fire_watches(conn, name, false);
945 }
946 send_ack(conn, XS_MKDIR);
947 }
949 static void delete_node(struct connection *conn, struct node *node)
950 {
951 unsigned int i;
953 /* Delete self, then delete children. If something goes wrong,
954 * consistency check will clean up this way. */
955 delete_node_single(conn, node);
957 /* Delete children, too. */
958 for (i = 0; i < node->childlen; i += strlen(node->children+i) + 1) {
959 struct node *child;
961 child = read_node(conn,
962 talloc_asprintf(node, "%s/%s", node->name,
963 node->children + i));
964 if (!child)
965 corrupt(conn, "No child '%s' found", child);
966 delete_node(conn, child);
967 }
968 }
970 /* Delete memory using memmove. */
971 static void memdel(void *mem, unsigned off, unsigned len, unsigned total)
972 {
973 memmove(mem + off, mem + off + len, total - off - len);
974 }
976 static bool delete_child(struct connection *conn,
977 struct node *node, const char *childname)
978 {
979 unsigned int i;
981 for (i = 0; i < node->childlen; i += strlen(node->children+i) + 1) {
982 if (streq(node->children+i, childname)) {
983 memdel(node->children, i, strlen(childname) + 1,
984 node->childlen);
985 node->childlen -= strlen(childname) + 1;
986 return write_node(conn, node);
987 }
988 }
989 corrupt(conn, "Can't find child '%s' in %s", childname, node->name);
990 }
993 static int _rm(struct connection *conn, struct node *node, const char *name)
994 {
995 /* Delete from parent first, then if something explodes fsck cleans. */
996 struct node *parent = read_node(conn, get_parent(name));
997 if (!parent) {
998 send_error(conn, EINVAL);
999 return 0;
1002 if (!delete_child(conn, parent, basename(name))) {
1003 send_error(conn, EINVAL);
1004 return 0;
1007 delete_node(conn, node);
1008 return 1;
1012 static void internal_rm(const char *name)
1014 char *tname = talloc_strdup(talloc_autofree_context(), name);
1015 struct node *node = read_node(NULL, tname);
1016 if (node)
1017 _rm(NULL, node, tname);
1021 static void do_rm(struct connection *conn, const char *name)
1023 struct node *node;
1025 name = canonicalize(conn, name);
1026 node = get_node(conn, name, XS_PERM_WRITE);
1027 if (!node) {
1028 /* Didn't exist already? Fine, if parent exists. */
1029 if (errno == ENOENT) {
1030 node = read_node(conn, get_parent(name));
1031 if (node) {
1032 send_ack(conn, XS_RM);
1033 return;
1035 /* Restore errno, just in case. */
1036 errno = ENOENT;
1038 send_error(conn, errno);
1039 return;
1042 if (streq(name, "/")) {
1043 send_error(conn, EINVAL);
1044 return;
1047 if (_rm(conn, node, name)) {
1048 add_change_node(conn->transaction, name, true);
1049 fire_watches(conn, name, true);
1050 send_ack(conn, XS_RM);
1055 static void do_get_perms(struct connection *conn, const char *name)
1057 struct node *node;
1058 char *strings;
1059 unsigned int len;
1061 name = canonicalize(conn, name);
1062 node = get_node(conn, name, XS_PERM_READ);
1063 if (!node) {
1064 send_error(conn, errno);
1065 return;
1068 strings = perms_to_strings(node, node->perms, node->num_perms, &len);
1069 if (!strings)
1070 send_error(conn, errno);
1071 else
1072 send_reply(conn, XS_GET_PERMS, strings, len);
1075 static void do_set_perms(struct connection *conn, struct buffered_data *in)
1077 unsigned int num;
1078 char *name, *permstr;
1079 struct node *node;
1081 num = xs_count_strings(in->buffer, in->used);
1082 if (num < 2) {
1083 send_error(conn, EINVAL);
1084 return;
1087 /* First arg is node name. */
1088 name = canonicalize(conn, in->buffer);
1089 permstr = in->buffer + strlen(in->buffer) + 1;
1090 num--;
1092 /* We must own node to do this (tools can do this too). */
1093 node = get_node(conn, name, XS_PERM_WRITE|XS_PERM_OWNER);
1094 if (!node) {
1095 send_error(conn, errno);
1096 return;
1099 node->perms = talloc_array(node, struct xs_permissions, num);
1100 node->num_perms = num;
1101 if (!xs_strings_to_perms(node->perms, num, permstr)) {
1102 send_error(conn, errno);
1103 return;
1105 if (!write_node(conn, node)) {
1106 send_error(conn, errno);
1107 return;
1110 add_change_node(conn->transaction, name, false);
1111 fire_watches(conn, name, false);
1112 send_ack(conn, XS_SET_PERMS);
1115 /* Process "in" for conn: "in" will vanish after this conversation, so
1116 * we can talloc off it for temporary variables. May free "conn".
1117 */
1118 static void process_message(struct connection *conn, struct buffered_data *in)
1120 struct transaction *trans;
1122 trans = transaction_lookup(conn, in->hdr.msg.tx_id);
1123 if (IS_ERR(trans)) {
1124 send_error(conn, -PTR_ERR(trans));
1125 return;
1128 assert(conn->transaction == NULL);
1129 conn->transaction = trans;
1131 switch (in->hdr.msg.type) {
1132 case XS_DIRECTORY:
1133 send_directory(conn, onearg(in));
1134 break;
1136 case XS_READ:
1137 do_read(conn, onearg(in));
1138 break;
1140 case XS_WRITE:
1141 do_write(conn, in);
1142 break;
1144 case XS_MKDIR:
1145 do_mkdir(conn, onearg(in));
1146 break;
1148 case XS_RM:
1149 do_rm(conn, onearg(in));
1150 break;
1152 case XS_GET_PERMS:
1153 do_get_perms(conn, onearg(in));
1154 break;
1156 case XS_SET_PERMS:
1157 do_set_perms(conn, in);
1158 break;
1160 case XS_DEBUG:
1161 if (streq(in->buffer, "print"))
1162 xprintf("debug: %s", in->buffer + get_string(in, 0));
1163 #ifdef TESTING
1164 /* For testing, we allow them to set id. */
1165 if (streq(in->buffer, "setid")) {
1166 conn->id = atoi(in->buffer + get_string(in, 0));
1167 send_ack(conn, XS_DEBUG);
1168 } else if (streq(in->buffer, "failtest")) {
1169 if (get_string(in, 0) < in->used)
1170 srandom(atoi(in->buffer + get_string(in, 0)));
1171 send_ack(conn, XS_DEBUG);
1172 failtest = true;
1174 #endif /* TESTING */
1175 break;
1177 case XS_WATCH:
1178 do_watch(conn, in);
1179 break;
1181 case XS_UNWATCH:
1182 do_unwatch(conn, in);
1183 break;
1185 case XS_TRANSACTION_START:
1186 do_transaction_start(conn, in);
1187 break;
1189 case XS_TRANSACTION_END:
1190 do_transaction_end(conn, onearg(in));
1191 break;
1193 case XS_INTRODUCE:
1194 do_introduce(conn, in);
1195 break;
1197 case XS_IS_DOMAIN_INTRODUCED:
1198 do_is_domain_introduced(conn, onearg(in));
1199 break;
1201 case XS_RELEASE:
1202 do_release(conn, onearg(in));
1203 break;
1205 case XS_GET_DOMAIN_PATH:
1206 do_get_domain_path(conn, onearg(in));
1207 break;
1209 default:
1210 eprintf("Client unknown operation %i", in->hdr.msg.type);
1211 send_error(conn, ENOSYS);
1212 break;
1215 conn->transaction = NULL;
1218 static int out_of_mem(void *data)
1220 longjmp(*(jmp_buf *)data, 1);
1223 static void consider_message(struct connection *conn)
1225 jmp_buf talloc_fail;
1227 if (verbose)
1228 xprintf("Got message %s len %i from %p\n",
1229 sockmsg_string(conn->in->hdr.msg.type),
1230 conn->in->hdr.msg.len, conn);
1232 /* For simplicity, we kill the connection on OOM. */
1233 talloc_set_fail_handler(out_of_mem, &talloc_fail);
1234 if (setjmp(talloc_fail)) {
1235 talloc_free(conn);
1236 goto end;
1239 process_message(conn, conn->in);
1241 talloc_free(conn->in);
1242 conn->in = new_buffer(conn);
1244 end:
1245 talloc_set_fail_handler(NULL, NULL);
1246 if (talloc_total_blocks(NULL)
1247 != talloc_total_blocks(talloc_autofree_context()) + 1) {
1248 talloc_report_full(NULL, stderr);
1249 abort();
1253 /* Errors in reading or allocating here mean we get out of sync, so we
1254 * drop the whole client connection. */
1255 static void handle_input(struct connection *conn)
1257 int bytes;
1258 struct buffered_data *in = conn->in;
1260 /* Not finished header yet? */
1261 if (in->inhdr) {
1262 bytes = conn->read(conn, in->hdr.raw + in->used,
1263 sizeof(in->hdr) - in->used);
1264 if (bytes <= 0)
1265 goto bad_client;
1266 in->used += bytes;
1267 if (in->used != sizeof(in->hdr))
1268 return;
1270 if (in->hdr.msg.len > PATH_MAX) {
1271 #ifndef TESTING
1272 syslog(LOG_DAEMON, "Client tried to feed us %i",
1273 in->hdr.msg.len);
1274 #endif
1275 goto bad_client;
1278 in->buffer = talloc_array(in, char, in->hdr.msg.len);
1279 if (!in->buffer)
1280 goto bad_client;
1281 in->used = 0;
1282 in->inhdr = false;
1283 return;
1286 bytes = conn->read(conn, in->buffer + in->used,
1287 in->hdr.msg.len - in->used);
1288 if (bytes < 0)
1289 goto bad_client;
1291 in->used += bytes;
1292 if (in->used != in->hdr.msg.len)
1293 return;
1295 trace_io(conn, "IN ", in);
1296 consider_message(conn);
1297 return;
1299 bad_client:
1300 /* Kill it. */
1301 talloc_free(conn);
1304 static void handle_output(struct connection *conn)
1306 if (!write_messages(conn))
1307 talloc_free(conn);
1310 struct connection *new_connection(connwritefn_t *write, connreadfn_t *read)
1312 struct connection *new;
1314 new = talloc(talloc_autofree_context(), struct connection);
1315 if (!new)
1316 return NULL;
1318 memset(new, 0, sizeof(*new));
1319 new->fd = -1;
1320 new->write = write;
1321 new->read = read;
1322 new->can_write = true;
1323 INIT_LIST_HEAD(&new->out_list);
1324 INIT_LIST_HEAD(&new->watches);
1325 INIT_LIST_HEAD(&new->transaction_list);
1327 new->in = new_buffer(new);
1328 if (new->in == NULL) {
1329 talloc_free(new);
1330 return NULL;
1333 list_add_tail(&new->list, &connections);
1334 talloc_set_destructor(new, destroy_conn);
1335 trace_create(new, "connection");
1336 return new;
1339 static int writefd(struct connection *conn, const void *data, unsigned int len)
1341 return write(conn->fd, data, len);
1344 static int readfd(struct connection *conn, void *data, unsigned int len)
1346 return read(conn->fd, data, len);
1349 static void accept_connection(int sock, bool canwrite)
1351 int fd;
1352 struct connection *conn;
1354 fd = accept(sock, NULL, NULL);
1355 if (fd < 0)
1356 return;
1358 conn = new_connection(writefd, readfd);
1359 if (conn) {
1360 conn->fd = fd;
1361 conn->can_write = canwrite;
1362 } else
1363 close(fd);
1366 #ifdef TESTING
1367 /* Valgrind can check our writes better if we don't use mmap */
1368 #define TDB_FLAGS TDB_NOMMAP
1369 /* Useful for running under debugger. */
1370 void dump_connection(void)
1372 struct connection *i;
1374 list_for_each_entry(i, &connections, list) {
1375 printf("Connection %p:\n", i);
1376 printf(" state = %s\n",
1377 list_empty(&i->out_list) ? "OK" : "BUSY");
1378 if (i->id)
1379 printf(" id = %i\n", i->id);
1380 if (!i->in->inhdr || i->in->used)
1381 printf(" got %i bytes of %s\n",
1382 i->in->used, i->in->inhdr ? "header" : "data");
1383 #if 0
1384 if (i->out)
1385 printf(" sending message %s (%s) out\n",
1386 sockmsg_string(i->out->hdr.msg.type),
1387 i->out->buffer);
1388 if (i->transaction)
1389 dump_transaction(i);
1390 if (i->domain)
1391 dump_domain(i);
1392 #endif
1393 dump_watches(i);
1396 #else
1397 #define TDB_FLAGS 0
1398 #endif
1400 /* We create initial nodes manually. */
1401 static void manual_node(const char *name, const char *child)
1403 struct node *node;
1404 struct xs_permissions perms = { .id = 0, .perms = XS_PERM_NONE };
1406 node = talloc(NULL, struct node);
1407 node->name = name;
1408 node->perms = &perms;
1409 node->num_perms = 1;
1410 node->data = NULL;
1411 node->datalen = 0;
1412 node->children = (char *)child;
1413 if (child)
1414 node->childlen = strlen(child) + 1;
1415 else
1416 node->childlen = 0;
1418 if (!write_node(NULL, node))
1419 barf_perror("Could not create initial node %s", name);
1420 talloc_free(node);
1423 static void setup_structure(void)
1425 char *tdbname;
1426 tdbname = talloc_strdup(talloc_autofree_context(), xs_daemon_tdb());
1427 tdb_ctx = tdb_open(tdbname, 0, TDB_FLAGS, O_RDWR, 0);
1429 if (tdb_ctx) {
1430 /* XXX When we make xenstored able to restart, this will have
1431 to become cleverer, checking for existing domains and not
1432 removing the corresponding entries, but for now xenstored
1433 cannot be restarted without losing all the registered
1434 watches, which breaks all the backend drivers anyway. We
1435 can therefore get away with just clearing /local and
1436 expecting Xend to put the appropriate entries back in.
1438 When this change is made it is important to note that
1439 dom0's entries must be cleaned up on reboot _before_ this
1440 daemon starts, otherwise the backend drivers and dom0's
1441 balloon driver will pick up stale entries. In the case of
1442 the balloon driver, this can be fatal.
1443 */
1444 char *tlocal = talloc_strdup(talloc_autofree_context(),
1445 "/local");
1446 internal_rm("/local");
1447 create_node(NULL, tlocal, NULL, 0);
1449 else {
1450 tdb_ctx = tdb_open(tdbname, 7919, TDB_FLAGS, O_RDWR|O_CREAT,
1451 0640);
1452 if (!tdb_ctx)
1453 barf_perror("Could not create tdb file %s", tdbname);
1455 manual_node("/", "tool");
1456 manual_node("/tool", "xenstored");
1457 manual_node("/tool/xenstored", NULL);
1460 /* FIXME: Fsck */
1463 static void write_pidfile(const char *pidfile)
1465 char buf[100];
1466 int len;
1467 int fd;
1469 fd = open(pidfile, O_RDWR | O_CREAT, 0600);
1470 if (fd == -1)
1471 barf_perror("Opening pid file %s", pidfile);
1473 /* We exit silently if daemon already running. */
1474 if (lockf(fd, F_TLOCK, 0) == -1)
1475 exit(0);
1477 len = sprintf(buf, "%d\n", getpid());
1478 write(fd, buf, len);
1481 /* Stevens. */
1482 static void daemonize(void)
1484 pid_t pid;
1486 /* Separate from our parent via fork, so init inherits us. */
1487 if ((pid = fork()) < 0)
1488 barf_perror("Failed to fork daemon");
1489 if (pid != 0)
1490 exit(0);
1492 /* Session leader so ^C doesn't whack us. */
1493 setsid();
1495 /* Let session leader exit so child cannot regain CTTY */
1496 if ((pid = fork()) < 0)
1497 barf_perror("Failed to fork daemon");
1498 if (pid != 0)
1499 exit(0);
1501 #ifndef TESTING /* Relative paths for socket names */
1502 /* Move off any mount points we might be in. */
1503 chdir("/");
1504 #endif
1505 /* Discard our parent's old-fashioned umask prejudices. */
1506 umask(0);
1510 static void usage(void)
1512 fprintf(stderr,
1513 "Usage:\n"
1514 "\n"
1515 " xenstored <options>\n"
1516 "\n"
1517 "where options may include:\n"
1518 "\n"
1519 " --no-domain-init to state that xenstored should not initialise dom0,\n"
1520 " --pid-file <file> giving a file for the daemon's pid to be written,\n"
1521 " --help to output this message,\n"
1522 " --no-fork to request that the daemon does not fork,\n"
1523 " --output-pid to request that the pid of the daemon is output,\n"
1524 " --trace-file <file> giving the file for logging, and\n"
1525 " --verbose to request verbose execution.\n");
1529 static struct option options[] = {
1530 { "no-domain-init", 0, NULL, 'D' },
1531 { "pid-file", 1, NULL, 'F' },
1532 { "help", 0, NULL, 'H' },
1533 { "no-fork", 0, NULL, 'N' },
1534 { "output-pid", 0, NULL, 'P' },
1535 { "trace-file", 1, NULL, 'T' },
1536 { "verbose", 0, NULL, 'V' },
1537 { NULL, 0, NULL, 0 } };
1539 extern void dump_conn(struct connection *conn);
1541 int main(int argc, char *argv[])
1543 int opt, *sock, *ro_sock, max;
1544 struct sockaddr_un addr;
1545 fd_set inset, outset;
1546 bool dofork = true;
1547 bool outputpid = false;
1548 bool no_domain_init = false;
1549 const char *pidfile = NULL;
1551 while ((opt = getopt_long(argc, argv, "DF:HNPT:V", options,
1552 NULL)) != -1) {
1553 switch (opt) {
1554 case 'D':
1555 no_domain_init = true;
1556 break;
1557 case 'F':
1558 pidfile = optarg;
1559 break;
1560 case 'H':
1561 usage();
1562 return 0;
1563 case 'N':
1564 dofork = false;
1565 break;
1566 case 'P':
1567 outputpid = true;
1568 break;
1569 case 'T':
1570 tracefile = optarg;
1571 break;
1572 case 'V':
1573 verbose = true;
1574 break;
1577 if (optind != argc)
1578 barf("%s: No arguments desired", argv[0]);
1580 reopen_log();
1582 if (dofork) {
1583 openlog("xenstored", 0, LOG_DAEMON);
1584 daemonize();
1586 if (pidfile)
1587 write_pidfile(pidfile);
1589 talloc_enable_leak_report_full();
1591 /* Create sockets for them to listen to. */
1592 sock = talloc(talloc_autofree_context(), int);
1593 *sock = socket(PF_UNIX, SOCK_STREAM, 0);
1594 if (*sock < 0)
1595 barf_perror("Could not create socket");
1596 ro_sock = talloc(talloc_autofree_context(), int);
1597 *ro_sock = socket(PF_UNIX, SOCK_STREAM, 0);
1598 if (*ro_sock < 0)
1599 barf_perror("Could not create socket");
1600 talloc_set_destructor(sock, destroy_fd);
1601 talloc_set_destructor(ro_sock, destroy_fd);
1603 /* Don't kill us with SIGPIPE. */
1604 signal(SIGPIPE, SIG_IGN);
1606 /* FIXME: Be more sophisticated, don't mug running daemon. */
1607 unlink(xs_daemon_socket());
1608 unlink(xs_daemon_socket_ro());
1610 addr.sun_family = AF_UNIX;
1611 strcpy(addr.sun_path, xs_daemon_socket());
1612 if (bind(*sock, (struct sockaddr *)&addr, sizeof(addr)) != 0)
1613 barf_perror("Could not bind socket to %s", xs_daemon_socket());
1614 strcpy(addr.sun_path, xs_daemon_socket_ro());
1615 if (bind(*ro_sock, (struct sockaddr *)&addr, sizeof(addr)) != 0)
1616 barf_perror("Could not bind socket to %s",
1617 xs_daemon_socket_ro());
1618 if (chmod(xs_daemon_socket(), 0600) != 0
1619 || chmod(xs_daemon_socket_ro(), 0660) != 0)
1620 barf_perror("Could not chmod sockets");
1622 if (listen(*sock, 1) != 0
1623 || listen(*ro_sock, 1) != 0)
1624 barf_perror("Could not listen on sockets");
1626 if (pipe(reopen_log_pipe)) {
1627 barf_perror("pipe");
1630 /* Setup the database */
1631 setup_structure();
1633 /* Listen to hypervisor. */
1634 if (!no_domain_init)
1635 domain_init();
1637 /* Restore existing connections. */
1638 restore_existing_connections();
1640 if (outputpid) {
1641 printf("%i\n", getpid());
1642 fflush(stdout);
1645 /* close stdin/stdout now we're ready to accept connections */
1646 if (dofork) {
1647 close(STDIN_FILENO);
1648 close(STDOUT_FILENO);
1649 close(STDERR_FILENO);
1652 signal(SIGHUP, trigger_reopen_log);
1654 #ifdef TESTING
1655 signal(SIGUSR1, stop_failtest);
1656 #endif
1658 /* Get ready to listen to the tools. */
1659 max = initialize_set(&inset, &outset, *sock, *ro_sock);
1661 /* Main loop. */
1662 /* FIXME: Rewrite so noone can starve. */
1663 for (;;) {
1664 struct connection *i;
1666 if (select(max+1, &inset, &outset, NULL, NULL) < 0) {
1667 if (errno == EINTR)
1668 continue;
1669 barf_perror("Select failed");
1672 if (FD_ISSET(reopen_log_pipe[0], &inset)) {
1673 char c;
1674 read(reopen_log_pipe[0], &c, 1);
1675 reopen_log();
1678 if (FD_ISSET(*sock, &inset))
1679 accept_connection(*sock, true);
1681 if (FD_ISSET(*ro_sock, &inset))
1682 accept_connection(*ro_sock, false);
1684 if (FD_ISSET(eventchn_fd, &inset))
1685 handle_event();
1687 list_for_each_entry(i, &connections, list) {
1688 if (i->domain)
1689 continue;
1691 /* Operations can delete themselves or others
1692 * (xs_release): list is not safe after input,
1693 * so break. */
1694 if (FD_ISSET(i->fd, &inset)) {
1695 handle_input(i);
1696 break;
1698 if (FD_ISSET(i->fd, &outset)) {
1699 handle_output(i);
1700 break;
1704 /* Handle all possible I/O for domain connections. */
1705 more:
1706 list_for_each_entry(i, &connections, list) {
1707 if (!i->domain)
1708 continue;
1710 if (domain_can_read(i)) {
1711 handle_input(i);
1712 goto more;
1715 if (domain_can_write(i) && !list_empty(&i->out_list)) {
1716 handle_output(i);
1717 goto more;
1721 max = initialize_set(&inset, &outset, *sock, *ro_sock);
1725 /*
1726 * Local variables:
1727 * c-file-style: "linux"
1728 * indent-tabs-mode: t
1729 * c-indent-level: 8
1730 * c-basic-offset: 8
1731 * tab-width: 8
1732 * End:
1733 */