Add: pvresize, sfdisk-N, sfdisk-l, sfdisk-kernel-geomtry, sfdisk-disk-geometry comman...
authorRichard W.M. Jones <rjones@redhat.com>
Fri, 15 May 2009 13:01:28 +0000 (14:01 +0100)
committerRichard W.M. Jones <rjones@redhat.com>
Fri, 15 May 2009 13:52:34 +0000 (14:52 +0100)
28 files changed:
daemon/Makefile.am
daemon/actions.h
daemon/devsparts.c
daemon/lvm.c
daemon/sfdisk.c [new file with mode: 0644]
daemon/stubs.c
fish/cmds.c
fish/completion.c
guestfish-actions.pod
guestfs-actions.pod
haskell/Guestfs.hs
java/com/redhat/et/libguestfs/GuestFS.java
java/com_redhat_et_libguestfs_GuestFS.c
ocaml/guestfs.ml
ocaml/guestfs.mli
ocaml/guestfs_c_actions.c
perl/Guestfs.xs
perl/lib/Sys/Guestfs.pm
python/guestfs-py.c
python/guestfs.py
ruby/ext/guestfs/_guestfs.c
src/generator.ml
src/guestfs-actions.c
src/guestfs-actions.h
src/guestfs_protocol.c
src/guestfs_protocol.h
src/guestfs_protocol.x
tests.c

index d6ae6c3..ac1f8c5 100644 (file)
@@ -43,6 +43,7 @@ guestfsd_SOURCES = \
        mount.c \
        pingdaemon.c \
        proto.c \
+       sfdisk.c \
        stat.c \
        strings.c \
        stubs.c \
index 37ec125..3e6589e 100644 (file)
@@ -118,3 +118,8 @@ extern char **do_strings (const char *path);
 extern char **do_strings_e (const char *encoding, const char *path);
 extern char *do_hexdump (const char *path);
 extern int do_zerofree (const char *device);
+extern int do_pvresize (const char *device);
+extern int do_sfdisk_N (const char *device, int n, int cyls, int heads, int sectors, const char *line);
+extern char *do_sfdisk_l (const char *device);
+extern char *do_sfdisk_kernel_geometry (const char *device);
+extern char *do_sfdisk_disk_geometry (const char *device);
index 0a4d5e4..21854b5 100644 (file)
@@ -152,46 +152,3 @@ do_mkfs (const char *fstype, const char *device)
   free (err);
   return 0;
 }
-
-int
-do_sfdisk (const char *device, int cyls, int heads, int sectors,
-          char * const* const lines)
-{
-  FILE *fp;
-  char buf[256];
-  int i;
-
-  IS_DEVICE (device, -1);
-
-  /* Safe because of IS_DEVICE above. */
-  strcpy (buf, "/sbin/sfdisk");
-  if (cyls)
-    sprintf (buf + strlen (buf), " -C %d", cyls);
-  if (heads)
-    sprintf (buf + strlen (buf), " -H %d", heads);
-  if (sectors)
-    sprintf (buf + strlen (buf), " -S %d", sectors);
-  sprintf (buf + strlen (buf), " %s", device);
-
-  fp = popen (buf, "w");
-  if (fp == NULL) {
-    reply_with_perror (buf);
-    return -1;
-  }
-
-  for (i = 0; lines[i] != NULL; ++i) {
-    if (fprintf (fp, "%s\n", lines[i]) < 0) {
-      reply_with_perror (buf);
-      fclose (fp);
-      return -1;
-    }
-  }
-
-  if (fclose (fp) == EOF) {
-    reply_with_perror (buf);
-    fclose (fp);
-    return -1;
-  }
-
-  return 0;
-}
index 326b583..d1a6cd6 100644 (file)
@@ -358,3 +358,21 @@ do_pvremove (const char *device)
   free (err);
   return 0;
 }
+
+int
+do_pvresize (const char *device)
+{
+  char *err;
+  int r;
+
+  r = command (NULL, &err,
+              "/sbin/lvm", "pvresize", device, NULL);
+  if (r == -1) {
+    reply_with_error ("pvresize: %s: %s", device, err);
+    free (err);
+    return -1;
+  }
+
+  free (err);
+  return 0;
+}
diff --git a/daemon/sfdisk.c b/daemon/sfdisk.c
new file mode 100644 (file)
index 0000000..9d7a220
--- /dev/null
@@ -0,0 +1,130 @@
+/* libguestfs - the guestfsd daemon
+ * Copyright (C) 2009 Red Hat Inc. 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <sys/stat.h>
+
+#include "daemon.h"
+#include "actions.h"
+
+static int
+sfdisk (const char *device, int n, int cyls, int heads, int sectors,
+       char * const* const lines)
+{
+  FILE *fp;
+  char buf[256];
+  int i;
+
+  IS_DEVICE (device, -1);
+
+  strcpy (buf, "/sbin/sfdisk --no-reread");
+  if (n > 0)
+    sprintf (buf + strlen (buf), " -N %d", n);
+  if (cyls)
+    sprintf (buf + strlen (buf), " -C %d", cyls);
+  if (heads)
+    sprintf (buf + strlen (buf), " -H %d", heads);
+  if (sectors)
+    sprintf (buf + strlen (buf), " -S %d", sectors);
+  /* Safe because of IS_DEVICE above: */
+  sprintf (buf + strlen (buf), " %s", device);
+
+  fp = popen (buf, "w");
+  if (fp == NULL) {
+    reply_with_perror (buf);
+    return -1;
+  }
+
+  for (i = 0; lines[i] != NULL; ++i) {
+    if (fprintf (fp, "%s\n", lines[i]) < 0) {
+      reply_with_perror (buf);
+      fclose (fp);
+      return -1;
+    }
+  }
+
+  if (fclose (fp) == EOF) {
+    reply_with_perror (buf);
+    fclose (fp);
+    return -1;
+  }
+
+  return 0;
+}
+
+int
+do_sfdisk (const char *device, int cyls, int heads, int sectors,
+          char * const* const lines)
+{
+  return sfdisk (device, 0, cyls, heads, sectors, lines);
+}
+
+int
+do_sfdisk_N (const char *device, int n, int cyls, int heads, int sectors,
+            const char *line)
+{
+  const char *lines[2] = { line, NULL };
+
+  return sfdisk (device, n, cyls, heads, sectors, lines);
+}
+
+static char *
+sfdisk_flag (const char *device, const char *flag)
+{
+  char *out, *err;
+  int r;
+
+  IS_DEVICE (device, NULL);
+
+  r = command (&out, &err, "/sbin/sfdisk", flag, device, NULL);
+  if (r == -1) {
+    reply_with_error ("sfdisk: %s: %s", device, err);
+    free (out);
+    free (err);
+    return NULL;
+  }
+
+  free (err);
+
+  return out;                  /* caller frees */
+}
+
+char *
+do_sfdisk_l (const char *device)
+{
+  return sfdisk_flag (device, "-l");
+}
+
+char *
+do_sfdisk_kernel_geometry (const char *device)
+{
+  return sfdisk_flag (device, "-g");
+}
+
+char *
+do_sfdisk_disk_geometry (const char *device)
+{
+  return sfdisk_flag (device, "-G");
+}
index 212634f..e80ba9b 100644 (file)
@@ -2421,6 +2421,145 @@ done:
   xdr_free ((xdrproc_t) xdr_guestfs_zerofree_args, (char *) &args);
 }
 
+static void pvresize_stub (XDR *xdr_in)
+{
+  int r;
+  struct guestfs_pvresize_args args;
+  const char *device;
+
+  memset (&args, 0, sizeof args);
+
+  if (!xdr_guestfs_pvresize_args (xdr_in, &args)) {
+    reply_with_error ("%s: daemon failed to decode procedure arguments", "pvresize");
+    return;
+  }
+  device = args.device;
+
+  r = do_pvresize (device);
+  if (r == -1)
+    /* do_pvresize has already called reply_with_error */
+    goto done;
+
+  reply (NULL, NULL);
+done:
+  xdr_free ((xdrproc_t) xdr_guestfs_pvresize_args, (char *) &args);
+}
+
+static void sfdisk_N_stub (XDR *xdr_in)
+{
+  int r;
+  struct guestfs_sfdisk_N_args args;
+  const char *device;
+  int n;
+  int cyls;
+  int heads;
+  int sectors;
+  const char *line;
+
+  memset (&args, 0, sizeof args);
+
+  if (!xdr_guestfs_sfdisk_N_args (xdr_in, &args)) {
+    reply_with_error ("%s: daemon failed to decode procedure arguments", "sfdisk_N");
+    return;
+  }
+  device = args.device;
+  n = args.n;
+  cyls = args.cyls;
+  heads = args.heads;
+  sectors = args.sectors;
+  line = args.line;
+
+  r = do_sfdisk_N (device, n, cyls, heads, sectors, line);
+  if (r == -1)
+    /* do_sfdisk_N has already called reply_with_error */
+    goto done;
+
+  reply (NULL, NULL);
+done:
+  xdr_free ((xdrproc_t) xdr_guestfs_sfdisk_N_args, (char *) &args);
+}
+
+static void sfdisk_l_stub (XDR *xdr_in)
+{
+  char *r;
+  struct guestfs_sfdisk_l_args args;
+  const char *device;
+
+  memset (&args, 0, sizeof args);
+
+  if (!xdr_guestfs_sfdisk_l_args (xdr_in, &args)) {
+    reply_with_error ("%s: daemon failed to decode procedure arguments", "sfdisk_l");
+    return;
+  }
+  device = args.device;
+
+  r = do_sfdisk_l (device);
+  if (r == NULL)
+    /* do_sfdisk_l has already called reply_with_error */
+    goto done;
+
+  struct guestfs_sfdisk_l_ret ret;
+  ret.partitions = r;
+  reply ((xdrproc_t) &xdr_guestfs_sfdisk_l_ret, (char *) &ret);
+  free (r);
+done:
+  xdr_free ((xdrproc_t) xdr_guestfs_sfdisk_l_args, (char *) &args);
+}
+
+static void sfdisk_kernel_geometry_stub (XDR *xdr_in)
+{
+  char *r;
+  struct guestfs_sfdisk_kernel_geometry_args args;
+  const char *device;
+
+  memset (&args, 0, sizeof args);
+
+  if (!xdr_guestfs_sfdisk_kernel_geometry_args (xdr_in, &args)) {
+    reply_with_error ("%s: daemon failed to decode procedure arguments", "sfdisk_kernel_geometry");
+    return;
+  }
+  device = args.device;
+
+  r = do_sfdisk_kernel_geometry (device);
+  if (r == NULL)
+    /* do_sfdisk_kernel_geometry has already called reply_with_error */
+    goto done;
+
+  struct guestfs_sfdisk_kernel_geometry_ret ret;
+  ret.partitions = r;
+  reply ((xdrproc_t) &xdr_guestfs_sfdisk_kernel_geometry_ret, (char *) &ret);
+  free (r);
+done:
+  xdr_free ((xdrproc_t) xdr_guestfs_sfdisk_kernel_geometry_args, (char *) &args);
+}
+
+static void sfdisk_disk_geometry_stub (XDR *xdr_in)
+{
+  char *r;
+  struct guestfs_sfdisk_disk_geometry_args args;
+  const char *device;
+
+  memset (&args, 0, sizeof args);
+
+  if (!xdr_guestfs_sfdisk_disk_geometry_args (xdr_in, &args)) {
+    reply_with_error ("%s: daemon failed to decode procedure arguments", "sfdisk_disk_geometry");
+    return;
+  }
+  device = args.device;
+
+  r = do_sfdisk_disk_geometry (device);
+  if (r == NULL)
+    /* do_sfdisk_disk_geometry has already called reply_with_error */
+    goto done;
+
+  struct guestfs_sfdisk_disk_geometry_ret ret;
+  ret.partitions = r;
+  reply ((xdrproc_t) &xdr_guestfs_sfdisk_disk_geometry_ret, (char *) &ret);
+  free (r);
+done:
+  xdr_free ((xdrproc_t) xdr_guestfs_sfdisk_disk_geometry_args, (char *) &args);
+}
+
 void dispatch_incoming_message (XDR *xdr_in)
 {
   switch (proc_nr) {
@@ -2715,6 +2854,21 @@ void dispatch_incoming_message (XDR *xdr_in)
     case GUESTFS_PROC_ZEROFREE:
       zerofree_stub (xdr_in);
       break;
+    case GUESTFS_PROC_PVRESIZE:
+      pvresize_stub (xdr_in);
+      break;
+    case GUESTFS_PROC_SFDISK_N:
+      sfdisk_N_stub (xdr_in);
+      break;
+    case GUESTFS_PROC_SFDISK_L:
+      sfdisk_l_stub (xdr_in);
+      break;
+    case GUESTFS_PROC_SFDISK_KERNEL_GEOMETRY:
+      sfdisk_kernel_geometry_stub (xdr_in);
+      break;
+    case GUESTFS_PROC_SFDISK_DISK_GEOMETRY:
+      sfdisk_disk_geometry_stub (xdr_in);
+      break;
     default:
       reply_with_error ("dispatch_incoming_message: unknown procedure number %d", proc_nr);
   }
index 1f3d9ce..5680bfa 100644 (file)
@@ -113,6 +113,7 @@ void list_commands (void)
   printf ("%-20s %s\n", "ping-daemon", "ping the guest daemon");
   printf ("%-20s %s\n", "pvcreate", "create an LVM physical volume");
   printf ("%-20s %s\n", "pvremove", "remove an LVM physical volume");
+  printf ("%-20s %s\n", "pvresize", "resize an LVM physical volume");
   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", "read-lines", "read file as lines");
@@ -127,6 +128,10 @@ void list_commands (void)
   printf ("%-20s %s\n", "set-qemu", "set the qemu binary");
   printf ("%-20s %s\n", "set-verbose", "set verbose mode");
   printf ("%-20s %s\n", "sfdisk", "create partitions on a block device");
+  printf ("%-20s %s\n", "sfdisk-N", "modify a single partition on a block device");
+  printf ("%-20s %s\n", "sfdisk-disk-geometry", "display the disk geometry from the partition table");
+  printf ("%-20s %s\n", "sfdisk-kernel-geometry", "display the kernel geometry");
+  printf ("%-20s %s\n", "sfdisk-l", "display the partition table");
   printf ("%-20s %s\n", "stat", "get file information");
   printf ("%-20s %s\n", "statvfs", "get file system statistics");
   printf ("%-20s %s\n", "strings", "print the printable strings in a file");
@@ -340,7 +345,7 @@ void display_command (const char *cmd)
     pod2text ("mkfs - make a filesystem", " mkfs <fstype> <device>\n\nThis creates a filesystem on C<device> (usually a partition\nor LVM logical volume).  The filesystem type is C<fstype>, for\nexample C<ext3>.");
   else
   if (strcasecmp (cmd, "sfdisk") == 0)
-    pod2text ("sfdisk - create partitions on a block device", " sfdisk <device> <cyls> <heads> <sectors> <lines>\n\nThis is a direct interface to the L<sfdisk(8)> program for creating\npartitions on block devices.\n\nC<device> should be a block device, for example C</dev/sda>.\n\nC<cyls>, C<heads> and C<sectors> are the number of cylinders, heads\nand sectors on the device, which are passed directly to sfdisk as\nthe I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any\nof these, then the corresponding parameter is omitted.  Usually for\n'large' disks, you can just pass C<0> for these, but for small\n(floppy-sized) disks, sfdisk (or rather, the kernel) cannot work\nout the right geometry and you will need to tell it.\n\nC<lines> is a list of lines that we feed to C<sfdisk>.  For more\ninformation refer to the L<sfdisk(8)> manpage.\n\nTo create a single partition occupying the whole disk, you would\npass C<lines> as a single element list, when the single element being\nthe string C<,> (comma).\n\nB<This command is dangerous.  Without careful use you\ncan easily destroy all your data>.");
+    pod2text ("sfdisk - create partitions on a block device", " sfdisk <device> <cyls> <heads> <sectors> <lines>\n\nThis is a direct interface to the L<sfdisk(8)> program for creating\npartitions on block devices.\n\nC<device> should be a block device, for example C</dev/sda>.\n\nC<cyls>, C<heads> and C<sectors> are the number of cylinders, heads\nand sectors on the device, which are passed directly to sfdisk as\nthe I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any\nof these, then the corresponding parameter is omitted.  Usually for\n'large' disks, you can just pass C<0> for these, but for small\n(floppy-sized) disks, sfdisk (or rather, the kernel) cannot work\nout the right geometry and you will need to tell it.\n\nC<lines> is a list of lines that we feed to C<sfdisk>.  For more\ninformation refer to the L<sfdisk(8)> manpage.\n\nTo create a single partition occupying the whole disk, you would\npass C<lines> as a single element list, when the single element being\nthe string C<,> (comma).\n\nSee also: C<sfdisk_l>, C<sfdisk_N>\n\nB<This command is dangerous.  Without careful use you\ncan easily destroy all your data>.");
   else
   if (strcasecmp (cmd, "write_file") == 0 || strcasecmp (cmd, "write-file") == 0)
     pod2text ("write-file - create a file", " write-file <path> <content> <size>\n\nThis call creates a file called C<path>.  The contents of the\nfile is the string C<content> (which can contain any 8 bit data),\nwith length C<size>.\n\nAs a special case, if C<size> is C<0>\nthen the length is calculated using C<strlen> (so in this case\nthe content cannot contain embedded ASCII NULs).\n\nI<NB.> Owing to a bug, writing content containing ASCII NUL\ncharacters does I<not> work, even if the length is specified.\nWe hope to resolve this bug in a future version.  In the meantime\nuse C<upload>.\n\nBecause of the message protocol, there is a transfer limit \nof somewhere between 2MB and 4MB.  To transfer large files you should use\nFTP.");
@@ -504,6 +509,21 @@ void display_command (const char *cmd)
   if (strcasecmp (cmd, "zerofree") == 0)
     pod2text ("zerofree - zero unused inodes and disk blocks on ext2/3 filesystem", " zerofree <device>\n\nThis runs the I<zerofree> program on C<device>.  This program\nclaims to zero unused inodes and disk blocks on an ext2/3\nfilesystem, thus making it possible to compress the filesystem\nmore effectively.\n\nYou should B<not> run this program if the filesystem is\nmounted.\n\nIt is possible that using this program can damage the filesystem\nor data on the filesystem.");
   else
+  if (strcasecmp (cmd, "pvresize") == 0)
+    pod2text ("pvresize - resize an LVM physical volume", " pvresize <device>\n\nThis resizes (expands or shrinks) an existing LVM physical\nvolume to match the new size of the underlying device.");
+  else
+  if (strcasecmp (cmd, "sfdisk_N") == 0 || strcasecmp (cmd, "sfdisk-N") == 0)
+    pod2text ("sfdisk-N - modify a single partition on a block device", " sfdisk-N <device> <n> <cyls> <heads> <sectors> <line>\n\nThis runs L<sfdisk(8)> option to modify just the single\npartition C<n> (note: C<n> counts from 1).\n\nFor other parameters, see C<sfdisk>.  You should usually\npass C<0> for the cyls/heads/sectors parameters.\n\nB<This command is dangerous.  Without careful use you\ncan easily destroy all your data>.");
+  else
+  if (strcasecmp (cmd, "sfdisk_l") == 0 || strcasecmp (cmd, "sfdisk-l") == 0)
+    pod2text ("sfdisk-l - display the partition table", " sfdisk-l <device>\n\nThis displays the partition table on C<device>, in the\nhuman-readable output of the L<sfdisk(8)> command.  It is\nnot intended to be parsed.");
+  else
+  if (strcasecmp (cmd, "sfdisk_kernel_geometry") == 0 || strcasecmp (cmd, "sfdisk-kernel-geometry") == 0)
+    pod2text ("sfdisk-kernel-geometry - display the kernel geometry", " sfdisk-kernel-geometry <device>\n\nThis displays the kernel's idea of the geometry of C<device>.\n\nThe result is in human-readable format, and not designed to\nbe parsed.");
+  else
+  if (strcasecmp (cmd, "sfdisk_disk_geometry") == 0 || strcasecmp (cmd, "sfdisk-disk-geometry") == 0)
+    pod2text ("sfdisk-disk-geometry - display the disk geometry from the partition table", " sfdisk-disk-geometry <device>\n\nThis displays the disk geometry of C<device> read from the\npartition table.  Especially in the case where the underlying\nblock device has been resized, this can be different from the\nkernel's idea of the geometry (see C<sfdisk_kernel_geometry>).\n\nThe result is in human-readable format, and not designed to\nbe parsed.");
+  else
     display_builtin_command (cmd);
 }
 
@@ -2456,6 +2476,95 @@ static int run_zerofree (const char *cmd, int argc, char *argv[])
   return r;
 }
 
+static int run_pvresize (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  const char *device;
+  if (argc != 1) {
+    fprintf (stderr, "%s should have 1 parameter(s)\n", cmd);
+    fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+    return -1;
+  }
+  device = argv[0];
+  r = guestfs_pvresize (g, device);
+  return r;
+}
+
+static int run_sfdisk_N (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  const char *device;
+  int n;
+  int cyls;
+  int heads;
+  int sectors;
+  const char *line;
+  if (argc != 6) {
+    fprintf (stderr, "%s should have 6 parameter(s)\n", cmd);
+    fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+    return -1;
+  }
+  device = argv[0];
+  n = atoi (argv[1]);
+  cyls = atoi (argv[2]);
+  heads = atoi (argv[3]);
+  sectors = atoi (argv[4]);
+  line = argv[5];
+  r = guestfs_sfdisk_N (g, device, n, cyls, heads, sectors, line);
+  return r;
+}
+
+static int run_sfdisk_l (const char *cmd, int argc, char *argv[])
+{
+  char *r;
+  const char *device;
+  if (argc != 1) {
+    fprintf (stderr, "%s should have 1 parameter(s)\n", cmd);
+    fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+    return -1;
+  }
+  device = argv[0];
+  r = guestfs_sfdisk_l (g, device);
+  if (r == NULL) return -1;
+  printf ("%s\n", r);
+  free (r);
+  return 0;
+}
+
+static int run_sfdisk_kernel_geometry (const char *cmd, int argc, char *argv[])
+{
+  char *r;
+  const char *device;
+  if (argc != 1) {
+    fprintf (stderr, "%s should have 1 parameter(s)\n", cmd);
+    fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+    return -1;
+  }
+  device = argv[0];
+  r = guestfs_sfdisk_kernel_geometry (g, device);
+  if (r == NULL) return -1;
+  printf ("%s\n", r);
+  free (r);
+  return 0;
+}
+
+static int run_sfdisk_disk_geometry (const char *cmd, int argc, char *argv[])
+{
+  char *r;
+  const char *device;
+  if (argc != 1) {
+    fprintf (stderr, "%s should have 1 parameter(s)\n", cmd);
+    fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+    return -1;
+  }
+  device = argv[0];
+  r = guestfs_sfdisk_disk_geometry (g, device);
+  if (r == NULL) return -1;
+  printf ("%s\n", r);
+  free (r);
+  return 0;
+}
+
 int run_action (const char *cmd, int argc, char *argv[])
 {
   if (strcasecmp (cmd, "launch") == 0 || strcasecmp (cmd, "run") == 0)
@@ -2809,6 +2918,21 @@ int run_action (const char *cmd, int argc, char *argv[])
   if (strcasecmp (cmd, "zerofree") == 0)
     return run_zerofree (cmd, argc, argv);
   else
+  if (strcasecmp (cmd, "pvresize") == 0)
+    return run_pvresize (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "sfdisk_N") == 0 || strcasecmp (cmd, "sfdisk-N") == 0)
+    return run_sfdisk_N (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "sfdisk_l") == 0 || strcasecmp (cmd, "sfdisk-l") == 0)
+    return run_sfdisk_l (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "sfdisk_kernel_geometry") == 0 || strcasecmp (cmd, "sfdisk-kernel-geometry") == 0)
+    return run_sfdisk_kernel_geometry (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "sfdisk_disk_geometry") == 0 || strcasecmp (cmd, "sfdisk-disk-geometry") == 0)
+    return run_sfdisk_disk_geometry (cmd, argc, argv);
+  else
     {
       fprintf (stderr, "%s: unknown command\n", cmd);
       return -1;
index 5c7f5e0..03760ad 100644 (file)
@@ -121,6 +121,7 @@ static const char *const commands[] = {
   "ping-daemon",
   "pvcreate",
   "pvremove",
+  "pvresize",
   "pvs",
   "pvs-full",
   "qemu",
@@ -137,6 +138,10 @@ static const char *const commands[] = {
   "set-qemu",
   "set-verbose",
   "sfdisk",
+  "sfdisk-N",
+  "sfdisk-disk-geometry",
+  "sfdisk-kernel-geometry",
+  "sfdisk-l",
   "stat",
   "statvfs",
   "strings",
index 7b5a4be..213fa66 100644 (file)
@@ -905,6 +905,13 @@ The implementation uses the C<pvremove> command which refuses to
 wipe physical volumes that contain any volume groups, so you have
 to remove those first.
 
+=head2 pvresize
+
+ pvresize device
+
+This resizes (expands or shrinks) an existing LVM physical
+volume to match the new size of the underlying device.
+
 =head2 pvs
 
  pvs
@@ -1064,9 +1071,53 @@ To create a single partition occupying the whole disk, you would
 pass C<lines> as a single element list, when the single element being
 the string C<,> (comma).
 
+See also: C<sfdisk-l>, C<sfdisk-N>
+
+B<This command is dangerous.  Without careful use you
+can easily destroy all your data>.
+
+=head2 sfdisk-N
+
+ sfdisk-N device n cyls heads sectors line
+
+This runs L<sfdisk(8)> option to modify just the single
+partition C<n> (note: C<n> counts from 1).
+
+For other parameters, see C<sfdisk>.  You should usually
+pass C<0> for the cyls/heads/sectors parameters.
+
 B<This command is dangerous.  Without careful use you
 can easily destroy all your data>.
 
+=head2 sfdisk-disk-geometry
+
+ sfdisk-disk-geometry device
+
+This displays the disk geometry of C<device> read from the
+partition table.  Especially in the case where the underlying
+block device has been resized, this can be different from the
+kernel's idea of the geometry (see C<sfdisk-kernel-geometry>).
+
+The result is in human-readable format, and not designed to
+be parsed.
+
+=head2 sfdisk-kernel-geometry
+
+ sfdisk-kernel-geometry device
+
+This displays the kernel's idea of the geometry of C<device>.
+
+The result is in human-readable format, and not designed to
+be parsed.
+
+=head2 sfdisk-l
+
+ sfdisk-l device
+
+This displays the partition table on C<device>, in the
+human-readable output of the L<sfdisk(8)> command.  It is
+not intended to be parsed.
+
 =head2 stat
 
  stat path
index 109c73e..abeed8f 100644 (file)
@@ -1208,6 +1208,16 @@ to remove those first.
 
 This function returns 0 on success or -1 on error.
 
+=head2 guestfs_pvresize
+
+ int guestfs_pvresize (guestfs_h *handle,
+               const char *device);
+
+This resizes (expands or shrinks) an existing LVM physical
+volume to match the new size of the underlying device.
+
+This function returns 0 on success or -1 on error.
+
 =head2 guestfs_pvs
 
  char **guestfs_pvs (guestfs_h *handle);
@@ -1440,11 +1450,75 @@ To create a single partition occupying the whole disk, you would
 pass C<lines> as a single element list, when the single element being
 the string C<,> (comma).
 
+See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>
+
+This function returns 0 on success or -1 on error.
+
+B<This command is dangerous.  Without careful use you
+can easily destroy all your data>.
+
+=head2 guestfs_sfdisk_N
+
+ int guestfs_sfdisk_N (guestfs_h *handle,
+               const char *device,
+               int n,
+               int cyls,
+               int heads,
+               int sectors,
+               const char *line);
+
+This runs L<sfdisk(8)> option to modify just the single
+partition C<n> (note: C<n> counts from 1).
+
+For other parameters, see C<guestfs_sfdisk>.  You should usually
+pass C<0> for the cyls/heads/sectors parameters.
+
 This function returns 0 on success or -1 on error.
 
 B<This command is dangerous.  Without careful use you
 can easily destroy all your data>.
 
+=head2 guestfs_sfdisk_disk_geometry
+
+ char *guestfs_sfdisk_disk_geometry (guestfs_h *handle,
+               const char *device);
+
+This displays the disk geometry of C<device> read from the
+partition table.  Especially in the case where the underlying
+block device has been resized, this can be different from the
+kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
+
+The result is in human-readable format, and not designed to
+be parsed.
+
+This function returns a string, or NULL on error.
+I<The caller must free the returned string after use>.
+
+=head2 guestfs_sfdisk_kernel_geometry
+
+ char *guestfs_sfdisk_kernel_geometry (guestfs_h *handle,
+               const char *device);
+
+This displays the kernel's idea of the geometry of C<device>.
+
+The result is in human-readable format, and not designed to
+be parsed.
+
+This function returns a string, or NULL on error.
+I<The caller must free the returned string after use>.
+
+=head2 guestfs_sfdisk_l
+
+ char *guestfs_sfdisk_l (guestfs_h *handle,
+               const char *device);
+
+This displays the partition table on C<device>, in the
+human-readable output of the L<sfdisk(8)> command.  It is
+not intended to be parsed.
+
+This function returns a string, or NULL on error.
+I<The caller must free the returned string after use>.
+
 =head2 guestfs_stat
 
  struct guestfs_stat *guestfs_stat (guestfs_h *handle,
index c061a7a..170f040 100644 (file)
@@ -79,7 +79,8 @@ module Guestfs (
   cp_a,
   mv,
   ping_daemon,
-  zerofree
+  zerofree,
+  pvresize
   ) where
 import Foreign
 import Foreign.C
@@ -801,3 +802,15 @@ zerofree h device = do
       fail err
     else return ()
 
+foreign import ccall unsafe "guestfs_pvresize" c_pvresize
+  :: GuestfsP -> CString -> IO (CInt)
+
+pvresize :: GuestfsH -> String -> IO ()
+pvresize h device = do
+  r <- withCString device $ \device -> withForeignPtr h (\p -> c_pvresize p device)
+  if (r == -1)
+    then do
+      err <- last_error h
+      fail err
+    else return ()
+
index 76ada90..7eafce0 100644 (file)
@@ -1518,6 +1518,8 @@ public class GuestFS {
    * you would pass "lines" as a single element list, when
    * the single element being the string "," (comma).
    * 
+   * See also: "g.sfdisk_l", "g.sfdisk_N"
+   * 
    * This command is dangerous. Without careful use you can
    * easily destroy all your data.
    * 
@@ -2755,4 +2757,111 @@ public class GuestFS {
   private native void _zerofree (long g, String device)
     throws LibGuestFSException;
 
+  /**
+   * resize an LVM physical volume
+   *
+   * This resizes (expands or shrinks) an existing LVM
+   * physical volume to match the new size of the underlying
+   * device.
+   * 
+   * @throws LibGuestFSException
+   */
+  public void pvresize (String device)
+    throws LibGuestFSException
+  {
+    if (g == 0)
+      throw new LibGuestFSException ("pvresize: handle is closed");
+    _pvresize (g, device);
+  }
+  private native void _pvresize (long g, String device)
+    throws LibGuestFSException;
+
+  /**
+   * modify a single partition on a block device
+   *
+   * This runs sfdisk(8) option to modify just the single
+   * partition "n" (note: "n" counts from 1).
+   * 
+   * For other parameters, see "g.sfdisk". You should usually
+   * pass 0 for the cyls/heads/sectors parameters.
+   * 
+   * This command is dangerous. Without careful use you can
+   * easily destroy all your data.
+   * 
+   * @throws LibGuestFSException
+   */
+  public void sfdisk_N (String device, int n, int cyls, int heads, int sectors, String line)
+    throws LibGuestFSException
+  {
+    if (g == 0)
+      throw new LibGuestFSException ("sfdisk_N: handle is closed");
+    _sfdisk_N (g, device, n, cyls, heads, sectors, line);
+  }
+  private native void _sfdisk_N (long g, String device, int n, int cyls, int heads, int sectors, String line)
+    throws LibGuestFSException;
+
+  /**
+   * display the partition table
+   *
+   * This displays the partition table on "device", in the
+   * human-readable output of the sfdisk(8) command. It is
+   * not intended to be parsed.
+   * 
+   * @throws LibGuestFSException
+   */
+  public String sfdisk_l (String device)
+    throws LibGuestFSException
+  {
+    if (g == 0)
+      throw new LibGuestFSException ("sfdisk_l: handle is closed");
+    return _sfdisk_l (g, device);
+  }
+  private native String _sfdisk_l (long g, String device)
+    throws LibGuestFSException;
+
+  /**
+   * display the kernel geometry
+   *
+   * This displays the kernel's idea of the geometry of
+   * "device".
+   * 
+   * The result is in human-readable format, and not designed
+   * to be parsed.
+   * 
+   * @throws LibGuestFSException
+   */
+  public String sfdisk_kernel_geometry (String device)
+    throws LibGuestFSException
+  {
+    if (g == 0)
+      throw new LibGuestFSException ("sfdisk_kernel_geometry: handle is closed");
+    return _sfdisk_kernel_geometry (g, device);
+  }
+  private native String _sfdisk_kernel_geometry (long g, String device)
+    throws LibGuestFSException;
+
+  /**
+   * display the disk geometry from the partition table
+   *
+   * This displays the disk geometry of "device" read from
+   * the partition table. Especially in the case where the
+   * underlying block device has been resized, this can be
+   * different from the kernel's idea of the geometry (see
+   * "g.sfdisk_kernel_geometry").
+   * 
+   * The result is in human-readable format, and not designed
+   * to be parsed.
+   * 
+   * @throws LibGuestFSException
+   */
+  public String sfdisk_disk_geometry (String device)
+    throws LibGuestFSException
+  {
+    if (g == 0)
+      throw new LibGuestFSException ("sfdisk_disk_geometry: handle is closed");
+    return _sfdisk_disk_geometry (g, device);
+  }
+  private native String _sfdisk_disk_geometry (long g, String device)
+    throws LibGuestFSException;
+
 }
index a823d84..be7ea9f 100644 (file)
@@ -2739,3 +2739,111 @@ Java_com_redhat_et_libguestfs_GuestFS__1zerofree
   }
 }
 
+JNIEXPORT void JNICALL
+Java_com_redhat_et_libguestfs_GuestFS__1pvresize
+  (JNIEnv *env, jobject obj, jlong jg, jstring jdevice)
+{
+  guestfs_h *g = (guestfs_h *) (long) jg;
+  int r;
+  const char *device;
+
+  device = (*env)->GetStringUTFChars (env, jdevice, NULL);
+  r = guestfs_pvresize (g, device);
+  (*env)->ReleaseStringUTFChars (env, jdevice, device);
+  if (r == -1) {
+    throw_exception (env, guestfs_last_error (g));
+    return ;
+  }
+}
+
+JNIEXPORT void JNICALL
+Java_com_redhat_et_libguestfs_GuestFS__1sfdisk_1N
+  (JNIEnv *env, jobject obj, jlong jg, jstring jdevice, jint jn, jint jcyls, jint jheads, jint jsectors, jstring jline)
+{
+  guestfs_h *g = (guestfs_h *) (long) jg;
+  int r;
+  const char *device;
+  int n;
+  int cyls;
+  int heads;
+  int sectors;
+  const char *line;
+
+  device = (*env)->GetStringUTFChars (env, jdevice, NULL);
+  n = jn;
+  cyls = jcyls;
+  heads = jheads;
+  sectors = jsectors;
+  line = (*env)->GetStringUTFChars (env, jline, NULL);
+  r = guestfs_sfdisk_N (g, device, n, cyls, heads, sectors, line);
+  (*env)->ReleaseStringUTFChars (env, jdevice, device);
+  (*env)->ReleaseStringUTFChars (env, jline, line);
+  if (r == -1) {
+    throw_exception (env, guestfs_last_error (g));
+    return ;
+  }
+}
+
+JNIEXPORT jstring JNICALL
+Java_com_redhat_et_libguestfs_GuestFS__1sfdisk_1l
+  (JNIEnv *env, jobject obj, jlong jg, jstring jdevice)
+{
+  guestfs_h *g = (guestfs_h *) (long) jg;
+  jstring jr;
+  char *r;
+  const char *device;
+
+  device = (*env)->GetStringUTFChars (env, jdevice, NULL);
+  r = guestfs_sfdisk_l (g, device);
+  (*env)->ReleaseStringUTFChars (env, jdevice, device);
+  if (r == NULL) {
+    throw_exception (env, guestfs_last_error (g));
+    return NULL;
+  }
+  jr = (*env)->NewStringUTF (env, r);
+  free (r);
+  return jr;
+}
+
+JNIEXPORT jstring JNICALL
+Java_com_redhat_et_libguestfs_GuestFS__1sfdisk_1kernel_1geometry
+  (JNIEnv *env, jobject obj, jlong jg, jstring jdevice)
+{
+  guestfs_h *g = (guestfs_h *) (long) jg;
+  jstring jr;
+  char *r;
+  const char *device;
+
+  device = (*env)->GetStringUTFChars (env, jdevice, NULL);
+  r = guestfs_sfdisk_kernel_geometry (g, device);
+  (*env)->ReleaseStringUTFChars (env, jdevice, device);
+  if (r == NULL) {
+    throw_exception (env, guestfs_last_error (g));
+    return NULL;
+  }
+  jr = (*env)->NewStringUTF (env, r);
+  free (r);
+  return jr;
+}
+
+JNIEXPORT jstring JNICALL
+Java_com_redhat_et_libguestfs_GuestFS__1sfdisk_1disk_1geometry
+  (JNIEnv *env, jobject obj, jlong jg, jstring jdevice)
+{
+  guestfs_h *g = (guestfs_h *) (long) jg;
+  jstring jr;
+  char *r;
+  const char *device;
+
+  device = (*env)->GetStringUTFChars (env, jdevice, NULL);
+  r = guestfs_sfdisk_disk_geometry (g, device);
+  (*env)->ReleaseStringUTFChars (env, jdevice, device);
+  if (r == NULL) {
+    throw_exception (env, guestfs_last_error (g));
+    return NULL;
+  }
+  jr = (*env)->NewStringUTF (env, r);
+  free (r);
+  return jr;
+}
+
index 3886022..d50b2d8 100644 (file)
@@ -236,3 +236,8 @@ external strings : t -> string -> string array = "ocaml_guestfs_strings"
 external strings_e : t -> string -> string -> string array = "ocaml_guestfs_strings_e"
 external hexdump : t -> string -> string = "ocaml_guestfs_hexdump"
 external zerofree : t -> string -> unit = "ocaml_guestfs_zerofree"
+external pvresize : t -> string -> unit = "ocaml_guestfs_pvresize"
+external sfdisk_N : t -> string -> int -> int -> int -> int -> string -> unit = "ocaml_guestfs_sfdisk_N_byte" "ocaml_guestfs_sfdisk_N"
+external sfdisk_l : t -> string -> string = "ocaml_guestfs_sfdisk_l"
+external sfdisk_kernel_geometry : t -> string -> string = "ocaml_guestfs_sfdisk_kernel_geometry"
+external sfdisk_disk_geometry : t -> string -> string = "ocaml_guestfs_sfdisk_disk_geometry"
index 3776abe..358a6d3 100644 (file)
@@ -487,3 +487,18 @@ val hexdump : t -> string -> string
 val zerofree : t -> string -> unit
 (** zero unused inodes and disk blocks on ext2/3 filesystem *)
 
+val pvresize : t -> string -> unit
+(** resize an LVM physical volume *)
+
+val sfdisk_N : t -> string -> int -> int -> int -> int -> string -> unit
+(** modify a single partition on a block device *)
+
+val sfdisk_l : t -> string -> string
+(** display the partition table *)
+
+val sfdisk_kernel_geometry : t -> string -> string
+(** display the kernel geometry *)
+
+val sfdisk_disk_geometry : t -> string -> string
+(** display the disk geometry from the partition table *)
+
index 79a5c16..f2d13b0 100644 (file)
@@ -3201,3 +3201,133 @@ ocaml_guestfs_zerofree (value gv, value devicev)
   CAMLreturn (rv);
 }
 
+CAMLprim value
+ocaml_guestfs_pvresize (value gv, value devicev)
+{
+  CAMLparam2 (gv, devicev);
+  CAMLlocal1 (rv);
+
+  guestfs_h *g = Guestfs_val (gv);
+  if (g == NULL)
+    caml_failwith ("pvresize: used handle after closing it");
+
+  const char *device = String_val (devicev);
+  int r;
+
+  caml_enter_blocking_section ();
+  r = guestfs_pvresize (g, device);
+  caml_leave_blocking_section ();
+  if (r == -1)
+    ocaml_guestfs_raise_error (g, "pvresize");
+
+  rv = Val_unit;
+  CAMLreturn (rv);
+}
+
+CAMLprim value
+ocaml_guestfs_sfdisk_N (value gv, value devicev, value nv, value cylsv, value headsv, value sectorsv, value linev)
+{
+  CAMLparam5 (gv, devicev, nv, cylsv, headsv);
+  CAMLxparam2 (sectorsv, linev);
+  CAMLlocal1 (rv);
+
+  guestfs_h *g = Guestfs_val (gv);
+  if (g == NULL)
+    caml_failwith ("sfdisk_N: used handle after closing it");
+
+  const char *device = String_val (devicev);
+  int n = Int_val (nv);
+  int cyls = Int_val (cylsv);
+  int heads = Int_val (headsv);
+  int sectors = Int_val (sectorsv);
+  const char *line = String_val (linev);
+  int r;
+
+  caml_enter_blocking_section ();
+  r = guestfs_sfdisk_N (g, device, n, cyls, heads, sectors, line);
+  caml_leave_blocking_section ();
+  if (r == -1)
+    ocaml_guestfs_raise_error (g, "sfdisk_N");
+
+  rv = Val_unit;
+  CAMLreturn (rv);
+}
+
+CAMLprim value
+ocaml_guestfs_sfdisk_N_byte (value *argv, int argn)
+{
+  return ocaml_guestfs_sfdisk_N (argv[0], argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
+}
+
+CAMLprim value
+ocaml_guestfs_sfdisk_l (value gv, value devicev)
+{
+  CAMLparam2 (gv, devicev);
+  CAMLlocal1 (rv);
+
+  guestfs_h *g = Guestfs_val (gv);
+  if (g == NULL)
+    caml_failwith ("sfdisk_l: used handle after closing it");
+
+  const char *device = String_val (devicev);
+  char *r;
+
+  caml_enter_blocking_section ();
+  r = guestfs_sfdisk_l (g, device);
+  caml_leave_blocking_section ();
+  if (r == NULL)
+    ocaml_guestfs_raise_error (g, "sfdisk_l");
+
+  rv = caml_copy_string (r);
+  free (r);
+  CAMLreturn (rv);
+}
+
+CAMLprim value
+ocaml_guestfs_sfdisk_kernel_geometry (value gv, value devicev)
+{
+  CAMLparam2 (gv, devicev);
+  CAMLlocal1 (rv);
+
+  guestfs_h *g = Guestfs_val (gv);
+  if (g == NULL)
+    caml_failwith ("sfdisk_kernel_geometry: used handle after closing it");
+
+  const char *device = String_val (devicev);
+  char *r;
+
+  caml_enter_blocking_section ();
+  r = guestfs_sfdisk_kernel_geometry (g, device);
+  caml_leave_blocking_section ();
+  if (r == NULL)
+    ocaml_guestfs_raise_error (g, "sfdisk_kernel_geometry");
+
+  rv = caml_copy_string (r);
+  free (r);
+  CAMLreturn (rv);
+}
+
+CAMLprim value
+ocaml_guestfs_sfdisk_disk_geometry (value gv, value devicev)
+{
+  CAMLparam2 (gv, devicev);
+  CAMLlocal1 (rv);
+
+  guestfs_h *g = Guestfs_val (gv);
+  if (g == NULL)
+    caml_failwith ("sfdisk_disk_geometry: used handle after closing it");
+
+  const char *device = String_val (devicev);
+  char *r;
+
+  caml_enter_blocking_section ();
+  r = guestfs_sfdisk_disk_geometry (g, device);
+  caml_leave_blocking_section ();
+  if (r == NULL)
+    ocaml_guestfs_raise_error (g, "sfdisk_disk_geometry");
+
+  rv = caml_copy_string (r);
+  free (r);
+  CAMLreturn (rv);
+}
+
index e87131b..ff7ca9e 100644 (file)
@@ -1798,3 +1798,75 @@ PREINIT:
       if (r == -1)
         croak ("zerofree: %s", guestfs_last_error (g));
 
+void
+pvresize (g, device)
+      guestfs_h *g;
+      char *device;
+PREINIT:
+      int r;
+ PPCODE:
+      r = guestfs_pvresize (g, device);
+      if (r == -1)
+        croak ("pvresize: %s", guestfs_last_error (g));
+
+void
+sfdisk_N (g, device, n, cyls, heads, sectors, line)
+      guestfs_h *g;
+      char *device;
+      int n;
+      int cyls;
+      int heads;
+      int sectors;
+      char *line;
+PREINIT:
+      int r;
+ PPCODE:
+      r = guestfs_sfdisk_N (g, device, n, cyls, heads, sectors, line);
+      if (r == -1)
+        croak ("sfdisk_N: %s", guestfs_last_error (g));
+
+SV *
+sfdisk_l (g, device)
+      guestfs_h *g;
+      char *device;
+PREINIT:
+      char *partitions;
+   CODE:
+      partitions = guestfs_sfdisk_l (g, device);
+      if (partitions == NULL)
+        croak ("sfdisk_l: %s", guestfs_last_error (g));
+      RETVAL = newSVpv (partitions, 0);
+      free (partitions);
+ OUTPUT:
+      RETVAL
+
+SV *
+sfdisk_kernel_geometry (g, device)
+      guestfs_h *g;
+      char *device;
+PREINIT:
+      char *partitions;
+   CODE:
+      partitions = guestfs_sfdisk_kernel_geometry (g, device);
+      if (partitions == NULL)
+        croak ("sfdisk_kernel_geometry: %s", guestfs_last_error (g));
+      RETVAL = newSVpv (partitions, 0);
+      free (partitions);
+ OUTPUT:
+      RETVAL
+
+SV *
+sfdisk_disk_geometry (g, device)
+      guestfs_h *g;
+      char *device;
+PREINIT:
+      char *partitions;
+   CODE:
+      partitions = guestfs_sfdisk_disk_geometry (g, device);
+      if (partitions == NULL)
+        croak ("sfdisk_disk_geometry: %s", guestfs_last_error (g));
+      RETVAL = newSVpv (partitions, 0);
+      free (partitions);
+ OUTPUT:
+      RETVAL
+
index b11594f..0249a41 100644 (file)
@@ -840,6 +840,11 @@ The implementation uses the C<pvremove> command which refuses to
 wipe physical volumes that contain any volume groups, so you have
 to remove those first.
 
+=item $h->pvresize ($device);
+
+This resizes (expands or shrinks) an existing LVM physical
+volume to match the new size of the underlying device.
+
 =item @physvols = $h->pvs ();
 
 List all the physical volumes detected.  This is the equivalent
@@ -985,9 +990,45 @@ To create a single partition occupying the whole disk, you would
 pass C<lines> as a single element list, when the single element being
 the string C<,> (comma).
 
+See also: C<$h-E<gt>sfdisk_l>, C<$h-E<gt>sfdisk_N>
+
+B<This command is dangerous.  Without careful use you
+can easily destroy all your data>.
+
+=item $h->sfdisk_N ($device, $n, $cyls, $heads, $sectors, $line);
+
+This runs L<sfdisk(8)> option to modify just the single
+partition C<n> (note: C<n> counts from 1).
+
+For other parameters, see C<$h-E<gt>sfdisk>.  You should usually
+pass C<0> for the cyls/heads/sectors parameters.
+
 B<This command is dangerous.  Without careful use you
 can easily destroy all your data>.
 
+=item $partitions = $h->sfdisk_disk_geometry ($device);
+
+This displays the disk geometry of C<device> read from the
+partition table.  Especially in the case where the underlying
+block device has been resized, this can be different from the
+kernel's idea of the geometry (see C<$h-E<gt>sfdisk_kernel_geometry>).
+
+The result is in human-readable format, and not designed to
+be parsed.
+
+=item $partitions = $h->sfdisk_kernel_geometry ($device);
+
+This displays the kernel's idea of the geometry of C<device>.
+
+The result is in human-readable format, and not designed to
+be parsed.
+
+=item $partitions = $h->sfdisk_l ($device);
+
+This displays the partition table on C<device>, in the
+human-readable output of the L<sfdisk(8)> command.  It is
+not intended to be parsed.
+
 =item %statbuf = $h->stat ($path);
 
 Returns file information for the given C<path>.
index 8301c70..140594d 100644 (file)
@@ -3427,6 +3427,136 @@ py_guestfs_zerofree (PyObject *self, PyObject *args)
   return py_r;
 }
 
+static PyObject *
+py_guestfs_pvresize (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *device;
+
+  if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_pvresize",
+                         &py_g, &device))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_pvresize (g, device);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_sfdisk_N (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *device;
+  int n;
+  int cyls;
+  int heads;
+  int sectors;
+  const char *line;
+
+  if (!PyArg_ParseTuple (args, (char *) "Osiiiis:guestfs_sfdisk_N",
+                         &py_g, &device, &n, &cyls, &heads, &sectors, &line))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_sfdisk_N (g, device, n, cyls, heads, sectors, line);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_sfdisk_l (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  char *r;
+  const char *device;
+
+  if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_sfdisk_l",
+                         &py_g, &device))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_sfdisk_l (g, device);
+  if (r == NULL) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = PyString_FromString (r);
+  free (r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_sfdisk_kernel_geometry (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  char *r;
+  const char *device;
+
+  if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_sfdisk_kernel_geometry",
+                         &py_g, &device))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_sfdisk_kernel_geometry (g, device);
+  if (r == NULL) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = PyString_FromString (r);
+  free (r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_sfdisk_disk_geometry (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  char *r;
+  const char *device;
+
+  if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_sfdisk_disk_geometry",
+                         &py_g, &device))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_sfdisk_disk_geometry (g, device);
+  if (r == NULL) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = PyString_FromString (r);
+  free (r);
+  return py_r;
+}
+
 static PyMethodDef methods[] = {
   { (char *) "create", py_guestfs_create, METH_VARARGS, NULL },
   { (char *) "close", py_guestfs_close, METH_VARARGS, NULL },
@@ -3551,6 +3681,11 @@ static PyMethodDef methods[] = {
   { (char *) "strings_e", py_guestfs_strings_e, METH_VARARGS, NULL },
   { (char *) "hexdump", py_guestfs_hexdump, METH_VARARGS, NULL },
   { (char *) "zerofree", py_guestfs_zerofree, METH_VARARGS, NULL },
+  { (char *) "pvresize", py_guestfs_pvresize, METH_VARARGS, NULL },
+  { (char *) "sfdisk_N", py_guestfs_sfdisk_N, METH_VARARGS, NULL },
+  { (char *) "sfdisk_l", py_guestfs_sfdisk_l, METH_VARARGS, NULL },
+  { (char *) "sfdisk_kernel_geometry", py_guestfs_sfdisk_kernel_geometry, METH_VARARGS, NULL },
+  { (char *) "sfdisk_disk_geometry", py_guestfs_sfdisk_disk_geometry, METH_VARARGS, NULL },
   { NULL, NULL, 0, NULL }
 };
 
index 044e1fa..8ac4037 100644 (file)
@@ -750,6 +750,8 @@ class GuestFS:
         you would pass "lines" as a single element list, when
         the single element being the string "," (comma).
         
+        See also: "g.sfdisk_l", "g.sfdisk_N"
+        
         This command is dangerous. Without careful use you can
         easily destroy all your data.
         """
@@ -1348,3 +1350,50 @@ class GuestFS:
         """
         return libguestfsmod.zerofree (self._o, device)
 
+    def pvresize (self, device):
+        u"""This resizes (expands or shrinks) an existing LVM
+        physical volume to match the new size of the underlying
+        device.
+        """
+        return libguestfsmod.pvresize (self._o, device)
+
+    def sfdisk_N (self, device, n, cyls, heads, sectors, line):
+        u"""This runs sfdisk(8) option to modify just the single
+        partition "n" (note: "n" counts from 1).
+        
+        For other parameters, see "g.sfdisk". You should usually
+        pass 0 for the cyls/heads/sectors parameters.
+        
+        This command is dangerous. Without careful use you can
+        easily destroy all your data.
+        """
+        return libguestfsmod.sfdisk_N (self._o, device, n, cyls, heads, sectors, line)
+
+    def sfdisk_l (self, device):
+        u"""This displays the partition table on "device", in the
+        human-readable output of the sfdisk(8) command. It is
+        not intended to be parsed.
+        """
+        return libguestfsmod.sfdisk_l (self._o, device)
+
+    def sfdisk_kernel_geometry (self, device):
+        u"""This displays the kernel's idea of the geometry of
+        "device".
+        
+        The result is in human-readable format, and not designed
+        to be parsed.
+        """
+        return libguestfsmod.sfdisk_kernel_geometry (self._o, device)
+
+    def sfdisk_disk_geometry (self, device):
+        u"""This displays the disk geometry of "device" read from
+        the partition table. Especially in the case where the
+        underlying block device has been resized, this can be
+        different from the kernel's idea of the geometry (see
+        "g.sfdisk_kernel_geometry").
+        
+        The result is in human-readable format, and not designed
+        to be parsed.
+        """
+        return libguestfsmod.sfdisk_disk_geometry (self._o, device)
+
index 4fb6ce7..b5c9b53 100644 (file)
@@ -2906,6 +2906,125 @@ static VALUE ruby_guestfs_zerofree (VALUE gv, VALUE devicev)
   return Qnil;
 }
 
+static VALUE ruby_guestfs_pvresize (VALUE gv, VALUE devicev)
+{
+  guestfs_h *g;
+  Data_Get_Struct (gv, guestfs_h, g);
+  if (!g)
+    rb_raise (rb_eArgError, "%s: used handle after closing it", "pvresize");
+
+  const char *device = StringValueCStr (devicev);
+  if (!device)
+    rb_raise (rb_eTypeError, "expected string for parameter %s of %s",
+              "device", "pvresize");
+
+  int r;
+
+  r = guestfs_pvresize (g, device);
+  if (r == -1)
+    rb_raise (e_Error, "%s", guestfs_last_error (g));
+
+  return Qnil;
+}
+
+static VALUE ruby_guestfs_sfdisk_N (VALUE gv, VALUE devicev, VALUE nv, VALUE cylsv, VALUE headsv, VALUE sectorsv, VALUE linev)
+{
+  guestfs_h *g;
+  Data_Get_Struct (gv, guestfs_h, g);
+  if (!g)
+    rb_raise (rb_eArgError, "%s: used handle after closing it", "sfdisk_N");
+
+  const char *device = StringValueCStr (devicev);
+  if (!device)
+    rb_raise (rb_eTypeError, "expected string for parameter %s of %s",
+              "device", "sfdisk_N");
+  int n = NUM2INT (nv);
+  int cyls = NUM2INT (cylsv);
+  int heads = NUM2INT (headsv);
+  int sectors = NUM2INT (sectorsv);
+  const char *line = StringValueCStr (linev);
+  if (!line)
+    rb_raise (rb_eTypeError, "expected string for parameter %s of %s",
+              "line", "sfdisk_N");
+
+  int r;
+
+  r = guestfs_sfdisk_N (g, device, n, cyls, heads, sectors, line);
+  if (r == -1)
+    rb_raise (e_Error, "%s", guestfs_last_error (g));
+
+  return Qnil;
+}
+
+static VALUE ruby_guestfs_sfdisk_l (VALUE gv, VALUE devicev)
+{
+  guestfs_h *g;
+  Data_Get_Struct (gv, guestfs_h, g);
+  if (!g)
+    rb_raise (rb_eArgError, "%s: used handle after closing it", "sfdisk_l");
+
+  const char *device = StringValueCStr (devicev);
+  if (!device)
+    rb_raise (rb_eTypeError, "expected string for parameter %s of %s",
+              "device", "sfdisk_l");
+
+  char *r;
+
+  r = guestfs_sfdisk_l (g, device);
+  if (r == NULL)
+    rb_raise (e_Error, "%s", guestfs_last_error (g));
+
+  VALUE rv = rb_str_new2 (r);
+  free (r);
+  return rv;
+}
+
+static VALUE ruby_guestfs_sfdisk_kernel_geometry (VALUE gv, VALUE devicev)
+{
+  guestfs_h *g;
+  Data_Get_Struct (gv, guestfs_h, g);
+  if (!g)
+    rb_raise (rb_eArgError, "%s: used handle after closing it", "sfdisk_kernel_geometry");
+
+  const char *device = StringValueCStr (devicev);
+  if (!device)
+    rb_raise (rb_eTypeError, "expected string for parameter %s of %s",
+              "device", "sfdisk_kernel_geometry");
+
+  char *r;
+
+  r = guestfs_sfdisk_kernel_geometry (g, device);
+  if (r == NULL)
+    rb_raise (e_Error, "%s", guestfs_last_error (g));
+
+  VALUE rv = rb_str_new2 (r);
+  free (r);
+  return rv;
+}
+
+static VALUE ruby_guestfs_sfdisk_disk_geometry (VALUE gv, VALUE devicev)
+{
+  guestfs_h *g;
+  Data_Get_Struct (gv, guestfs_h, g);
+  if (!g)
+    rb_raise (rb_eArgError, "%s: used handle after closing it", "sfdisk_disk_geometry");
+
+  const char *device = StringValueCStr (devicev);
+  if (!device)
+    rb_raise (rb_eTypeError, "expected string for parameter %s of %s",
+              "device", "sfdisk_disk_geometry");
+
+  char *r;
+
+  r = guestfs_sfdisk_disk_geometry (g, device);
+  if (r == NULL)
+    rb_raise (e_Error, "%s", guestfs_last_error (g));
+
+  VALUE rv = rb_str_new2 (r);
+  free (r);
+  return rv;
+}
+
 /* Initialize the module. */
 void Init__guestfs ()
 {
@@ -3158,4 +3277,14 @@ void Init__guestfs ()
         ruby_guestfs_hexdump, 1);
   rb_define_method (c_guestfs, "zerofree",
         ruby_guestfs_zerofree, 1);
+  rb_define_method (c_guestfs, "pvresize",
+        ruby_guestfs_pvresize, 1);
+  rb_define_method (c_guestfs, "sfdisk_N",
+        ruby_guestfs_sfdisk_N, 6);
+  rb_define_method (c_guestfs, "sfdisk_l",
+        ruby_guestfs_sfdisk_l, 1);
+  rb_define_method (c_guestfs, "sfdisk_kernel_geometry",
+        ruby_guestfs_sfdisk_kernel_geometry, 1);
+  rb_define_method (c_guestfs, "sfdisk_disk_geometry",
+        ruby_guestfs_sfdisk_disk_geometry, 1);
 }
index 652564d..19dc20d 100755 (executable)
@@ -1076,7 +1076,9 @@ information refer to the L<sfdisk(8)> manpage.
 
 To create a single partition occupying the whole disk, you would
 pass C<lines> as a single element list, when the single element being
-the string C<,> (comma).");
+the string C<,> (comma).
+
+See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>");
 
   ("write_file", (RErr, [String "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
    [InitBasicFS, Always, TestOutput (
@@ -2019,6 +2021,54 @@ mounted.
 It is possible that using this program can damage the filesystem
 or data on the filesystem.");
 
+  ("pvresize", (RErr, [String "device"]), 98, [],
+   [],
+   "resize an LVM physical volume",
+   "\
+This resizes (expands or shrinks) an existing LVM physical
+volume to match the new size of the underlying device.");
+
+  ("sfdisk_N", (RErr, [String "device"; Int "n";
+                      Int "cyls"; Int "heads"; Int "sectors";
+                      String "line"]), 99, [DangerWillRobinson],
+   [],
+   "modify a single partition on a block device",
+   "\
+This runs L<sfdisk(8)> option to modify just the single
+partition C<n> (note: C<n> counts from 1).
+
+For other parameters, see C<guestfs_sfdisk>.  You should usually
+pass C<0> for the cyls/heads/sectors parameters.");
+
+  ("sfdisk_l", (RString "partitions", [String "device"]), 100, [],
+   [],
+   "display the partition table",
+   "\
+This displays the partition table on C<device>, in the
+human-readable output of the L<sfdisk(8)> command.  It is
+not intended to be parsed.");
+
+  ("sfdisk_kernel_geometry", (RString "partitions", [String "device"]), 101, [],
+   [],
+   "display the kernel geometry",
+   "\
+This displays the kernel's idea of the geometry of C<device>.
+
+The result is in human-readable format, and not designed to
+be parsed.");
+
+  ("sfdisk_disk_geometry", (RString "partitions", [String "device"]), 102, [],
+   [],
+   "display the disk geometry from the partition table",
+   "\
+This displays the disk geometry of C<device> read from the
+partition table.  Especially in the case where the underlying
+block device has been resized, this can be different from the
+kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
+
+The result is in human-readable format, and not designed to
+be parsed.");
+
 ]
 
 let all_functions = non_daemon_functions @ daemon_functions
@@ -2267,8 +2317,10 @@ let check_functions () =
     fun (name, _, _, _, _, _, _) ->
       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
        failwithf "function name %s does not need 'guestfs' prefix" name;
-      if contains_uppercase name then
-       failwithf "function name %s should not contain uppercase chars" name;
+      if name = "" then
+       failwithf "function name is empty";
+      if name.[0] < 'a' || name.[0] > 'z' then
+       failwithf "function name %s must start with lowercase a-z" name;
       if String.contains name '-' then
        failwithf "function name %s should not contain '-', use '_' instead."
          name
index d27ef01..49e8961 100644 (file)
@@ -8896,3 +8896,463 @@ int guestfs_zerofree (guestfs_h *g,
   return 0;
 }
 
+struct pvresize_ctx {
+  /* This flag is set by the callbacks, so we know we've done
+   * the callbacks as expected, and in the right sequence.
+   * 0 = not called, 1 = reply_cb called.
+   */
+  int cb_sequence;
+  struct guestfs_message_header hdr;
+  struct guestfs_message_error err;
+};
+
+static void pvresize_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+  guestfs_main_loop *ml = guestfs_get_main_loop (g);
+  struct pvresize_ctx *ctx = (struct pvresize_ctx *) data;
+
+  /* This should definitely not happen. */
+  if (ctx->cb_sequence != 0) {
+    ctx->cb_sequence = 9999;
+    error (g, "%s: internal error: reply callback called twice", "guestfs_pvresize");
+    return;
+  }
+
+  ml->main_loop_quit (ml, g);
+
+  if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+    error (g, "%s: failed to parse reply header", "guestfs_pvresize");
+    return;
+  }
+  if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+      error (g, "%s: failed to parse reply error", "guestfs_pvresize");
+      return;
+    }
+    goto done;
+  }
+ done:
+  ctx->cb_sequence = 1;
+}
+
+int guestfs_pvresize (guestfs_h *g,
+               const char *device)
+{
+  struct guestfs_pvresize_args args;
+  struct pvresize_ctx ctx;
+  guestfs_main_loop *ml = guestfs_get_main_loop (g);
+  int serial;
+
+  if (check_state (g, "guestfs_pvresize") == -1) return -1;
+  guestfs_set_busy (g);
+
+  memset (&ctx, 0, sizeof ctx);
+
+  args.device = (char *) device;
+  serial = guestfs__send_sync (g, GUESTFS_PROC_PVRESIZE,
+        (xdrproc_t) xdr_guestfs_pvresize_args, (char *) &args);
+  if (serial == -1) {
+    guestfs_end_busy (g);
+    return -1;
+  }
+
+  guestfs__switch_to_receiving (g);
+  ctx.cb_sequence = 0;
+  guestfs_set_reply_callback (g, pvresize_reply_cb, &ctx);
+  (void) ml->main_loop_run (ml, g);
+  guestfs_set_reply_callback (g, NULL, NULL);
+  if (ctx.cb_sequence != 1) {
+    error (g, "%s reply failed, see earlier error messages", "guestfs_pvresize");
+    guestfs_end_busy (g);
+    return -1;
+  }
+
+  if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_PVRESIZE, serial) == -1) {
+    guestfs_end_busy (g);
+    return -1;
+  }
+
+  if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", ctx.err.error_message);
+    free (ctx.err.error_message);
+    guestfs_end_busy (g);
+    return -1;
+  }
+
+  guestfs_end_busy (g);
+  return 0;
+}
+
+struct sfdisk_N_ctx {
+  /* This flag is set by the callbacks, so we know we've done
+   * the callbacks as expected, and in the right sequence.
+   * 0 = not called, 1 = reply_cb called.
+   */
+  int cb_sequence;
+  struct guestfs_message_header hdr;
+  struct guestfs_message_error err;
+};
+
+static void sfdisk_N_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+  guestfs_main_loop *ml = guestfs_get_main_loop (g);
+  struct sfdisk_N_ctx *ctx = (struct sfdisk_N_ctx *) data;
+
+  /* This should definitely not happen. */
+  if (ctx->cb_sequence != 0) {
+    ctx->cb_sequence = 9999;
+    error (g, "%s: internal error: reply callback called twice", "guestfs_sfdisk_N");
+    return;
+  }
+
+  ml->main_loop_quit (ml, g);
+
+  if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+    error (g, "%s: failed to parse reply header", "guestfs_sfdisk_N");
+    return;
+  }
+  if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+      error (g, "%s: failed to parse reply error", "guestfs_sfdisk_N");
+      return;
+    }
+    goto done;
+  }
+ done:
+  ctx->cb_sequence = 1;
+}
+
+int guestfs_sfdisk_N (guestfs_h *g,
+               const char *device,
+               int n,
+               int cyls,
+               int heads,
+               int sectors,
+               const char *line)
+{
+  struct guestfs_sfdisk_N_args args;
+  struct sfdisk_N_ctx ctx;
+  guestfs_main_loop *ml = guestfs_get_main_loop (g);
+  int serial;
+
+  if (check_state (g, "guestfs_sfdisk_N") == -1) return -1;
+  guestfs_set_busy (g);
+
+  memset (&ctx, 0, sizeof ctx);
+
+  args.device = (char *) device;
+  args.n = n;
+  args.cyls = cyls;
+  args.heads = heads;
+  args.sectors = sectors;
+  args.line = (char *) line;
+  serial = guestfs__send_sync (g, GUESTFS_PROC_SFDISK_N,
+        (xdrproc_t) xdr_guestfs_sfdisk_N_args, (char *) &args);
+  if (serial == -1) {
+    guestfs_end_busy (g);
+    return -1;
+  }
+
+  guestfs__switch_to_receiving (g);
+  ctx.cb_sequence = 0;
+  guestfs_set_reply_callback (g, sfdisk_N_reply_cb, &ctx);
+  (void) ml->main_loop_run (ml, g);
+  guestfs_set_reply_callback (g, NULL, NULL);
+  if (ctx.cb_sequence != 1) {
+    error (g, "%s reply failed, see earlier error messages", "guestfs_sfdisk_N");
+    guestfs_end_busy (g);
+    return -1;
+  }
+
+  if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SFDISK_N, serial) == -1) {
+    guestfs_end_busy (g);
+    return -1;
+  }
+
+  if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", ctx.err.error_message);
+    free (ctx.err.error_message);
+    guestfs_end_busy (g);
+    return -1;
+  }
+
+  guestfs_end_busy (g);
+  return 0;
+}
+
+struct sfdisk_l_ctx {
+  /* This flag is set by the callbacks, so we know we've done
+   * the callbacks as expected, and in the right sequence.
+   * 0 = not called, 1 = reply_cb called.
+   */
+  int cb_sequence;
+  struct guestfs_message_header hdr;
+  struct guestfs_message_error err;
+  struct guestfs_sfdisk_l_ret ret;
+};
+
+static void sfdisk_l_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+  guestfs_main_loop *ml = guestfs_get_main_loop (g);
+  struct sfdisk_l_ctx *ctx = (struct sfdisk_l_ctx *) data;
+
+  /* This should definitely not happen. */
+  if (ctx->cb_sequence != 0) {
+    ctx->cb_sequence = 9999;
+    error (g, "%s: internal error: reply callback called twice", "guestfs_sfdisk_l");
+    return;
+  }
+
+  ml->main_loop_quit (ml, g);
+
+  if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+    error (g, "%s: failed to parse reply header", "guestfs_sfdisk_l");
+    return;
+  }
+  if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+      error (g, "%s: failed to parse reply error", "guestfs_sfdisk_l");
+      return;
+    }
+    goto done;
+  }
+  if (!xdr_guestfs_sfdisk_l_ret (xdr, &ctx->ret)) {
+    error (g, "%s: failed to parse reply", "guestfs_sfdisk_l");
+    return;
+  }
+ done:
+  ctx->cb_sequence = 1;
+}
+
+char *guestfs_sfdisk_l (guestfs_h *g,
+               const char *device)
+{
+  struct guestfs_sfdisk_l_args args;
+  struct sfdisk_l_ctx ctx;
+  guestfs_main_loop *ml = guestfs_get_main_loop (g);
+  int serial;
+
+  if (check_state (g, "guestfs_sfdisk_l") == -1) return NULL;
+  guestfs_set_busy (g);
+
+  memset (&ctx, 0, sizeof ctx);
+
+  args.device = (char *) device;
+  serial = guestfs__send_sync (g, GUESTFS_PROC_SFDISK_L,
+        (xdrproc_t) xdr_guestfs_sfdisk_l_args, (char *) &args);
+  if (serial == -1) {
+    guestfs_end_busy (g);
+    return NULL;
+  }
+
+  guestfs__switch_to_receiving (g);
+  ctx.cb_sequence = 0;
+  guestfs_set_reply_callback (g, sfdisk_l_reply_cb, &ctx);
+  (void) ml->main_loop_run (ml, g);
+  guestfs_set_reply_callback (g, NULL, NULL);
+  if (ctx.cb_sequence != 1) {
+    error (g, "%s reply failed, see earlier error messages", "guestfs_sfdisk_l");
+    guestfs_end_busy (g);
+    return NULL;
+  }
+
+  if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SFDISK_L, serial) == -1) {
+    guestfs_end_busy (g);
+    return NULL;
+  }
+
+  if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", ctx.err.error_message);
+    free (ctx.err.error_message);
+    guestfs_end_busy (g);
+    return NULL;
+  }
+
+  guestfs_end_busy (g);
+  return ctx.ret.partitions; /* caller will free */
+}
+
+struct sfdisk_kernel_geometry_ctx {
+  /* This flag is set by the callbacks, so we know we've done
+   * the callbacks as expected, and in the right sequence.
+   * 0 = not called, 1 = reply_cb called.
+   */
+  int cb_sequence;
+  struct guestfs_message_header hdr;
+  struct guestfs_message_error err;
+  struct guestfs_sfdisk_kernel_geometry_ret ret;
+};
+
+static void sfdisk_kernel_geometry_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+  guestfs_main_loop *ml = guestfs_get_main_loop (g);
+  struct sfdisk_kernel_geometry_ctx *ctx = (struct sfdisk_kernel_geometry_ctx *) data;
+
+  /* This should definitely not happen. */
+  if (ctx->cb_sequence != 0) {
+    ctx->cb_sequence = 9999;
+    error (g, "%s: internal error: reply callback called twice", "guestfs_sfdisk_kernel_geometry");
+    return;
+  }
+
+  ml->main_loop_quit (ml, g);
+
+  if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+    error (g, "%s: failed to parse reply header", "guestfs_sfdisk_kernel_geometry");
+    return;
+  }
+  if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+      error (g, "%s: failed to parse reply error", "guestfs_sfdisk_kernel_geometry");
+      return;
+    }
+    goto done;
+  }
+  if (!xdr_guestfs_sfdisk_kernel_geometry_ret (xdr, &ctx->ret)) {
+    error (g, "%s: failed to parse reply", "guestfs_sfdisk_kernel_geometry");
+    return;
+  }
+ done:
+  ctx->cb_sequence = 1;
+}
+
+char *guestfs_sfdisk_kernel_geometry (guestfs_h *g,
+               const char *device)
+{
+  struct guestfs_sfdisk_kernel_geometry_args args;
+  struct sfdisk_kernel_geometry_ctx ctx;
+  guestfs_main_loop *ml = guestfs_get_main_loop (g);
+  int serial;
+
+  if (check_state (g, "guestfs_sfdisk_kernel_geometry") == -1) return NULL;
+  guestfs_set_busy (g);
+
+  memset (&ctx, 0, sizeof ctx);
+
+  args.device = (char *) device;
+  serial = guestfs__send_sync (g, GUESTFS_PROC_SFDISK_KERNEL_GEOMETRY,
+        (xdrproc_t) xdr_guestfs_sfdisk_kernel_geometry_args, (char *) &args);
+  if (serial == -1) {
+    guestfs_end_busy (g);
+    return NULL;
+  }
+
+  guestfs__switch_to_receiving (g);
+  ctx.cb_sequence = 0;
+  guestfs_set_reply_callback (g, sfdisk_kernel_geometry_reply_cb, &ctx);
+  (void) ml->main_loop_run (ml, g);
+  guestfs_set_reply_callback (g, NULL, NULL);
+  if (ctx.cb_sequence != 1) {
+    error (g, "%s reply failed, see earlier error messages", "guestfs_sfdisk_kernel_geometry");
+    guestfs_end_busy (g);
+    return NULL;
+  }
+
+  if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SFDISK_KERNEL_GEOMETRY, serial) == -1) {
+    guestfs_end_busy (g);
+    return NULL;
+  }
+
+  if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", ctx.err.error_message);
+    free (ctx.err.error_message);
+    guestfs_end_busy (g);
+    return NULL;
+  }
+
+  guestfs_end_busy (g);
+  return ctx.ret.partitions; /* caller will free */
+}
+
+struct sfdisk_disk_geometry_ctx {
+  /* This flag is set by the callbacks, so we know we've done
+   * the callbacks as expected, and in the right sequence.
+   * 0 = not called, 1 = reply_cb called.
+   */
+  int cb_sequence;
+  struct guestfs_message_header hdr;
+  struct guestfs_message_error err;
+  struct guestfs_sfdisk_disk_geometry_ret ret;
+};
+
+static void sfdisk_disk_geometry_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+  guestfs_main_loop *ml = guestfs_get_main_loop (g);
+  struct sfdisk_disk_geometry_ctx *ctx = (struct sfdisk_disk_geometry_ctx *) data;
+
+  /* This should definitely not happen. */
+  if (ctx->cb_sequence != 0) {
+    ctx->cb_sequence = 9999;
+    error (g, "%s: internal error: reply callback called twice", "guestfs_sfdisk_disk_geometry");
+    return;
+  }
+
+  ml->main_loop_quit (ml, g);
+
+  if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+    error (g, "%s: failed to parse reply header", "guestfs_sfdisk_disk_geometry");
+    return;
+  }
+  if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+      error (g, "%s: failed to parse reply error", "guestfs_sfdisk_disk_geometry");
+      return;
+    }
+    goto done;
+  }
+  if (!xdr_guestfs_sfdisk_disk_geometry_ret (xdr, &ctx->ret)) {
+    error (g, "%s: failed to parse reply", "guestfs_sfdisk_disk_geometry");
+    return;
+  }
+ done:
+  ctx->cb_sequence = 1;
+}
+
+char *guestfs_sfdisk_disk_geometry (guestfs_h *g,
+               const char *device)
+{
+  struct guestfs_sfdisk_disk_geometry_args args;
+  struct sfdisk_disk_geometry_ctx ctx;
+  guestfs_main_loop *ml = guestfs_get_main_loop (g);
+  int serial;
+
+  if (check_state (g, "guestfs_sfdisk_disk_geometry") == -1) return NULL;
+  guestfs_set_busy (g);
+
+  memset (&ctx, 0, sizeof ctx);
+
+  args.device = (char *) device;
+  serial = guestfs__send_sync (g, GUESTFS_PROC_SFDISK_DISK_GEOMETRY,
+        (xdrproc_t) xdr_guestfs_sfdisk_disk_geometry_args, (char *) &args);
+  if (serial == -1) {
+    guestfs_end_busy (g);
+    return NULL;
+  }
+
+  guestfs__switch_to_receiving (g);
+  ctx.cb_sequence = 0;
+  guestfs_set_reply_callback (g, sfdisk_disk_geometry_reply_cb, &ctx);
+  (void) ml->main_loop_run (ml, g);
+  guestfs_set_reply_callback (g, NULL, NULL);
+  if (ctx.cb_sequence != 1) {
+    error (g, "%s reply failed, see earlier error messages", "guestfs_sfdisk_disk_geometry");
+    guestfs_end_busy (g);
+    return NULL;
+  }
+
+  if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SFDISK_DISK_GEOMETRY, serial) == -1) {
+    guestfs_end_busy (g);
+    return NULL;
+  }
+
+  if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", ctx.err.error_message);
+    free (ctx.err.error_message);
+    guestfs_end_busy (g);
+    return NULL;
+  }
+
+  guestfs_end_busy (g);
+  return ctx.ret.partitions; /* caller will free */
+}
+
index 9a4e923..b07e3dd 100644 (file)
@@ -140,3 +140,8 @@ extern char **guestfs_strings (guestfs_h *handle, const char *path);
 extern char **guestfs_strings_e (guestfs_h *handle, const char *encoding, const char *path);
 extern char *guestfs_hexdump (guestfs_h *handle, const char *path);
 extern int guestfs_zerofree (guestfs_h *handle, const char *device);
+extern int guestfs_pvresize (guestfs_h *handle, const char *device);
+extern int guestfs_sfdisk_N (guestfs_h *handle, const char *device, int n, int cyls, int heads, int sectors, const char *line);
+extern char *guestfs_sfdisk_l (guestfs_h *handle, const char *device);
+extern char *guestfs_sfdisk_kernel_geometry (guestfs_h *handle, const char *device);
+extern char *guestfs_sfdisk_disk_geometry (guestfs_h *handle, const char *device);
index c505b25..e6e865e 100644 (file)
@@ -1624,6 +1624,145 @@ xdr_guestfs_zerofree_args (XDR *xdrs, guestfs_zerofree_args *objp)
 }
 
 bool_t
+xdr_guestfs_pvresize_args (XDR *xdrs, guestfs_pvresize_args *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_string (xdrs, &objp->device, ~0))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_guestfs_sfdisk_N_args (XDR *xdrs, guestfs_sfdisk_N_args *objp)
+{
+       register int32_t *buf;
+
+
+       if (xdrs->x_op == XDR_ENCODE) {
+                if (!xdr_string (xdrs, &objp->device, ~0))
+                        return FALSE;
+               buf = XDR_INLINE (xdrs, 4 * BYTES_PER_XDR_UNIT);
+               if (buf == NULL) {
+                        if (!xdr_int (xdrs, &objp->n))
+                                return FALSE;
+                        if (!xdr_int (xdrs, &objp->cyls))
+                                return FALSE;
+                        if (!xdr_int (xdrs, &objp->heads))
+                                return FALSE;
+                        if (!xdr_int (xdrs, &objp->sectors))
+                                return FALSE;
+
+               } else {
+               IXDR_PUT_LONG(buf, objp->n);
+               IXDR_PUT_LONG(buf, objp->cyls);
+               IXDR_PUT_LONG(buf, objp->heads);
+               IXDR_PUT_LONG(buf, objp->sectors);
+               }
+                if (!xdr_string (xdrs, &objp->line, ~0))
+                        return FALSE;
+               return TRUE;
+       } else if (xdrs->x_op == XDR_DECODE) {
+                if (!xdr_string (xdrs, &objp->device, ~0))
+                        return FALSE;
+               buf = XDR_INLINE (xdrs, 4 * BYTES_PER_XDR_UNIT);
+               if (buf == NULL) {
+                        if (!xdr_int (xdrs, &objp->n))
+                                return FALSE;
+                        if (!xdr_int (xdrs, &objp->cyls))
+                                return FALSE;
+                        if (!xdr_int (xdrs, &objp->heads))
+                                return FALSE;
+                        if (!xdr_int (xdrs, &objp->sectors))
+                                return FALSE;
+
+               } else {
+               objp->n = IXDR_GET_LONG(buf);
+               objp->cyls = IXDR_GET_LONG(buf);
+               objp->heads = IXDR_GET_LONG(buf);
+               objp->sectors = IXDR_GET_LONG(buf);
+               }
+                if (!xdr_string (xdrs, &objp->line, ~0))
+                        return FALSE;
+        return TRUE;
+       }
+
+        if (!xdr_string (xdrs, &objp->device, ~0))
+                return FALSE;
+        if (!xdr_int (xdrs, &objp->n))
+                return FALSE;
+        if (!xdr_int (xdrs, &objp->cyls))
+                return FALSE;
+        if (!xdr_int (xdrs, &objp->heads))
+                return FALSE;
+        if (!xdr_int (xdrs, &objp->sectors))
+                return FALSE;
+        if (!xdr_string (xdrs, &objp->line, ~0))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_guestfs_sfdisk_l_args (XDR *xdrs, guestfs_sfdisk_l_args *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_string (xdrs, &objp->device, ~0))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_guestfs_sfdisk_l_ret (XDR *xdrs, guestfs_sfdisk_l_ret *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_string (xdrs, &objp->partitions, ~0))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_guestfs_sfdisk_kernel_geometry_args (XDR *xdrs, guestfs_sfdisk_kernel_geometry_args *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_string (xdrs, &objp->device, ~0))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_guestfs_sfdisk_kernel_geometry_ret (XDR *xdrs, guestfs_sfdisk_kernel_geometry_ret *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_string (xdrs, &objp->partitions, ~0))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_guestfs_sfdisk_disk_geometry_args (XDR *xdrs, guestfs_sfdisk_disk_geometry_args *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_string (xdrs, &objp->device, ~0))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_guestfs_sfdisk_disk_geometry_ret (XDR *xdrs, guestfs_sfdisk_disk_geometry_ret *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_string (xdrs, &objp->partitions, ~0))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
 xdr_guestfs_procedure (XDR *xdrs, guestfs_procedure *objp)
 {
        register int32_t *buf;
index a855307..6235577 100644 (file)
@@ -842,6 +842,51 @@ struct guestfs_zerofree_args {
 };
 typedef struct guestfs_zerofree_args guestfs_zerofree_args;
 
+struct guestfs_pvresize_args {
+       char *device;
+};
+typedef struct guestfs_pvresize_args guestfs_pvresize_args;
+
+struct guestfs_sfdisk_N_args {
+       char *device;
+       int n;
+       int cyls;
+       int heads;
+       int sectors;
+       char *line;
+};
+typedef struct guestfs_sfdisk_N_args guestfs_sfdisk_N_args;
+
+struct guestfs_sfdisk_l_args {
+       char *device;
+};
+typedef struct guestfs_sfdisk_l_args guestfs_sfdisk_l_args;
+
+struct guestfs_sfdisk_l_ret {
+       char *partitions;
+};
+typedef struct guestfs_sfdisk_l_ret guestfs_sfdisk_l_ret;
+
+struct guestfs_sfdisk_kernel_geometry_args {
+       char *device;
+};
+typedef struct guestfs_sfdisk_kernel_geometry_args guestfs_sfdisk_kernel_geometry_args;
+
+struct guestfs_sfdisk_kernel_geometry_ret {
+       char *partitions;
+};
+typedef struct guestfs_sfdisk_kernel_geometry_ret guestfs_sfdisk_kernel_geometry_ret;
+
+struct guestfs_sfdisk_disk_geometry_args {
+       char *device;
+};
+typedef struct guestfs_sfdisk_disk_geometry_args guestfs_sfdisk_disk_geometry_args;
+
+struct guestfs_sfdisk_disk_geometry_ret {
+       char *partitions;
+};
+typedef struct guestfs_sfdisk_disk_geometry_ret guestfs_sfdisk_disk_geometry_ret;
+
 enum guestfs_procedure {
        GUESTFS_PROC_MOUNT = 1,
        GUESTFS_PROC_SYNC = 2,
@@ -940,7 +985,12 @@ enum guestfs_procedure {
        GUESTFS_PROC_STRINGS_E = 95,
        GUESTFS_PROC_HEXDUMP = 96,
        GUESTFS_PROC_ZEROFREE = 97,
-       GUESTFS_PROC_NR_PROCS = 97 + 1,
+       GUESTFS_PROC_PVRESIZE = 98,
+       GUESTFS_PROC_SFDISK_N = 99,
+       GUESTFS_PROC_SFDISK_L = 100,
+       GUESTFS_PROC_SFDISK_KERNEL_GEOMETRY = 101,
+       GUESTFS_PROC_SFDISK_DISK_GEOMETRY = 102,
+       GUESTFS_PROC_NR_PROCS = 102 + 1,
 };
 typedef enum guestfs_procedure guestfs_procedure;
 #define GUESTFS_MESSAGE_MAX 4194304
@@ -1123,6 +1173,14 @@ extern  bool_t xdr_guestfs_strings_e_ret (XDR *, guestfs_strings_e_ret*);
 extern  bool_t xdr_guestfs_hexdump_args (XDR *, guestfs_hexdump_args*);
 extern  bool_t xdr_guestfs_hexdump_ret (XDR *, guestfs_hexdump_ret*);
 extern  bool_t xdr_guestfs_zerofree_args (XDR *, guestfs_zerofree_args*);
+extern  bool_t xdr_guestfs_pvresize_args (XDR *, guestfs_pvresize_args*);
+extern  bool_t xdr_guestfs_sfdisk_N_args (XDR *, guestfs_sfdisk_N_args*);
+extern  bool_t xdr_guestfs_sfdisk_l_args (XDR *, guestfs_sfdisk_l_args*);
+extern  bool_t xdr_guestfs_sfdisk_l_ret (XDR *, guestfs_sfdisk_l_ret*);
+extern  bool_t xdr_guestfs_sfdisk_kernel_geometry_args (XDR *, guestfs_sfdisk_kernel_geometry_args*);
+extern  bool_t xdr_guestfs_sfdisk_kernel_geometry_ret (XDR *, guestfs_sfdisk_kernel_geometry_ret*);
+extern  bool_t xdr_guestfs_sfdisk_disk_geometry_args (XDR *, guestfs_sfdisk_disk_geometry_args*);
+extern  bool_t xdr_guestfs_sfdisk_disk_geometry_ret (XDR *, guestfs_sfdisk_disk_geometry_ret*);
 extern  bool_t xdr_guestfs_procedure (XDR *, guestfs_procedure*);
 extern  bool_t xdr_guestfs_message_direction (XDR *, guestfs_message_direction*);
 extern  bool_t xdr_guestfs_message_status (XDR *, guestfs_message_status*);
@@ -1264,6 +1322,14 @@ extern bool_t xdr_guestfs_strings_e_ret ();
 extern bool_t xdr_guestfs_hexdump_args ();
 extern bool_t xdr_guestfs_hexdump_ret ();
 extern bool_t xdr_guestfs_zerofree_args ();
+extern bool_t xdr_guestfs_pvresize_args ();
+extern bool_t xdr_guestfs_sfdisk_N_args ();
+extern bool_t xdr_guestfs_sfdisk_l_args ();
+extern bool_t xdr_guestfs_sfdisk_l_ret ();
+extern bool_t xdr_guestfs_sfdisk_kernel_geometry_args ();
+extern bool_t xdr_guestfs_sfdisk_kernel_geometry_ret ();
+extern bool_t xdr_guestfs_sfdisk_disk_geometry_args ();
+extern bool_t xdr_guestfs_sfdisk_disk_geometry_ret ();
 extern bool_t xdr_guestfs_procedure ();
 extern bool_t xdr_guestfs_message_direction ();
 extern bool_t xdr_guestfs_message_status ();
index f09e5b5..0df5cb0 100644 (file)
@@ -652,6 +652,43 @@ struct guestfs_zerofree_args {
   string device<>;
 };
 
+struct guestfs_pvresize_args {
+  string device<>;
+};
+
+struct guestfs_sfdisk_N_args {
+  string device<>;
+  int n;
+  int cyls;
+  int heads;
+  int sectors;
+  string line<>;
+};
+
+struct guestfs_sfdisk_l_args {
+  string device<>;
+};
+
+struct guestfs_sfdisk_l_ret {
+  string partitions<>;
+};
+
+struct guestfs_sfdisk_kernel_geometry_args {
+  string device<>;
+};
+
+struct guestfs_sfdisk_kernel_geometry_ret {
+  string partitions<>;
+};
+
+struct guestfs_sfdisk_disk_geometry_args {
+  string device<>;
+};
+
+struct guestfs_sfdisk_disk_geometry_ret {
+  string partitions<>;
+};
+
 enum guestfs_procedure {
   GUESTFS_PROC_MOUNT = 1,
   GUESTFS_PROC_SYNC = 2,
@@ -750,6 +787,11 @@ enum guestfs_procedure {
   GUESTFS_PROC_STRINGS_E = 95,
   GUESTFS_PROC_HEXDUMP = 96,
   GUESTFS_PROC_ZEROFREE = 97,
+  GUESTFS_PROC_PVRESIZE = 98,
+  GUESTFS_PROC_SFDISK_N = 99,
+  GUESTFS_PROC_SFDISK_L = 100,
+  GUESTFS_PROC_SFDISK_KERNEL_GEOMETRY = 101,
+  GUESTFS_PROC_SFDISK_DISK_GEOMETRY = 102,
   GUESTFS_PROC_NR_PROCS
 };
 
diff --git a/tests.c b/tests.c
index 11a1568..31fa3bf 100644 (file)
--- a/tests.c
+++ b/tests.c
@@ -116,6 +116,11 @@ static void no_test_warnings (void)
   fprintf (stderr, "warning: \"guestfs_debug\" has no tests\n");
   fprintf (stderr, "warning: \"guestfs_get_e2label\" has no tests\n");
   fprintf (stderr, "warning: \"guestfs_get_e2uuid\" has no tests\n");
+  fprintf (stderr, "warning: \"guestfs_pvresize\" has no tests\n");
+  fprintf (stderr, "warning: \"guestfs_sfdisk_N\" has no tests\n");
+  fprintf (stderr, "warning: \"guestfs_sfdisk_l\" has no tests\n");
+  fprintf (stderr, "warning: \"guestfs_sfdisk_kernel_geometry\" has no tests\n");
+  fprintf (stderr, "warning: \"guestfs_sfdisk_disk_geometry\" has no tests\n");
 }
 
 static int test_zerofree_0 (void)