New API: Add aug-clear call for clearing an Augeas node.
[libguestfs.git] / src / generator.ml
index 4f569ba..79a10dd 100755 (executable)
@@ -42,6 +42,7 @@
 #load "unix.cma";;
 #load "str.cma";;
 #directory "+xml-light";;
 #load "unix.cma";;
 #load "str.cma";;
 #directory "+xml-light";;
+#directory "+../pkg-lib/xml-light";; (* for GODI users *)
 #load "xml-light.cma";;
 
 open Unix
 #load "xml-light.cma";;
 
 open Unix
@@ -544,13 +545,15 @@ handle is closed.  We don't currently have any method to enable
 changes to be committed, although qemu can support this.
 
 This is equivalent to the qemu parameter
 changes to be committed, although qemu can support this.
 
 This is equivalent to the qemu parameter
-C<-drive file=filename,snapshot=on,if=...>.
+C<-drive file=filename,snapshot=on,readonly=on,if=...>.
 
 C<if=...> is set at compile time by the configuration option
 C<./configure --with-drive-if=...>.  In the rare case where you
 might need to change this at run time, use C<guestfs_add_drive_with_if>
 or C<guestfs_add_drive_ro_with_if>.
 
 
 C<if=...> is set at compile time by the configuration option
 C<./configure --with-drive-if=...>.  In the rare case where you
 might need to change this at run time, use C<guestfs_add_drive_with_if>
 or C<guestfs_add_drive_ro_with_if>.
 
+C<readonly=on> is only added where qemu supports this option.
+
 Note that this call checks for the existence of C<filename>.  This
 stops you from specifying other types of drive which are supported
 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
 Note that this call checks for the existence of C<filename>.  This
 stops you from specifying other types of drive which are supported
 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
@@ -1235,7 +1238,12 @@ matches exactly one node, the C<value> is returned.");
    [], (* XXX Augeas code needs tests. *)
    "set Augeas path to value",
    "\
    [], (* XXX Augeas code needs tests. *)
    "set Augeas path to value",
    "\
-Set the value associated with C<path> to C<value>.");
+Set the value associated with C<path> to C<val>.
+
+In the Augeas API, it is possible to clear a node by setting
+the value to NULL.  Due to an oversight in the libguestfs API
+you cannot do that with this call.  Instead you must use the
+C<guestfs_aug_clear> call.");
 
   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
    [], (* XXX Augeas code needs tests. *)
 
   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
    [], (* XXX Augeas code needs tests. *)
@@ -2022,7 +2030,8 @@ The checksum is returned as a printable string.");
 This command uploads and unpacks local file C<tarfile> (an
 I<uncompressed> tar file) into C<directory>.
 
 This command uploads and unpacks local file C<tarfile> (an
 I<uncompressed> tar file) into C<directory>.
 
-To upload a compressed tarball, use C<guestfs_tgz_in>.");
+To upload a compressed tarball, use C<guestfs_tgz_in>
+or C<guestfs_txz_in>.");
 
   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
    [],
 
   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
    [],
@@ -2031,7 +2040,8 @@ To upload a compressed tarball, use C<guestfs_tgz_in>.");
 This command packs the contents of C<directory> and downloads
 it to local file C<tarfile>.
 
 This command packs the contents of C<directory> and downloads
 it to local file C<tarfile>.
 
-To download a compressed tarball, use C<guestfs_tgz_out>.");
+To download a compressed tarball, use C<guestfs_tgz_out>
+or C<guestfs_txz_out>.");
 
   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
    [InitBasicFS, Always, TestOutput (
 
   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
    [InitBasicFS, Always, TestOutput (
@@ -2291,7 +2301,7 @@ How many blocks are zeroed isn't specified (but it's I<not> enough
 to securely wipe the device).  It should be sufficient to remove
 any partition tables, filesystem superblocks and so on.
 
 to securely wipe the device).  It should be sufficient to remove
 any partition tables, filesystem superblocks and so on.
 
-See also: C<guestfs_scrub_device>.");
+See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
 
   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
    (* Test disabled because grub-install incompatible with virtio-blk driver.
 
   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
    (* Test disabled because grub-install incompatible with virtio-blk driver.
@@ -4090,10 +4100,9 @@ but other possible values are described in C<guestfs_part_init>.");
 This sets the bootable flag on partition numbered C<partnum> on
 device C<device>.  Note that partitions are numbered from 1.
 
 This sets the bootable flag on partition numbered C<partnum> on
 device C<device>.  Note that partitions are numbered from 1.
 
-The bootable flag is used by some PC BIOSes to determine which
-partition to boot from.  It is by no means universally recognized,
-and in any case if your operating system installed a boot
-sector on the device itself, then that takes precedence.");
+The bootable flag is used by some operating systems (notably
+Windows) to determine which partition to boot from.  It is by
+no means universally recognized.");
 
   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
    [InitEmpty, Always, TestRun (
 
   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
    [InitEmpty, Always, TestRun (
@@ -4237,7 +4246,7 @@ example to duplicate a filesystem.
 
 If the destination is a device, it must be as large or larger
 than the source file or device, otherwise the copy will fail.
 
 If the destination is a device, it must be as large or larger
 than the source file or device, otherwise the copy will fail.
-This command cannot do partial copies.");
+This command cannot do partial copies (see C<guestfs_copy_size>).");
 
   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
    [InitBasicFS, Always, TestOutputInt (
 
   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
    [InitBasicFS, Always, TestOutputInt (
@@ -4288,6 +4297,189 @@ contained in a Linux initrd or initramfs image:
 
 See also C<guestfs_initrd_list>.");
 
 
 See also C<guestfs_initrd_list>.");
 
+  ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
+   [],
+   "get the UUID of a physical volume",
+   "\
+This command returns the UUID of the LVM PV C<device>.");
+
+  ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
+   [],
+   "get the UUID of a volume group",
+   "\
+This command returns the UUID of the LVM VG named C<vgname>.");
+
+  ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
+   [],
+   "get the UUID of a logical volume",
+   "\
+This command returns the UUID of the LVM LV C<device>.");
+
+  ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
+   [],
+   "get the PV UUIDs containing the volume group",
+   "\
+Given a VG called C<vgname>, this returns the UUIDs of all
+the physical volumes that this volume group resides on.
+
+You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
+calls to associate physical volumes and volume groups.
+
+See also C<guestfs_vglvuuids>.");
+
+  ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
+   [],
+   "get the LV UUIDs of all LVs in the volume group",
+   "\
+Given a VG called C<vgname>, this returns the UUIDs of all
+the logical volumes created in this volume group.
+
+You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
+calls to associate logical volumes and volume groups.
+
+See also C<guestfs_vgpvuuids>.");
+
+  ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
+   [InitBasicFS, Always, TestOutputBuffer (
+      [["write_file"; "/src"; "hello, world"; "0"];
+       ["copy_size"; "/src"; "/dest"; "5"];
+       ["read_file"; "/dest"]], "hello")],
+   "copy size bytes from source to destination using dd",
+   "\
+This command copies exactly C<size> bytes from one source device
+or file C<src> to another destination device or file C<dest>.
+
+Note this will fail if the source is too short or if the destination
+is not large enough.");
+
+  ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
+   [InitBasicFSonLVM, Always, TestRun (
+      [["zero_device"; "/dev/VG/LV"]])],
+   "write zeroes to an entire device",
+   "\
+This command writes zeroes over the entire C<device>.  Compare
+with C<guestfs_zero> which just zeroes the first few blocks of
+a device.");
+
+  ("txz_in", (RErr, [FileIn "tarball"; String "directory"]), 229, [],
+   [InitBasicFS, Always, TestOutput (
+      [["txz_in"; "../images/helloworld.tar.xz"; "/"];
+       ["cat"; "/hello"]], "hello\n")],
+   "unpack compressed tarball to directory",
+   "\
+This command uploads and unpacks local file C<tarball> (an
+I<xz compressed> tar file) into C<directory>.");
+
+  ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
+   [],
+   "pack directory into compressed tarball",
+   "\
+This command packs the contents of C<directory> and downloads
+it to local file C<tarball> (as an xz compressed tar archive).");
+
+  ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
+   [],
+   "resize an NTFS filesystem",
+   "\
+This command resizes an NTFS filesystem, expanding or
+shrinking it to the size of the underlying device.
+See also L<ntfsresize(8)>.");
+
+  ("vgscan", (RErr, []), 232, [],
+   [InitEmpty, Always, TestRun (
+      [["vgscan"]])],
+   "rescan for LVM physical volumes, volume groups and logical volumes",
+   "\
+This rescans all block devices and rebuilds the list of LVM
+physical volumes, volume groups and logical volumes.");
+
+  ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
+   [InitEmpty, Always, TestRun (
+      [["part_init"; "/dev/sda"; "mbr"];
+       ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
+       ["part_del"; "/dev/sda"; "1"]])],
+   "delete a partition",
+   "\
+This command deletes the partition numbered C<partnum> on C<device>.
+
+Note that in the case of MBR partitioning, deleting an
+extended partition also deletes any logical partitions
+it contains.");
+
+  ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
+   [InitEmpty, Always, TestOutputTrue (
+      [["part_init"; "/dev/sda"; "mbr"];
+       ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
+       ["part_set_bootable"; "/dev/sda"; "1"; "true"];
+       ["part_get_bootable"; "/dev/sda"; "1"]])],
+   "return true if a partition is bootable",
+   "\
+This command returns true if the partition C<partnum> on
+C<device> has the bootable flag set.
+
+See also C<guestfs_part_set_bootable>.");
+
+  ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [],
+   [InitEmpty, Always, TestOutputInt (
+      [["part_init"; "/dev/sda"; "mbr"];
+       ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
+       ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
+       ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
+   "get the MBR type byte (ID byte) from a partition",
+   "\
+Returns the MBR type byte (also known as the ID byte) from
+the numbered partition C<partnum>.
+
+Note that only MBR (old DOS-style) partitions have type bytes.
+You will get undefined results for other partition table
+types (see C<guestfs_part_get_parttype>).");
+
+  ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
+   [], (* tested by part_get_mbr_id *)
+   "set the MBR type byte (ID byte) of a partition",
+   "\
+Sets the MBR type byte (also known as the ID byte) of
+the numbered partition C<partnum> to C<idbyte>.  Note
+that the type bytes quoted in most documentation are
+in fact hexadecimal numbers, but usually documented
+without any leading \"0x\" which might be confusing.
+
+Note that only MBR (old DOS-style) partitions have type bytes.
+You will get undefined results for other partition table
+types (see C<guestfs_part_get_parttype>).");
+
+  ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
+   [InitISOFS, Always, TestOutput (
+      [["checksum_device"; "md5"; "/dev/sdd"]],
+      (Digest.to_hex (Digest.file "images/test.iso")))],
+   "compute MD5, SHAx or CRC checksum of the contents of a device",
+   "\
+This call computes the MD5, SHAx or CRC checksum of the
+contents of the device named C<device>.  For the types of
+checksums supported see the C<guestfs_checksum> command.");
+
+  ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
+   [InitNone, Always, TestRun (
+      [["part_disk"; "/dev/sda"; "mbr"];
+       ["pvcreate"; "/dev/sda1"];
+       ["vgcreate"; "VG"; "/dev/sda1"];
+       ["lvcreate"; "LV"; "VG"; "10"];
+       ["lvresize_free"; "/dev/VG/LV"; "100"]])],
+   "expand an LV to fill free space",
+   "\
+This expands an existing logical volume C<lv> so that it fills
+C<pc>% of the remaining free space in the volume group.  Commonly
+you would call this with pc = 100 which expands the logical volume
+as much as possible, using all remaining free space in the volume
+group.");
+
+  ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
+   [], (* XXX Augeas code needs tests. *)
+   "clear Augeas path",
+   "\
+Set the value associated with C<path> to C<NULL>.  This
+is the same as the L<augtool(1)> C<clear> command.");
+
 ]
 
 let all_functions = non_daemon_functions @ daemon_functions
 ]
 
 let all_functions = non_daemon_functions @ daemon_functions
@@ -5348,6 +5540,7 @@ and generate_client_actions () =
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
+#include <string.h>
 #include <inttypes.h>
 
 #include \"guestfs.h\"
 #include <inttypes.h>
 
 #include \"guestfs.h\"
@@ -6086,7 +6279,7 @@ and generate_daemon_actions () =
         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
         pr "\n";
         pr "  r = command (&out, &err,\n";
         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
         pr "\n";
         pr "  r = command (&out, &err,\n";
-        pr "          \"/sbin/lvm\", \"%ss\",\n" typ;
+        pr "          \"lvm\", \"%ss\",\n" typ;
         pr "          \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
         pr "          \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
         pr "  if (r == -1) {\n";
         pr "          \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
         pr "          \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
         pr "  if (r == -1) {\n";
@@ -6391,14 +6584,14 @@ int main (int argc, char *argv[])
     exit (EXIT_FAILURE);
   }
 
     exit (EXIT_FAILURE);
   }
 
+  /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
+  alarm (600);
+
   if (guestfs_launch (g) == -1) {
     printf (\"guestfs_launch FAILED\\n\");
     exit (EXIT_FAILURE);
   }
 
   if (guestfs_launch (g) == -1) {
     printf (\"guestfs_launch FAILED\\n\");
     exit (EXIT_FAILURE);
   }
 
-  /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
-  alarm (600);
-
   /* Cancel previous alarm. */
   alarm (0);
 
   /* Cancel previous alarm. */
   alarm (0);
 
@@ -7335,6 +7528,8 @@ and generate_fish_cmds () =
   ) all_functions;
   pr "    {\n";
   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
   ) all_functions;
   pr "    {\n";
   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
+  pr "      if (command_num == 1)\n";
+  pr "        extended_help_message ();\n";
   pr "      return -1;\n";
   pr "    }\n";
   pr "  return 0;\n";
   pr "      return -1;\n";
   pr "    }\n";
   pr "  return 0;\n";
@@ -7413,7 +7608,16 @@ generator (const char *text, int state)
 
 #endif /* HAVE_LIBREADLINE */
 
 
 #endif /* HAVE_LIBREADLINE */
 
-char **do_completion (const char *text, int start, int end)
+#ifdef HAVE_RL_COMPLETION_MATCHES
+#define RL_COMPLETION_MATCHES rl_completion_matches
+#else
+#ifdef HAVE_COMPLETION_MATCHES
+#define RL_COMPLETION_MATCHES completion_matches
+#endif
+#endif /* else just fail if we don't have either symbol */
+
+char **
+do_completion (const char *text, int start, int end)
 {
   char **matches = NULL;
 
 {
   char **matches = NULL;
 
@@ -7421,9 +7625,9 @@ char **do_completion (const char *text, int start, int end)
   rl_completion_append_character = ' ';
 
   if (start == 0)
   rl_completion_append_character = ' ';
 
   if (start == 0)
-    matches = rl_completion_matches (text, generator);
+    matches = RL_COMPLETION_MATCHES (text, generator);
   else if (complete_dest_paths)
   else if (complete_dest_paths)
-    matches = rl_completion_matches (text, complete_dest_paths_generator);
+    matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
 #endif
 
   return matches;
 #endif
 
   return matches;
@@ -8259,7 +8463,7 @@ DESTROY (g)
            do_cleanups ();
            pr "      if (%s == NULL)\n" n;
            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
            do_cleanups ();
            pr "      if (%s == NULL)\n" n;
            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
-           pr "      RETVAL = newSVpv (%s, size);\n" n;
+           pr "      RETVAL = newSVpvn (%s, size);\n" n;
            pr "      free (%s);\n" n;
            pr " OUTPUT:\n";
            pr "      RETVAL\n"
            pr "      free (%s);\n" n;
            pr " OUTPUT:\n";
            pr "      RETVAL\n"
@@ -8292,7 +8496,7 @@ and generate_perl_struct_list_code typ cols name style n do_cleanups =
         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
           name (String.length name) n name
     | name, FBuffer ->
         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
           name (String.length name) n name
     | name, FBuffer ->
-        pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
+        pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
           name (String.length name) n name n name
     | name, (FBytes|FUInt64) ->
         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
           name (String.length name) n name n name
     | name, (FBytes|FUInt64) ->
         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
@@ -8334,7 +8538,7 @@ and generate_perl_struct_code typ cols name style n do_cleanups =
           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
             n name
       | name, FBuffer ->
           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
             n name
       | name, FBuffer ->
-          pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
+          pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
             n name n name
       | name, FUUID ->
           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
             n name n name
       | name, FUUID ->
           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"