summaryrefslogtreecommitdiffstats
path: root/daemon
diff options
context:
space:
mode:
authorRichard W.M. Jones <rjones@redhat.com>2012-03-17 14:36:28 +0000
committerRichard W.M. Jones <rjones@redhat.com>2012-03-17 14:36:28 +0000
commita4fd393663babbd242f209ed29033b3cb4943749 (patch)
treec7b66e95f7237e2e83fe3eafed36ced7b18c3b56 /daemon
parent05461175c48b9d7ac7c42d0a243971f489578295 (diff)
downloadlibguestfs-a4fd393663babbd242f209ed29033b3cb4943749.tar.gz
libguestfs-a4fd393663babbd242f209ed29033b3cb4943749.tar.xz
libguestfs-a4fd393663babbd242f209ed29033b3cb4943749.zip
New API: vgmeta: Download volume group metadata.
Diffstat (limited to 'daemon')
-rw-r--r--daemon/lvm.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/daemon/lvm.c b/daemon/lvm.c
index 9103a33d..06fdbff0 100644
--- a/daemon/lvm.c
+++ b/daemon/lvm.c
@@ -23,6 +23,7 @@
#include <inttypes.h>
#include <string.h>
#include <unistd.h>
+#include <fcntl.h>
#include <sys/stat.h>
#include <dirent.h>
@@ -872,3 +873,90 @@ do_list_dm_devices (void)
return ret.argv;
}
+
+char *
+do_vgmeta (const char *vg, size_t *size_r)
+{
+ char *err;
+ int fd, r;
+ char tmp[] = "/tmp/vgmetaXXXXXX";
+ size_t alloc, size, max;
+ ssize_t rs;
+ char *buf, *buf2;
+
+ /* Make a temporary file. */
+ fd = mkstemp (tmp);
+ if (fd == -1) {
+ reply_with_perror ("mkstemp");
+ return NULL;
+ }
+
+ close (fd);
+
+ r = command (NULL, &err, "lvm", "vgcfgbackup", "-f", tmp, vg, NULL);
+ if (r == -1) {
+ reply_with_error ("vgcfgbackup: %s", err);
+ free (err);
+ return NULL;
+ }
+ free (err);
+
+ /* Now read back the temporary file. */
+ fd = open (tmp, O_RDONLY|O_CLOEXEC);
+ if (fd == -1) {
+ reply_with_error ("%s", tmp);
+ return NULL;
+ }
+
+ /* Read up to GUESTFS_MESSAGE_MAX - <overhead> bytes. If it's
+ * larger than that, we need to return an error instead (for
+ * correctness).
+ */
+ max = GUESTFS_MESSAGE_MAX - 1000;
+ buf = NULL;
+ size = alloc = 0;
+
+ for (;;) {
+ if (size >= alloc) {
+ alloc += 8192;
+ if (alloc > max) {
+ reply_with_error ("metadata is too large for message buffer");
+ free (buf);
+ close (fd);
+ return NULL;
+ }
+ buf2 = realloc (buf, alloc);
+ if (buf2 == NULL) {
+ reply_with_perror ("realloc");
+ free (buf);
+ close (fd);
+ return NULL;
+ }
+ buf = buf2;
+ }
+
+ rs = read (fd, buf + size, alloc - size);
+ if (rs == -1) {
+ reply_with_perror ("read: %s", tmp);
+ free (buf);
+ close (fd);
+ return NULL;
+ }
+ if (rs == 0)
+ break;
+ if (rs > 0)
+ size += rs;
+ }
+
+ if (close (fd) == -1) {
+ reply_with_perror ("close: %s", tmp);
+ free (buf);
+ return NULL;
+ }
+
+ unlink (tmp);
+
+ *size_r = size;
+
+ return buf; /* caller will free */
+}