Implement simple lvs/vgs/pvs commands.
authorRichard Jones <rjones@redhat.com>
Tue, 7 Apr 2009 09:25:46 +0000 (10:25 +0100)
committerRichard Jones <rjones@redhat.com>
Tue, 7 Apr 2009 09:25:46 +0000 (10:25 +0100)
daemon/actions.h
daemon/lvm.c
daemon/stubs.c
fish/cmds.c
guestfs-actions.pod
src/generator.ml
src/guestfs-actions.c
src/guestfs-actions.h
src/guestfs_protocol.c
src/guestfs_protocol.h
src/guestfs_protocol.x

index 194986f..02fe55e 100644 (file)
@@ -29,6 +29,9 @@ extern char *do_ll (const char *directory);
 extern char **do_ls (const char *directory);
 extern char **do_list_devices ();
 extern char **do_list_partitions ();
 extern char **do_ls (const char *directory);
 extern char **do_list_devices ();
 extern char **do_list_partitions ();
+extern char **do_pvs ();
+extern char **do_vgs ();
+extern char **do_lvs ();
 extern guestfs_lvm_int_pv_list *do_pvs_full ();
 extern guestfs_lvm_int_vg_list *do_vgs_full ();
 extern guestfs_lvm_int_lv_list *do_lvs_full ();
 extern guestfs_lvm_int_pv_list *do_pvs_full ();
 extern guestfs_lvm_int_vg_list *do_vgs_full ();
 extern guestfs_lvm_int_lv_list *do_lvs_full ();
index 43f5cd1..bc38547 100644 (file)
  * of writing it hasn't progressed very far.
  */
 
  * of writing it hasn't progressed very far.
  */
 
+static char **
+convert_lvm_output (char *out, char *prefix)
+{
+  char *p, *pend;
+  char **r = NULL;
+  int size = 0, alloc = 0;
+  char buf[256];
+  char *str;
+
+  p = out;
+  while (p) {
+    pend = strchr (p, '\n');   /* Get the next line of output. */
+    if (pend) {
+      *pend = '\0';
+      pend++;
+    }
+
+    while (*p && isspace (*p)) /* Skip any leading whitespace. */
+      p++;
+
+    if (!*p) {                 /* Empty line?  Skip it. */
+      p = pend;
+      continue;
+    }
+
+    /* Prefix? */
+    if (prefix) {
+      snprintf (buf, sizeof buf, "%s%s", prefix, p);
+      str = buf;
+    } else
+      str = p;
+
+    if (add_string (&r, &size, &alloc, str) == -1) {
+      free (out);
+      return NULL;
+    }
+
+    p = pend;
+  }
+
+  free (out);
+
+  if (add_string (&r, &size, &alloc, NULL) == -1)
+    return NULL;
+
+  sort_strings (r, size-1);
+  return r;
+}
+
+char **
+do_pvs (void)
+{
+  char *out, *err;
+  int r;
+
+  r = command (&out, &err,
+              "/sbin/lvm", "pvs", "-o", "pv_name", "--noheadings", NULL);
+  if (r == -1) {
+    reply_with_error ("%s", err);
+    free (out);
+    free (err);
+    return NULL;
+  }
+
+  free (err);
+
+  return convert_lvm_output (out, NULL);
+}
+
+char **
+do_vgs (void)
+{
+  char *out, *err;
+  int r;
+
+  r = command (&out, &err,
+              "/sbin/lvm", "vgs", "-o", "vg_name", "--noheadings", NULL);
+  if (r == -1) {
+    reply_with_error ("%s", err);
+    free (out);
+    free (err);
+    return NULL;
+  }
+
+  free (err);
+
+  return convert_lvm_output (out, NULL);
+}
+
+char **
+do_lvs (void)
+{
+  char *out, *err;
+  int r;
+
+  r = command (&out, &err,
+              "/sbin/lvm", "lvs",
+              "-o", "vg_name,lv_name", "--noheadings",
+              "--separator", "/", NULL);
+  if (r == -1) {
+    reply_with_error ("%s", err);
+    free (out);
+    free (err);
+    return NULL;
+  }
+
+  free (err);
+
+  return convert_lvm_output (out, "/dev/");
+}
+
+/* These were so complex to implement that I ended up auto-generating
+ * the code.  That code is in stubs.c, and it is generated as usual
+ * by generator.ml.
+ */
 guestfs_lvm_int_pv_list *
 do_pvs_full (void)
 {
 guestfs_lvm_int_pv_list *
 do_pvs_full (void)
 {
index 63ca770..06a8600 100644 (file)
@@ -199,6 +199,54 @@ static void list_partitions_stub (XDR *xdr_in)
   free_strings (r);
 }
 
   free_strings (r);
 }
 
+static void pvs_stub (XDR *xdr_in)
+{
+  char **r;
+
+  r = do_pvs ();
+  if (r == NULL)
+    /* do_pvs has already called reply_with_error, so just return */
+    return;
+
+  struct guestfs_pvs_ret ret;
+  ret.physvols.physvols_len = count_strings (r);
+  ret.physvols.physvols_val = r;
+  reply ((xdrproc_t) &xdr_guestfs_pvs_ret, (char *) &ret);
+  free_strings (r);
+}
+
+static void vgs_stub (XDR *xdr_in)
+{
+  char **r;
+
+  r = do_vgs ();
+  if (r == NULL)
+    /* do_vgs has already called reply_with_error, so just return */
+    return;
+
+  struct guestfs_vgs_ret ret;
+  ret.volgroups.volgroups_len = count_strings (r);
+  ret.volgroups.volgroups_val = r;
+  reply ((xdrproc_t) &xdr_guestfs_vgs_ret, (char *) &ret);
+  free_strings (r);
+}
+
+static void lvs_stub (XDR *xdr_in)
+{
+  char **r;
+
+  r = do_lvs ();
+  if (r == NULL)
+    /* do_lvs has already called reply_with_error, so just return */
+    return;
+
+  struct guestfs_lvs_ret ret;
+  ret.logvols.logvols_len = count_strings (r);
+  ret.logvols.logvols_val = r;
+  reply ((xdrproc_t) &xdr_guestfs_lvs_ret, (char *) &ret);
+  free_strings (r);
+}
+
 static void pvs_full_stub (XDR *xdr_in)
 {
   guestfs_lvm_int_pv_list *r;
 static void pvs_full_stub (XDR *xdr_in)
 {
   guestfs_lvm_int_pv_list *r;
@@ -271,6 +319,15 @@ void dispatch_incoming_message (XDR *xdr_in)
     case GUESTFS_PROC_LIST_PARTITIONS:
       list_partitions_stub (xdr_in);
       break;
     case GUESTFS_PROC_LIST_PARTITIONS:
       list_partitions_stub (xdr_in);
       break;
+    case GUESTFS_PROC_PVS:
+      pvs_stub (xdr_in);
+      break;
+    case GUESTFS_PROC_VGS:
+      vgs_stub (xdr_in);
+      break;
+    case GUESTFS_PROC_LVS:
+      lvs_stub (xdr_in);
+      break;
     case GUESTFS_PROC_PVS_FULL:
       pvs_full_stub (xdr_in);
       break;
     case GUESTFS_PROC_PVS_FULL:
       pvs_full_stub (xdr_in);
       break;
index dc951e3..1035b67 100644 (file)
@@ -36,11 +36,14 @@ void list_commands (void)
   printf ("%-20s %s\n", "list-partitions", "list the partitions");
   printf ("%-20s %s\n", "ll", "list the files in a directory (long format)");
   printf ("%-20s %s\n", "ls", "list the files in a directory");
   printf ("%-20s %s\n", "list-partitions", "list the partitions");
   printf ("%-20s %s\n", "ll", "list the files in a directory (long format)");
   printf ("%-20s %s\n", "ls", "list the files in a directory");
+  printf ("%-20s %s\n", "lvs", "list the LVM logical volumes (LVs)");
   printf ("%-20s %s\n", "lvs-full", "list the LVM logical volumes (LVs)");
   printf ("%-20s %s\n", "mount", "mount a guest disk at a position in the filesystem");
   printf ("%-20s %s\n", "lvs-full", "list the LVM logical volumes (LVs)");
   printf ("%-20s %s\n", "mount", "mount a guest disk at a position in the filesystem");
+  printf ("%-20s %s\n", "pvs", "list the LVM physical volumes (PVs)");
   printf ("%-20s %s\n", "pvs-full", "list the LVM physical volumes (PVs)");
   printf ("%-20s %s\n", "sync", "sync disks, writes are flushed through to the disk image");
   printf ("%-20s %s\n", "touch", "update file timestamps or create a new file");
   printf ("%-20s %s\n", "pvs-full", "list the LVM physical volumes (PVs)");
   printf ("%-20s %s\n", "sync", "sync disks, writes are flushed through to the disk image");
   printf ("%-20s %s\n", "touch", "update file timestamps or create a new file");
+  printf ("%-20s %s\n", "vgs", "list the LVM volume groups (VGs)");
   printf ("%-20s %s\n", "vgs-full", "list the LVM volume groups (VGs)");
   printf ("    Use -h <cmd> / help <cmd> to show detailed help for a command.\n");
 }
   printf ("%-20s %s\n", "vgs-full", "list the LVM volume groups (VGs)");
   printf ("    Use -h <cmd> / help <cmd> to show detailed help for a command.\n");
 }
@@ -71,14 +74,23 @@ void display_command (const char *cmd)
   if (strcasecmp (cmd, "list_partitions") == 0 || strcasecmp (cmd, "list-partitions") == 0)
     pod2text ("list-partitions - list the partitions", " list-partitions\n\nList all the partitions detected on all block devices.\n\nThe full partition device names are returned, eg. C</dev/sda1>\n\nThis does not return logical volumes.  For that you will need to\ncall C<guestfs_lvs>.");
   else
   if (strcasecmp (cmd, "list_partitions") == 0 || strcasecmp (cmd, "list-partitions") == 0)
     pod2text ("list-partitions - list the partitions", " list-partitions\n\nList all the partitions detected on all block devices.\n\nThe full partition device names are returned, eg. C</dev/sda1>\n\nThis does not return logical volumes.  For that you will need to\ncall C<guestfs_lvs>.");
   else
+  if (strcasecmp (cmd, "pvs") == 0)
+    pod2text ("pvs - list the LVM physical volumes (PVs)", " pvs\n\nList all the physical volumes detected.  This is the equivalent\nof the L<pvs(8)> command.\n\nThis returns a list of just the device names that contain\nPVs (eg. C</dev/sda2>).\n\nSee also C<guestfs_pvs_full>.");
+  else
+  if (strcasecmp (cmd, "vgs") == 0)
+    pod2text ("vgs - list the LVM volume groups (VGs)", " vgs\n\nList all the volumes groups detected.  This is the equivalent\nof the L<vgs(8)> command.\n\nThis returns a list of just the volume group names that were\ndetected (eg. C<VolGroup00>).\n\nSee also C<guestfs_vgs_full>.");
+  else
+  if (strcasecmp (cmd, "lvs") == 0)
+    pod2text ("lvs - list the LVM logical volumes (LVs)", " lvs\n\nList all the logical volumes detected.  This is the equivalent\nof the L<lvs(8)> command.\n\nThis returns a list of the logical volume device names\n(eg. C</dev/VolGroup00/LogVol00>).\n\nSee also C<guestfs_lvs_full>.");
+  else
   if (strcasecmp (cmd, "pvs_full") == 0 || strcasecmp (cmd, "pvs-full") == 0)
   if (strcasecmp (cmd, "pvs_full") == 0 || strcasecmp (cmd, "pvs-full") == 0)
-    pod2text ("pvs-full - list the LVM physical volumes (PVs)", " pvs-full\n\nList all the physical volumes detected.  This is the equivalent\nof the L<pvs(8)> command.");
+    pod2text ("pvs-full - list the LVM physical volumes (PVs)", " pvs-full\n\nList all the physical volumes detected.  This is the equivalent\nof the L<pvs(8)> command.  The \"full\" version includes all fields.");
   else
   if (strcasecmp (cmd, "vgs_full") == 0 || strcasecmp (cmd, "vgs-full") == 0)
   else
   if (strcasecmp (cmd, "vgs_full") == 0 || strcasecmp (cmd, "vgs-full") == 0)
-    pod2text ("vgs-full - list the LVM volume groups (VGs)", " vgs-full\n\nList all the volumes groups detected.  This is the equivalent\nof the L<vgs(8)> command.");
+    pod2text ("vgs-full - list the LVM volume groups (VGs)", " vgs-full\n\nList all the volumes groups detected.  This is the equivalent\nof the L<vgs(8)> command.  The \"full\" version includes all fields.");
   else
   if (strcasecmp (cmd, "lvs_full") == 0 || strcasecmp (cmd, "lvs-full") == 0)
   else
   if (strcasecmp (cmd, "lvs_full") == 0 || strcasecmp (cmd, "lvs-full") == 0)
-    pod2text ("lvs-full - list the LVM logical volumes (LVs)", " lvs-full\n\nList all the logical volumes detected.  This is the equivalent\nof the L<lvs(8)> command.");
+    pod2text ("lvs-full - list the LVM logical volumes (LVs)", " lvs-full\n\nList all the logical volumes detected.  This is the equivalent\nof the L<lvs(8)> command.  The \"full\" version includes all fields.");
   else
     display_builtin_command (cmd);
 }
   else
     display_builtin_command (cmd);
 }
@@ -308,6 +320,51 @@ static int run_list_partitions (const char *cmd, int argc, char *argv[])
   return 0;
 }
 
   return 0;
 }
 
+static int run_pvs (const char *cmd, int argc, char *argv[])
+{
+  char **r;
+  if (argc != 0) {
+    fprintf (stderr, "%s should have 0 parameter(s)\n", cmd);
+    fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+    return -1;
+  }
+  r = guestfs_pvs (g);
+  if (r == NULL) return -1;
+  print_strings (r);
+  free_strings (r);
+  return 0;
+}
+
+static int run_vgs (const char *cmd, int argc, char *argv[])
+{
+  char **r;
+  if (argc != 0) {
+    fprintf (stderr, "%s should have 0 parameter(s)\n", cmd);
+    fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+    return -1;
+  }
+  r = guestfs_vgs (g);
+  if (r == NULL) return -1;
+  print_strings (r);
+  free_strings (r);
+  return 0;
+}
+
+static int run_lvs (const char *cmd, int argc, char *argv[])
+{
+  char **r;
+  if (argc != 0) {
+    fprintf (stderr, "%s should have 0 parameter(s)\n", cmd);
+    fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+    return -1;
+  }
+  r = guestfs_lvs (g);
+  if (r == NULL) return -1;
+  print_strings (r);
+  free_strings (r);
+  return 0;
+}
+
 static int run_pvs_full (const char *cmd, int argc, char *argv[])
 {
   struct guestfs_lvm_pv_list *r;
 static int run_pvs_full (const char *cmd, int argc, char *argv[])
 {
   struct guestfs_lvm_pv_list *r;
@@ -379,6 +436,15 @@ int run_action (const char *cmd, int argc, char *argv[])
   if (strcasecmp (cmd, "list_partitions") == 0 || strcasecmp (cmd, "list-partitions") == 0)
     return run_list_partitions (cmd, argc, argv);
   else
   if (strcasecmp (cmd, "list_partitions") == 0 || strcasecmp (cmd, "list-partitions") == 0)
     return run_list_partitions (cmd, argc, argv);
   else
+  if (strcasecmp (cmd, "pvs") == 0)
+    return run_pvs (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "vgs") == 0)
+    return run_vgs (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "lvs") == 0)
+    return run_lvs (cmd, argc, argv);
+  else
   if (strcasecmp (cmd, "pvs_full") == 0 || strcasecmp (cmd, "pvs-full") == 0)
     return run_pvs_full (cmd, argc, argv);
   else
   if (strcasecmp (cmd, "pvs_full") == 0 || strcasecmp (cmd, "pvs-full") == 0)
     return run_pvs_full (cmd, argc, argv);
   else
index 1a57ae2..eb3898a 100644 (file)
@@ -75,12 +75,28 @@ This function returns a NULL-terminated array of strings
 (like L<environ(3)>), or NULL if there was an error.
 I<The caller must free the strings and the array after use>.
 
 (like L<environ(3)>), or NULL if there was an error.
 I<The caller must free the strings and the array after use>.
 
+=head2 guestfs_lvs
+
+ char **guestfs_lvs (guestfs_h *handle);
+
+List all the logical volumes detected.  This is the equivalent
+of the L<lvs(8)> command.
+
+This returns a list of the logical volume device names
+(eg. C</dev/VolGroup00/LogVol00>).
+
+See also C<guestfs_lvs_full>.
+
+This function returns a NULL-terminated array of strings
+(like L<environ(3)>), or NULL if there was an error.
+I<The caller must free the strings and the array after use>.
+
 =head2 guestfs_lvs_full
 
  struct guestfs_lvm_lv_list *guestfs_lvs_full (guestfs_h *handle);
 
 List all the logical volumes detected.  This is the equivalent
 =head2 guestfs_lvs_full
 
  struct guestfs_lvm_lv_list *guestfs_lvs_full (guestfs_h *handle);
 
 List all the logical volumes detected.  This is the equivalent
-of the L<lvs(8)> command.
+of the L<lvs(8)> command.  The "full" version includes all fields.
 
 This function returns a C<struct guestfs_lvm_lv_list>.
 I<The caller must call C<guestfs_free_lvm_lv_list> after use.>.
 
 This function returns a C<struct guestfs_lvm_lv_list>.
 I<The caller must call C<guestfs_free_lvm_lv_list> after use.>.
@@ -110,12 +126,28 @@ call, in order to improve reliability.
 
 This function returns 0 on success or -1 on error.
 
 
 This function returns 0 on success or -1 on error.
 
+=head2 guestfs_pvs
+
+ char **guestfs_pvs (guestfs_h *handle);
+
+List all the physical volumes detected.  This is the equivalent
+of the L<pvs(8)> command.
+
+This returns a list of just the device names that contain
+PVs (eg. C</dev/sda2>).
+
+See also C<guestfs_pvs_full>.
+
+This function returns a NULL-terminated array of strings
+(like L<environ(3)>), or NULL if there was an error.
+I<The caller must free the strings and the array after use>.
+
 =head2 guestfs_pvs_full
 
  struct guestfs_lvm_pv_list *guestfs_pvs_full (guestfs_h *handle);
 
 List all the physical volumes detected.  This is the equivalent
 =head2 guestfs_pvs_full
 
  struct guestfs_lvm_pv_list *guestfs_pvs_full (guestfs_h *handle);
 
 List all the physical volumes detected.  This is the equivalent
-of the L<pvs(8)> command.
+of the L<pvs(8)> command.  The "full" version includes all fields.
 
 This function returns a C<struct guestfs_lvm_pv_list>.
 I<The caller must call C<guestfs_free_lvm_pv_list> after use.>.
 
 This function returns a C<struct guestfs_lvm_pv_list>.
 I<The caller must call C<guestfs_free_lvm_pv_list> after use.>.
@@ -143,12 +175,28 @@ to create a new zero-length file.
 
 This function returns 0 on success or -1 on error.
 
 
 This function returns 0 on success or -1 on error.
 
+=head2 guestfs_vgs
+
+ char **guestfs_vgs (guestfs_h *handle);
+
+List all the volumes groups detected.  This is the equivalent
+of the L<vgs(8)> command.
+
+This returns a list of just the volume group names that were
+detected (eg. C<VolGroup00>).
+
+See also C<guestfs_vgs_full>.
+
+This function returns a NULL-terminated array of strings
+(like L<environ(3)>), or NULL if there was an error.
+I<The caller must free the strings and the array after use>.
+
 =head2 guestfs_vgs_full
 
  struct guestfs_lvm_vg_list *guestfs_vgs_full (guestfs_h *handle);
 
 List all the volumes groups detected.  This is the equivalent
 =head2 guestfs_vgs_full
 
  struct guestfs_lvm_vg_list *guestfs_vgs_full (guestfs_h *handle);
 
 List all the volumes groups detected.  This is the equivalent
-of the L<vgs(8)> command.
+of the L<vgs(8)> command.  The "full" version includes all fields.
 
 This function returns a C<struct guestfs_lvm_vg_list>.
 I<The caller must call C<guestfs_free_lvm_vg_list> after use.>.
 
 This function returns a C<struct guestfs_lvm_vg_list>.
 I<The caller must call C<guestfs_free_lvm_vg_list> after use.>.
index 69981f0..d598975 100755 (executable)
@@ -135,43 +135,56 @@ The full partition device names are returned, eg. C</dev/sda1>
 This does not return logical volumes.  For that you will need to
 call C<guestfs_lvs>.");
 
 This does not return logical volumes.  For that you will need to
 call C<guestfs_lvs>.");
 
-(*
-  ("pvs", (RPVList "physvols", P0), 9, [],
+  ("pvs", (RStringList "physvols", P0), 9, [],
    "list the LVM physical volumes (PVs)",
    "\
 List all the physical volumes detected.  This is the equivalent
    "list the LVM physical volumes (PVs)",
    "\
 List all the physical volumes detected.  This is the equivalent
-of the L<pvs(8)> command.");
+of the L<pvs(8)> command.
 
 
-  ("vgs", (RVGList "volgroups", P0), 10, [],
+This returns a list of just the device names that contain
+PVs (eg. C</dev/sda2>).
+
+See also C<guestfs_pvs_full>.");
+
+  ("vgs", (RStringList "volgroups", P0), 10, [],
    "list the LVM volume groups (VGs)",
    "\
 List all the volumes groups detected.  This is the equivalent
    "list the LVM volume groups (VGs)",
    "\
 List all the volumes groups detected.  This is the equivalent
-of the L<vgs(8)> command.");
+of the L<vgs(8)> command.
+
+This returns a list of just the volume group names that were
+detected (eg. C<VolGroup00>).
+
+See also C<guestfs_vgs_full>.");
 
 
-  ("lvs", (RLVList "logvols", P0), 11, [],
+  ("lvs", (RStringList "logvols", P0), 11, [],
    "list the LVM logical volumes (LVs)",
    "\
 List all the logical volumes detected.  This is the equivalent
    "list the LVM logical volumes (LVs)",
    "\
 List all the logical volumes detected.  This is the equivalent
-of the L<lvs(8)> command.");
-*)
+of the L<lvs(8)> command.
+
+This returns a list of the logical volume device names
+(eg. C</dev/VolGroup00/LogVol00>).
+
+See also C<guestfs_lvs_full>.");
 
   ("pvs_full", (RPVList "physvols", P0), 12, [],
    "list the LVM physical volumes (PVs)",
    "\
 List all the physical volumes detected.  This is the equivalent
 
   ("pvs_full", (RPVList "physvols", P0), 12, [],
    "list the LVM physical volumes (PVs)",
    "\
 List all the physical volumes detected.  This is the equivalent
-of the L<pvs(8)> command.");
+of the L<pvs(8)> command.  The \"full\" version includes all fields.");
 
   ("vgs_full", (RVGList "volgroups", P0), 13, [],
    "list the LVM volume groups (VGs)",
    "\
 List all the volumes groups detected.  This is the equivalent
 
   ("vgs_full", (RVGList "volgroups", P0), 13, [],
    "list the LVM volume groups (VGs)",
    "\
 List all the volumes groups detected.  This is the equivalent
-of the L<vgs(8)> command.");
+of the L<vgs(8)> command.  The \"full\" version includes all fields.");
 
   ("lvs_full", (RLVList "logvols", P0), 14, [],
    "list the LVM logical volumes (LVs)",
    "\
 List all the logical volumes detected.  This is the equivalent
 
   ("lvs_full", (RLVList "logvols", P0), 14, [],
    "list the LVM logical volumes (LVs)",
    "\
 List all the logical volumes detected.  This is the equivalent
-of the L<lvs(8)> command.");
+of the L<lvs(8)> command.  The \"full\" version includes all fields.");
 ]
 
 (* Column names and types from LVM PVs/VGs/LVs. *)
 ]
 
 (* Column names and types from LVM PVs/VGs/LVs. *)
index e3598eb..3446a2d 100644 (file)
@@ -595,6 +595,225 @@ char **guestfs_list_partitions (guestfs_h *g)
   return rv.ret.partitions.partitions_val;
 }
 
   return rv.ret.partitions.partitions_val;
 }
 
+struct pvs_rv {
+  int cb_done;  /* flag to indicate callback was called */
+  struct guestfs_message_header hdr;
+  struct guestfs_message_error err;
+  struct guestfs_pvs_ret ret;
+};
+
+static void pvs_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+  struct pvs_rv *rv = (struct pvs_rv *) data;
+
+  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+    error (g, "guestfs_pvs: failed to parse reply header");
+    return;
+  }
+  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+      error (g, "guestfs_pvs: failed to parse reply error");
+      return;
+    }
+    goto done;
+  }
+  if (!xdr_guestfs_pvs_ret (xdr, &rv->ret)) {
+    error (g, "guestfs_pvs: failed to parse reply");
+    return;
+  }
+ done:
+  rv->cb_done = 1;
+  main_loop.main_loop_quit (g);
+}
+
+char **guestfs_pvs (guestfs_h *g)
+{
+  struct pvs_rv rv;
+  int serial;
+
+  if (g->state != READY) {
+    error (g, "guestfs_pvs called from the wrong state, %d != READY",
+      g->state);
+    return NULL;
+  }
+
+  memset (&rv, 0, sizeof rv);
+
+  serial = dispatch (g, GUESTFS_PROC_PVS, NULL, NULL);
+  if (serial == -1)
+    return NULL;
+
+  rv.cb_done = 0;
+  g->reply_cb_internal = pvs_cb;
+  g->reply_cb_internal_data = &rv;
+  main_loop.main_loop_run (g);
+  g->reply_cb_internal = NULL;
+  g->reply_cb_internal_data = NULL;
+  if (!rv.cb_done) {
+    error (g, "guestfs_pvs failed, see earlier error messages");
+    return NULL;
+  }
+
+  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_PVS, serial) == -1)
+    return NULL;
+
+  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", rv.err.error);
+    return NULL;
+  }
+
+  /* caller will free this, but we need to add a NULL entry */
+  rv.ret.physvols.physvols_val = safe_realloc (g, rv.ret.physvols.physvols_val, rv.ret.physvols.physvols_len + 1);
+  rv.ret.physvols.physvols_val[rv.ret.physvols.physvols_len] = NULL;
+  return rv.ret.physvols.physvols_val;
+}
+
+struct vgs_rv {
+  int cb_done;  /* flag to indicate callback was called */
+  struct guestfs_message_header hdr;
+  struct guestfs_message_error err;
+  struct guestfs_vgs_ret ret;
+};
+
+static void vgs_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+  struct vgs_rv *rv = (struct vgs_rv *) data;
+
+  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+    error (g, "guestfs_vgs: failed to parse reply header");
+    return;
+  }
+  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+      error (g, "guestfs_vgs: failed to parse reply error");
+      return;
+    }
+    goto done;
+  }
+  if (!xdr_guestfs_vgs_ret (xdr, &rv->ret)) {
+    error (g, "guestfs_vgs: failed to parse reply");
+    return;
+  }
+ done:
+  rv->cb_done = 1;
+  main_loop.main_loop_quit (g);
+}
+
+char **guestfs_vgs (guestfs_h *g)
+{
+  struct vgs_rv rv;
+  int serial;
+
+  if (g->state != READY) {
+    error (g, "guestfs_vgs called from the wrong state, %d != READY",
+      g->state);
+    return NULL;
+  }
+
+  memset (&rv, 0, sizeof rv);
+
+  serial = dispatch (g, GUESTFS_PROC_VGS, NULL, NULL);
+  if (serial == -1)
+    return NULL;
+
+  rv.cb_done = 0;
+  g->reply_cb_internal = vgs_cb;
+  g->reply_cb_internal_data = &rv;
+  main_loop.main_loop_run (g);
+  g->reply_cb_internal = NULL;
+  g->reply_cb_internal_data = NULL;
+  if (!rv.cb_done) {
+    error (g, "guestfs_vgs failed, see earlier error messages");
+    return NULL;
+  }
+
+  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_VGS, serial) == -1)
+    return NULL;
+
+  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", rv.err.error);
+    return NULL;
+  }
+
+  /* caller will free this, but we need to add a NULL entry */
+  rv.ret.volgroups.volgroups_val = safe_realloc (g, rv.ret.volgroups.volgroups_val, rv.ret.volgroups.volgroups_len + 1);
+  rv.ret.volgroups.volgroups_val[rv.ret.volgroups.volgroups_len] = NULL;
+  return rv.ret.volgroups.volgroups_val;
+}
+
+struct lvs_rv {
+  int cb_done;  /* flag to indicate callback was called */
+  struct guestfs_message_header hdr;
+  struct guestfs_message_error err;
+  struct guestfs_lvs_ret ret;
+};
+
+static void lvs_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+  struct lvs_rv *rv = (struct lvs_rv *) data;
+
+  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+    error (g, "guestfs_lvs: failed to parse reply header");
+    return;
+  }
+  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+      error (g, "guestfs_lvs: failed to parse reply error");
+      return;
+    }
+    goto done;
+  }
+  if (!xdr_guestfs_lvs_ret (xdr, &rv->ret)) {
+    error (g, "guestfs_lvs: failed to parse reply");
+    return;
+  }
+ done:
+  rv->cb_done = 1;
+  main_loop.main_loop_quit (g);
+}
+
+char **guestfs_lvs (guestfs_h *g)
+{
+  struct lvs_rv rv;
+  int serial;
+
+  if (g->state != READY) {
+    error (g, "guestfs_lvs called from the wrong state, %d != READY",
+      g->state);
+    return NULL;
+  }
+
+  memset (&rv, 0, sizeof rv);
+
+  serial = dispatch (g, GUESTFS_PROC_LVS, NULL, NULL);
+  if (serial == -1)
+    return NULL;
+
+  rv.cb_done = 0;
+  g->reply_cb_internal = lvs_cb;
+  g->reply_cb_internal_data = &rv;
+  main_loop.main_loop_run (g);
+  g->reply_cb_internal = NULL;
+  g->reply_cb_internal_data = NULL;
+  if (!rv.cb_done) {
+    error (g, "guestfs_lvs failed, see earlier error messages");
+    return NULL;
+  }
+
+  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_LVS, serial) == -1)
+    return NULL;
+
+  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", rv.err.error);
+    return NULL;
+  }
+
+  /* caller will free this, but we need to add a NULL entry */
+  rv.ret.logvols.logvols_val = safe_realloc (g, rv.ret.logvols.logvols_val, rv.ret.logvols.logvols_len + 1);
+  rv.ret.logvols.logvols_val[rv.ret.logvols.logvols_len] = NULL;
+  return rv.ret.logvols.logvols_val;
+}
+
 struct pvs_full_rv {
   int cb_done;  /* flag to indicate callback was called */
   struct guestfs_message_header hdr;
 struct pvs_full_rv {
   int cb_done;  /* flag to indicate callback was called */
   struct guestfs_message_header hdr;
index 8e73a5e..61eedd3 100644 (file)
@@ -27,6 +27,9 @@ extern char *guestfs_ll (guestfs_h *handle, const char *directory);
 extern char **guestfs_ls (guestfs_h *handle, const char *directory);
 extern char **guestfs_list_devices (guestfs_h *handle);
 extern char **guestfs_list_partitions (guestfs_h *handle);
 extern char **guestfs_ls (guestfs_h *handle, const char *directory);
 extern char **guestfs_list_devices (guestfs_h *handle);
 extern char **guestfs_list_partitions (guestfs_h *handle);
+extern char **guestfs_pvs (guestfs_h *handle);
+extern char **guestfs_vgs (guestfs_h *handle);
+extern char **guestfs_lvs (guestfs_h *handle);
 extern struct guestfs_lvm_pv_list *guestfs_pvs_full (guestfs_h *handle);
 extern struct guestfs_lvm_vg_list *guestfs_vgs_full (guestfs_h *handle);
 extern struct guestfs_lvm_lv_list *guestfs_lvs_full (guestfs_h *handle);
 extern struct guestfs_lvm_pv_list *guestfs_pvs_full (guestfs_h *handle);
 extern struct guestfs_lvm_vg_list *guestfs_vgs_full (guestfs_h *handle);
 extern struct guestfs_lvm_lv_list *guestfs_lvs_full (guestfs_h *handle);
index a19d7a1..2a194a7 100644 (file)
@@ -279,6 +279,39 @@ xdr_guestfs_list_partitions_ret (XDR *xdrs, guestfs_list_partitions_ret *objp)
 }
 
 bool_t
 }
 
 bool_t
+xdr_guestfs_pvs_ret (XDR *xdrs, guestfs_pvs_ret *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_array (xdrs, (char **)&objp->physvols.physvols_val, (u_int *) &objp->physvols.physvols_len, ~0,
+               sizeof (str), (xdrproc_t) xdr_str))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_guestfs_vgs_ret (XDR *xdrs, guestfs_vgs_ret *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_array (xdrs, (char **)&objp->volgroups.volgroups_val, (u_int *) &objp->volgroups.volgroups_len, ~0,
+               sizeof (str), (xdrproc_t) xdr_str))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_guestfs_lvs_ret (XDR *xdrs, guestfs_lvs_ret *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_array (xdrs, (char **)&objp->logvols.logvols_val, (u_int *) &objp->logvols.logvols_len, ~0,
+               sizeof (str), (xdrproc_t) xdr_str))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
 xdr_guestfs_pvs_full_ret (XDR *xdrs, guestfs_pvs_full_ret *objp)
 {
        register int32_t *buf;
 xdr_guestfs_pvs_full_ret (XDR *xdrs, guestfs_pvs_full_ret *objp)
 {
        register int32_t *buf;
index 55faa85..9a7187d 100644 (file)
@@ -152,6 +152,30 @@ struct guestfs_list_partitions_ret {
 };
 typedef struct guestfs_list_partitions_ret guestfs_list_partitions_ret;
 
 };
 typedef struct guestfs_list_partitions_ret guestfs_list_partitions_ret;
 
+struct guestfs_pvs_ret {
+       struct {
+               u_int physvols_len;
+               str *physvols_val;
+       } physvols;
+};
+typedef struct guestfs_pvs_ret guestfs_pvs_ret;
+
+struct guestfs_vgs_ret {
+       struct {
+               u_int volgroups_len;
+               str *volgroups_val;
+       } volgroups;
+};
+typedef struct guestfs_vgs_ret guestfs_vgs_ret;
+
+struct guestfs_lvs_ret {
+       struct {
+               u_int logvols_len;
+               str *logvols_val;
+       } logvols;
+};
+typedef struct guestfs_lvs_ret guestfs_lvs_ret;
+
 struct guestfs_pvs_full_ret {
        guestfs_lvm_int_pv_list physvols;
 };
 struct guestfs_pvs_full_ret {
        guestfs_lvm_int_pv_list physvols;
 };
@@ -176,6 +200,9 @@ enum guestfs_procedure {
        GUESTFS_PROC_LS = 6,
        GUESTFS_PROC_LIST_DEVICES = 7,
        GUESTFS_PROC_LIST_PARTITIONS = 8,
        GUESTFS_PROC_LS = 6,
        GUESTFS_PROC_LIST_DEVICES = 7,
        GUESTFS_PROC_LIST_PARTITIONS = 8,
+       GUESTFS_PROC_PVS = 9,
+       GUESTFS_PROC_VGS = 10,
+       GUESTFS_PROC_LVS = 11,
        GUESTFS_PROC_PVS_FULL = 12,
        GUESTFS_PROC_VGS_FULL = 13,
        GUESTFS_PROC_LVS_FULL = 14,
        GUESTFS_PROC_PVS_FULL = 12,
        GUESTFS_PROC_VGS_FULL = 13,
        GUESTFS_PROC_LVS_FULL = 14,
@@ -234,6 +261,9 @@ extern  bool_t xdr_guestfs_ls_args (XDR *, guestfs_ls_args*);
 extern  bool_t xdr_guestfs_ls_ret (XDR *, guestfs_ls_ret*);
 extern  bool_t xdr_guestfs_list_devices_ret (XDR *, guestfs_list_devices_ret*);
 extern  bool_t xdr_guestfs_list_partitions_ret (XDR *, guestfs_list_partitions_ret*);
 extern  bool_t xdr_guestfs_ls_ret (XDR *, guestfs_ls_ret*);
 extern  bool_t xdr_guestfs_list_devices_ret (XDR *, guestfs_list_devices_ret*);
 extern  bool_t xdr_guestfs_list_partitions_ret (XDR *, guestfs_list_partitions_ret*);
+extern  bool_t xdr_guestfs_pvs_ret (XDR *, guestfs_pvs_ret*);
+extern  bool_t xdr_guestfs_vgs_ret (XDR *, guestfs_vgs_ret*);
+extern  bool_t xdr_guestfs_lvs_ret (XDR *, guestfs_lvs_ret*);
 extern  bool_t xdr_guestfs_pvs_full_ret (XDR *, guestfs_pvs_full_ret*);
 extern  bool_t xdr_guestfs_vgs_full_ret (XDR *, guestfs_vgs_full_ret*);
 extern  bool_t xdr_guestfs_lvs_full_ret (XDR *, guestfs_lvs_full_ret*);
 extern  bool_t xdr_guestfs_pvs_full_ret (XDR *, guestfs_pvs_full_ret*);
 extern  bool_t xdr_guestfs_vgs_full_ret (XDR *, guestfs_vgs_full_ret*);
 extern  bool_t xdr_guestfs_lvs_full_ret (XDR *, guestfs_lvs_full_ret*);
@@ -261,6 +291,9 @@ extern bool_t xdr_guestfs_ls_args ();
 extern bool_t xdr_guestfs_ls_ret ();
 extern bool_t xdr_guestfs_list_devices_ret ();
 extern bool_t xdr_guestfs_list_partitions_ret ();
 extern bool_t xdr_guestfs_ls_ret ();
 extern bool_t xdr_guestfs_list_devices_ret ();
 extern bool_t xdr_guestfs_list_partitions_ret ();
+extern bool_t xdr_guestfs_pvs_ret ();
+extern bool_t xdr_guestfs_vgs_ret ();
+extern bool_t xdr_guestfs_lvs_ret ();
 extern bool_t xdr_guestfs_pvs_full_ret ();
 extern bool_t xdr_guestfs_vgs_full_ret ();
 extern bool_t xdr_guestfs_lvs_full_ret ();
 extern bool_t xdr_guestfs_pvs_full_ret ();
 extern bool_t xdr_guestfs_vgs_full_ret ();
 extern bool_t xdr_guestfs_lvs_full_ret ();
index 9bc556b..b2fe535 100644 (file)
@@ -142,6 +142,24 @@ struct guestfs_list_partitions_ret {
   str partitions<>;
 };
 
   str partitions<>;
 };
 
+/* guestfs_pvs */
+
+struct guestfs_pvs_ret {
+  str physvols<>;
+};
+
+/* guestfs_vgs */
+
+struct guestfs_vgs_ret {
+  str volgroups<>;
+};
+
+/* guestfs_lvs */
+
+struct guestfs_lvs_ret {
+  str logvols<>;
+};
+
 /* guestfs_pvs_full */
 
 struct guestfs_pvs_full_ret {
 /* guestfs_pvs_full */
 
 struct guestfs_pvs_full_ret {
@@ -169,6 +187,9 @@ enum guestfs_procedure {
   GUESTFS_PROC_LS = 6,
   GUESTFS_PROC_LIST_DEVICES = 7,
   GUESTFS_PROC_LIST_PARTITIONS = 8,
   GUESTFS_PROC_LS = 6,
   GUESTFS_PROC_LIST_DEVICES = 7,
   GUESTFS_PROC_LIST_PARTITIONS = 8,
+  GUESTFS_PROC_PVS = 9,
+  GUESTFS_PROC_VGS = 10,
+  GUESTFS_PROC_LVS = 11,
   GUESTFS_PROC_PVS_FULL = 12,
   GUESTFS_PROC_VGS_FULL = 13,
   GUESTFS_PROC_LVS_FULL = 14,
   GUESTFS_PROC_PVS_FULL = 12,
   GUESTFS_PROC_VGS_FULL = 13,
   GUESTFS_PROC_LVS_FULL = 14,