X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=src%2Fgenerator.ml;h=31f0e02716268449eae6e9378c93ad69a72afede;hp=7db58eb0ba06770227ce1de3ddbdc4cf772fcd62;hb=0c1e77219ea264a51b62e648003bfbea51db8ffb;hpb=48a9ff73319d0d065bff2b9374c84bcf6438cb20 diff --git a/src/generator.ml b/src/generator.ml index 7db58eb..31f0e02 100755 --- a/src/generator.ml +++ b/src/generator.ml @@ -19,17 +19,17 @@ (* 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/.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. - * + * * 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";; +#directory "+../pkg-lib/xml-light";; (* for GODI users *) #load "xml-light.cma";; open Unix @@ -180,12 +181,16 @@ type flags = | ProtocolLimitWarning (* display warning about protocol size limits *) | DangerWillRobinson (* flags particularly dangerous commands *) | FishAlias of string (* provide an alias for this cmd in guestfish *) - | FishAction of string (* call this function in guestfish *) + | FishOutput of fish_output_t (* how to display output in guestfish *) | NotInFish (* do not export via guestfish *) | NotInDocs (* do not add this function to documentation *) | DeprecatedBy of string (* function is deprecated, use .. instead *) | Optional of string (* function is part of an optional group *) +and fish_output_t = + | FishOutputOctal (* for int return, print in octal *) + | FishOutputHexadecimal (* for int return, print in hex *) + (* You can supply zero or as many tests as you want per API call. * * Note that the test environment has 3 block devices, of size 500MB, @@ -441,7 +446,7 @@ You probably don't want to call this function.")] *) let non_daemon_functions = test_functions @ [ - ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"], + ("launch", (RErr, []), -1, [FishAlias "run"], [], "launch the qemu subprocess", "\ @@ -489,9 +494,15 @@ image). This is equivalent to the qemu parameter C<-drive file=filename,cache=off,if=...>. + C is omitted in cases where it is not supported by the underlying filesystem. +C 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 +or C. + Note that this call checks for the existence of C. This stops you from specifying other types of drive which are supported by qemu such as C and C URLs. To specify those, use @@ -538,7 +549,14 @@ 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 -C<-drive file=filename,snapshot=on,if=...>. +C<-drive file=filename,snapshot=on,readonly=on,if=...>. + +C 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 +or C. + +C is only added where qemu supports this option. Note that this call checks for the existence of C. This stops you from specifying other types of drive which are supported @@ -570,7 +588,15 @@ configure script. You can also override this by setting the C environment variable. -Setting C to C restores the default qemu binary."); +Setting C to C 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). +If the qemu binary changes, we don't retest features, and +so you might see inconsistent results. Using the environment +variable C 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 ( @@ -887,6 +913,20 @@ qemu, which is not very helpful."); "\ Return the recovery process enabled flag."); + ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [], + [], + "add a drive specifying the QEMU block emulation to use", + "\ +This is the same as C but it allows you +to specify the QEMU interface emulation to use at run time."); + + ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [], + [], + "add a drive read-only specifying the QEMU block emulation to use", + "\ +This is the same as C but it allows you +to specify the QEMU interface emulation to use at run time."); + ] (* daemon_functions are any functions which cause some action @@ -917,8 +957,15 @@ exist. The mounted filesystem is writable, if we have sufficient permissions on the underlying device. -The filesystem options C and C are set with this -call, in order to improve reliability."); +B +When you use this call, the filesystem options C and C +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 in any code that needs performance, and instead +use C (use an empty string for the first +parameter if you don't want any options)."); ("sync", (RErr, []), 2, [], [ InitEmpty, Always, TestRun [["sync"]]], @@ -1202,7 +1249,12 @@ matches exactly one node, the C is returned."); [], (* XXX Augeas code needs tests. *) "set Augeas path to value", "\ -Set the value associated with C to C."); +Set the value associated with C to C. + +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 call."); ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"], [], (* XXX Augeas code needs tests. *) @@ -1344,7 +1396,9 @@ numeric modes are supported. I: When using this command from guestfish, C 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 *) @@ -1437,9 +1491,9 @@ from the non-empty list of physical volumes C."); ["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 +This creates an LVM logical volume called C on the volume group C, with C megabytes."); ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [], @@ -1936,7 +1990,10 @@ See also C, C."); InitISOFS, Always, TestOutput ( [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640"); InitISOFS, Always, TestOutput ( - [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")], + [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6"); + (* Test for RHBZ#579608, absolute symbolic links. *) + InitISOFS, Always, TestOutput ( + [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")], "compute MD5, SHAx or CRC checksum of file", "\ This call computes the MD5, SHAx or CRC checksum of the @@ -1978,9 +2035,13 @@ Compute the SHA512 hash (using the C program). =back -The checksum is returned as a printable string."); +The checksum is returned as a printable string. + +To get the checksum for a device, use C. + +To get the checksums for many files, use C."); - ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [], + ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [], [InitBasicFS, Always, TestOutput ( [["tar_in"; "../images/helloworld.tar"; "/"]; ["cat"; "/hello"]], "hello\n")], @@ -1989,7 +2050,8 @@ The checksum is returned as a printable string."); This command uploads and unpacks local file C (an I tar file) into C. -To upload a compressed tarball, use C."); +To upload a compressed tarball, use C +or C."); ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [], [], @@ -1998,9 +2060,10 @@ To upload a compressed tarball, use C."); This command packs the contents of C and downloads it to local file C. -To download a compressed tarball, use C."); +To download a compressed tarball, use C +or C."); - ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [], + ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [], [InitBasicFS, Always, TestOutput ( [["tgz_in"; "../images/helloworld.tar.gz"; "/"]; ["cat"; "/hello"]], "hello\n")], @@ -2041,7 +2104,11 @@ mounts the filesystem with the read-only (I<-o ro>) flag."); "\ This is the same as the C command, but it allows you to set the mount options as for the -L I<-o> flag."); +L I<-o> flag. + +If the C 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, [], [], @@ -2207,7 +2274,7 @@ to return the existing UUID of a filesystem."); This returns the ext2/3/4 filesystem UUID of the filesystem on C."); - ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [], + ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal], [InitBasicFS, Always, TestOutputInt ( [["umount"; "/dev/sda1"]; ["fsck"; "ext2"; "/dev/sda1"]], 0); @@ -2258,7 +2325,7 @@ How many blocks are zeroed isn't specified (but it's I enough to securely wipe the device). It should be sufficient to remove any partition tables, filesystem superblocks and so on. -See also: C."); +See also: C, C."); ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [], (* Test disabled because grub-install incompatible with virtio-blk driver. @@ -2378,7 +2445,10 @@ The external L program is used for the comparison."); [InitISOFS, Always, TestOutputList ( [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]); InitISOFS, Always, TestOutputList ( - [["strings"; "/empty"]], [])], + [["strings"; "/empty"]], []); + (* Test for RHBZ#579608, absolute symbolic links. *) + InitISOFS, Always, TestRun ( + [["strings"; "/abssymlink"]])], "print the printable strings in a file", "\ This runs the L command on a file and returns @@ -2409,7 +2479,10 @@ The returned strings are transcoded to UTF-8."); * commands to segfault. *) InitISOFS, Always, TestRun ( - [["hexdump"; "/100krandom"]])], + [["hexdump"; "/100krandom"]]); + (* Test for RHBZ#579608, absolute symbolic links. *) + InitISOFS, Always, TestRun ( + [["hexdump"; "/abssymlink"]])], "dump a file in hexadecimal", "\ This runs C on the given C. The result is @@ -2531,7 +2604,14 @@ are activated or deactivated."); ["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 @@ -2757,7 +2837,10 @@ See also: L"); ("wc_l", (RInt "lines", [Pathname "path"]), 118, [], [InitISOFS, Always, TestOutputInt ( - [["wc_l"; "/10klines"]], 10000)], + [["wc_l"; "/10klines"]], 10000); + (* Test for RHBZ#579608, absolute symbolic links. *) + InitISOFS, Always, TestOutputInt ( + [["wc_l"; "/abssymlink"]], 10000)], "count lines in a file", "\ This command counts the lines in a file, using the @@ -2781,7 +2864,10 @@ C external command."); ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning], [InitISOFS, Always, TestOutputList ( - [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])], + [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]); + (* Test for RHBZ#579608, absolute symbolic links. *) + InitISOFS, Always, TestOutputList ( + [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])], "return first 10 lines of a file", "\ This command returns up to the first 10 lines of a file as @@ -2937,7 +3023,17 @@ named pipes (FIFOs). The C parameter should be the mode, using the standard constants. C and C 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, 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, C or C +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 ( @@ -2947,7 +3043,9 @@ and character special devices."); "\ This call creates a FIFO (named pipe) called C with mode C. It is just a convenient wrapper around -C."); +C. + +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 ( @@ -2957,7 +3055,9 @@ C."); "\ This call creates a block device node called C with mode C and device major/minor C and C. -It is just a convenient wrapper around C."); +It is just a convenient wrapper around C. + +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 ( @@ -2967,12 +3067,13 @@ It is just a convenient wrapper around C."); "\ This call creates a char device node called C with mode C and device major/minor C and C. -It is just a convenient wrapper around C."); +It is just a convenient wrapper around C. - ("umask", (RInt "oldmask", [Int "mask"]), 137, [], - [], (* XXX umask is one of those stateful things that we should - * reset between each test. - *) +The mode actually set is affected by the umask."); + + ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal], + [InitEmpty, Always, TestOutputInt ( + [["umask"; "0o22"]], 0o22)], "set file mode creation mask (umask)", "\ This function sets the mask used for creating new files and @@ -2987,7 +3088,8 @@ The default umask is C<022>. This is important because it means that directories and device nodes will be created with C<0644> or C<0755> mode even if you specify C<0777>. -See also L, C, C. +See also C, +L, C, C. This call returns the previous umask."); @@ -3184,7 +3286,20 @@ for full details."); ("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 as a @@ -3199,7 +3314,10 @@ in the total size of file that can be handled."); [InitISOFS, Always, TestOutputList ( [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]); InitISOFS, Always, TestOutputList ( - [["grep"; "nomatch"; "/test-grep.txt"]], [])], + [["grep"; "nomatch"; "/test-grep.txt"]], []); + (* Test for RHBZ#579608, absolute symbolic links. *) + InitISOFS, Always, TestOutputList ( + [["grep"; "nomatch"; "/abssymlink"]], [])], "return lines matching a pattern", "\ This calls the external C program and returns the @@ -3831,7 +3949,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 -of the directory to C. See also C."); +of the directory to C. + +For common Linux filesystems, the actual mode which is set will +be C. Non-native-Linux filesystems may +interpret the mode in other ways. + +See also C, C"); ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [], [], (* XXX *) @@ -4057,10 +4181,9 @@ but other possible values are described in C."); This sets the bootable flag on partition numbered C on device C. 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 ( @@ -4129,7 +4252,9 @@ content of the file is C octets of C, where C must be a number in the range C<[0..255]>. To fill a file with zero bytes (sparsely), it is -much more efficient to use C."); +much more efficient to use C. +To create a file with a pattern of repeating bytes +use C."); ("available", (RErr, [StringList "groups"]), 216, [], [InitNone, Always, TestRun [["available"; ""]]], @@ -4204,7 +4329,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. -This command cannot do partial copies."); +This command cannot do partial copies (see C)."); ("filesize", (RInt64 "size", [Pathname "file"]), 218, [], [InitBasicFS, Always, TestOutputInt ( @@ -4238,7 +4363,7 @@ Rename a logical volume C with the new name C."); "\ Rename a volume group C with the new name C."); - ("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", @@ -4255,6 +4380,251 @@ contained in a Linux initrd or initramfs image: See also C."); + ("pvuuid", (RString "uuid", [Device "device"]), 222, [], + [], + "get the UUID of a physical volume", + "\ +This command returns the UUID of the LVM PV C."); + + ("vguuid", (RString "uuid", [String "vgname"]), 223, [], + [], + "get the UUID of a volume group", + "\ +This command returns the UUID of the LVM VG named C."); + + ("lvuuid", (RString "uuid", [Device "device"]), 224, [], + [], + "get the UUID of a logical volume", + "\ +This command returns the UUID of the LVM LV C."); + + ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [], + [], + "get the PV UUIDs containing the volume group", + "\ +Given a VG called C, this returns the UUIDs of all +the physical volumes that this volume group resides on. + +You can use this along with C and C +calls to associate physical volumes and volume groups. + +See also C."); + + ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [], + [], + "get the LV UUIDs of all LVs in the volume group", + "\ +Given a VG called C, this returns the UUIDs of all +the logical volumes created in this volume group. + +You can use this along with C and C +calls to associate logical volumes and volume groups. + +See also C."); + + ("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 bytes from one source device +or file C to another destination device or file C. + +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. Compare +with C which just zeroes the first few blocks of +a device."); + + ("txz_in", (RErr, [FileIn "tarball"; Pathname "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 (an +I tar file) into C."); + + ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [], + [], + "pack directory into compressed tarball", + "\ +This command packs the contents of C and downloads +it to local file C (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."); + + ("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 on C. + +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 on +C has the bootable flag set. + +See also C."); + + ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal], + [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. + +Note that only MBR (old DOS-style) partitions have type bytes. +You will get undefined results for other partition table +types (see C)."); + + ("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 to C. 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)."); + + ("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. For the types of +checksums supported see the C 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 so that it fills +C% 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 to C. This +is the same as the L C command."); + + ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal], + [InitEmpty, Always, TestOutputInt ( + [["get_umask"]], 0o22)], + "get the current umask", + "\ +Return the current umask. By default the umask is C<022> +unless it has been set by calling C."); + + ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [], + [], + "upload a file to the appliance (internal use only)", + "\ +The C command uploads a file to +the libguestfs appliance. + +There is no comprehensive help for this command. You have +to look at the file C in the libguestfs source +to find out what it is for."); + + ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [], + [InitBasicFS, Always, TestOutput ( + [["base64_in"; "../images/hello.b64"; "/hello"]; + ["cat"; "/hello"]], "hello\n")], + "upload base64-encoded data to file", + "\ +This command uploads base64-encoded data from C +to C."); + + ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [], + [], + "download file and encode as base64", + "\ +This command downloads the contents of C, writing +it out to local file C encoded as base64."); + + ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [], + [], + "compute MD5, SHAx or CRC checksum of files in a directory", + "\ +This command computes the checksums of all regular files in +C and then emits a list of those checksums to +the local output file C. + +This can be used for verifying the integrity of a virtual +machine. However to be properly secure you should pay +attention to the output of the checksum command (it uses +the ones from GNU coreutils). In particular when the +filename is not printable, coreutils uses a special +backslash syntax. For more information, see the GNU +coreutils info file."); + + ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [], + [InitBasicFS, Always, TestOutputBuffer ( + [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"]; + ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")], + "fill a file with a repeating pattern of bytes", + "\ +This function is like C except that it creates +a new file of length C containing the repeating pattern +of bytes in C. The pattern is truncated if necessary +to ensure the length of the file is exactly C bytes."); + ] let all_functions = non_daemon_functions @ daemon_functions @@ -4679,8 +5049,7 @@ let seq_of_test = function (* 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 you should use -FTP." +of somewhere between 2MB and 4MB. See L." let danger_will_robinson = "B if longdesc.[String.length longdesc-1] = '\n' then @@ -4966,7 +5335,7 @@ let rec generate_actions_pod () = 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 @@ -5188,8 +5557,7 @@ and generate_xdr () = (* Having to choose a maximum message size is annoying for several * reasons (it limits what we can do in the API), but it (a) makes * the protocol a lot simpler, and (b) provides a bound on the size - * of the daemon which operates in limited memory space. For large - * file transfers you should use FTP. + * of the daemon which operates in limited memory space. *) pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024); pr "\n"; @@ -5295,7 +5663,7 @@ and generate_actions_h () = 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 @@ -5305,7 +5673,7 @@ and generate_internal_actions_h () = 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 @@ -5317,6 +5685,7 @@ and generate_client_actions () = #include #include #include +#include #include #include \"guestfs.h\" @@ -5489,7 +5858,8 @@ check_state (guestfs_h *g, const char *caller) pr " int r;\n"; pr "\n"; trace_call shortname style; - pr " if (check_state (g, \"%s\") == -1) return %s;\n" name error_code; + pr " if (check_state (g, \"%s\") == -1) return %s;\n" + shortname error_code; pr " guestfs___set_busy (g);\n"; pr "\n"; @@ -5779,14 +6149,19 @@ and generate_daemon_actions () = ); pr "\n"; + let is_filein = + List.exists (function FileIn _ -> true | _ -> false) (snd style) in + (match snd style with | [] -> () | args -> pr " memset (&args, 0, sizeof args);\n"; pr "\n"; pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name; - pr " reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name; - pr " return;\n"; + if is_filein then + pr " cancel_receive ();\n"; + pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n"; + pr " goto done;\n"; pr " }\n"; let pr_args n = pr " char *%s = args.%s;\n" n n @@ -5795,6 +6170,8 @@ and generate_daemon_actions () = pr " %s = realloc (args.%s.%s_val,\n" n n n; pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n; pr " if (%s == NULL) {\n" n; + if is_filein then + pr " cancel_receive ();\n"; pr " reply_with_perror (\"realloc\");\n"; pr " goto done;\n"; pr " }\n"; @@ -5805,13 +6182,16 @@ and generate_daemon_actions () = function | Pathname n -> pr_args n; - pr " ABS_PATH (%s, goto done);\n" n; + pr " ABS_PATH (%s, %s, goto done);\n" + n (if is_filein then "cancel_receive ()" else ""); | Device n -> pr_args n; - pr " RESOLVE_DEVICE (%s, goto done);\n" n; + pr " RESOLVE_DEVICE (%s, %s, goto done);\n" + n (if is_filein then "cancel_receive ()" else ""); | Dev_or_Path n -> pr_args n; - pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n; + pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n" + n (if is_filein then "cancel_receive ()" else ""); | String n -> pr_args n | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n | StringList n -> @@ -5821,7 +6201,8 @@ and generate_daemon_actions () = pr " /* Ensure that each is a device,\n"; pr " * and perform device name translation. */\n"; pr " { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n"; - pr " RESOLVE_DEVICE (physvols[pvi], goto done);\n"; + pr " RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n" + (if is_filein then "cancel_receive ()" else ""); pr " }\n"; | Bool n -> pr " %s = args.%s;\n" n n | Int n -> pr " %s = args.%s;\n" n n @@ -5836,7 +6217,8 @@ and generate_daemon_actions () = if List.exists (function Pathname _ -> true | _ -> false) (snd style) then ( (* Emit NEED_ROOT just once, even when there are two or more Pathname args *) - pr " NEED_ROOT (goto done);\n"; + pr " NEED_ROOT (%s, goto done);\n" + (if is_filein then "cancel_receive ()" else ""); ); (* Don't want to call the impl with any FileIn or FileOut @@ -5922,15 +6304,14 @@ and generate_daemon_actions () = ); (* Free the args. *) + pr "done:\n"; (match snd style with - | [] -> - pr "done: ;\n"; + | [] -> () | _ -> - pr "done:\n"; pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n" name ); - + pr " return;\n"; pr "}\n\n"; ) daemon_functions; @@ -6055,7 +6436,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 " \"/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"; @@ -6360,14 +6741,14 @@ int main (int argc, char *argv[]) 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); } - /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */ - alarm (600); - /* Cancel previous alarm. */ alarm (0); @@ -6378,6 +6759,8 @@ int main (int argc, char *argv[]) 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; @@ -6795,7 +7178,7 @@ and generate_test_command_call ?(expect_error = false) ?test test_name cmd = | 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 ( @@ -7120,11 +7503,11 @@ and generate_fish_cmds () = function | Device n | String n - | OptString n - | FileIn n - | FileOut n -> pr " const char *%s;\n" n + | OptString n -> pr " const char *%s;\n" n | Pathname n - | Dev_or_Path n -> pr " char *%s;\n" n + | Dev_or_Path n + | FileIn n + | FileOut n -> pr " char *%s;\n" n | StringList n | DeviceList n -> pr " char **%s;\n" n | Bool n -> pr " int %s;\n" n | Int n -> pr " int %s;\n" n @@ -7181,11 +7564,11 @@ and generate_fish_cmds () = pr " %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n" name i i | FileIn name -> - pr " %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n" - name i i + pr " %s = file_in (argv[%d]);\n" name i; + pr " if (%s == NULL) return -1;\n" name | FileOut name -> - pr " %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n" - name i i + pr " %s = file_out (argv[%d]);\n" name i; + pr " if (%s == NULL) return -1;\n" name | StringList name | DeviceList name -> pr " %s = parse_string_list (argv[%d]);\n" name i; pr " if (%s == NULL) return -1;\n" name; @@ -7198,40 +7581,62 @@ and generate_fish_cmds () = 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); (* Call C API function. *) - let fn = - try find_map (function FishAction n -> Some n | _ -> None) flags - with Not_found -> sprintf "guestfs_%s" name in - pr " r = %s " fn; + pr " r = guestfs_%s " name; generate_c_call_args ~handle:"g" style; pr ";\n"; List.iter ( function | Device name | String name - | OptString name | FileIn name | FileOut name | Bool name + | OptString name | Bool name | Int name | Int64 name -> () - | Pathname name | Dev_or_Path name -> + | Pathname name | Dev_or_Path name | FileOut name -> pr " free (%s);\n" name + | FileIn name -> + pr " free_file_in (%s);\n" name | StringList name | DeviceList name -> pr " free_strings (%s);\n" name ) (snd style); + (* Any output flags? *) + let fish_output = + let flags = filter_map ( + function FishOutput flag -> Some flag | _ -> None + ) flags in + match flags with + | [] -> None + | [f] -> Some f + | _ -> + failwithf "%s: more than one FishOutput flag is not allowed" name in + (* Check return value for errors and display command results. *) (match fst style with | RErr -> pr " return r;\n" | RInt _ -> pr " if (r == -1) return -1;\n"; - pr " printf (\"%%d\\n\", r);\n"; + (match fish_output with + | None -> + pr " printf (\"%%d\\n\", r);\n"; + | Some FishOutputOctal -> + pr " printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n"; + | Some FishOutputHexadecimal -> + pr " printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n"); pr " return 0;\n" | RInt64 _ -> pr " if (r == -1) return -1;\n"; - pr " printf (\"%%\" PRIi64 \"\\n\", r);\n"; + (match fish_output with + | None -> + pr " printf (\"%%\" PRIi64 \"\\n\", r);\n"; + | Some FishOutputOctal -> + pr " printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n"; + | Some FishOutputHexadecimal -> + pr " printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n"); pr " return 0;\n" | RBool _ -> pr " if (r == -1) return -1;\n"; @@ -7304,6 +7709,8 @@ and generate_fish_cmds () = ) 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"; @@ -7382,7 +7789,16 @@ generator (const char *text, int state) #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; @@ -7390,9 +7806,9 @@ char **do_completion (const char *text, int start, int end) rl_completion_append_character = ' '; if (start == 0) - matches = rl_completion_matches (text, generator); + matches = RL_COMPLETION_MATCHES (text, generator); 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; @@ -8124,7 +8540,7 @@ DESTROY (g) pr ";\n"; do_cleanups (); pr " if (r == -1)\n"; - pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name; + pr " croak (\"%%s\", guestfs_last_error (g));\n"; | RInt n | RBool n -> pr "PREINIT:\n"; @@ -8135,7 +8551,7 @@ DESTROY (g) pr ";\n"; do_cleanups (); pr " if (%s == -1)\n" n; - pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name; + pr " croak (\"%%s\", guestfs_last_error (g));\n"; pr " RETVAL = newSViv (%s);\n" n; pr " OUTPUT:\n"; pr " RETVAL\n" @@ -8148,7 +8564,7 @@ DESTROY (g) pr ";\n"; do_cleanups (); pr " if (%s == -1)\n" n; - pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name; + pr " croak (\"%%s\", guestfs_last_error (g));\n"; pr " RETVAL = my_newSVll (%s);\n" n; pr " OUTPUT:\n"; pr " RETVAL\n" @@ -8161,7 +8577,7 @@ DESTROY (g) pr ";\n"; do_cleanups (); pr " if (%s == NULL)\n" n; - pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name; + pr " croak (\"%%s\", guestfs_last_error (g));\n"; pr " RETVAL = newSVpv (%s, 0);\n" n; pr " OUTPUT:\n"; pr " RETVAL\n" @@ -8188,7 +8604,7 @@ DESTROY (g) pr ";\n"; do_cleanups (); pr " if (%s == NULL)\n" n; - pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name; + pr " croak (\"%%s\", guestfs_last_error (g));\n"; pr " RETVAL = newSVpv (%s, 0);\n" n; pr " free (%s);\n" n; pr " OUTPUT:\n"; @@ -8203,7 +8619,7 @@ DESTROY (g) pr ";\n"; do_cleanups (); pr " if (%s == NULL)\n" n; - pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name; + pr " croak (\"%%s\", guestfs_last_error (g));\n"; pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n; pr " EXTEND (SP, n);\n"; pr " for (i = 0; i < n; ++i) {\n"; @@ -8227,8 +8643,8 @@ DESTROY (g) pr ";\n"; do_cleanups (); pr " if (%s == NULL)\n" n; - pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name; - pr " RETVAL = newSVpv (%s, size);\n" n; + pr " croak (\"%%s\", guestfs_last_error (g));\n"; + pr " RETVAL = newSVpvn (%s, size);\n" n; pr " free (%s);\n" n; pr " OUTPUT:\n"; pr " RETVAL\n" @@ -8248,7 +8664,7 @@ and generate_perl_struct_list_code typ cols name style n do_cleanups = pr ";\n"; do_cleanups (); pr " if (%s == NULL)\n" n; - pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name; + pr " croak (\"%%s\", guestfs_last_error (g));\n"; pr " EXTEND (SP, %s->len);\n" n; pr " for (i = 0; i < %s->len; ++i) {\n" n; pr " hv = newHV ();\n"; @@ -8261,7 +8677,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, %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" @@ -8292,7 +8708,7 @@ and generate_perl_struct_code typ cols name style n do_cleanups = pr ";\n"; do_cleanups (); pr " if (%s == NULL)\n" n; - pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name; + pr " croak (\"%%s\", guestfs_last_error (g));\n"; pr " EXTEND (SP, 2 * %d);\n" (List.length cols); List.iter ( fun ((name, _) as col) -> @@ -8303,7 +8719,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, %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" @@ -8368,7 +8784,8 @@ schemes, qcow, qcow2, vmdk. Libguestfs provides ways to enumerate guest storage (eg. partitions, LVs, what filesystem is in each LV, etc.). It can also run commands -in the context of the guest. Also you can access filesystems over FTP. +in the context of the guest. Also you can access filesystems over +FUSE. See also L for a set of useful library functions for using libguestfs from Perl, including integration @@ -8905,7 +9322,8 @@ schemes, qcow, qcow2, vmdk. Libguestfs provides ways to enumerate guest storage (eg. partitions, LVs, what filesystem is in each LV, etc.). It can also run commands -in the context of the guest. Also you can access filesystems over FTP. +in the context of the guest. Also you can access filesystems over +FUSE. Errors which happen while using the API are turned into Python RuntimeError exceptions. @@ -10198,96 +10616,96 @@ namespace Guestfs 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 () = - 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 () = - 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 () = - 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 - | StringList n | DeviceList n -> + | StringList n | DeviceList 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 () = - 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 - | StringList n | DeviceList n -> + | StringList n | DeviceList 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 () = - 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; @@ -10302,8 +10720,7 @@ namespace Guestfs pr " r = "; generate_call (); pr " if (r %s)\n" (c_error_comparison ()); - pr " throw new Error (\"%s: \" + guestfs_last_error (_handle));\n" - name; + pr " throw new Error (guestfs_last_error (_handle));\n"; (match fst style with | RErr -> () | RBool _ ->