X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=src%2Fgenerator.ml;h=40ffc064c6c4d02b769d4ff7815c1c5a18e38f52;hp=6792e07a9416e5c842281a5a06f797b6735430e3;hb=ab0397017cc26833c09946cca19d86b907822a94;hpb=b4d2a01828e5de85e5eee3631f7fe3925a0312ca diff --git a/src/generator.ml b/src/generator.ml index 6792e07..40ffc06 100755 --- a/src/generator.ml +++ b/src/generator.ml @@ -33,6 +33,7 @@ *) #load "unix.cma";; +#load "str.cma";; open Printf @@ -43,9 +44,15 @@ and ret = *) | RErr (* "RInt" as a return value means an int which is -1 for error - * or any value >= 0 on success. + * or any value >= 0 on success. Only use this for smallish + * positive ints (0 <= i < 2^30). *) | RInt of string + (* "RInt64" is the same as RInt, but is guaranteed to be able + * to return a full 64 bit value, _except_ that -1 means error + * (so -1 cannot be a valid, non-error return value). + *) + | RInt64 of string (* "RBool" is a bool return value which can be true/false or * -1 for error. *) @@ -65,6 +72,18 @@ and ret = | RPVList of string | RVGList of string | RLVList of string + (* Stat buffers. *) + | RStat of string + | RStatVFS of string + (* Key-value pairs of untyped strings. Turns into a hashtable or + * dictionary in languages which support it. DON'T use this as a + * general "bucket" for results. Prefer a stronger typed return + * value if one is available, or write a custom struct. Don't use + * this if the list could potentially be very long, since it is + * inefficient. Keys should be unique. NULLs are not permitted. + *) + | RHashtable of string + and args = argt list (* Function parameters, guestfs handle is implicit. *) (* Note in future we should allow a "variable args" parameter as @@ -80,6 +99,16 @@ and argt = | StringList of string(* list of strings (each string cannot be NULL) *) | Bool of string (* boolean *) | Int of string (* int (smallish ints, signed, <= 31 bits) *) + (* These are treated as filenames (simple string parameters) in + * the C API and bindings. But in the RPC protocol, we transfer + * the actual file content up to or down from the daemon. + * FileIn: local machine -> daemon (in request) + * FileOut: daemon -> local machine (in reply) + * In guestfish (only), the special name "-" means read from + * stdin or write to stdout. + *) + | FileIn of string + | FileOut of string type flags = | ProtocolLimitWarning (* display warning about protocol size limits *) @@ -107,7 +136,7 @@ can easily destroy all your data>." * the virtual machine and block devices are reused between tests. * So don't try testing kill_subprocess :-x * - * Between each test we umount-all and lvm-remove-all. + * Between each test we umount-all and lvm-remove-all (except InitNone). * * Don't assume anything about the previous contents of the block * devices. Use 'Init*' to create some initial scenarios. @@ -141,28 +170,43 @@ and test = * content). *) | TestOutputLength of seq * int + (* Run the command sequence and expect the output of the final + * command to be a structure. + *) + | TestOutputStruct of seq * test_field_compare list (* Run the command sequence and expect the final command (only) * to fail. *) | TestLastFail of seq +and test_field_compare = + | CompareWithInt of string * int + | CompareWithString of string * string + | CompareFieldsIntEq of string * string + | CompareFieldsStrEq of string * string + (* Some initial scenarios for testing. *) and test_init = - (* Do nothing, block devices could contain random stuff. *) + (* Do nothing, block devices could contain random stuff including + * LVM PVs, and some filesystems might be mounted. This is usually + * a bad idea. + *) | InitNone + (* Block devices are empty and no filesystems are mounted. *) + | InitEmpty (* /dev/sda contains a single partition /dev/sda1, which is formatted * as ext2, empty [except for lost+found] and mounted on /. * /dev/sdb and /dev/sdc may have random content. * No LVM. *) - | InitEmpty + | InitBasicFS (* /dev/sda: * /dev/sda1 (is a PV): * /dev/VG/LV (size 8MB): * formatted as ext2, empty [except for lost+found], mounted on / * /dev/sdb and /dev/sdc may have random content. *) - | InitEmptyLVM + | InitBasicFSonLVM (* Sequence of commands for testing. *) and seq = cmd list @@ -241,6 +285,32 @@ The first character of C string must be a C<-> (dash). C can be NULL."); + ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"], + [], + "set the qemu binary", + "\ +Set the qemu binary that we will use. + +The default is chosen when the library was compiled by the +configure script. + +You can also override this by setting the C +environment variable. + +The string C is stashed in the libguestfs handle, so the caller +must make sure it remains valid for the lifetime of the handle. + +Setting C to C restores the default qemu binary."); + + ("get_qemu", (RConstString "qemu", []), -1, [], + [], + "get the qemu binary", + "\ +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."); + ("set_path", (RErr, [String "path"]), -1, [FishAlias "path"], [], "set the search path", @@ -291,12 +361,76 @@ C is defined and set to C<1>."); [], "get verbose mode", "\ -This returns the verbose messages flag.") +This returns the verbose messages flag."); + + ("is_ready", (RBool "ready", []), -1, [], + [], + "is ready to accept commands", + "\ +This returns true iff this handle is ready to accept commands +(in the C state). + +For more information on states, see L."); + + ("is_config", (RBool "config", []), -1, [], + [], + "is in configuration state", + "\ +This returns true iff this handle is being configured +(in the C state). + +For more information on states, see L."); + + ("is_launching", (RBool "launching", []), -1, [], + [], + "is launching subprocess", + "\ +This returns true iff this handle is launching the subprocess +(in the C state). + +For more information on states, see L."); + + ("is_busy", (RBool "busy", []), -1, [], + [], + "is busy processing a command", + "\ +This returns true iff this handle is busy processing a command +(in the C state). + +For more information on states, see L."); + + ("get_state", (RInt "state", []), -1, [], + [], + "get the current state", + "\ +This returns the current state as an opaque integer. This is +only useful for printing debug and internal error messages. + +For more information on states, see L."); + + ("set_busy", (RErr, []), -1, [NotInFish], + [], + "set state to busy", + "\ +This sets the state to C. This is only used when implementing +actions using the low-level API. + +For more information on states, see L."); + + ("set_ready", (RErr, []), -1, [NotInFish], + [], + "set state to ready", + "\ +This sets the state to C. This is only used when implementing +actions using the low-level API. + +For more information on states, see L."); + ] let daemon_functions = [ ("mount", (RErr, [String "device"; String "mountpoint"]), 1, [], - [InitNone, TestOutput ( + [InitEmpty, TestOutput ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","]; ["mkfs"; "ext2"; "/dev/sda1"]; ["mount"; "/dev/sda1"; "/"]; @@ -322,7 +456,7 @@ The filesystem options C and C are set with this call, in order to improve reliability."); ("sync", (RErr, []), 2, [], - [ InitNone, TestRun [["sync"]]], + [ InitEmpty, TestRun [["sync"]]], "sync disks, writes are flushed through to the disk image", "\ This syncs the disk, so that any writes are flushed through to the @@ -332,7 +466,7 @@ You should always call this if you have modified a disk image, before closing the handle."); ("touch", (RErr, [String "path"]), 3, [], - [InitEmpty, TestOutputTrue ( + [InitBasicFS, TestOutputTrue ( [["touch"; "/new"]; ["exists"; "/new"]])], "update file timestamps or create a new file", @@ -342,7 +476,7 @@ update the timestamps on a file, or, if the file does not exist, to create a new zero-length file."); ("cat", (RString "content", [String "path"]), 4, [ProtocolLimitWarning], - [InitEmpty, TestOutput ( + [InitBasicFS, TestOutput ( [["write_file"; "/new"; "new file contents"; "0"]; ["cat"; "/new"]], "new file contents")], "list the contents of a file", @@ -351,7 +485,7 @@ Return the contents of the file named C. Note that this function cannot correctly handle binary files (specifically, files containing C<\\0> character which is treated -as end of string). For those you need to use the C +as end of string). For those you need to use the C function which has a more complex interface."); ("ll", (RString "listing", [String "directory"]), 5, [], @@ -367,7 +501,7 @@ This command is mostly useful for interactive sessions. It is I intended that you try to parse the output string."); ("ls", (RStringList "listing", [String "directory"]), 6, [], - [InitEmpty, TestOutputList ( + [InitBasicFS, TestOutputList ( [["touch"; "/new"]; ["touch"; "/newer"]; ["touch"; "/newest"]; @@ -382,7 +516,7 @@ This command is mostly useful for interactive sessions. Programs should probably use C instead."); ("list_devices", (RStringList "devices", []), 7, [], - [InitNone, TestOutputList ( + [InitEmpty, TestOutputList ( [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"])], "list the block devices", "\ @@ -391,9 +525,9 @@ List all the block devices. The full block device names are returned, eg. C"); ("list_partitions", (RStringList "partitions", []), 8, [], - [InitEmpty, TestOutputList ( + [InitBasicFS, TestOutputList ( [["list_partitions"]], ["/dev/sda1"]); - InitNone, TestOutputList ( + InitEmpty, TestOutputList ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"]; ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])], "list the partitions", @@ -406,9 +540,9 @@ This does not return logical volumes. For that you will need to call C."); ("pvs", (RStringList "physvols", []), 9, [], - [InitEmptyLVM, TestOutputList ( + [InitBasicFSonLVM, TestOutputList ( [["pvs"]], ["/dev/sda1"]); - InitNone, TestOutputList ( + InitEmpty, TestOutputList ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"]; ["pvcreate"; "/dev/sda1"]; ["pvcreate"; "/dev/sda2"]; @@ -425,9 +559,9 @@ PVs (eg. C). See also C."); ("vgs", (RStringList "volgroups", []), 10, [], - [InitEmptyLVM, TestOutputList ( + [InitBasicFSonLVM, TestOutputList ( [["vgs"]], ["VG"]); - InitNone, TestOutputList ( + InitEmpty, TestOutputList ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"]; ["pvcreate"; "/dev/sda1"]; ["pvcreate"; "/dev/sda2"]; @@ -446,9 +580,9 @@ detected (eg. C). See also C."); ("lvs", (RStringList "logvols", []), 11, [], - [InitEmptyLVM, TestOutputList ( + [InitBasicFSonLVM, TestOutputList ( [["lvs"]], ["/dev/VG/LV"]); - InitNone, TestOutputList ( + InitEmpty, TestOutputList ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"]; ["pvcreate"; "/dev/sda1"]; ["pvcreate"; "/dev/sda2"]; @@ -470,34 +604,31 @@ This returns a list of the logical volume device names See also C."); ("pvs_full", (RPVList "physvols", []), 12, [], - [InitEmptyLVM, TestOutputLength ( - [["pvs"]], 1)], + [], (* XXX how to test? *) "list the LVM physical volumes (PVs)", "\ List all the physical volumes detected. This is the equivalent of the L command. The \"full\" version includes all fields."); ("vgs_full", (RVGList "volgroups", []), 13, [], - [InitEmptyLVM, TestOutputLength ( - [["pvs"]], 1)], + [], (* XXX how to test? *) "list the LVM volume groups (VGs)", "\ List all the volumes groups detected. This is the equivalent of the L command. The \"full\" version includes all fields."); ("lvs_full", (RLVList "logvols", []), 14, [], - [InitEmptyLVM, TestOutputLength ( - [["pvs"]], 1)], + [], (* XXX how to test? *) "list the LVM logical volumes (LVs)", "\ List all the logical volumes detected. This is the equivalent of the L command. The \"full\" version includes all fields."); ("read_lines", (RStringList "lines", [String "path"]), 15, [], - [InitEmpty, TestOutputList ( + [InitBasicFS, TestOutputList ( [["write_file"; "/new"; "line1\r\nline2\nline3"; "0"]; ["read_lines"; "/new"]], ["line1"; "line2"; "line3"]); - InitEmpty, TestOutputList ( + InitBasicFS, TestOutputList ( [["write_file"; "/new"; ""; "0"]; ["read_lines"; "/new"]], [])], "read file as lines", @@ -672,12 +803,12 @@ This is just a shortcut for listing C C and sorting the resulting nodes into alphabetical order."); ("rm", (RErr, [String "path"]), 29, [], - [InitEmpty, TestRun + [InitBasicFS, TestRun [["touch"; "/new"]; ["rm"; "/new"]]; - InitEmpty, TestLastFail + InitBasicFS, TestLastFail [["rm"; "/new"]]; - InitEmpty, TestLastFail + InitBasicFS, TestLastFail [["mkdir"; "/new"]; ["rm"; "/new"]]], "remove a file", @@ -685,12 +816,12 @@ C and sorting the resulting nodes into alphabetical order."); Remove the single file C."); ("rmdir", (RErr, [String "path"]), 30, [], - [InitEmpty, TestRun + [InitBasicFS, TestRun [["mkdir"; "/new"]; ["rmdir"; "/new"]]; - InitEmpty, TestLastFail + InitBasicFS, TestLastFail [["rmdir"; "/new"]]; - InitEmpty, TestLastFail + InitBasicFS, TestLastFail [["touch"; "/new"]; ["rmdir"; "/new"]]], "remove a directory", @@ -698,7 +829,7 @@ Remove the single file C."); Remove the single directory C."); ("rm_rf", (RErr, [String "path"]), 31, [], - [InitEmpty, TestOutputFalse + [InitBasicFS, TestOutputFalse [["mkdir"; "/new"]; ["mkdir"; "/new/foo"]; ["touch"; "/new/foo/bar"]; @@ -711,23 +842,23 @@ contents if its a directory. This is like the C shell command."); ("mkdir", (RErr, [String "path"]), 32, [], - [InitEmpty, TestOutputTrue + [InitBasicFS, TestOutputTrue [["mkdir"; "/new"]; ["is_dir"; "/new"]]; - InitEmpty, TestLastFail + InitBasicFS, TestLastFail [["mkdir"; "/new/foo/bar"]]], "create a directory", "\ Create a directory named C."); ("mkdir_p", (RErr, [String "path"]), 33, [], - [InitEmpty, TestOutputTrue + [InitBasicFS, TestOutputTrue [["mkdir_p"; "/new/foo/bar"]; ["is_dir"; "/new/foo/bar"]]; - InitEmpty, TestOutputTrue + InitBasicFS, TestOutputTrue [["mkdir_p"; "/new/foo/bar"]; ["is_dir"; "/new/foo"]]; - InitEmpty, TestOutputTrue + InitBasicFS, TestOutputTrue [["mkdir_p"; "/new/foo/bar"]; ["is_dir"; "/new"]]], "create a directory and parents", @@ -753,10 +884,10 @@ names, you will need to locate and parse the password file yourself (Augeas support makes this relatively easy)."); ("exists", (RBool "existsflag", [String "path"]), 36, [], - [InitEmpty, TestOutputTrue ( + [InitBasicFS, TestOutputTrue ( [["touch"; "/new"]; ["exists"; "/new"]]); - InitEmpty, TestOutputTrue ( + InitBasicFS, TestOutputTrue ( [["mkdir"; "/new"]; ["exists"; "/new"]])], "test if file or directory exists", @@ -767,10 +898,10 @@ This returns C if and only if there is a file, directory See also C, C, C."); ("is_file", (RBool "fileflag", [String "path"]), 37, [], - [InitEmpty, TestOutputTrue ( + [InitBasicFS, TestOutputTrue ( [["touch"; "/new"]; ["is_file"; "/new"]]); - InitEmpty, TestOutputFalse ( + InitBasicFS, TestOutputFalse ( [["mkdir"; "/new"]; ["is_file"; "/new"]])], "test if file exists", @@ -782,10 +913,10 @@ other objects like directories. See also C."); ("is_dir", (RBool "dirflag", [String "path"]), 38, [], - [InitEmpty, TestOutputFalse ( + [InitBasicFS, TestOutputFalse ( [["touch"; "/new"]; ["is_dir"; "/new"]]); - InitEmpty, TestOutputTrue ( + InitBasicFS, TestOutputTrue ( [["mkdir"; "/new"]; ["is_dir"; "/new"]])], "test if file exists", @@ -797,7 +928,7 @@ other objects like files. See also C."); ("pvcreate", (RErr, [String "device"]), 39, [], - [InitNone, TestOutputList ( + [InitEmpty, TestOutputList ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"]; ["pvcreate"; "/dev/sda1"]; ["pvcreate"; "/dev/sda2"]; @@ -810,7 +941,7 @@ where C should usually be a partition name such as C."); ("vgcreate", (RErr, [String "volgroup"; StringList "physvols"]), 40, [], - [InitNone, TestOutputList ( + [InitEmpty, TestOutputList ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"]; ["pvcreate"; "/dev/sda1"]; ["pvcreate"; "/dev/sda2"]; @@ -824,7 +955,7 @@ This creates an LVM volume group called C from the non-empty list of physical volumes C."); ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [], - [InitNone, TestOutputList ( + [InitEmpty, TestOutputList ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"]; ["pvcreate"; "/dev/sda1"]; ["pvcreate"; "/dev/sda2"]; @@ -845,7 +976,7 @@ This creates an LVM volume group called C on the volume group C, with C megabytes."); ("mkfs", (RErr, [String "fstype"; String "device"]), 42, [], - [InitNone, TestOutput ( + [InitEmpty, TestOutput ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","]; ["mkfs"; "ext2"; "/dev/sda1"]; ["mount"; "/dev/sda1"; "/"]; @@ -884,13 +1015,25 @@ pass C as a single element list, when the single element being the string C<,> (comma)."); ("write_file", (RErr, [String "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning], - [InitNone, TestOutput ( - [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","]; - ["mkfs"; "ext2"; "/dev/sda1"]; - ["mount"; "/dev/sda1"; "/"]; - ["write_file"; "/new"; "new file contents"; "0"]; - ["cat"; "/new"]], "new file contents")], - "Create a file", + [InitBasicFS, TestOutput ( + [["write_file"; "/new"; "new file contents"; "0"]; + ["cat"; "/new"]], "new file contents"); + InitBasicFS, TestOutput ( + [["write_file"; "/new"; "\nnew file contents\n"; "0"]; + ["cat"; "/new"]], "\nnew file contents\n"); + InitBasicFS, TestOutput ( + [["write_file"; "/new"; "\n\n"; "0"]; + ["cat"; "/new"]], "\n\n"); + InitBasicFS, TestOutput ( + [["write_file"; "/new"; ""; "0"]; + ["cat"; "/new"]], ""); + InitBasicFS, TestOutput ( + [["write_file"; "/new"; "\n\n\n"; "0"]; + ["cat"; "/new"]], "\n\n\n"); + InitBasicFS, TestOutput ( + [["write_file"; "/new"; "\n"; "0"]; + ["cat"; "/new"]], "\n")], + "create a file", "\ This call creates a file called C. The contents of the file is the string C (which can contain any 8 bit data), @@ -901,12 +1044,12 @@ then the length is calculated using C (so in this case the content cannot contain embedded ASCII NULs)."); ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"], - [InitNone, TestOutputList ( + [InitEmpty, TestOutputList ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","]; ["mkfs"; "ext2"; "/dev/sda1"]; ["mount"; "/dev/sda1"; "/"]; ["mounts"]], ["/dev/sda1"]); - InitNone, TestOutputList ( + InitEmpty, TestOutputList ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","]; ["mkfs"; "ext2"; "/dev/sda1"]; ["mount"; "/dev/sda1"; "/"]; @@ -919,7 +1062,7 @@ specified either by its mountpoint (path) or the device which contains the filesystem."); ("mounts", (RStringList "devices", []), 46, [], - [InitEmpty, TestOutputList ( + [InitBasicFS, TestOutputList ( [["mounts"]], ["/dev/sda1"])], "show mounted filesystems", "\ @@ -929,7 +1072,7 @@ the list of devices (eg. C, C). Some internal mounts are not shown."); ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"], - [InitEmpty, TestOutputList ( + [InitBasicFS, TestOutputList ( [["umount_all"]; ["mounts"]], [])], "unmount all filesystems", @@ -945,6 +1088,532 @@ Some internal mounts are not unmounted by this call."); This command removes all LVM logical volumes, volume groups and physical volumes."); + ("file", (RString "description", [String "path"]), 49, [], + [InitBasicFS, TestOutput ( + [["touch"; "/new"]; + ["file"; "/new"]], "empty"); + InitBasicFS, TestOutput ( + [["write_file"; "/new"; "some content\n"; "0"]; + ["file"; "/new"]], "ASCII text"); + InitBasicFS, TestLastFail ( + [["file"; "/nofile"]])], + "determine file type", + "\ +This call uses the standard L command to determine +the type or contents of the file. This also works on devices, +for example to find out whether a partition contains a filesystem. + +The exact command which runs is C. Note in +particular that the filename is not prepended to the output +(the C<-b> option)."); + + ("command", (RString "output", [StringList "arguments"]), 50, [], + [], (* XXX how to test? *) + "run a command from the guest filesystem", + "\ +This call runs a command from the guest filesystem. The +filesystem must be mounted, and must contain a compatible +operating system (ie. something Linux, with the same +or compatible processor architecture). + +The single parameter is an argv-style list of arguments. +The first element is the name of the program to run. +Subsequent elements are parameters. The list must be +non-empty (ie. must contain a program name). + +The C<$PATH> environment variable will contain at least +C and C. If you require a program from +another location, you should provide the full path in the +first parameter. + +Shared libraries and data files required by the program +must be available on filesystems which are mounted in the +correct places. It is the caller's responsibility to ensure +all filesystems that are needed are mounted at the right +locations."); + + ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [], + [], (* XXX how to test? *) + "run a command, returning lines", + "\ +This is the same as C, but splits the +result into a list of lines."); + + ("stat", (RStat "statbuf", [String "path"]), 52, [], + [InitBasicFS, TestOutputStruct ( + [["touch"; "/new"]; + ["stat"; "/new"]], [CompareWithInt ("size", 0)])], + "get file information", + "\ +Returns file information for the given C. + +This is the same as the C system call."); + + ("lstat", (RStat "statbuf", [String "path"]), 53, [], + [InitBasicFS, TestOutputStruct ( + [["touch"; "/new"]; + ["lstat"; "/new"]], [CompareWithInt ("size", 0)])], + "get file information for a symbolic link", + "\ +Returns file information for the given C. + +This is the same as C except that if C +is a symbolic link, then the link is stat-ed, not the file it +refers to. + +This is the same as the C system call."); + + ("statvfs", (RStatVFS "statbuf", [String "path"]), 54, [], + [InitBasicFS, TestOutputStruct ( + [["statvfs"; "/"]], [CompareWithInt ("bfree", 487702); + CompareWithInt ("blocks", 490020); + CompareWithInt ("bsize", 1024)])], + "get file system statistics", + "\ +Returns file system statistics for any mounted file system. +C should be a file or directory in the mounted file system +(typically it is the mount point itself, but it doesn't need to be). + +This is the same as the C system call."); + + ("tune2fs_l", (RHashtable "superblock", [String "device"]), 55, [], + [], (* XXX test *) + "get ext2/ext3/ext4 superblock details", + "\ +This returns the contents of the ext2, ext3 or ext4 filesystem +superblock on C. + +It is the same as running C. See L +manpage for more details. The list of fields returned isn't +clearly defined, and depends on both the version of C +that libguestfs was built against, and the filesystem itself."); + + ("blockdev_setro", (RErr, [String "device"]), 56, [], + [InitEmpty, TestOutputTrue ( + [["blockdev_setro"; "/dev/sda"]; + ["blockdev_getro"; "/dev/sda"]])], + "set block device to read-only", + "\ +Sets the block device named C to read-only. + +This uses the L command."); + + ("blockdev_setrw", (RErr, [String "device"]), 57, [], + [InitEmpty, TestOutputFalse ( + [["blockdev_setrw"; "/dev/sda"]; + ["blockdev_getro"; "/dev/sda"]])], + "set block device to read-write", + "\ +Sets the block device named C to read-write. + +This uses the L command."); + + ("blockdev_getro", (RBool "ro", [String "device"]), 58, [], + [InitEmpty, TestOutputTrue ( + [["blockdev_setro"; "/dev/sda"]; + ["blockdev_getro"; "/dev/sda"]])], + "is block device set to read-only", + "\ +Returns a boolean indicating if the block device is read-only +(true if read-only, false if not). + +This uses the L command."); + + ("blockdev_getss", (RInt "sectorsize", [String "device"]), 59, [], + [InitEmpty, TestOutputInt ( + [["blockdev_getss"; "/dev/sda"]], 512)], + "get sectorsize of block device", + "\ +This returns the size of sectors on a block device. +Usually 512, but can be larger for modern devices. + +(Note, this is not the size in sectors, use C +for that). + +This uses the L command."); + + ("blockdev_getbsz", (RInt "blocksize", [String "device"]), 60, [], + [InitEmpty, TestOutputInt ( + [["blockdev_getbsz"; "/dev/sda"]], 4096)], + "get blocksize of block device", + "\ +This returns the block size of a device. + +(Note this is different from both I and +I). + +This uses the L command."); + + ("blockdev_setbsz", (RErr, [String "device"; Int "blocksize"]), 61, [], + [], (* XXX test *) + "set blocksize of block device", + "\ +This sets the block size of a device. + +(Note this is different from both I and +I). + +This uses the L command."); + + ("blockdev_getsz", (RInt64 "sizeinsectors", [String "device"]), 62, [], + [InitEmpty, TestOutputInt ( + [["blockdev_getsz"; "/dev/sda"]], 1024000)], + "get total size of device in 512-byte sectors", + "\ +This returns the size of the device in units of 512-byte sectors +(even if the sectorsize isn't 512 bytes ... weird). + +See also C for the real sector size of +the device, and C for the more +useful I. + +This uses the L command."); + + ("blockdev_getsize64", (RInt64 "sizeinbytes", [String "device"]), 63, [], + [InitEmpty, TestOutputInt ( + [["blockdev_getsize64"; "/dev/sda"]], 524288000)], + "get total size of device in bytes", + "\ +This returns the size of the device in bytes. + +See also C. + +This uses the L command."); + + ("blockdev_flushbufs", (RErr, [String "device"]), 64, [], + [InitEmpty, TestRun + [["blockdev_flushbufs"; "/dev/sda"]]], + "flush device buffers", + "\ +This tells the kernel to flush internal buffers associated +with C. + +This uses the L command."); + + ("blockdev_rereadpt", (RErr, [String "device"]), 65, [], + [InitEmpty, TestRun + [["blockdev_rereadpt"; "/dev/sda"]]], + "reread partition table", + "\ +Reread the partition table on C. + +This uses the L command."); + + ("upload", (RErr, [FileIn "filename"; String "remotefilename"]), 66, [], + [InitBasicFS, TestOutput ( + (* Pick a file from cwd which isn't likely to change. *) + [["upload"; "COPYING.LIB"; "/COPYING.LIB"]; + ["checksum"; "md5"; "/COPYING.LIB"]], "e3eda01d9815f8d24aae2dbd89b68b06")], + "upload a file from the local machine", + "\ +Upload local file C to C on the +filesystem. + +C can also be a named pipe. + +See also C."); + + ("download", (RErr, [String "remotefilename"; FileOut "filename"]), 67, [], + [InitBasicFS, TestOutput ( + (* Pick a file from cwd which isn't likely to change. *) + [["upload"; "COPYING.LIB"; "/COPYING.LIB"]; + ["download"; "/COPYING.LIB"; "testdownload.tmp"]; + ["upload"; "testdownload.tmp"; "/upload"]; + ["checksum"; "md5"; "/upload"]], "e3eda01d9815f8d24aae2dbd89b68b06")], + "download a file to the local machine", + "\ +Download file C and save it as C +on the local machine. + +C can also be a named pipe. + +See also C, C."); + + ("checksum", (RString "checksum", [String "csumtype"; String "path"]), 68, [], + [InitBasicFS, TestOutput ( + [["write_file"; "/new"; "test\n"; "0"]; + ["checksum"; "crc"; "/new"]], "935282863"); + InitBasicFS, TestLastFail ( + [["checksum"; "crc"; "/new"]]); + InitBasicFS, TestOutput ( + [["write_file"; "/new"; "test\n"; "0"]; + ["checksum"; "md5"; "/new"]], "d8e8fca2dc0f896fd7cb4cb0031ba249"); + InitBasicFS, TestOutput ( + [["write_file"; "/new"; "test\n"; "0"]; + ["checksum"; "sha1"; "/new"]], "4e1243bd22c66e76c2ba9eddc1f91394e57f9f83"); + InitBasicFS, TestOutput ( + [["write_file"; "/new"; "test\n"; "0"]; + ["checksum"; "sha224"; "/new"]], "52f1bf093f4b7588726035c176c0cdb4376cfea53819f1395ac9e6ec"); + InitBasicFS, TestOutput ( + [["write_file"; "/new"; "test\n"; "0"]; + ["checksum"; "sha256"; "/new"]], "f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2"); + InitBasicFS, TestOutput ( + [["write_file"; "/new"; "test\n"; "0"]; + ["checksum"; "sha384"; "/new"]], "109bb6b5b6d5547c1ce03c7a8bd7d8f80c1cb0957f50c4f7fda04692079917e4f9cad52b878f3d8234e1a170b154b72d"); + InitBasicFS, TestOutput ( + [["write_file"; "/new"; "test\n"; "0"]; + ["checksum"; "sha512"; "/new"]], "0e3e75234abc68f4378a86b3f4b32a198ba301845b0cd6e50106e874345700cc6663a86c1ea125dc5e92be17c98f9a0f85ca9d5f595db2012f7cc3571945c123")], + "compute MD5, SHAx or CRC checksum of file", + "\ +This call computes the MD5, SHAx or CRC checksum of the +file named C. + +The type of checksum to compute is given by the C +parameter which must have one of the following values: + +=over 4 + +=item C + +Compute the cyclic redundancy check (CRC) specified by POSIX +for the C command. + +=item C + +Compute the MD5 hash (using the C program). + +=item C + +Compute the SHA1 hash (using the C program). + +=item C + +Compute the SHA224 hash (using the C program). + +=item C + +Compute the SHA256 hash (using the C program). + +=item C + +Compute the SHA384 hash (using the C program). + +=item C + +Compute the SHA512 hash (using the C program). + +=back + +The checksum is returned as a printable string."); + + ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [], + [InitBasicFS, TestOutput ( + [["tar_in"; "images/helloworld.tar"; "/"]; + ["cat"; "/hello"]], "hello\n")], + "unpack tarfile to directory", + "\ +This command uploads and unpacks local file C (an +I tar file) into C. + +To upload a compressed tarball, use C."); + + ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [], + [], + "pack directory into tarfile", + "\ +This command packs the contents of C and downloads +it to local file C. + +To download a compressed tarball, use C."); + + ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [], + [InitBasicFS, TestOutput ( + [["tgz_in"; "images/helloworld.tar.gz"; "/"]; + ["cat"; "/hello"]], "hello\n")], + "unpack compressed tarball to directory", + "\ +This command uploads and unpacks local file C (a +I tar file) into C. + +To upload an uncompressed tarball, use C."); + + ("tgz_out", (RErr, [String "directory"; FileOut "tarball"]), 72, [], + [], + "pack directory into compressed tarball", + "\ +This command packs the contents of C and downloads +it to local file C. + +To download an uncompressed tarball, use C."); + + ("mount_ro", (RErr, [String "device"; String "mountpoint"]), 73, [], + [InitBasicFS, TestLastFail ( + [["umount"; "/"]; + ["mount_ro"; "/dev/sda1"; "/"]; + ["touch"; "/new"]]); + InitBasicFS, TestOutput ( + [["write_file"; "/new"; "data"; "0"]; + ["umount"; "/"]; + ["mount_ro"; "/dev/sda1"; "/"]; + ["cat"; "/new"]], "data")], + "mount a guest disk, read-only", + "\ +This is the same as the C command, but it +mounts the filesystem with the read-only (I<-o ro>) flag."); + + ("mount_options", (RErr, [String "options"; String "device"; String "mountpoint"]), 74, [], + [], + "mount a guest disk with mount options", + "\ +This is the same as the C command, but it +allows you to set the mount options as for the +L I<-o> flag."); + + ("mount_vfs", (RErr, [String "options"; String "vfstype"; String "device"; String "mountpoint"]), 75, [], + [], + "mount a guest disk with mount options and vfstype", + "\ +This is the same as the C command, but it +allows you to set both the mount options and the vfstype +as for the L I<-o> and I<-t> flags."); + + ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [], + [], + "debugging and internals", + "\ +The C command exposes some internals of +C (the guestfs daemon) that runs inside the +qemu subprocess. + +There is no comprehensive help for this command. You have +to look at the file C in the libguestfs source +to find out what you can do."); + + ("lvremove", (RErr, [String "device"]), 77, [], + [InitEmpty, TestOutputList ( + [["pvcreate"; "/dev/sda"]; + ["vgcreate"; "VG"; "/dev/sda"]; + ["lvcreate"; "LV1"; "VG"; "50"]; + ["lvcreate"; "LV2"; "VG"; "50"]; + ["lvremove"; "/dev/VG/LV1"]; + ["lvs"]], ["/dev/VG/LV2"]); + InitEmpty, TestOutputList ( + [["pvcreate"; "/dev/sda"]; + ["vgcreate"; "VG"; "/dev/sda"]; + ["lvcreate"; "LV1"; "VG"; "50"]; + ["lvcreate"; "LV2"; "VG"; "50"]; + ["lvremove"; "/dev/VG"]; + ["lvs"]], []); + InitEmpty, TestOutputList ( + [["pvcreate"; "/dev/sda"]; + ["vgcreate"; "VG"; "/dev/sda"]; + ["lvcreate"; "LV1"; "VG"; "50"]; + ["lvcreate"; "LV2"; "VG"; "50"]; + ["lvremove"; "/dev/VG"]; + ["vgs"]], ["VG"])], + "remove an LVM logical volume", + "\ +Remove an LVM logical volume C, where C is +the path to the LV, such as C. + +You can also remove all LVs in a volume group by specifying +the VG name, C."); + + ("vgremove", (RErr, [String "vgname"]), 78, [], + [InitEmpty, TestOutputList ( + [["pvcreate"; "/dev/sda"]; + ["vgcreate"; "VG"; "/dev/sda"]; + ["lvcreate"; "LV1"; "VG"; "50"]; + ["lvcreate"; "LV2"; "VG"; "50"]; + ["vgremove"; "VG"]; + ["lvs"]], []); + InitEmpty, TestOutputList ( + [["pvcreate"; "/dev/sda"]; + ["vgcreate"; "VG"; "/dev/sda"]; + ["lvcreate"; "LV1"; "VG"; "50"]; + ["lvcreate"; "LV2"; "VG"; "50"]; + ["vgremove"; "VG"]; + ["vgs"]], [])], + "remove an LVM volume group", + "\ +Remove an LVM volume group C, (for example C). + +This also forcibly removes all logical volumes in the volume +group (if any)."); + + ("pvremove", (RErr, [String "device"]), 79, [], + [InitEmpty, TestOutputList ( + [["pvcreate"; "/dev/sda"]; + ["vgcreate"; "VG"; "/dev/sda"]; + ["lvcreate"; "LV1"; "VG"; "50"]; + ["lvcreate"; "LV2"; "VG"; "50"]; + ["vgremove"; "VG"]; + ["pvremove"; "/dev/sda"]; + ["lvs"]], []); + InitEmpty, TestOutputList ( + [["pvcreate"; "/dev/sda"]; + ["vgcreate"; "VG"; "/dev/sda"]; + ["lvcreate"; "LV1"; "VG"; "50"]; + ["lvcreate"; "LV2"; "VG"; "50"]; + ["vgremove"; "VG"]; + ["pvremove"; "/dev/sda"]; + ["vgs"]], []); + InitEmpty, TestOutputList ( + [["pvcreate"; "/dev/sda"]; + ["vgcreate"; "VG"; "/dev/sda"]; + ["lvcreate"; "LV1"; "VG"; "50"]; + ["lvcreate"; "LV2"; "VG"; "50"]; + ["vgremove"; "VG"]; + ["pvremove"; "/dev/sda"]; + ["pvs"]], [])], + "remove an LVM physical volume", + "\ +This wipes a physical volume C so that LVM will no longer +recognise it. + +The implementation uses the C command which refuses to +wipe physical volumes that contain any volume groups, so you have +to remove those first."); + + ("set_e2label", (RErr, [String "device"; String "label"]), 80, [], + [InitBasicFS, TestOutput ( + [["set_e2label"; "/dev/sda1"; "testlabel"]; + ["get_e2label"; "/dev/sda1"]], "testlabel")], + "set the ext2/3/4 filesystem label", + "\ +This sets the ext2/3/4 filesystem label of the filesystem on +C to C