Hi all,
this patch implements functions in libxenlight to change the cdrom in a
VM at run time and to handle cdrom eject requests from guests.
This patch adds two new commands to xl: cd-insert and cd-eject; it also
modifies xl to handle cdrom eject requests coming from guests (actually
coming from qemu).
Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
---
diff -r b07a720e30de tools/libxl/libxl.c
--- a/tools/libxl/libxl.c Mon Dec 07 15:19:24 2009 +0000
+++ b/tools/libxl/libxl.c Mon Dec 07 15:20:05 2009 +0000
@@ -460,25 +460,80 @@
return 0;
}
-int libxl_wait_for_domain_death(struct libxl_ctx *ctx, uint32_t domid, int *fd)
+int libxl_get_wait_fd(struct libxl_ctx *ctx, int *fd)
{
- if (!xs_watch(ctx->xsh, "@releaseDomain", "domain_death"))
- return -1;
*fd = xs_fileno(ctx->xsh);
return 0;
}
-int libxl_is_domain_dead(struct libxl_ctx *ctx, uint32_t domid, xc_dominfo_t
*info)
+int libxl_wait_for_domain_death(struct libxl_ctx *ctx, uint32_t domid,
libxl_waiter *waiter)
+{
+ waiter->path = strdup("@releaseDomain");
+ asprintf(&(waiter->token), "%d", DOMAIN_DEATH);
+ if (!xs_watch(ctx->xsh, waiter->path, waiter->token))
+ return -1;
+ return 0;
+}
+
+int libxl_wait_for_disk_ejects(struct libxl_ctx *ctx, uint32_t guest_domid,
libxl_device_disk *disks, int num_disks, libxl_waiter *waiter)
+{
+ int i;
+ uint32_t domid = libxl_get_stubdom_id(ctx, guest_domid);
+
+ if (!domid)
+ domid = guest_domid;
+
+ for (i = 0; i < num_disks; i++) {
+ asprintf(&(waiter[i].path), "%s/device/vbd/%d/eject",
libxl_xs_get_dompath(ctx, domid), device_disk_dev_number(disks[i].virtpath));
+ asprintf(&(waiter[i].token), "%d", DISK_EJECT);
+ xs_watch(ctx->xsh, waiter->path, waiter->token);
+ }
+ return 0;
+}
+
+int libxl_get_event(struct libxl_ctx *ctx, libxl_event *event)
{
unsigned int num;
+ char **events = xs_read_watch(ctx->xsh, &num);
+ if (num != 2) {
+ free(events);
+ return -1;
+ }
+ event->path = strdup(events[XS_WATCH_PATH]);
+ event->token = strdup(events[XS_WATCH_TOKEN]);
+ event->type = atoi(event->token);
+ free(events);
+ return 0;
+}
+
+int libxl_stop_waiting(struct libxl_ctx *ctx, libxl_waiter *waiter)
+{
+ if (!xs_unwatch(ctx->xsh, waiter->path, waiter->token))
+ return -1;
+ else
+ return 0;
+}
+
+int libxl_free_event(libxl_event *event)
+{
+ free(event->path);
+ free(event->token);
+ return 0;
+}
+
+int libxl_free_waiter(libxl_waiter *waiter)
+{
+ free(waiter->path);
+ free(waiter->token);
+ return 0;
+}
+
+int libxl_event_get_domain_death_info(struct libxl_ctx *ctx, uint32_t domid,
libxl_event *event, xc_dominfo_t *info)
+{
int nb_domain, i, rc = 0;
- char **vec = NULL;
xc_dominfo_t *list = NULL;
- vec = xs_read_watch(ctx->xsh, &num);
- if (!vec)
- return 0;
- if (!strcmp(vec[XS_WATCH_TOKEN], "domain_death")) {
+ if (event && event->type == DOMAIN_DEATH) {
list = libxl_domain_infolist(ctx, &nb_domain);
for (i = 0; i < nb_domain; i++) {
if (domid == list[i].domid) {
@@ -493,11 +548,39 @@
rc = 1;
goto out;
}
-
out:
free(list);
- free(vec);
return rc;
+}
+
+int libxl_event_get_disk_eject_info(struct libxl_ctx *ctx, uint32_t domid,
libxl_event *event, libxl_device_disk *disk)
+{
+ if (event && event->type == DISK_EJECT) {
+ char *path;
+ char *backend;
+ char *value = libxl_xs_read(ctx, XBT_NULL, event->path);
+
+ if (!value || strcmp(value, "eject"))
+ return 0;
+
+ path = strdup(event->path);
+ path[strlen(path) - 6] = '\0';
+ backend = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx,
"%s/backend", path));
+
+ disk->backend_domid = 0;
+ disk->domid = domid;
+ disk->physpath = NULL;
+ disk->phystype = 0;
+ /* this value is returned to the user: do not free right away */
+ disk->virtpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx,
"%s/dev", backend));
+ disk->unpluggable = 1;
+ disk->readwrite = 0;
+ disk->is_cdrom = 1;
+
+ free(path);
+ return 1;
+ }
+ return 0;
}
static int libxl_destroy_device_model(struct libxl_ctx *ctx, uint32_t domid)
@@ -1419,6 +1502,95 @@
int libxl_device_vkb_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid)
{
return ERROR_NI;
+}
+
+libxl_device_disk *libxl_device_disk_list(struct libxl_ctx *ctx, uint32_t
domid, int *num)
+{
+ char *be_path_tap, *be_path_vbd;
+ libxl_device_disk *disks = NULL;
+ char **l = NULL;
+ unsigned int numl;
+ int num_disks = 0, i;
+ char *type;
+
+ be_path_vbd = libxl_sprintf(ctx, "%s/backend/vbd/%d",
libxl_xs_get_dompath(ctx, 0), domid);
+ be_path_tap = libxl_sprintf(ctx, "%s/backend/tap/%d",
libxl_xs_get_dompath(ctx, 0), domid);
+
+ l = libxl_xs_directory(ctx, XBT_NULL, be_path_vbd, &numl);
+ if (l) {
+ num_disks += numl;
+ disks = realloc(disks, sizeof(libxl_device_disk) * num_disks);
+ for (i = 0; i < numl; i++) {
+ disks[i].backend_domid = 0;
+ disks[i].domid = domid;
+ disks[i].physpath = libxl_xs_read(ctx, XBT_NULL,
libxl_sprintf(ctx, "%s/%s/params", be_path_vbd, l[i]));
+ libxl_string_to_phystype(ctx, libxl_xs_read(ctx, XBT_NULL,
libxl_sprintf(ctx, "%s/%s/type", be_path_vbd, l[i])), &(disks[i].phystype));
+ disks[i].virtpath = libxl_xs_read(ctx, XBT_NULL,
libxl_sprintf(ctx, "%s/%s/dev", be_path_vbd, l[i]));
+ disks[i].unpluggable = atoi(libxl_xs_read(ctx, XBT_NULL,
libxl_sprintf(ctx, "%s/%s/removable", be_path_vbd, l[i])));
+ if (!strcmp(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx,
"%s/%s/mode", be_path_vbd, l[i])), "w"))
+ disks[i].readwrite = 1;
+ else
+ disks[i].readwrite = 0;
+ type = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx,
"%s/device-type", libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx,
"%s/%s/frontend", be_path_vbd, l[i]))));
+ disks[i].is_cdrom = !strcmp(type, "cdrom");
+ }
+ free(l);
+ }
+ l = libxl_xs_directory(ctx, XBT_NULL, be_path_tap, &numl);
+ if (l) {
+ num_disks += numl;
+ disks = realloc(disks, sizeof(libxl_device_disk) * num_disks);
+ for (i = 0; i < numl; i++) {
+ disks[i].backend_domid = 0;
+ disks[i].domid = domid;
+ disks[i].physpath = libxl_xs_read(ctx, XBT_NULL,
libxl_sprintf(ctx, "%s/%s/params", be_path_tap, l[i]));
+ libxl_string_to_phystype(ctx, libxl_xs_read(ctx, XBT_NULL,
libxl_sprintf(ctx, "%s/%s/type", be_path_tap, l[i])), &(disks[i].phystype));
+ disks[i].virtpath = libxl_xs_read(ctx, XBT_NULL,
libxl_sprintf(ctx, "%s/%s/dev", be_path_tap, l[i]));
+ disks[i].unpluggable = atoi(libxl_xs_read(ctx, XBT_NULL,
libxl_sprintf(ctx, "%s/%s/removable", be_path_tap, l[i])));
+ if (!strcmp(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx,
"%s/%s/mode", be_path_tap, l[i])), "w"))
+ disks[i].readwrite = 1;
+ else
+ disks[i].readwrite = 0;
+ type = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx,
"%s/device-type", libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx,
"%s/%s/frontend", be_path_vbd, l[i]))));
+ disks[i].is_cdrom = !strcmp(type, "cdrom");
+ }
+ free(l);
+ }
+ *num = num_disks;
+ return disks;
+}
+
+int libxl_cdrom_insert(struct libxl_ctx *ctx, uint32_t domid,
libxl_device_disk *disk)
+{
+ int num, i;
+ uint32_t stubdomid;
+ libxl_device_disk *disks;
+
+ if (!disk->physpath) {
+ disk->physpath = "";
+ disk->phystype = PHYSTYPE_PHY;
+ }
+ disks = libxl_device_disk_list(ctx, domid, &num);
+ for (i = 0; i < num; i++) {
+ if (disks[i].is_cdrom && !strcmp(disk->virtpath, disks[i].virtpath))
+ /* found */
+ break;
+ }
+ if (i == num) {
+ XL_LOG(ctx, XL_LOG_ERROR, "Virtual device not found");
+ return -1;
+ }
+ libxl_device_disk_del(ctx, disks + i, 1);
+ libxl_device_disk_add(ctx, domid, disk);
+ stubdomid = libxl_get_stubdom_id(ctx, domid);
+ if (stubdomid) {
+ disk_info_domid_fixup(disks + i, stubdomid);
+ libxl_device_disk_del(ctx, disks + i, 1);
+ disk_info_domid_fixup(disk, stubdomid);
+ libxl_device_disk_add(ctx, stubdomid, disk);
+ disk_info_domid_fixup(disk, domid);
+ }
+ return 0;
}
/******************************************************************************/
diff -r b07a720e30de tools/libxl/libxl.h
--- a/tools/libxl/libxl.h Mon Dec 07 15:19:24 2009 +0000
+++ b/tools/libxl/libxl.h Mon Dec 07 15:20:05 2009 +0000
@@ -267,8 +267,40 @@
int libxl_domain_shutdown(struct libxl_ctx *ctx, uint32_t domid, int req);
int libxl_domain_destroy(struct libxl_ctx *ctx, uint32_t domid, int force);
-int libxl_wait_for_domain_death(struct libxl_ctx *ctx, uint32_t domid, int
*fd);
-int libxl_is_domain_dead(struct libxl_ctx *ctx, uint32_t domid, xc_dominfo_t
*info);
+/* events handling */
+
+typedef enum {
+ DOMAIN_DEATH,
+ DISK_EJECT,
+} libxl_event_type;
+
+typedef struct {
+ /* event type */
+ libxl_event_type type;
+ /* data for internal use of the library */
+ char *path;
+ char *token;
+} libxl_event;
+
+typedef struct {
+ char *path;
+ char *token;
+} libxl_waiter;
+
+
+int libxl_get_wait_fd(struct libxl_ctx *ctx, int *fd);
+/* waiter is allocated by the caller */
+int libxl_wait_for_domain_death(struct libxl_ctx *ctx, uint32_t domid,
libxl_waiter *waiter);
+/* waiter is a preallocated array of num_disks libxl_waiter elements */
+int libxl_wait_for_disk_ejects(struct libxl_ctx *ctx, uint32_t domid,
libxl_device_disk *disks, int num_disks, libxl_waiter *waiter);
+int libxl_get_event(struct libxl_ctx *ctx, libxl_event *event);
+int libxl_stop_waiting(struct libxl_ctx *ctx, libxl_waiter *waiter);
+int libxl_free_event(libxl_event *event);
+int libxl_free_waiter(libxl_waiter *waiter);
+
+int libxl_event_get_domain_death_info(struct libxl_ctx *ctx, uint32_t domid,
libxl_event *event, xc_dominfo_t *info);
+int libxl_event_get_disk_eject_info(struct libxl_ctx *ctx, uint32_t domid,
libxl_event *event, libxl_device_disk *disk);
+
int libxl_domain_pause(struct libxl_ctx *ctx, uint32_t domid);
int libxl_domain_unpause(struct libxl_ctx *ctx, uint32_t domid);
@@ -299,6 +331,8 @@
int libxl_device_disk_add(struct libxl_ctx *ctx, uint32_t domid,
libxl_device_disk *disk);
int libxl_device_disk_del(struct libxl_ctx *ctx, libxl_device_disk *disk, int
wait);
+libxl_device_disk *libxl_device_disk_list(struct libxl_ctx *ctx, uint32_t
domid, int *num);
+int libxl_cdrom_insert(struct libxl_ctx *ctx, uint32_t domid,
libxl_device_disk *disk);
int libxl_device_nic_add(struct libxl_ctx *ctx, uint32_t domid,
libxl_device_nic *nic);
int libxl_device_nic_del(struct libxl_ctx *ctx, libxl_device_nic *nic, int
wait);
diff -r b07a720e30de tools/libxl/libxl_device.c
--- a/tools/libxl/libxl_device.c Mon Dec 07 15:19:24 2009 +0000
+++ b/tools/libxl/libxl_device.c Mon Dec 07 15:20:05 2009 +0000
@@ -26,7 +26,7 @@
#include "libxl.h"
#include "libxl_internal.h"
-char *string_of_kinds[] = {
+const char *string_of_kinds[] = {
[DEVICE_VIF] = "vif",
[DEVICE_VBD] = "vbd",
[DEVICE_TAP] = "tap",
diff -r b07a720e30de tools/libxl/libxl_internal.h
--- a/tools/libxl/libxl_internal.h Mon Dec 07 15:19:24 2009 +0000
+++ b/tools/libxl/libxl_internal.h Mon Dec 07 15:20:05 2009 +0000
@@ -44,6 +44,8 @@
DEVICE_VKBD,
DEVICE_CONSOLE,
} libxl_device_kinds;
+
+extern const char *string_of_kinds[];
typedef struct {
uint32_t backend_devid;
diff -r b07a720e30de tools/libxl/libxl_utils.c
--- a/tools/libxl/libxl_utils.c Mon Dec 07 15:19:24 2009 +0000
+++ b/tools/libxl/libxl_utils.c Mon Dec 07 15:20:05 2009 +0000
@@ -214,3 +214,33 @@
return 0;
}
+int libxl_string_to_phystype(struct libxl_ctx *ctx, char *s,
libxl_disk_phystype *phystype)
+{
+ char *p;
+ int rc = 0;
+
+ if (!strcmp(s, "phy")) {
+ *phystype = PHYSTYPE_PHY;
+ } else if (!strcmp(s, "file")) {
+ *phystype = PHYSTYPE_FILE;
+ } else if (!strcmp(s, "tap")) {
+ p = strchr(s, ':');
+ if (!p) {
+ rc = -1;
+ goto out;
+ }
+ p++;
+ if (!strcmp(p, "aio")) {
+ *phystype = PHYSTYPE_AIO;
+ } else if (!strcmp(p, "vhd")) {
+ *phystype = PHYSTYPE_VHD;
+ } else if (!strcmp(p, "qcow")) {
+ *phystype = PHYSTYPE_QCOW;
+ } else if (!strcmp(p, "qcow2")) {
+ *phystype = PHYSTYPE_QCOW2;
+ }
+ }
+out:
+ return rc;
+}
+
diff -r b07a720e30de tools/libxl/libxl_utils.h
--- a/tools/libxl/libxl_utils.h Mon Dec 07 15:19:24 2009 +0000
+++ b/tools/libxl/libxl_utils.h Mon Dec 07 15:20:05 2009 +0000
@@ -32,6 +32,7 @@
int libxl_get_stubdom_id(struct libxl_ctx *ctx, int guest_domid);
int libxl_is_stubdom(struct libxl_ctx *ctx, int domid);
int libxl_create_logfile(struct libxl_ctx *ctx, char *name, char **full_name);
+int libxl_string_to_phystype(struct libxl_ctx *ctx, char *s,
libxl_disk_phystype *phystype);
#endif
diff -r b07a720e30de tools/libxl/xl.c
--- a/tools/libxl/xl.c Mon Dec 07 15:19:24 2009 +0000
+++ b/tools/libxl/xl.c Mon Dec 07 15:20:05 2009 +0000
@@ -356,12 +356,14 @@
if (p2 == NULL) {
(*disks)[*num_disks].virtpath = strdup(p);
(*disks)[*num_disks].is_cdrom = 0;
+ (*disks)[*num_disks].unpluggable = 1;
} else {
*p2 = '\0';
(*disks)[*num_disks].virtpath = strdup(p);
- if (!strcmp(p2 + 1, "cdrom"))
+ if (!strcmp(p2 + 1, "cdrom")) {
(*disks)[*num_disks].is_cdrom = 1;
- else
+ (*disks)[*num_disks].unpluggable = 1;
+ } else
(*disks)[*num_disks].is_cdrom = 0;
}
p = strtok(NULL, ",");
@@ -594,6 +596,7 @@
int i, fd;
int need_daemon = 1;
libxl_device_model_starting *dm_starting = 0;
+ libxl_waiter *w1 = NULL, *w2 = NULL;
memset(&dm_info, 0x00, sizeof(dm_info));
printf("Parsing config file %s\n", config_file);
@@ -671,12 +674,17 @@
need_daemon = 0;
}
XL_LOG(&ctx, XL_LOG_DEBUG, "Waiting for domain %s (domid %d) to die",
info1.name, domid);
-
- libxl_wait_for_domain_death(&ctx, domid, &fd);
+ w1 = (libxl_waiter*) malloc(sizeof(libxl_waiter) * num_disks);
+ w2 = (libxl_waiter*) malloc(sizeof(libxl_waiter));
+ libxl_wait_for_disk_ejects(&ctx, domid, disks, num_disks, w1);
+ libxl_wait_for_domain_death(&ctx, domid, w2);
+ libxl_get_wait_fd(&ctx, &fd);
while (1) {
int ret;
fd_set rfds;
xc_dominfo_t info;
+ libxl_event event;
+ libxl_device_disk disk;
memset(&info, 0x00, sizeof(xc_dominfo_t));
FD_ZERO(&rfds);
@@ -685,21 +693,35 @@
ret = select(fd + 1, &rfds, NULL, NULL, NULL);
if (!ret)
continue;
- if (libxl_is_domain_dead(&ctx, domid, &info)) {
- XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d is dead", domid);
- if (info.crashed || info.dying || (info.shutdown &&
(info.shutdown_reason != SHUTDOWN_suspend))) {
- XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d needs to be clean:
destroying the domain", domid);
- libxl_domain_destroy(&ctx, domid, 0);
- if (info.shutdown && (info.shutdown_reason ==
SHUTDOWN_reboot)) {
- libxl_ctx_free(&ctx);
- XL_LOG(&ctx, XL_LOG_DEBUG, "Done. Rebooting now");
- goto start;
+ libxl_get_event(&ctx, &event);
+ switch (event.type) {
+ case DOMAIN_DEATH:
+ if (libxl_event_get_domain_death_info(&ctx, domid, &event,
&info)) {
+ XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d is dead", domid);
+ if (info.crashed || info.dying || (info.shutdown &&
(info.shutdown_reason != SHUTDOWN_suspend))) {
+ XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d needs to be
clean: destroying the domain", domid);
+ libxl_domain_destroy(&ctx, domid, 0);
+ if (info.shutdown && (info.shutdown_reason ==
SHUTDOWN_reboot)) {
+ libxl_free_waiter(w1);
+ libxl_free_waiter(w2);
+ free(w1);
+ free(w2);
+ libxl_ctx_free(&ctx);
+ XL_LOG(&ctx, XL_LOG_DEBUG, "Done. Rebooting now");
+ goto start;
+ }
+ XL_LOG(&ctx, XL_LOG_DEBUG, "Done. Exiting now");
+ }
+ XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d does not need to be
clean, exiting now", domid);
+ exit(0);
}
- XL_LOG(&ctx, XL_LOG_DEBUG, "Done. Exiting now");
- }
- XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d does not need to be clean,
exiting now", domid);
- exit(0);
+ break;
+ case DISK_EJECT:
+ if (libxl_event_get_disk_eject_info(&ctx, domid, &event,
&disk))
+ libxl_cdrom_insert(&ctx, domid, &disk);
+ break;
}
+ libxl_free_event(&event);
}
close(logfile);
@@ -730,6 +752,8 @@
printf(" console attach to domain's
console\n\n");
printf(" save save a domain state to restore
later\n\n");
printf(" restore restore a domain from a saved
state\n\n");
+ printf(" cd-insert insert a cdrom into a guest's
cd drive\n\n");
+ printf(" cd-eject eject a cdrom from a guest's cd
drive\n\n");
} else if(!strcmp(command, "create")) {
printf("Usage: xl create <ConfigFile> [options] [vars]\n\n");
printf("Create a domain based on <ConfigFile>.\n\n");
@@ -772,6 +796,12 @@
} else if (!strcmp(command, "console")) {
printf("Usage: xl console <Domain>\n\n");
printf("Attach to domain's console.\n\n");
+ } else if (!strcmp(command, "cd-insert")) {
+ printf("Usage: xl cd-insert <Domain> <VirtualDevice> <type:path>\n\n");
+ printf("Insert a cdrom into a guest's cd drive.\n\n");
+ } else if (!strcmp(command, "cd-eject")) {
+ printf("Usage: xl cd-eject <Domain> <VirtualDevice>\n\n");
+ printf("Eject a cdrom from a guest's cd drive.\n\n");
}
}
@@ -788,6 +818,108 @@
exit(2);
}
libxl_console_attach(&ctx, domid, cons_num);
+}
+
+void cd_insert(char *dom, char *virtdev, char *phys)
+{
+ struct libxl_ctx ctx;
+ uint32_t domid;
+ libxl_device_disk disk;
+ char *p;
+
+ libxl_ctx_init(&ctx);
+ libxl_ctx_set_log(&ctx, log_callback, NULL);
+
+ if (libxl_param_to_domid(&ctx, dom, &domid) < 0) {
+ fprintf(stderr, "%s is an invalid domain identifier\n", dom);
+ exit(2);
+ }
+
+ disk.backend_domid = 0;
+ disk.domid = domid;
+ if (phys) {
+ p = strchr(phys, ':');
+ if (!p) {
+ fprintf(stderr, "No type specified, ");
+ disk.physpath = phys;
+ if (!strncmp(phys, "/dev", 4)) {
+ fprintf(stderr, "assuming phy:\n");
+ disk.phystype = PHYSTYPE_PHY;
+ } else {
+ fprintf(stderr, "assuming file:\n");
+ disk.phystype = PHYSTYPE_FILE;
+ }
+ } else {
+ p = '\0';
+ disk.physpath = strdup(p);
+ p++;
+ libxl_string_to_phystype(&ctx, p, &disk.phystype);
+ }
+ } else {
+ disk.physpath = NULL;
+ disk.phystype = 0;
+ }
+ disk.virtpath = virtdev;
+ disk.unpluggable = 1;
+ disk.readwrite = 0;
+ disk.is_cdrom = 1;
+
+ libxl_cdrom_insert(&ctx, domid, &disk);
+}
+
+int main_cd_eject(int argc, char **argv)
+{
+ int opt = 0;
+ char *p = NULL, *virtdev;
+
+ while ((opt = getopt(argc, argv, "hn:")) != -1) {
+ switch (opt) {
+ case 'h':
+ help("cd-eject");
+ exit(0);
+ default:
+ fprintf(stderr, "option not supported\n");
+ break;
+ }
+ }
+ if (optind >= argc - 1) {
+ help("cd-eject");
+ exit(2);
+ }
+
+ p = argv[optind];
+ virtdev = argv[optind + 1];
+
+ cd_insert(p, virtdev, NULL);
+ exit(0);
+}
+
+int main_cd_insert(int argc, char **argv)
+{
+ int opt = 0;
+ char *p = NULL, *file = NULL, *virtdev;
+
+ while ((opt = getopt(argc, argv, "hn:")) != -1) {
+ switch (opt) {
+ case 'h':
+ help("cd-insert");
+ exit(0);
+ default:
+ fprintf(stderr, "option not supported\n");
+ break;
+ }
+ }
+ if (optind >= argc - 2) {
+ help("cd-insert");
+ exit(2);
+ }
+
+ p = argv[optind];
+ virtdev = argv[optind + 1];
+ file = argv[optind + 2];
+
+ cd_insert(p, virtdev, file);
+ exit(0);
}
int main_console(int argc, char **argv)
@@ -1298,6 +1430,10 @@
main_save(argc - 1, argv + 1);
} else if (!strcmp(argv[1], "restore")) {
main_restore(argc - 1, argv + 1);
+ } else if (!strcmp(argv[1], "cd-insert")) {
+ main_cd_insert(argc - 1, argv + 1);
+ } else if (!strcmp(argv[1], "cd-eject")) {
+ main_cd_eject(argc - 1, argv + 1);
} else if (!strcmp(argv[1], "help")) {
if (argc > 2)
help(argv[2]);
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|