diff options
author | Richard W.M. Jones <rjones@redhat.com> | 2009-05-15 14:01:28 +0100 |
---|---|---|
committer | Richard W.M. Jones <rjones@redhat.com> | 2009-05-15 14:52:34 +0100 |
commit | 5cd39c83e23eb300d1bdfa806902a31b409ff420 (patch) | |
tree | a47e2bf9afc16cb9404ae996f512a9d3f22e553b | |
parent | b8e5f51c79f539a740827506cc9da3ffcb6c87f8 (diff) | |
download | libguestfs-5cd39c83e23eb300d1bdfa806902a31b409ff420.tar.gz libguestfs-5cd39c83e23eb300d1bdfa806902a31b409ff420.tar.xz libguestfs-5cd39c83e23eb300d1bdfa806902a31b409ff420.zip |
Add: pvresize, sfdisk-N, sfdisk-l, sfdisk-kernel-geomtry, sfdisk-disk-geometry commands. Pass --no-reread flag to sfdisk.
-rw-r--r-- | daemon/Makefile.am | 1 | ||||
-rw-r--r-- | daemon/actions.h | 5 | ||||
-rw-r--r-- | daemon/devsparts.c | 43 | ||||
-rw-r--r-- | daemon/lvm.c | 18 | ||||
-rw-r--r-- | daemon/sfdisk.c | 130 | ||||
-rw-r--r-- | daemon/stubs.c | 154 | ||||
-rw-r--r-- | fish/cmds.c | 126 | ||||
-rw-r--r-- | fish/completion.c | 5 | ||||
-rw-r--r-- | guestfish-actions.pod | 51 | ||||
-rw-r--r-- | guestfs-actions.pod | 74 | ||||
-rw-r--r-- | haskell/Guestfs.hs | 15 | ||||
-rw-r--r-- | java/com/redhat/et/libguestfs/GuestFS.java | 109 | ||||
-rw-r--r-- | java/com_redhat_et_libguestfs_GuestFS.c | 108 | ||||
-rw-r--r-- | ocaml/guestfs.ml | 5 | ||||
-rw-r--r-- | ocaml/guestfs.mli | 15 | ||||
-rw-r--r-- | ocaml/guestfs_c_actions.c | 130 | ||||
-rw-r--r-- | perl/Guestfs.xs | 72 | ||||
-rw-r--r-- | perl/lib/Sys/Guestfs.pm | 41 | ||||
-rw-r--r-- | python/guestfs-py.c | 135 | ||||
-rw-r--r-- | python/guestfs.py | 49 | ||||
-rw-r--r-- | ruby/ext/guestfs/_guestfs.c | 129 | ||||
-rwxr-xr-x | src/generator.ml | 58 | ||||
-rw-r--r-- | src/guestfs-actions.c | 460 | ||||
-rw-r--r-- | src/guestfs-actions.h | 5 | ||||
-rw-r--r-- | src/guestfs_protocol.c | 139 | ||||
-rw-r--r-- | src/guestfs_protocol.h | 68 | ||||
-rw-r--r-- | src/guestfs_protocol.x | 42 | ||||
-rw-r--r-- | tests.c | 5 |
28 files changed, 2143 insertions, 49 deletions
diff --git a/daemon/Makefile.am b/daemon/Makefile.am index d6ae6c38..ac1f8c58 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -43,6 +43,7 @@ guestfsd_SOURCES = \ mount.c \ pingdaemon.c \ proto.c \ + sfdisk.c \ stat.c \ strings.c \ stubs.c \ diff --git a/daemon/actions.h b/daemon/actions.h index 37ec1253..3e6589e2 100644 --- a/daemon/actions.h +++ b/daemon/actions.h @@ -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); diff --git a/daemon/devsparts.c b/daemon/devsparts.c index 0a4d5e46..21854b5c 100644 --- a/daemon/devsparts.c +++ b/daemon/devsparts.c @@ -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; -} diff --git a/daemon/lvm.c b/daemon/lvm.c index 326b5830..d1a6cd60 100644 --- a/daemon/lvm.c +++ b/daemon/lvm.c @@ -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 index 00000000..9d7a220f --- /dev/null +++ b/daemon/sfdisk.c @@ -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"); +} diff --git a/daemon/stubs.c b/daemon/stubs.c index 212634fd..e80ba9be 100644 --- a/daemon/stubs.c +++ b/daemon/stubs.c @@ -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); } diff --git a/fish/cmds.c b/fish/cmds.c index 1f3d9cee..5680bfa3 100644 --- a/fish/cmds.c +++ b/fish/cmds.c @@ -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; diff --git a/fish/completion.c b/fish/completion.c index 5c7f5e01..03760ad6 100644 --- a/fish/completion.c +++ b/fish/completion.c @@ -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", diff --git a/guestfish-actions.pod b/guestfish-actions.pod index 7b5a4bed..213fa66e 100644 --- a/guestfish-actions.pod +++ b/guestfish-actions.pod @@ -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 diff --git a/guestfs-actions.pod b/guestfs-actions.pod index 109c73ea..abeed8ff 100644 --- a/guestfs-actions.pod +++ b/guestfs-actions.pod @@ -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, diff --git a/haskell/Guestfs.hs b/haskell/Guestfs.hs index c061a7a6..170f0403 100644 --- a/haskell/Guestfs.hs +++ b/haskell/Guestfs.hs @@ -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 () + diff --git a/java/com/redhat/et/libguestfs/GuestFS.java b/java/com/redhat/et/libguestfs/GuestFS.java index 76ada908..7eafce0f 100644 --- a/java/com/redhat/et/libguestfs/GuestFS.java +++ b/java/com/redhat/et/libguestfs/GuestFS.java @@ -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; + } diff --git a/java/com_redhat_et_libguestfs_GuestFS.c b/java/com_redhat_et_libguestfs_GuestFS.c index a823d84e..be7ea9f2 100644 --- a/java/com_redhat_et_libguestfs_GuestFS.c +++ b/java/com_redhat_et_libguestfs_GuestFS.c @@ -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; +} + diff --git a/ocaml/guestfs.ml b/ocaml/guestfs.ml index 3886022d..d50b2d8c 100644 --- a/ocaml/guestfs.ml +++ b/ocaml/guestfs.ml @@ -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" diff --git a/ocaml/guestfs.mli b/ocaml/guestfs.mli index 3776abe7..358a6d30 100644 --- a/ocaml/guestfs.mli +++ b/ocaml/guestfs.mli @@ -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 *) + diff --git a/ocaml/guestfs_c_actions.c b/ocaml/guestfs_c_actions.c index 79a5c16f..f2d13b03 100644 --- a/ocaml/guestfs_c_actions.c +++ b/ocaml/guestfs_c_actions.c @@ -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); +} + diff --git a/perl/Guestfs.xs b/perl/Guestfs.xs index e87131bd..ff7ca9e1 100644 --- a/perl/Guestfs.xs +++ b/perl/Guestfs.xs @@ -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 + diff --git a/perl/lib/Sys/Guestfs.pm b/perl/lib/Sys/Guestfs.pm index b11594f2..0249a412 100644 --- a/perl/lib/Sys/Guestfs.pm +++ b/perl/lib/Sys/Guestfs.pm @@ -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>. diff --git a/python/guestfs-py.c b/python/guestfs-py.c index 8301c703..140594d2 100644 --- a/python/guestfs-py.c +++ b/python/guestfs-py.c @@ -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, §ors, &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 } }; diff --git a/python/guestfs.py b/python/guestfs.py index 044e1fac..8ac4037c 100644 --- a/python/guestfs.py +++ b/python/guestfs.py @@ -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) + diff --git a/ruby/ext/guestfs/_guestfs.c b/ruby/ext/guestfs/_guestfs.c index 4fb6ce71..b5c9b53a 100644 --- a/ruby/ext/guestfs/_guestfs.c +++ b/ruby/ext/guestfs/_guestfs.c @@ -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); } diff --git a/src/generator.ml b/src/generator.ml index 652564d8..19dc20d5 100755 --- a/src/generator.ml +++ b/src/generator.ml @@ -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 diff --git a/src/guestfs-actions.c b/src/guestfs-actions.c index d27ef012..49e8961d 100644 --- a/src/guestfs-actions.c +++ b/src/guestfs-actions.c @@ -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 */ +} + diff --git a/src/guestfs-actions.h b/src/guestfs-actions.h index 9a4e9232..b07e3dd5 100644 --- a/src/guestfs-actions.h +++ b/src/guestfs-actions.h @@ -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); diff --git a/src/guestfs_protocol.c b/src/guestfs_protocol.c index c505b251..e6e865e6 100644 --- a/src/guestfs_protocol.c +++ b/src/guestfs_protocol.c @@ -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; diff --git a/src/guestfs_protocol.h b/src/guestfs_protocol.h index a855307c..62355774 100644 --- a/src/guestfs_protocol.h +++ b/src/guestfs_protocol.h @@ -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 (); diff --git a/src/guestfs_protocol.x b/src/guestfs_protocol.x index f09e5b5b..0df5cb07 100644 --- a/src/guestfs_protocol.x +++ b/src/guestfs_protocol.x @@ -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 }; @@ -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) |