summaryrefslogtreecommitdiffstats
path: root/daemon
diff options
context:
space:
mode:
authorRichard W.M. Jones <rjones@redhat.com>2012-10-03 10:50:51 +0100
committerRichard W.M. Jones <rjones@redhat.com>2012-10-08 20:04:47 +0100
commit7786d56db8c22413949f98ef6b15fe0ea367d195 (patch)
tree7234b2d5b450a21677a9cc19e0b1c506546fa1ee /daemon
parent3ad44c866042919374e2d840502e53da2ed8aef0 (diff)
downloadlibguestfs-7786d56db8c22413949f98ef6b15fe0ea367d195.tar.gz
libguestfs-7786d56db8c22413949f98ef6b15fe0ea367d195.tar.xz
libguestfs-7786d56db8c22413949f98ef6b15fe0ea367d195.zip
launch: Add add_drive 'label' option.
New API: list-disk-labels Allow the user to pass an optional disk label when adding a drive. This is passed through to qemu / libvirt using the disk serial field, and from there to the appliance which exposes it through udev, creating a special alias of the device /dev/disk/guestfs/<label>. Partitions are named /dev/disk/guestfs/<label><partnum>. virtio-blk and virtio-scsi limit the serial field to 20 bytes. We further limit the name to maximum 20 ASCII characters in [a-zA-Z]. list-devices and list-partitions are not changed: these calls still return raw block device names. However a new call, list-disk-labels, returns a hash table allowing callers to map between disk labels, and block device and partition names. This commit also includes a test.
Diffstat (limited to 'daemon')
-rw-r--r--daemon/devsparts.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/daemon/devsparts.c b/daemon/devsparts.c
index 8f6c5078..7e319cbe 100644
--- a/daemon/devsparts.c
+++ b/daemon/devsparts.c
@@ -24,6 +24,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
+#include <limits.h>
#include <sys/stat.h>
#include "c-ctype.h"
@@ -282,3 +283,78 @@ do_nr_devices (void)
return (int) i;
}
+
+#define GUESTFSDIR "/dev/disk/guestfs"
+
+char **
+do_list_disk_labels (void)
+{
+ DIR *dir = NULL;
+ struct dirent *d;
+ char *path = NULL, *rawdev = NULL;
+ DECLARE_STRINGSBUF (ret);
+
+ dir = opendir (GUESTFSDIR);
+ if (!dir) {
+ reply_with_perror ("opendir: %s", GUESTFSDIR);
+ return NULL;
+ }
+
+ errno = 0;
+ while ((d = readdir (dir)) != NULL) {
+ if (d->d_name[0] == '.')
+ continue;
+
+ if (asprintf (&path, "%s/%s", GUESTFSDIR, d->d_name) == -1) {
+ reply_with_perror ("asprintf");
+ free_stringslen (ret.argv, ret.size);
+ goto error;
+ }
+
+ rawdev = realpath (path, NULL);
+ if (rawdev == NULL) {
+ reply_with_perror ("realpath: %s", path);
+ free_stringslen (ret.argv, ret.size);
+ goto error;
+ }
+
+ free (path);
+ path = NULL;
+
+ if (add_string (&ret, d->d_name) == -1)
+ goto error;
+
+ if (add_string_nodup (&ret, rawdev) == -1)
+ goto error;
+ rawdev = NULL; /* buffer now owned by the stringsbuf */
+ }
+
+ /* Check readdir didn't fail */
+ if (errno != 0) {
+ reply_with_perror ("readdir: %s", GUESTFSDIR);
+ free_stringslen (ret.argv, ret.size);
+ goto error;
+ }
+
+ /* Close the directory handle */
+ if (closedir (dir) == -1) {
+ reply_with_perror ("closedir: %s", GUESTFSDIR);
+ free_stringslen (ret.argv, ret.size);
+ dir = NULL;
+ goto error;
+ }
+
+ dir = NULL;
+
+ if (end_stringsbuf (&ret) == -1)
+ goto error;
+
+ return ret.argv; /* caller frees */
+
+ error:
+ if (dir)
+ closedir (dir);
+ free (path);
+ free (rawdev);
+ return NULL;
+}