generator: Some String parameters should be OptString (RHBZ#501894).
[libguestfs.git] / src / generator.ml
index 9a989f2..fbb992a 100755 (executable)
 
 (* This script generates a large amount of code and documentation for
  * all the daemon actions.
 
 (* This script generates a large amount of code and documentation for
  * all the daemon actions.
- * 
+ *
  * To add a new action there are only two files you need to change,
  * this one to describe the interface (see the big table of
  * 'daemon_functions' below), and daemon/<somefile>.c to write the
  * implementation.
  * To add a new action there are only two files you need to change,
  * this one to describe the interface (see the big table of
  * 'daemon_functions' below), and daemon/<somefile>.c to write the
  * implementation.
- * 
+ *
  * After editing this file, run it (./src/generator.ml) to regenerate
  * all the output files.  'make' will rerun this automatically when
  * necessary.  Note that if you are using a separate build directory
  * you must run generator.ml from the _source_ directory.
  * After editing this file, run it (./src/generator.ml) to regenerate
  * all the output files.  'make' will rerun this automatically when
  * necessary.  Note that if you are using a separate build directory
  * you must run generator.ml from the _source_ directory.
- * 
+ *
  * IMPORTANT: This script should NOT print any warnings.  If it prints
  * warnings, you should treat them as errors.
  *
  * IMPORTANT: This script should NOT print any warnings.  If it prints
  * warnings, you should treat them as errors.
  *
@@ -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
@@ -569,7 +572,7 @@ The first character of C<param> string must be a C<-> (dash).
 
 C<value> can be NULL.");
 
 
 C<value> can be NULL.");
 
-  ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
+  ("set_qemu", (RErr, [OptString "qemu"]), -1, [FishAlias "qemu"],
    [],
    "set the qemu binary",
    "\
    [],
    "set the qemu binary",
    "\
@@ -581,7 +584,15 @@ configure script.
 You can also override this by setting the C<LIBGUESTFS_QEMU>
 environment variable.
 
 You can also override this by setting the C<LIBGUESTFS_QEMU>
 environment variable.
 
-Setting C<qemu> to C<NULL> restores the default qemu binary.");
+Setting C<qemu> to C<NULL> restores the default qemu binary.
+
+Note that you should call this function as early as possible
+after creating the handle.  This is because some pre-launch
+operations depend on testing qemu features (by running C<qemu -help>).
+If the qemu binary changes, we don't retest features, and
+so you might see inconsistent results.  Using the environment
+variable C<LIBGUESTFS_QEMU> is safest of all since that picks
+the qemu binary at the same time as the handle is created.");
 
   ("get_qemu", (RConstString "qemu", []), -1, [],
    [InitNone, Always, TestRun (
 
   ("get_qemu", (RConstString "qemu", []), -1, [],
    [InitNone, Always, TestRun (
@@ -593,7 +604,7 @@ Return the current qemu binary.
 This is always non-NULL.  If it wasn't set already, then this will
 return the default qemu binary name.");
 
 This is always non-NULL.  If it wasn't set already, then this will
 return the default qemu binary name.");
 
-  ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
+  ("set_path", (RErr, [OptString "searchpath"]), -1, [FishAlias "path"],
    [],
    "set the search path",
    "\
    [],
    "set the search path",
    "\
@@ -942,8 +953,15 @@ exist.
 The mounted filesystem is writable, if we have sufficient permissions
 on the underlying device.
 
 The mounted filesystem is writable, if we have sufficient permissions
 on the underlying device.
 
-The filesystem options C<sync> and C<noatime> are set with this
-call, in order to improve reliability.");
+B<Important note:>
+When you use this call, the filesystem options C<sync> and C<noatime>
+are set implicitly.  This was originally done because we thought it
+would improve reliability, but it turns out that I<-o sync> has a
+very large negative performance impact and negligible effect on
+reliability.  Therefore we recommend that you avoid using
+C<guestfs_mount> in any code that needs performance, and instead
+use C<guestfs_mount_options> (use an empty string for the first
+parameter if you don't want any options).");
 
   ("sync", (RErr, []), 2, [],
    [ InitEmpty, Always, TestRun [["sync"]]],
 
   ("sync", (RErr, []), 2, [],
    [ InitEmpty, Always, TestRun [["sync"]]],
@@ -1369,7 +1387,9 @@ numeric modes are supported.
 
 I<Note>: When using this command from guestfish, C<mode>
 by default would be decimal, unless you prefix it with
 
 I<Note>: When using this command from guestfish, C<mode>
 by default would be decimal, unless you prefix it with
-C<0> to get octal, ie. use C<0700> not C<700>.");
+C<0> to get octal, ie. use C<0700> not C<700>.
+
+The mode actually set is affected by the umask.");
 
   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
    [], (* XXX Need stat command to test *)
 
   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
    [], (* XXX Need stat command to test *)
@@ -1462,9 +1482,9 @@ from the non-empty list of physical volumes C<physvols>.");
        ["lvs"]],
       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
        ["lvs"]],
       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
-   "create an LVM volume group",
+   "create an LVM logical volume",
    "\
    "\
-This creates an LVM volume group called C<logvol>
+This creates an LVM logical volume called C<logvol>
 on the volume group C<volgroup>, with C<size> megabytes.");
 
   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
 on the volume group C<volgroup>, with C<size> megabytes.");
 
   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
@@ -2066,7 +2086,11 @@ mounts the filesystem with the read-only (I<-o ro>) flag.");
    "\
 This is the same as the C<guestfs_mount> command, but it
 allows you to set the mount options as for the
    "\
 This is the same as the C<guestfs_mount> command, but it
 allows you to set the mount options as for the
-L<mount(8)> I<-o> flag.");
+L<mount(8)> I<-o> flag.
+
+If the C<options> parameter is an empty string, then
+no options are passed (all options default to whatever
+the filesystem uses).");
 
   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
    [],
 
   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
    [],
@@ -2418,12 +2442,41 @@ the list of printable strings found.");
    "print the printable strings in a file",
    "\
 This is like the C<guestfs_strings> command, but allows you to
    "print the printable strings in a file",
    "\
 This is like the C<guestfs_strings> command, but allows you to
-specify the encoding.
+specify the encoding of strings that are looked for in
+the source file C<path>.
+
+Allowed encodings are:
+
+=over 4
+
+=item s
+
+Single 7-bit-byte characters like ASCII and the ASCII-compatible
+parts of ISO-8859-X (this is what C<guestfs_strings> uses).
+
+=item S
 
 
-See the L<strings(1)> manpage for the full list of encodings.
+Single 8-bit-byte characters.
 
 
-Commonly useful encodings are C<l> (lower case L) which will
-show strings inside Windows/x86 files.
+=item b
+
+16-bit big endian strings such as those encoded in
+UTF-16BE or UCS-2BE.
+
+=item l (lower case letter L)
+
+16-bit little endian such as UTF-16LE and UCS-2LE.
+This is useful for examining binaries in Windows guests.
+
+=item B
+
+32-bit big endian such as UCS-4BE.
+
+=item L
+
+32-bit little endian such as UCS-4LE.
+
+=back
 
 The returned strings are transcoded to UTF-8.");
 
 
 The returned strings are transcoded to UTF-8.");
 
@@ -2556,7 +2609,14 @@ are activated or deactivated.");
        ["e2fsck_f"; "/dev/VG/LV"];
        ["resize2fs"; "/dev/VG/LV"];
        ["mount_options"; ""; "/dev/VG/LV"; "/"];
        ["e2fsck_f"; "/dev/VG/LV"];
        ["resize2fs"; "/dev/VG/LV"];
        ["mount_options"; ""; "/dev/VG/LV"; "/"];
-       ["cat"; "/new"]], "test content")],
+       ["cat"; "/new"]], "test content");
+    InitNone, Always, TestRun (
+      (* Make an LV smaller to test RHBZ#587484. *)
+      [["part_disk"; "/dev/sda"; "mbr"];
+       ["pvcreate"; "/dev/sda1"];
+       ["vgcreate"; "VG"; "/dev/sda1"];
+       ["lvcreate"; "LV"; "VG"; "20"];
+       ["lvresize"; "/dev/VG/LV"; "10"]])],
    "resize an LVM logical volume",
    "\
 This resizes (expands or shrinks) an existing LVM logical
    "resize an LVM logical volume",
    "\
 This resizes (expands or shrinks) an existing LVM logical
@@ -2962,7 +3022,17 @@ named pipes (FIFOs).
 The C<mode> parameter should be the mode, using the standard
 constants.  C<devmajor> and C<devminor> are the
 device major and minor numbers, only used when creating block
 The C<mode> parameter should be the mode, using the standard
 constants.  C<devmajor> and C<devminor> are the
 device major and minor numbers, only used when creating block
-and character special devices.");
+and character special devices.
+
+Note that, just like L<mknod(2)>, the mode must be bitwise
+OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
+just creates a regular file).  These constants are
+available in the standard Linux header files, or you can use
+C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
+which are wrappers around this command which bitwise OR
+in the appropriate constant for you.
+
+The mode actually set is affected by the umask.");
 
   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
    [InitBasicFS, Always, TestOutputStruct (
 
   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
    [InitBasicFS, Always, TestOutputStruct (
@@ -2972,7 +3042,9 @@ and character special devices.");
    "\
 This call creates a FIFO (named pipe) called C<path> with
 mode C<mode>.  It is just a convenient wrapper around
    "\
 This call creates a FIFO (named pipe) called C<path> with
 mode C<mode>.  It is just a convenient wrapper around
-C<guestfs_mknod>.");
+C<guestfs_mknod>.
+
+The mode actually set is affected by the umask.");
 
   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
    [InitBasicFS, Always, TestOutputStruct (
 
   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
    [InitBasicFS, Always, TestOutputStruct (
@@ -2982,7 +3054,9 @@ C<guestfs_mknod>.");
    "\
 This call creates a block device node called C<path> with
 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
    "\
 This call creates a block device node called C<path> with
 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
-It is just a convenient wrapper around C<guestfs_mknod>.");
+It is just a convenient wrapper around C<guestfs_mknod>.
+
+The mode actually set is affected by the umask.");
 
   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
    [InitBasicFS, Always, TestOutputStruct (
 
   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
    [InitBasicFS, Always, TestOutputStruct (
@@ -2992,12 +3066,13 @@ It is just a convenient wrapper around C<guestfs_mknod>.");
    "\
 This call creates a char device node called C<path> with
 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
    "\
 This call creates a char device node called C<path> with
 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
-It is just a convenient wrapper around C<guestfs_mknod>.");
+It is just a convenient wrapper around C<guestfs_mknod>.
+
+The mode actually set is affected by the umask.");
 
   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
 
   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
-   [], (* XXX umask is one of those stateful things that we should
-        * reset between each test.
-        *)
+   [InitEmpty, Always, TestOutputInt (
+      [["umask"; "0o22"]], 0o22)],
    "set file mode creation mask (umask)",
    "\
 This function sets the mask used for creating new files and
    "set file mode creation mask (umask)",
    "\
 This function sets the mask used for creating new files and
@@ -3209,7 +3284,20 @@ for full details.");
 
   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
    [InitISOFS, Always, TestOutputBuffer (
 
   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
    [InitISOFS, Always, TestOutputBuffer (
-      [["read_file"; "/known-4"]], "abc\ndef\nghi")],
+      [["read_file"; "/known-4"]], "abc\ndef\nghi");
+    (* Test various near large, large and too large files (RHBZ#589039). *)
+    InitBasicFS, Always, TestLastFail (
+      [["touch"; "/a"];
+       ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
+       ["read_file"; "/a"]]);
+    InitBasicFS, Always, TestLastFail (
+      [["touch"; "/a"];
+       ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
+       ["read_file"; "/a"]]);
+    InitBasicFS, Always, TestLastFail (
+      [["touch"; "/a"];
+       ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
+       ["read_file"; "/a"]])],
    "read a file",
    "\
 This calls returns the contents of the file C<path> as a
    "read a file",
    "\
 This calls returns the contents of the file C<path> as a
@@ -3856,7 +3944,13 @@ C<*secs> field is ignored in this case).");
    "create a directory with a particular mode",
    "\
 This command creates a directory, setting the initial permissions
    "create a directory with a particular mode",
    "\
 This command creates a directory, setting the initial permissions
-of the directory to C<mode>.  See also C<guestfs_mkdir>.");
+of the directory to C<mode>.
+
+For common Linux filesystems, the actual mode which is set will
+be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
+interpret the mode in other ways.
+
+See also C<guestfs_mkdir>, C<guestfs_umask>");
 
   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
    [], (* XXX *)
 
   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
    [], (* XXX *)
@@ -4082,10 +4176,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 (
@@ -4229,7 +4322,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 (
@@ -4263,7 +4356,7 @@ Rename a logical volume C<logvol> with the new name C<newlogvol>.");
    "\
 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
 
    "\
 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
 
-  ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [],
+  ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
    [InitISOFS, Always, TestOutputBuffer (
       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
    "list the contents of a single file in an initrd",
    [InitISOFS, Always, TestOutputBuffer (
       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
    "list the contents of a single file in an initrd",
@@ -4280,6 +4373,116 @@ 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.");
+
+  ("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>).");
+
 ]
 
 let all_functions = non_daemon_functions @ daemon_functions
 ]
 
 let all_functions = non_daemon_functions @ daemon_functions
@@ -4704,8 +4907,7 @@ let seq_of_test = function
 (* Handling for function flags. *)
 let protocol_limit_warning =
   "Because of the message protocol, there is a transfer limit
 (* Handling for function flags. *)
 let protocol_limit_warning =
   "Because of the message protocol, there is a transfer limit
-of somewhere between 2MB and 4MB.  To transfer large files, see
-L<guestfs(3)/UPLOADING>."
+of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
 
 let danger_will_robinson =
   "B<This command is dangerous.  Without careful use you
 
 let danger_will_robinson =
   "B<This command is dangerous.  Without careful use you
@@ -4846,7 +5048,7 @@ let check_functions () =
         failwithf "short description of %s should not end with . or \\n." name
   ) all_functions;
 
         failwithf "short description of %s should not end with . or \\n." name
   ) all_functions;
 
-  (* Check long dscriptions. *)
+  (* Check long descriptions. *)
   List.iter (
     fun (name, _, _, _, _, _, longdesc) ->
       if longdesc.[String.length longdesc-1] = '\n' then
   List.iter (
     fun (name, _, _, _, _, _, longdesc) ->
       if longdesc.[String.length longdesc-1] = '\n' then
@@ -4991,7 +5193,7 @@ let rec generate_actions_pod () =
         let name = "guestfs_" ^ shortname in
         pr "=head2 %s\n\n" name;
         pr " ";
         let name = "guestfs_" ^ shortname in
         pr "=head2 %s\n\n" name;
         pr " ";
-        generate_prototype ~extern:false ~handle:"handle" name style;
+        generate_prototype ~extern:false ~handle:"g" name style;
         pr "\n\n";
         pr "%s\n\n" longdesc;
         (match fst style with
         pr "\n\n";
         pr "%s\n\n" longdesc;
         (match fst style with
@@ -5319,7 +5521,7 @@ and generate_actions_h () =
   List.iter (
     fun (shortname, style, _, _, _, _, _) ->
       let name = "guestfs_" ^ shortname in
   List.iter (
     fun (shortname, style, _, _, _, _, _) ->
       let name = "guestfs_" ^ shortname in
-      generate_prototype ~single_line:true ~newline:true ~handle:"handle"
+      generate_prototype ~single_line:true ~newline:true ~handle:"g"
         name style
   ) all_functions
 
         name style
   ) all_functions
 
@@ -5329,7 +5531,7 @@ and generate_internal_actions_h () =
   List.iter (
     fun (shortname, style, _, _, _, _, _) ->
       let name = "guestfs__" ^ shortname in
   List.iter (
     fun (shortname, style, _, _, _, _, _) ->
       let name = "guestfs__" ^ shortname in
-      generate_prototype ~single_line:true ~newline:true ~handle:"handle"
+      generate_prototype ~single_line:true ~newline:true ~handle:"g"
         name style
   ) non_daemon_functions
 
         name style
   ) non_daemon_functions
 
@@ -5341,6 +5543,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\"
@@ -6079,7 +6282,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";
@@ -6384,14 +6587,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);
 
@@ -6402,6 +6605,8 @@ int main (int argc, char *argv[])
   iteri (
     fun i test_name ->
       pr "  test_num++;\n";
   iteri (
     fun i test_name ->
       pr "  test_num++;\n";
+      pr "  if (guestfs_get_verbose (g))\n";
+      pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
       pr "  if (%s () == -1) {\n" test_name;
       pr "    printf (\"%s FAILED\\n\");\n" test_name;
       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
       pr "  if (%s () == -1) {\n" test_name;
       pr "    printf (\"%s FAILED\\n\");\n" test_name;
@@ -6819,7 +7024,7 @@ and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
         | Bool _, _
         | FileIn _, _ | FileOut _, _ -> ()
         | StringList n, "" | DeviceList n, "" ->
         | Bool _, _
         | FileIn _, _ | FileOut _, _ -> ()
         | StringList n, "" | DeviceList n, "" ->
-           pr "    const char *const %s[1] = { NULL };\n" n
+            pr "    const char *const %s[1] = { NULL };\n" n
         | StringList n, arg | DeviceList n, arg ->
             let strs = string_split " " arg in
             iteri (
         | StringList n, arg | DeviceList n, arg ->
             let strs = string_split " " arg in
             iteri (
@@ -7222,7 +7427,7 @@ and generate_fish_cmds () =
                 and comment =
                   "The Int type in the generator is a signed 31 bit int." in
                 Some (min, max, comment) in
                 and comment =
                   "The Int type in the generator is a signed 31 bit int." in
                 Some (min, max, comment) in
-              parse_integer "xstrtol" "long" "int" range name i
+              parse_integer "xstrtoll" "long long" "int" range name i
           | Int64 name ->
               parse_integer "xstrtoll" "long long" "int64_t" None name i
       ) (snd style);
           | Int64 name ->
               parse_integer "xstrtoll" "long long" "int64_t" None name i
       ) (snd style);
@@ -7328,6 +7533,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";
@@ -7406,7 +7613,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;
 
@@ -7414,9 +7630,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;
@@ -8252,7 +8468,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"
@@ -8285,7 +8501,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"
@@ -8327,7 +8543,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"
@@ -10224,96 +10440,96 @@ namespace Guestfs
   List.iter (
     fun (name, style, _, _, _, shortdesc, _) ->
       let rec csharp_return_type () =
   List.iter (
     fun (name, style, _, _, _, shortdesc, _) ->
       let rec csharp_return_type () =
-       match fst style with
-       | RErr -> "void"
-       | RBool n -> "bool"
-       | RInt n -> "int"
-       | RInt64 n -> "long"
-       | RConstString n
-       | RConstOptString n
-       | RString n
-       | RBufferOut n -> "string"
-       | RStruct (_,n) -> "_" ^ n
-       | RHashtable n -> "Hashtable"
-       | RStringList n -> "string[]"
-       | RStructList (_,n) -> sprintf "_%s[]" n
+        match fst style with
+        | RErr -> "void"
+        | RBool n -> "bool"
+        | RInt n -> "int"
+        | RInt64 n -> "long"
+        | RConstString n
+        | RConstOptString n
+        | RString n
+        | RBufferOut n -> "string"
+        | RStruct (_,n) -> "_" ^ n
+        | RHashtable n -> "Hashtable"
+        | RStringList n -> "string[]"
+        | RStructList (_,n) -> sprintf "_%s[]" n
 
       and c_return_type () =
 
       and c_return_type () =
-       match fst style with
-       | RErr
-       | RBool _
-       | RInt _ -> "int"
-       | RInt64 _ -> "long"
-       | RConstString _
-       | RConstOptString _
-       | RString _
-       | RBufferOut _ -> "string"
-       | RStruct (_,n) -> "_" ^ n
-       | RHashtable _
-       | RStringList _ -> "string[]"
-       | RStructList (_,n) -> sprintf "_%s[]" n
-    
+        match fst style with
+        | RErr
+        | RBool _
+        | RInt _ -> "int"
+        | RInt64 _ -> "long"
+        | RConstString _
+        | RConstOptString _
+        | RString _
+        | RBufferOut _ -> "string"
+        | RStruct (_,n) -> "_" ^ n
+        | RHashtable _
+        | RStringList _ -> "string[]"
+        | RStructList (_,n) -> sprintf "_%s[]" n
+
       and c_error_comparison () =
       and c_error_comparison () =
-       match fst style with
-       | RErr
-       | RBool _
-       | RInt _
-       | RInt64 _ -> "== -1"
-       | RConstString _
-       | RConstOptString _
-       | RString _
-       | RBufferOut _
-       | RStruct (_,_)
-       | RHashtable _
-       | RStringList _
-       | RStructList (_,_) -> "== null"
-    
+        match fst style with
+        | RErr
+        | RBool _
+        | RInt _
+        | RInt64 _ -> "== -1"
+        | RConstString _
+        | RConstOptString _
+        | RString _
+        | RBufferOut _
+        | RStruct (_,_)
+        | RHashtable _
+        | RStringList _
+        | RStructList (_,_) -> "== null"
+
       and generate_extern_prototype () =
       and generate_extern_prototype () =
-       pr "    static extern %s guestfs_%s (IntPtr h"
-         (c_return_type ()) name;
-       List.iter (
-         function
-         | Pathname n | Device n | Dev_or_Path n | String n | OptString n
-         | FileIn n | FileOut n ->
+        pr "    static extern %s guestfs_%s (IntPtr h"
+          (c_return_type ()) name;
+        List.iter (
+          function
+          | Pathname n | Device n | Dev_or_Path n | String n | OptString n
+          | FileIn n | FileOut n ->
               pr ", [In] string %s" n
               pr ", [In] string %s" n
-         | StringList n | DeviceList n ->
+          | StringList n | DeviceList n ->
               pr ", [In] string[] %s" n
               pr ", [In] string[] %s" n
-         | Bool n ->
-             pr ", bool %s" n
-         | Int n ->
-             pr ", int %s" n
-         | Int64 n ->
-             pr ", long %s" n
-       ) (snd style);
-       pr ");\n"
+          | Bool n ->
+              pr ", bool %s" n
+          | Int n ->
+              pr ", int %s" n
+          | Int64 n ->
+              pr ", long %s" n
+        ) (snd style);
+        pr ");\n"
 
       and generate_public_prototype () =
 
       and generate_public_prototype () =
-       pr "    public %s %s (" (csharp_return_type ()) name;
-       let comma = ref false in
-       let next () =
-         if !comma then pr ", ";
-         comma := true
-       in
-       List.iter (
-         function
-         | Pathname n | Device n | Dev_or_Path n | String n | OptString n
-         | FileIn n | FileOut n ->
+        pr "    public %s %s (" (csharp_return_type ()) name;
+        let comma = ref false in
+        let next () =
+          if !comma then pr ", ";
+          comma := true
+        in
+        List.iter (
+          function
+          | Pathname n | Device n | Dev_or_Path n | String n | OptString n
+          | FileIn n | FileOut n ->
               next (); pr "string %s" n
               next (); pr "string %s" n
-         | StringList n | DeviceList n ->
+          | StringList n | DeviceList n ->
               next (); pr "string[] %s" n
               next (); pr "string[] %s" n
-         | Bool n ->
-             next (); pr "bool %s" n
-         | Int n ->
-             next (); pr "int %s" n
-         | Int64 n ->
-             next (); pr "long %s" n
-       ) (snd style);
-       pr ")\n"
+          | Bool n ->
+              next (); pr "bool %s" n
+          | Int n ->
+              next (); pr "int %s" n
+          | Int64 n ->
+              next (); pr "long %s" n
+        ) (snd style);
+        pr ")\n"
 
       and generate_call () =
 
       and generate_call () =
-       pr "guestfs_%s (_handle" name;
-       List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
-       pr ");\n";
+        pr "guestfs_%s (_handle" name;
+        List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
+        pr ");\n";
       in
 
       pr "    [DllImport (\"%s\")]\n" library;
       in
 
       pr "    [DllImport (\"%s\")]\n" library;