ia64/xen-unstable

view tools/ioemu/xenstore.c @ 17042:a905c582a406

Add stubdomain support. See stubdom/README for usage details.

- Move PAGE_SIZE and STACK_SIZE into __PAGE_SIZE and __STACK_SIZE in
arch_limits.h so as to permit getting them from there without
pulling all the internal Mini-OS defines.
- Setup a xen-elf cross-compilation environment in stubdom/cross-root
- Add a POSIX layer on top of Mini-OS by linking against the newlib C
library and lwIP, and implementing the Unixish part in mini-os/lib/sys.c
- Cross-compile zlib and libpci too.
- Add an xs.h-compatible layer on top of Mini-OS' xenbus.
- Cross-compile libxc with an additional xc_minios.c and a few things
disabled.
- Cross-compile ioemu with an additional block-vbd, but without sound,
tpm and other details. A few hacks are needed:
- Align ide and scsi buffers at least on sector size to permit
direct transmission to the block backend. While we are at it, just
page-align it to possibly save a segment. Also, limit the scsi
buffer size because of limitations of the block paravirtualization
protocol.
- Allocate big tables dynamically rather that letting them go to
bss: when Mini-OS gets installed in memory, bss is not lazily
allocated, and doing so during Mini-OS is unnecessarily trick while
we can simply use malloc.
- Had to change the Mini-OS compilation somehow, so as to export
Mini-OS compilation flags to the Makefiles of libxc and ioemu.

Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Feb 12 14:35:39 2008 +0000 (2008-02-12)
parents 90844659c458
children c6eeb71a85cf
line source
1 /*
2 * This file is subject to the terms and conditions of the GNU General
3 * Public License. See the file "COPYING" in the main directory of
4 * this archive for more details.
5 *
6 * Copyright (C) 2006 Christian Limpach
7 * Copyright (C) 2006 XenSource Ltd.
8 *
9 */
11 #include "vl.h"
12 #include "block_int.h"
13 #include <unistd.h>
14 #ifndef CONFIG_STUBDOM
15 #include <sys/ipc.h>
16 #include <sys/shm.h>
17 #endif
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
22 struct xs_handle *xsh = NULL;
23 static char *media_filename[MAX_DISKS + MAX_SCSI_DISKS];
24 static QEMUTimer *insert_timer = NULL;
26 #define UWAIT_MAX (30*1000000) /* thirty seconds */
27 #define UWAIT (100000) /* 1/10th second */
29 static int pasprintf(char **buf, const char *fmt, ...)
30 {
31 va_list ap;
32 int ret = 0;
34 if (*buf)
35 free(*buf);
36 va_start(ap, fmt);
37 if (vasprintf(buf, fmt, ap) == -1) {
38 buf = NULL;
39 ret = -1;
40 }
41 va_end(ap);
42 return ret;
43 }
45 static void insert_media(void *opaque)
46 {
47 int i;
49 for (i = 0; i < MAX_DISKS + MAX_SCSI_DISKS; i++) {
50 if (media_filename[i] && bs_table[i]) {
51 do_change(bs_table[i]->device_name, media_filename[i]);
52 free(media_filename[i]);
53 media_filename[i] = NULL;
54 }
55 }
56 }
58 void xenstore_check_new_media_present(int timeout)
59 {
61 if (insert_timer == NULL)
62 insert_timer = qemu_new_timer(rt_clock, insert_media, NULL);
63 qemu_mod_timer(insert_timer, qemu_get_clock(rt_clock) + timeout);
64 }
66 static void waitForDevice(char *fn)
67 {
68 struct stat sbuf;
69 int status;
70 int uwait = UWAIT_MAX;
72 do {
73 status = stat(fn, &sbuf);
74 if (!status) break;
75 usleep(UWAIT);
76 uwait -= UWAIT;
77 } while (uwait > 0);
79 return;
80 }
82 void xenstore_parse_domain_config(int domid)
83 {
84 char **e = NULL;
85 char *buf = NULL, *path;
86 char *fpath = NULL, *bpath = NULL,
87 *dev = NULL, *params = NULL, *type = NULL, *drv = NULL;
88 int i, is_scsi, is_hdN = 0;
89 unsigned int len, num, hd_index;
90 BlockDriverState *bs;
92 for(i = 0; i < MAX_DISKS + MAX_SCSI_DISKS; i++)
93 media_filename[i] = NULL;
95 xsh = xs_daemon_open();
96 if (xsh == NULL) {
97 fprintf(logfile, "Could not contact xenstore for domain config\n");
98 return;
99 }
101 path = xs_get_domain_path(xsh, domid);
102 if (path == NULL) {
103 fprintf(logfile, "xs_get_domain_path() error\n");
104 goto out;
105 }
107 if (pasprintf(&buf, "%s/device/vbd", path) == -1)
108 goto out;
110 e = xs_directory(xsh, XBT_NULL, buf, &num);
111 if (e == NULL)
112 goto out;
114 for (i = 0; i < num; i++) {
115 /* read the backend path */
116 if (pasprintf(&buf, "%s/device/vbd/%s/backend", path, e[i]) == -1)
117 continue;
118 free(bpath);
119 bpath = xs_read(xsh, XBT_NULL, buf, &len);
120 if (bpath == NULL)
121 continue;
122 /* read the name of the device */
123 if (pasprintf(&buf, "%s/dev", bpath) == -1)
124 continue;
125 free(dev);
126 dev = xs_read(xsh, XBT_NULL, buf, &len);
127 if (dev == NULL)
128 continue;
129 if (!strncmp(dev, "hd", 2)) {
130 is_hdN = 1;
131 break;
132 }
133 }
135 for (i = 0; i < num; i++) {
136 /* read the backend path */
137 if (pasprintf(&buf, "%s/device/vbd/%s/backend", path, e[i]) == -1)
138 continue;
139 free(bpath);
140 bpath = xs_read(xsh, XBT_NULL, buf, &len);
141 if (bpath == NULL)
142 continue;
143 /* read the name of the device */
144 if (pasprintf(&buf, "%s/dev", bpath) == -1)
145 continue;
146 free(dev);
147 dev = xs_read(xsh, XBT_NULL, buf, &len);
148 if (dev == NULL)
149 continue;
150 /* Change xvdN to look like hdN */
151 if (!is_hdN && !strncmp(dev, "xvd", 3)) {
152 fprintf(logfile, "Change xvd%c to look like hd%c\n",
153 dev[3], dev[3]);
154 memmove(dev, dev+1, strlen(dev));
155 dev[0] = 'h';
156 dev[1] = 'd';
157 }
158 is_scsi = !strncmp(dev, "sd", 2);
159 if ((strncmp(dev, "hd", 2) && !is_scsi) || strlen(dev) != 3 )
160 continue;
161 hd_index = dev[2] - 'a';
162 if (hd_index >= (is_scsi ? MAX_SCSI_DISKS : MAX_DISKS))
163 continue;
164 /* read the type of the device */
165 if (pasprintf(&buf, "%s/device/vbd/%s/device-type", path, e[i]) == -1)
166 continue;
167 free(type);
168 type = xs_read(xsh, XBT_NULL, buf, &len);
169 if (pasprintf(&buf, "%s/params", bpath) == -1)
170 continue;
171 free(params);
172 params = xs_read(xsh, XBT_NULL, buf, &len);
173 if (params == NULL)
174 continue;
175 /* read the name of the device */
176 if (pasprintf(&buf, "%s/type", bpath) == -1)
177 continue;
178 free(drv);
179 drv = xs_read(xsh, XBT_NULL, buf, &len);
180 if (drv == NULL)
181 continue;
182 /* Strip off blktap sub-type prefix aio: - QEMU can autodetect this */
183 if (!strcmp(drv, "tap") && params[0]) {
184 char *offset = strchr(params, ':');
185 if (!offset)
186 continue ;
187 memmove(params, offset+1, strlen(offset+1)+1 );
188 fprintf(logfile, "Strip off blktap sub-type prefix to %s\n", params);
189 }
191 /*
192 * check if device has a phantom vbd; the phantom is hooked
193 * to the frontend device (for ease of cleanup), so lookup
194 * the frontend device, and see if there is a phantom_vbd
195 * if there is, we will use resolution as the filename
196 */
197 if (pasprintf(&buf, "%s/device/vbd/%s/phantom_vbd", path, e[i]) == -1)
198 continue;
199 free(fpath);
200 fpath = xs_read(xsh, XBT_NULL, buf, &len);
201 if (fpath) {
202 if (pasprintf(&buf, "%s/dev", fpath) == -1)
203 continue;
204 free(params);
205 params = xs_read(xsh, XBT_NULL, buf , &len);
206 if (params) {
207 /*
208 * wait for device, on timeout silently fail because we will
209 * fail to open below
210 */
211 waitForDevice(params);
212 }
213 }
215 bs = bs_table[hd_index + (is_scsi ? MAX_DISKS : 0)] = bdrv_new(dev);
216 /* check if it is a cdrom */
217 if (type && !strcmp(type, "cdrom")) {
218 bdrv_set_type_hint(bs, BDRV_TYPE_CDROM);
219 if (pasprintf(&buf, "%s/params", bpath) != -1)
220 xs_watch(xsh, buf, dev);
221 }
223 /* open device now if media present */
224 #ifdef CONFIG_STUBDOM
225 if (pasprintf(&buf, "%s/device/vbd/%s", path, e[i]) == -1)
226 continue;
227 if (bdrv_open2(bs, buf, 0 /* snapshot */, &bdrv_vbd) == 0) {
228 pstrcpy(bs->filename, sizeof(bs->filename), params);
229 continue;
230 }
231 #endif
233 if (params[0]) {
234 if (bdrv_open(bs, params, 0 /* snapshot */) < 0)
235 fprintf(stderr, "qemu: could not open vbd '%s' or hard disk image '%s'\n", buf, params);
236 }
237 }
239 /* Set a watch for log-dirty requests from the migration tools */
240 if (pasprintf(&buf, "/local/domain/0/device-model/%u/logdirty/next-active",
241 domid) != -1) {
242 xs_watch(xsh, buf, "logdirty");
243 fprintf(logfile, "Watching %s\n", buf);
244 }
246 /* Set a watch for suspend requests from the migration tools */
247 if (pasprintf(&buf,
248 "/local/domain/0/device-model/%u/command", domid) != -1) {
249 xs_watch(xsh, buf, "dm-command");
250 fprintf(logfile, "Watching %s\n", buf);
251 }
253 out:
254 free(type);
255 free(params);
256 free(dev);
257 free(bpath);
258 free(buf);
259 free(path);
260 free(e);
261 free(drv);
262 return;
263 }
265 int xenstore_fd(void)
266 {
267 if (xsh)
268 return xs_fileno(xsh);
269 return -1;
270 }
272 unsigned long *logdirty_bitmap = NULL;
273 unsigned long logdirty_bitmap_size;
274 extern int vga_ram_size, bios_size;
276 void xenstore_process_logdirty_event(void)
277 {
278 #ifdef CONFIG_STUBDOM
279 /* XXX we just can't use shm. */
280 return;
281 #else
282 char *act;
283 static char *active_path = NULL;
284 static char *next_active_path = NULL;
285 static char *seg = NULL;
286 unsigned int len;
287 int i;
289 if (!seg) {
290 char *path = NULL, *key_ascii, key_terminated[17] = {0,};
291 key_t key;
292 int shmid;
294 /* Find and map the shared memory segment for log-dirty bitmaps */
295 if (pasprintf(&path,
296 "/local/domain/0/device-model/%u/logdirty/key",
297 domid) == -1) {
298 fprintf(logfile, "Log-dirty: out of memory\n");
299 exit(1);
300 }
302 key_ascii = xs_read(xsh, XBT_NULL, path, &len);
303 free(path);
305 if (!key_ascii)
306 /* No key yet: wait for the next watch */
307 return;
309 strncpy(key_terminated, key_ascii, 16);
310 free(key_ascii);
311 key = (key_t) strtoull(key_terminated, NULL, 16);
313 /* Figure out how bit the log-dirty bitmaps are */
314 logdirty_bitmap_size = xc_memory_op(xc_handle,
315 XENMEM_maximum_gpfn, &domid) + 1;
316 logdirty_bitmap_size = ((logdirty_bitmap_size + HOST_LONG_BITS - 1)
317 / HOST_LONG_BITS); /* longs */
318 logdirty_bitmap_size *= sizeof (unsigned long); /* bytes */
320 /* Map the shared-memory segment */
321 fprintf(logfile, "%s: key=%16.16llx size=%lu\n", __FUNCTION__,
322 (unsigned long long)key, logdirty_bitmap_size);
323 shmid = shmget(key, 2 * logdirty_bitmap_size, S_IRUSR|S_IWUSR);
324 if (shmid == -1) {
325 fprintf(logfile, "Log-dirty: shmget failed: segment %16.16llx "
326 "(%s)\n", (unsigned long long)key, strerror(errno));
327 exit(1);
328 }
330 seg = shmat(shmid, NULL, 0);
331 if (seg == (void *)-1) {
332 fprintf(logfile, "Log-dirty: shmat failed: segment %16.16llx "
333 "(%s)\n", (unsigned long long)key, strerror(errno));
334 exit(1);
335 }
337 fprintf(logfile, "Log-dirty: mapped segment at %p\n", seg);
339 /* Double-check that the bitmaps are the size we expect */
340 if (logdirty_bitmap_size != *(uint32_t *)seg) {
341 fprintf(logfile, "Log-dirty: got %u, calc %lu\n",
342 *(uint32_t *)seg, logdirty_bitmap_size);
343 /* Stale key: wait for next watch */
344 shmdt(seg);
345 seg = NULL;
346 return;
347 }
349 /* Remember the paths for the next-active and active entries */
350 if (pasprintf(&active_path,
351 "/local/domain/0/device-model/%u/logdirty/active",
352 domid) == -1) {
353 fprintf(logfile, "Log-dirty: out of memory\n");
354 exit(1);
355 }
356 if (pasprintf(&next_active_path,
357 "/local/domain/0/device-model/%u/logdirty/next-active",
358 domid) == -1) {
359 fprintf(logfile, "Log-dirty: out of memory\n");
360 exit(1);
361 }
362 }
364 fprintf(logfile, "Triggered log-dirty buffer switch\n");
366 /* Read the required active buffer from the store */
367 act = xs_read(xsh, XBT_NULL, next_active_path, &len);
368 if (!act) {
369 fprintf(logfile, "Log-dirty: can't read next-active\n");
370 exit(1);
371 }
373 /* Switch buffers */
374 i = act[0] - '0';
375 if (i != 0 && i != 1) {
376 fprintf(logfile, "Log-dirty: bad next-active entry: %s\n", act);
377 exit(1);
378 }
379 logdirty_bitmap = (unsigned long *)(seg + i * logdirty_bitmap_size);
381 /* Ack that we've switched */
382 xs_write(xsh, XBT_NULL, active_path, act, len);
383 free(act);
384 #endif
385 }
388 /* Accept state change commands from the control tools */
389 static void xenstore_process_dm_command_event(void)
390 {
391 char *path = NULL, *command = NULL;
392 unsigned int len;
393 extern int suspend_requested;
395 if (pasprintf(&path,
396 "/local/domain/0/device-model/%u/command", domid) == -1) {
397 fprintf(logfile, "out of memory reading dm command\n");
398 goto out;
399 }
400 command = xs_read(xsh, XBT_NULL, path, &len);
401 if (!command)
402 goto out;
404 if (!strncmp(command, "save", len)) {
405 fprintf(logfile, "dm-command: pause and save state\n");
406 suspend_requested = 1;
407 } else if (!strncmp(command, "continue", len)) {
408 fprintf(logfile, "dm-command: continue after state save\n");
409 suspend_requested = 0;
410 } else {
411 fprintf(logfile, "dm-command: unknown command\"%*s\"\n", len, command);
412 }
414 out:
415 free(path);
416 free(command);
417 }
419 void xenstore_record_dm_state(char *state)
420 {
421 char *path = NULL;
423 if (pasprintf(&path,
424 "/local/domain/0/device-model/%u/state", domid) == -1) {
425 fprintf(logfile, "out of memory recording dm state\n");
426 goto out;
427 }
428 if (!xs_write(xsh, XBT_NULL, path, state, strlen(state)))
429 fprintf(logfile, "error recording dm state\n");
431 out:
432 free(path);
433 }
435 void xenstore_process_event(void *opaque)
436 {
437 char **vec, *offset, *bpath = NULL, *buf = NULL, *drv = NULL, *image = NULL;
438 unsigned int len, num, hd_index;
440 vec = xs_read_watch(xsh, &num);
441 if (!vec)
442 return;
444 if (!strcmp(vec[XS_WATCH_TOKEN], "logdirty")) {
445 xenstore_process_logdirty_event();
446 goto out;
447 }
449 if (!strcmp(vec[XS_WATCH_TOKEN], "dm-command")) {
450 xenstore_process_dm_command_event();
451 goto out;
452 }
454 if (strncmp(vec[XS_WATCH_TOKEN], "hd", 2) ||
455 strlen(vec[XS_WATCH_TOKEN]) != 3)
456 goto out;
457 hd_index = vec[XS_WATCH_TOKEN][2] - 'a';
458 image = xs_read(xsh, XBT_NULL, vec[XS_WATCH_PATH], &len);
459 if (image == NULL)
460 goto out; /* gone */
462 /* Strip off blktap sub-type prefix */
463 bpath = strdup(vec[XS_WATCH_PATH]);
464 if (bpath == NULL)
465 goto out;
466 if ((offset = strrchr(bpath, '/')) != NULL)
467 *offset = '\0';
468 if (pasprintf(&buf, "%s/type", bpath) == -1)
469 goto out;
470 drv = xs_read(xsh, XBT_NULL, buf, &len);
471 if (drv && !strcmp(drv, "tap") && ((offset = strchr(image, ':')) != NULL))
472 memmove(image, offset+1, strlen(offset+1)+1);
474 if (!strcmp(image, bs_table[hd_index]->filename))
475 goto out; /* identical */
477 do_eject(0, vec[XS_WATCH_TOKEN]);
478 bs_table[hd_index]->filename[0] = 0;
479 if (media_filename[hd_index]) {
480 free(media_filename[hd_index]);
481 media_filename[hd_index] = NULL;
482 }
484 if (image[0]) {
485 media_filename[hd_index] = strdup(image);
486 xenstore_check_new_media_present(5000);
487 }
489 out:
490 free(drv);
491 free(buf);
492 free(bpath);
493 free(image);
494 free(vec);
495 }
497 void xenstore_write_vncport(int display)
498 {
499 char *buf = NULL, *path;
500 char *portstr = NULL;
502 if (xsh == NULL)
503 return;
505 path = xs_get_domain_path(xsh, domid);
506 if (path == NULL) {
507 fprintf(logfile, "xs_get_domain_path() error\n");
508 goto out;
509 }
511 if (pasprintf(&buf, "%s/console/vnc-port", path) == -1)
512 goto out;
514 if (pasprintf(&portstr, "%d", display) == -1)
515 goto out;
517 if (xs_write(xsh, XBT_NULL, buf, portstr, strlen(portstr)) == 0)
518 fprintf(logfile, "xs_write() vncport failed\n");
520 out:
521 free(portstr);
522 free(buf);
523 }
525 void xenstore_read_vncpasswd(int domid, char *pwbuf, size_t pwbuflen)
526 {
527 char *buf = NULL, *path, *uuid = NULL, *passwd = NULL;
528 unsigned int i, len;
530 pwbuf[0] = '\0';
532 if (xsh == NULL)
533 return;
535 path = xs_get_domain_path(xsh, domid);
536 if (path == NULL) {
537 fprintf(logfile, "xs_get_domain_path() error. domid %d.\n", domid);
538 return;
539 }
541 pasprintf(&buf, "%s/vm", path);
542 free(path);
543 uuid = xs_read(xsh, XBT_NULL, buf, &len);
544 if (uuid == NULL) {
545 fprintf(logfile, "xs_read(): uuid get error. %s.\n", buf);
546 free(buf);
547 return;
548 }
550 pasprintf(&buf, "%s/vncpasswd", uuid);
551 free(uuid);
552 passwd = xs_read(xsh, XBT_NULL, buf, &len);
553 if (passwd == NULL) {
554 fprintf(logfile, "xs_read(): vncpasswd get error. %s.\n", buf);
555 free(buf);
556 return;
557 }
559 if (len >= pwbuflen)
560 {
561 fprintf(logfile, "xenstore_read_vncpasswd(): truncated password to avoid buffer overflow\n");
562 len = pwbuflen - 1;
563 }
565 for (i=0; i<len; i++)
566 pwbuf[i] = passwd[i];
567 pwbuf[len] = '\0';
568 passwd[0] = '\0';
569 if (xs_write(xsh, XBT_NULL, buf, passwd, 1) == 0)
570 fprintf(logfile, "xs_write() vncpasswd failed.\n");
572 free(passwd);
573 free(buf);
574 }
577 /*
578 * get all device instances of a certain type
579 */
580 char **xenstore_domain_get_devices(struct xs_handle *handle,
581 const char *devtype, unsigned int *num)
582 {
583 char *path;
584 char *buf = NULL;
585 char **e = NULL;
587 path = xs_get_domain_path(handle, domid);
588 if (path == NULL)
589 goto out;
591 if (pasprintf(&buf, "%s/device/%s", path,devtype) == -1)
592 goto out;
594 e = xs_directory(handle, XBT_NULL, buf, num);
596 out:
597 free(path);
598 free(buf);
599 return e;
600 }
602 /*
603 * Check whether a domain has devices of the given type
604 */
605 int xenstore_domain_has_devtype(struct xs_handle *handle, const char *devtype)
606 {
607 int rc = 0;
608 unsigned int num;
609 char **e = xenstore_domain_get_devices(handle, devtype, &num);
610 if (e)
611 rc = 1;
612 free(e);
613 return rc;
614 }
616 /*
617 * Function that creates a path to a variable of an instance of a
618 * certain device
619 */
620 static char *get_device_variable_path(const char *devtype, const char *inst,
621 const char *var)
622 {
623 char *buf = NULL;
624 if (pasprintf(&buf, "/local/domain/0/backend/%s/%d/%s/%s",
625 devtype,
626 domid,
627 inst,
628 var) == -1) {
629 free(buf);
630 buf = NULL;
631 }
632 return buf;
633 }
635 char *xenstore_backend_read_variable(struct xs_handle *handle,
636 const char *devtype, const char *inst,
637 const char *var)
638 {
639 char *value = NULL;
640 char *buf = NULL;
641 unsigned int len;
643 buf = get_device_variable_path(devtype, inst, var);
644 if (NULL == buf)
645 goto out;
647 value = xs_read(handle, XBT_NULL, buf, &len);
649 free(buf);
651 out:
652 return value;
653 }
655 /*
656 Read the hotplug status variable from the backend given the type
657 of device and its instance.
658 */
659 char *xenstore_read_hotplug_status(struct xs_handle *handle,
660 const char *devtype, const char *inst)
661 {
662 return xenstore_backend_read_variable(handle, devtype, inst,
663 "hotplug-status");
664 }
666 /*
667 Subscribe to the hotplug status of a device given the type of device and
668 its instance.
669 In case an error occurrs, a negative number is returned.
670 */
671 int xenstore_subscribe_to_hotplug_status(struct xs_handle *handle,
672 const char *devtype,
673 const char *inst,
674 const char *token)
675 {
676 int rc = 0;
677 char *path = get_device_variable_path(devtype, inst, "hotplug-status");
679 if (path == NULL)
680 return -1;
682 if (0 == xs_watch(handle, path, token))
683 rc = -2;
685 free(path);
687 return rc;
688 }
690 /*
691 * Unsubscribe from a subscription to the status of a hotplug variable of
692 * a device.
693 */
694 int xenstore_unsubscribe_from_hotplug_status(struct xs_handle *handle,
695 const char *devtype,
696 const char *inst,
697 const char *token)
698 {
699 int rc = 0;
700 char *path;
701 path = get_device_variable_path(devtype, inst, "hotplug-status");
702 if (path == NULL)
703 return -1;
705 if (0 == xs_unwatch(handle, path, token))
706 rc = -2;
708 free(path);
710 return rc;
711 }
713 char *xenstore_vm_read(int domid, char *key, unsigned int *len)
714 {
715 char *buf = NULL, *path = NULL, *value = NULL;
717 if (xsh == NULL)
718 goto out;
720 path = xs_get_domain_path(xsh, domid);
721 if (path == NULL) {
722 fprintf(logfile, "xs_get_domain_path(%d): error\n", domid);
723 goto out;
724 }
726 pasprintf(&buf, "%s/vm", path);
727 free(path);
728 path = xs_read(xsh, XBT_NULL, buf, NULL);
729 if (path == NULL) {
730 fprintf(logfile, "xs_read(%s): read error\n", buf);
731 goto out;
732 }
734 pasprintf(&buf, "%s/%s", path, key);
735 value = xs_read(xsh, XBT_NULL, buf, len);
736 if (value == NULL) {
737 fprintf(logfile, "xs_read(%s): read error\n", buf);
738 goto out;
739 }
741 out:
742 free(path);
743 free(buf);
744 return value;
745 }
747 int xenstore_vm_write(int domid, char *key, char *value)
748 {
749 char *buf = NULL, *path = NULL;
750 int rc = -1;
752 if (xsh == NULL)
753 goto out;
755 path = xs_get_domain_path(xsh, domid);
756 if (path == NULL) {
757 fprintf(logfile, "xs_get_domain_path: error\n");
758 goto out;
759 }
761 pasprintf(&buf, "%s/vm", path);
762 free(path);
763 path = xs_read(xsh, XBT_NULL, buf, NULL);
764 if (path == NULL) {
765 fprintf(logfile, "xs_read(%s): read error\n", buf);
766 goto out;
767 }
769 pasprintf(&buf, "%s/%s", path, key);
770 rc = xs_write(xsh, XBT_NULL, buf, value, strlen(value));
771 if (rc == 0) {
772 fprintf(logfile, "xs_write(%s, %s): write error\n", buf, key);
773 goto out;
774 }
776 out:
777 free(path);
778 free(buf);
779 return rc;
780 }