ia64/xen-unstable

view tools/ioemu/xenstore.c @ 17912:cebedb30a964

ioemu: Clean up after cset 17646:e3b13e1ecf6c

Remove redundant code.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 27 14:16:53 2008 +0100 (2008-06-27)
parents c2fab221b3ec
children 469d9b00382d
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 #define DIRECT_PCI_STR_LEN 160
83 char direct_pci_str[DIRECT_PCI_STR_LEN];
84 void xenstore_parse_domain_config(int hvm_domid)
85 {
86 char **e = NULL;
87 char *buf = NULL, *path;
88 char *fpath = NULL, *bpath = NULL,
89 *dev = NULL, *params = NULL, *type = NULL, *drv = NULL;
90 int i, is_scsi, is_hdN = 0;
91 unsigned int len, num, hd_index, pci_devid = 0;
92 BlockDriverState *bs;
93 BlockDriver *format;
95 for(i = 0; i < MAX_DISKS + MAX_SCSI_DISKS; i++)
96 media_filename[i] = NULL;
98 xsh = xs_daemon_open();
99 if (xsh == NULL) {
100 fprintf(logfile, "Could not contact xenstore for domain config\n");
101 return;
102 }
104 path = xs_get_domain_path(xsh, hvm_domid);
105 if (path == NULL) {
106 fprintf(logfile, "xs_get_domain_path() error\n");
107 goto out;
108 }
110 if (pasprintf(&buf, "%s/device/vbd", path) == -1)
111 goto out;
113 e = xs_directory(xsh, XBT_NULL, buf, &num);
114 if (e == NULL)
115 num = 0;
117 for (i = 0; i < num; i++) {
118 /* read the backend path */
119 if (pasprintf(&buf, "%s/device/vbd/%s/backend", path, e[i]) == -1)
120 continue;
121 free(bpath);
122 bpath = xs_read(xsh, XBT_NULL, buf, &len);
123 if (bpath == NULL)
124 continue;
125 /* read the name of the device */
126 if (pasprintf(&buf, "%s/dev", bpath) == -1)
127 continue;
128 free(dev);
129 dev = xs_read(xsh, XBT_NULL, buf, &len);
130 if (dev == NULL)
131 continue;
132 if (!strncmp(dev, "hd", 2)) {
133 is_hdN = 1;
134 break;
135 }
136 }
138 for (i = 0; i < num; i++) {
139 format = NULL; /* don't know what the format is yet */
141 /* read the backend path */
142 if (pasprintf(&buf, "%s/device/vbd/%s/backend", path, e[i]) == -1)
143 continue;
144 free(bpath);
145 bpath = xs_read(xsh, XBT_NULL, buf, &len);
146 if (bpath == NULL)
147 continue;
148 /* read the name of the device */
149 if (pasprintf(&buf, "%s/dev", bpath) == -1)
150 continue;
151 free(dev);
152 dev = xs_read(xsh, XBT_NULL, buf, &len);
153 if (dev == NULL)
154 continue;
155 /* Change xvdN to look like hdN */
156 if (!is_hdN && !strncmp(dev, "xvd", 3)) {
157 fprintf(logfile, "Change xvd%c to look like hd%c\n",
158 dev[3], dev[3]);
159 memmove(dev, dev+1, strlen(dev));
160 dev[0] = 'h';
161 dev[1] = 'd';
162 }
163 is_scsi = !strncmp(dev, "sd", 2);
164 if ((strncmp(dev, "hd", 2) && !is_scsi) || strlen(dev) != 3 )
165 continue;
166 hd_index = dev[2] - 'a';
167 if (hd_index >= (is_scsi ? MAX_SCSI_DISKS : MAX_DISKS))
168 continue;
169 /* read the type of the device */
170 if (pasprintf(&buf, "%s/device/vbd/%s/device-type", path, e[i]) == -1)
171 continue;
172 free(type);
173 type = xs_read(xsh, XBT_NULL, buf, &len);
174 if (pasprintf(&buf, "%s/params", bpath) == -1)
175 continue;
176 free(params);
177 params = xs_read(xsh, XBT_NULL, buf, &len);
178 if (params == NULL)
179 continue;
180 /* read the name of the device */
181 if (pasprintf(&buf, "%s/type", bpath) == -1)
182 continue;
183 free(drv);
184 drv = xs_read(xsh, XBT_NULL, buf, &len);
185 if (drv == NULL)
186 continue;
187 /* Obtain blktap sub-type prefix */
188 if (!strcmp(drv, "tap") && params[0]) {
189 char *offset = strchr(params, ':');
190 if (!offset)
191 continue ;
192 free(drv);
193 drv = malloc(offset - params + 1);
194 memcpy(drv, params, offset - params);
195 drv[offset - params] = '\0';
196 if (!strcmp(drv, "aio"))
197 /* qemu does aio anyway if it can */
198 format = &bdrv_raw;
199 memmove(params, offset+1, strlen(offset+1)+1 );
200 fprintf(logfile, "Strip off blktap sub-type prefix to %s (drv '%s')\n", params, drv);
201 }
202 /* Prefix with /dev/ if needed */
203 if (!strcmp(drv, "phy") && params[0] != '/') {
204 char *newparams = malloc(5 + strlen(params) + 1);
205 sprintf(newparams, "/dev/%s", params);
206 free(params);
207 params = newparams;
208 format = &bdrv_raw;
209 }
211 /*
212 * check if device has a phantom vbd; the phantom is hooked
213 * to the frontend device (for ease of cleanup), so lookup
214 * the frontend device, and see if there is a phantom_vbd
215 * if there is, we will use resolution as the filename
216 */
217 if (pasprintf(&buf, "%s/device/vbd/%s/phantom_vbd", path, e[i]) == -1)
218 continue;
219 free(fpath);
220 fpath = xs_read(xsh, XBT_NULL, buf, &len);
221 if (fpath) {
222 if (pasprintf(&buf, "%s/dev", fpath) == -1)
223 continue;
224 free(params);
225 params = xs_read(xsh, XBT_NULL, buf , &len);
226 if (params) {
227 /*
228 * wait for device, on timeout silently fail because we will
229 * fail to open below
230 */
231 waitForDevice(params);
232 }
233 }
235 bs = bs_table[hd_index + (is_scsi ? MAX_DISKS : 0)] = bdrv_new(dev);
236 /* check if it is a cdrom */
237 if (type && !strcmp(type, "cdrom")) {
238 bdrv_set_type_hint(bs, BDRV_TYPE_CDROM);
239 if (pasprintf(&buf, "%s/params", bpath) != -1)
240 xs_watch(xsh, buf, dev);
241 }
243 /* open device now if media present */
244 #ifdef CONFIG_STUBDOM
245 if (pasprintf(&buf, "%s/device/vbd/%s", path, e[i]) == -1)
246 continue;
247 if (bdrv_open2(bs, buf, 0 /* snapshot */, &bdrv_vbd) == 0) {
248 pstrcpy(bs->filename, sizeof(bs->filename), params);
249 continue;
250 }
251 #endif
253 if (params[0]) {
254 if (!format) {
255 if (!drv) {
256 fprintf(stderr, "qemu: type (image format) not specified for vbd '%s' or image '%s'\n", buf, params);
257 continue;
258 }
259 if (!strcmp(drv,"qcow")) {
260 /* autoguess qcow vs qcow2 */
261 } else if (!strcmp(drv,"file") || !strcmp(drv,"phy")) {
262 format = &bdrv_raw;
263 } else {
264 format = bdrv_find_format(drv);
265 if (!format) {
266 fprintf(stderr, "qemu: type (image format) '%s' unknown for vbd '%s' or image '%s'\n", drv, buf, params);
267 continue;
268 }
269 }
270 }
271 if (bdrv_open2(bs, params, 0 /* snapshot */, format) < 0)
272 fprintf(stderr, "qemu: could not open vbd '%s' or hard disk image '%s' (drv '%s' format '%s')\n", buf, params, drv ? drv : "?", format ? format->format_name : "0");
273 }
274 }
276 #ifdef CONFIG_STUBDOM
277 if (pasprintf(&buf, "%s/device/vkbd", path) == -1)
278 goto out;
280 free(e);
281 e = xs_directory(xsh, XBT_NULL, buf, &num);
283 if (e) {
284 for (i = 0; i < num; i++) {
285 if (pasprintf(&buf, "%s/device/vkbd/%s", path, e[i]) == -1)
286 continue;
287 xenfb_connect_vkbd(buf);
288 }
289 }
291 if (pasprintf(&buf, "%s/device/vfb", path) == -1)
292 goto out;
294 free(e);
295 e = xs_directory(xsh, XBT_NULL, buf, &num);
297 if (e) {
298 for (i = 0; i < num; i++) {
299 if (pasprintf(&buf, "%s/device/vfb/%s", path, e[i]) == -1)
300 continue;
301 xenfb_connect_vfb(buf);
302 }
303 }
304 #endif
307 /* Set a watch for log-dirty requests from the migration tools */
308 if (pasprintf(&buf, "/local/domain/0/device-model/%u/logdirty/next-active",
309 domid) != -1) {
310 xs_watch(xsh, buf, "logdirty");
311 fprintf(logfile, "Watching %s\n", buf);
312 }
314 /* Set a watch for suspend requests from the migration tools */
315 if (pasprintf(&buf,
316 "/local/domain/0/device-model/%u/command", domid) != -1) {
317 xs_watch(xsh, buf, "dm-command");
318 fprintf(logfile, "Watching %s\n", buf);
319 }
321 /* get the pci pass-through parameter */
322 if (pasprintf(&buf, "/local/domain/0/backend/pci/%u/%u/num_devs",
323 domid, pci_devid) == -1)
324 goto out;
326 free(params);
327 params = xs_read(xsh, XBT_NULL, buf, &len);
328 if (params == NULL)
329 goto out;
330 num = atoi(params);
332 for ( i = 0; i < num; i++ ) {
333 if (pasprintf(&buf, "/local/domain/0/backend/pci/%u/%u/dev-%d",
334 domid, pci_devid, i) != -1) {
335 free(dev);
336 dev = xs_read(xsh, XBT_NULL, buf, &len);
338 if ( strlen(dev) + strlen(direct_pci_str) > DIRECT_PCI_STR_LEN ) {
339 fprintf(stderr, "qemu: too many pci pass-through devices\n");
340 memset(direct_pci_str, 0, DIRECT_PCI_STR_LEN);
341 goto out;
342 }
344 /* append to direct_pci_str */
345 if ( dev ) {
346 strcat(direct_pci_str, dev);
347 strcat(direct_pci_str, "-");
348 }
349 }
350 }
353 out:
354 free(type);
355 free(params);
356 free(dev);
357 free(bpath);
358 free(buf);
359 free(path);
360 free(e);
361 free(drv);
362 return;
363 }
365 int xenstore_fd(void)
366 {
367 if (xsh)
368 return xs_fileno(xsh);
369 return -1;
370 }
372 unsigned long *logdirty_bitmap = NULL;
373 unsigned long logdirty_bitmap_size;
374 extern int vga_ram_size, bios_size;
376 void xenstore_process_logdirty_event(void)
377 {
378 char *act;
379 static char *active_path = NULL;
380 static char *next_active_path = NULL;
381 static char *seg = NULL;
382 unsigned int len;
383 int i;
385 if (!seg) {
386 char *path = NULL, *key_ascii, key_terminated[17] = {0,};
387 key_t key;
388 int shmid;
390 /* Find and map the shared memory segment for log-dirty bitmaps */
391 if (pasprintf(&path,
392 "/local/domain/0/device-model/%u/logdirty/key",
393 domid) == -1) {
394 fprintf(logfile, "Log-dirty: out of memory\n");
395 exit(1);
396 }
398 key_ascii = xs_read(xsh, XBT_NULL, path, &len);
399 free(path);
401 if (!key_ascii)
402 /* No key yet: wait for the next watch */
403 return;
405 strncpy(key_terminated, key_ascii, 16);
406 free(key_ascii);
407 key = (key_t) strtoull(key_terminated, NULL, 16);
409 /* Figure out how bit the log-dirty bitmaps are */
410 logdirty_bitmap_size = xc_memory_op(xc_handle,
411 XENMEM_maximum_gpfn, &domid) + 1;
412 logdirty_bitmap_size = ((logdirty_bitmap_size + HOST_LONG_BITS - 1)
413 / HOST_LONG_BITS); /* longs */
414 logdirty_bitmap_size *= sizeof (unsigned long); /* bytes */
416 /* Map the shared-memory segment */
417 fprintf(logfile, "%s: key=%16.16llx size=%lu\n", __FUNCTION__,
418 (unsigned long long)key, logdirty_bitmap_size);
420 #ifdef CONFIG_STUBDOM
421 /* XXX we just can't use shm. */
422 fprintf(logfile, "Log dirty is not implemented in stub domains!\n");
423 return;
424 #else
425 shmid = shmget(key, 2 * logdirty_bitmap_size, S_IRUSR|S_IWUSR);
426 if (shmid == -1) {
427 fprintf(logfile, "Log-dirty: shmget failed: segment %16.16llx "
428 "(%s)\n", (unsigned long long)key, strerror(errno));
429 exit(1);
430 }
432 seg = shmat(shmid, NULL, 0);
433 if (seg == (void *)-1) {
434 fprintf(logfile, "Log-dirty: shmat failed: segment %16.16llx "
435 "(%s)\n", (unsigned long long)key, strerror(errno));
436 exit(1);
437 }
439 fprintf(logfile, "Log-dirty: mapped segment at %p\n", seg);
441 /* Double-check that the bitmaps are the size we expect */
442 if (logdirty_bitmap_size != *(uint32_t *)seg) {
443 fprintf(logfile, "Log-dirty: got %u, calc %lu\n",
444 *(uint32_t *)seg, logdirty_bitmap_size);
445 /* Stale key: wait for next watch */
446 shmdt(seg);
447 seg = NULL;
448 return;
449 }
450 #endif
452 /* Remember the paths for the next-active and active entries */
453 if (pasprintf(&active_path,
454 "/local/domain/0/device-model/%u/logdirty/active",
455 domid) == -1) {
456 fprintf(logfile, "Log-dirty: out of memory\n");
457 exit(1);
458 }
459 if (pasprintf(&next_active_path,
460 "/local/domain/0/device-model/%u/logdirty/next-active",
461 domid) == -1) {
462 fprintf(logfile, "Log-dirty: out of memory\n");
463 exit(1);
464 }
465 }
467 fprintf(logfile, "Triggered log-dirty buffer switch\n");
469 /* Read the required active buffer from the store */
470 act = xs_read(xsh, XBT_NULL, next_active_path, &len);
471 if (!act) {
472 fprintf(logfile, "Log-dirty: can't read next-active\n");
473 exit(1);
474 }
476 /* Switch buffers */
477 i = act[0] - '0';
478 if (i != 0 && i != 1) {
479 fprintf(logfile, "Log-dirty: bad next-active entry: %s\n", act);
480 exit(1);
481 }
482 logdirty_bitmap = (unsigned long *)(seg + i * logdirty_bitmap_size);
484 /* Ack that we've switched */
485 xs_write(xsh, XBT_NULL, active_path, act, len);
486 free(act);
487 }
490 /* Accept state change commands from the control tools */
491 static void xenstore_process_dm_command_event(void)
492 {
493 char *path = NULL, *command = NULL, *par = NULL;
494 unsigned int len;
495 extern int suspend_requested;
497 if (pasprintf(&path,
498 "/local/domain/0/device-model/%u/command", domid) == -1) {
499 fprintf(logfile, "out of memory reading dm command\n");
500 goto out;
501 }
502 command = xs_read(xsh, XBT_NULL, path, &len);
503 if (!command)
504 goto out;
506 if (!strncmp(command, "save", len)) {
507 fprintf(logfile, "dm-command: pause and save state\n");
508 suspend_requested = 1;
509 } else if (!strncmp(command, "continue", len)) {
510 fprintf(logfile, "dm-command: continue after state save\n");
511 suspend_requested = 0;
512 } else if (!strncmp(command, "pci-rem", len)) {
513 fprintf(logfile, "dm-command: hot remove pass-through pci dev \n");
515 if (pasprintf(&path,
516 "/local/domain/0/device-model/%u/parameter", domid) == -1) {
517 fprintf(logfile, "out of memory reading dm command parameter\n");
518 goto out;
519 }
520 par = xs_read(xsh, XBT_NULL, path, &len);
521 if (!par)
522 goto out;
524 do_pci_del(par);
525 free(par);
526 } else if (!strncmp(command, "pci-ins", len)) {
527 fprintf(logfile, "dm-command: hot insert pass-through pci dev \n");
529 if (pasprintf(&path,
530 "/local/domain/0/device-model/%u/parameter", domid) == -1) {
531 fprintf(logfile, "out of memory reading dm command parameter\n");
532 goto out;
533 }
534 par = xs_read(xsh, XBT_NULL, path, &len);
535 if (!par)
536 goto out;
538 do_pci_add(par);
539 free(par);
540 } else {
541 fprintf(logfile, "dm-command: unknown command\"%*s\"\n", len, command);
542 }
544 out:
545 free(path);
546 free(command);
547 }
549 void xenstore_record_dm(char *subpath, char *state)
550 {
551 char *path = NULL;
553 if (pasprintf(&path,
554 "/local/domain/0/device-model/%u/%s", domid, subpath) == -1) {
555 fprintf(logfile, "out of memory recording dm \n");
556 goto out;
557 }
558 if (!xs_write(xsh, XBT_NULL, path, state, strlen(state)))
559 fprintf(logfile, "error recording dm \n");
561 out:
562 free(path);
563 }
565 void xenstore_record_dm_state(char *state)
566 {
567 xenstore_record_dm("state", state);
568 }
570 void xenstore_process_event(void *opaque)
571 {
572 char **vec, *offset, *bpath = NULL, *buf = NULL, *drv = NULL, *image = NULL;
573 unsigned int len, num, hd_index;
575 vec = xs_read_watch(xsh, &num);
576 if (!vec)
577 return;
579 if (!strcmp(vec[XS_WATCH_TOKEN], "logdirty")) {
580 xenstore_process_logdirty_event();
581 goto out;
582 }
584 if (!strcmp(vec[XS_WATCH_TOKEN], "dm-command")) {
585 xenstore_process_dm_command_event();
586 goto out;
587 }
589 if (strncmp(vec[XS_WATCH_TOKEN], "hd", 2) ||
590 strlen(vec[XS_WATCH_TOKEN]) != 3)
591 goto out;
592 hd_index = vec[XS_WATCH_TOKEN][2] - 'a';
593 image = xs_read(xsh, XBT_NULL, vec[XS_WATCH_PATH], &len);
594 if (image == NULL)
595 goto out; /* gone */
597 /* Strip off blktap sub-type prefix */
598 bpath = strdup(vec[XS_WATCH_PATH]);
599 if (bpath == NULL)
600 goto out;
601 if ((offset = strrchr(bpath, '/')) != NULL)
602 *offset = '\0';
603 if (pasprintf(&buf, "%s/type", bpath) == -1)
604 goto out;
605 drv = xs_read(xsh, XBT_NULL, buf, &len);
606 if (drv && !strcmp(drv, "tap") && ((offset = strchr(image, ':')) != NULL))
607 memmove(image, offset+1, strlen(offset+1)+1);
609 if (!strcmp(image, bs_table[hd_index]->filename))
610 goto out; /* identical */
612 do_eject(0, vec[XS_WATCH_TOKEN]);
613 bs_table[hd_index]->filename[0] = 0;
614 if (media_filename[hd_index]) {
615 free(media_filename[hd_index]);
616 media_filename[hd_index] = NULL;
617 }
619 if (image[0]) {
620 media_filename[hd_index] = strdup(image);
621 xenstore_check_new_media_present(5000);
622 }
624 out:
625 free(drv);
626 free(buf);
627 free(bpath);
628 free(image);
629 free(vec);
630 }
632 void xenstore_write_vncport(int display)
633 {
634 char *buf = NULL, *path;
635 char *portstr = NULL;
637 if (xsh == NULL)
638 return;
640 path = xs_get_domain_path(xsh, domid);
641 if (path == NULL) {
642 fprintf(logfile, "xs_get_domain_path() error\n");
643 goto out;
644 }
646 if (pasprintf(&buf, "%s/console/vnc-port", path) == -1)
647 goto out;
649 if (pasprintf(&portstr, "%d", display) == -1)
650 goto out;
652 if (xs_write(xsh, XBT_NULL, buf, portstr, strlen(portstr)) == 0)
653 fprintf(logfile, "xs_write() vncport failed\n");
655 out:
656 free(portstr);
657 free(buf);
658 }
660 void xenstore_write_vslots(char *vslots)
661 {
662 char *path = NULL;
663 int pci_devid = 0;
665 if (pasprintf(&path,
666 "/local/domain/0/backend/pci/%u/%u/vslots", domid, pci_devid) == -1) {
667 fprintf(logfile, "out of memory when updating vslots.\n");
668 goto out;
669 }
670 if (!xs_write(xsh, XBT_NULL, path, vslots, strlen(vslots)))
671 fprintf(logfile, "error updating vslots \n");
673 out:
674 free(path);
675 }
677 void xenstore_read_vncpasswd(int domid, char *pwbuf, size_t pwbuflen)
678 {
679 char *buf = NULL, *path, *uuid = NULL, *passwd = NULL;
680 unsigned int i, len;
682 pwbuf[0] = '\0';
684 if (xsh == NULL)
685 return;
687 path = xs_get_domain_path(xsh, domid);
688 if (path == NULL) {
689 fprintf(logfile, "xs_get_domain_path() error. domid %d.\n", domid);
690 return;
691 }
693 pasprintf(&buf, "%s/vm", path);
694 free(path);
695 uuid = xs_read(xsh, XBT_NULL, buf, &len);
696 if (uuid == NULL) {
697 fprintf(logfile, "xs_read(): uuid get error. %s.\n", buf);
698 free(buf);
699 return;
700 }
702 pasprintf(&buf, "%s/vncpasswd", uuid);
703 free(uuid);
704 passwd = xs_read(xsh, XBT_NULL, buf, &len);
705 if (passwd == NULL) {
706 fprintf(logfile, "xs_read(): vncpasswd get error. %s.\n", buf);
707 free(buf);
708 return;
709 }
711 if (len >= pwbuflen)
712 {
713 fprintf(logfile, "xenstore_read_vncpasswd(): truncated password to avoid buffer overflow\n");
714 len = pwbuflen - 1;
715 }
717 for (i=0; i<len; i++)
718 pwbuf[i] = passwd[i];
719 pwbuf[len] = '\0';
720 passwd[0] = '\0';
721 if (xs_write(xsh, XBT_NULL, buf, passwd, 1) == 0)
722 fprintf(logfile, "xs_write() vncpasswd failed.\n");
724 free(passwd);
725 free(buf);
726 }
729 /*
730 * get all device instances of a certain type
731 */
732 char **xenstore_domain_get_devices(struct xs_handle *handle,
733 const char *devtype, unsigned int *num)
734 {
735 char *path;
736 char *buf = NULL;
737 char **e = NULL;
739 path = xs_get_domain_path(handle, domid);
740 if (path == NULL)
741 goto out;
743 if (pasprintf(&buf, "%s/device/%s", path,devtype) == -1)
744 goto out;
746 e = xs_directory(handle, XBT_NULL, buf, num);
748 out:
749 free(path);
750 free(buf);
751 return e;
752 }
754 /*
755 * Check whether a domain has devices of the given type
756 */
757 int xenstore_domain_has_devtype(struct xs_handle *handle, const char *devtype)
758 {
759 int rc = 0;
760 unsigned int num;
761 char **e = xenstore_domain_get_devices(handle, devtype, &num);
762 if (e)
763 rc = 1;
764 free(e);
765 return rc;
766 }
768 /*
769 * Function that creates a path to a variable of an instance of a
770 * certain device
771 */
772 static char *get_device_variable_path(const char *devtype, const char *inst,
773 const char *var)
774 {
775 char *buf = NULL;
776 if (pasprintf(&buf, "/local/domain/0/backend/%s/%d/%s/%s",
777 devtype,
778 domid,
779 inst,
780 var) == -1) {
781 free(buf);
782 buf = NULL;
783 }
784 return buf;
785 }
787 char *xenstore_backend_read_variable(struct xs_handle *handle,
788 const char *devtype, const char *inst,
789 const char *var)
790 {
791 char *value = NULL;
792 char *buf = NULL;
793 unsigned int len;
795 buf = get_device_variable_path(devtype, inst, var);
796 if (NULL == buf)
797 goto out;
799 value = xs_read(handle, XBT_NULL, buf, &len);
801 free(buf);
803 out:
804 return value;
805 }
807 /*
808 Read the hotplug status variable from the backend given the type
809 of device and its instance.
810 */
811 char *xenstore_read_hotplug_status(struct xs_handle *handle,
812 const char *devtype, const char *inst)
813 {
814 return xenstore_backend_read_variable(handle, devtype, inst,
815 "hotplug-status");
816 }
818 /*
819 Subscribe to the hotplug status of a device given the type of device and
820 its instance.
821 In case an error occurrs, a negative number is returned.
822 */
823 int xenstore_subscribe_to_hotplug_status(struct xs_handle *handle,
824 const char *devtype,
825 const char *inst,
826 const char *token)
827 {
828 int rc = 0;
829 char *path = get_device_variable_path(devtype, inst, "hotplug-status");
831 if (path == NULL)
832 return -1;
834 if (0 == xs_watch(handle, path, token))
835 rc = -2;
837 free(path);
839 return rc;
840 }
842 /*
843 * Unsubscribe from a subscription to the status of a hotplug variable of
844 * a device.
845 */
846 int xenstore_unsubscribe_from_hotplug_status(struct xs_handle *handle,
847 const char *devtype,
848 const char *inst,
849 const char *token)
850 {
851 int rc = 0;
852 char *path;
853 path = get_device_variable_path(devtype, inst, "hotplug-status");
854 if (path == NULL)
855 return -1;
857 if (0 == xs_unwatch(handle, path, token))
858 rc = -2;
860 free(path);
862 return rc;
863 }
865 char *xenstore_vm_read(int domid, char *key, unsigned int *len)
866 {
867 char *buf = NULL, *path = NULL, *value = NULL;
869 if (xsh == NULL)
870 goto out;
872 path = xs_get_domain_path(xsh, domid);
873 if (path == NULL) {
874 fprintf(logfile, "xs_get_domain_path(%d): error\n", domid);
875 goto out;
876 }
878 pasprintf(&buf, "%s/vm", path);
879 free(path);
880 path = xs_read(xsh, XBT_NULL, buf, NULL);
881 if (path == NULL) {
882 fprintf(logfile, "xs_read(%s): read error\n", buf);
883 goto out;
884 }
886 pasprintf(&buf, "%s/%s", path, key);
887 value = xs_read(xsh, XBT_NULL, buf, len);
888 if (value == NULL) {
889 fprintf(logfile, "xs_read(%s): read error\n", buf);
890 goto out;
891 }
893 out:
894 free(path);
895 free(buf);
896 return value;
897 }
899 int xenstore_vm_write(int domid, char *key, char *value)
900 {
901 char *buf = NULL, *path = NULL;
902 int rc = -1;
904 if (xsh == NULL)
905 goto out;
907 path = xs_get_domain_path(xsh, domid);
908 if (path == NULL) {
909 fprintf(logfile, "xs_get_domain_path: error\n");
910 goto out;
911 }
913 pasprintf(&buf, "%s/vm", path);
914 free(path);
915 path = xs_read(xsh, XBT_NULL, buf, NULL);
916 if (path == NULL) {
917 fprintf(logfile, "xs_read(%s): read error\n", buf);
918 goto out;
919 }
921 pasprintf(&buf, "%s/%s", path, key);
922 rc = xs_write(xsh, XBT_NULL, buf, value, strlen(value));
923 if (rc == 0) {
924 fprintf(logfile, "xs_write(%s, %s): write error\n", buf, key);
925 goto out;
926 }
928 out:
929 free(path);
930 free(buf);
931 return rc;
932 }