+ ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutput (
+ [["cat"; "/known-2"]], "abcdef\n")],
+ "list the contents of a file",
+ "\
+Return the contents of the file named C<path>.
+
+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<guestfs_read_file>
+or C<guestfs_download> functions which have a more complex interface.");
+
+ ("ll", (RString "listing", [Pathname "directory"]), 5, [],
+ [], (* XXX Tricky to test because it depends on the exact format
+ * of the 'ls -l' command, which changes between F10 and F11.
+ *)
+ "list the files in a directory (long format)",
+ "\
+List the files in C<directory> (relative to the root directory,
+there is no cwd) in the format of 'ls -la'.
+
+This command is mostly useful for interactive sessions. It
+is I<not> intended that you try to parse the output string.");
+
+ ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
+ [InitBasicFS, Always, TestOutputList (
+ [["touch"; "/new"];
+ ["touch"; "/newer"];
+ ["touch"; "/newest"];
+ ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
+ "list the files in a directory",
+ "\
+List the files in C<directory> (relative to the root directory,
+there is no cwd). The '.' and '..' entries are not returned, but
+hidden files are shown.
+
+This command is mostly useful for interactive sessions. Programs
+should probably use C<guestfs_readdir> instead.");
+
+ ("list_devices", (RStringList "devices", []), 7, [],
+ [InitEmpty, Always, TestOutputListOfDevices (
+ [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
+ "list the block devices",
+ "\
+List all the block devices.
+
+The full block device names are returned, eg. C</dev/sda>");
+
+ ("list_partitions", (RStringList "partitions", []), 8, [],
+ [InitBasicFS, Always, TestOutputListOfDevices (
+ [["list_partitions"]], ["/dev/sda1"]);
+ InitEmpty, Always, TestOutputListOfDevices (
+ [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
+ ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
+ "list the partitions",
+ "\
+List all the partitions detected on all block devices.
+
+The full partition device names are returned, eg. C</dev/sda1>
+
+This does not return logical volumes. For that you will need to
+call C<guestfs_lvs>.");
+
+ ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
+ [InitBasicFSonLVM, Always, TestOutputListOfDevices (
+ [["pvs"]], ["/dev/sda1"]);
+ InitEmpty, Always, TestOutputListOfDevices (
+ [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
+ ["pvcreate"; "/dev/sda1"];
+ ["pvcreate"; "/dev/sda2"];
+ ["pvcreate"; "/dev/sda3"];
+ ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
+ "list the LVM physical volumes (PVs)",
+ "\
+List all the physical volumes detected. This is the equivalent
+of the L<pvs(8)> command.
+
+This returns a list of just the device names that contain
+PVs (eg. C</dev/sda2>).
+
+See also C<guestfs_pvs_full>.");
+
+ ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
+ [InitBasicFSonLVM, Always, TestOutputList (
+ [["vgs"]], ["VG"]);
+ InitEmpty, Always, TestOutputList (
+ [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
+ ["pvcreate"; "/dev/sda1"];
+ ["pvcreate"; "/dev/sda2"];
+ ["pvcreate"; "/dev/sda3"];
+ ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
+ ["vgcreate"; "VG2"; "/dev/sda3"];
+ ["vgs"]], ["VG1"; "VG2"])],
+ "list the LVM volume groups (VGs)",
+ "\
+List all the volumes groups detected. This is the equivalent
+of the L<vgs(8)> command.
+
+This returns a list of just the volume group names that were
+detected (eg. C<VolGroup00>).
+
+See also C<guestfs_vgs_full>.");
+
+ ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
+ [InitBasicFSonLVM, Always, TestOutputList (
+ [["lvs"]], ["/dev/VG/LV"]);
+ InitEmpty, Always, TestOutputList (
+ [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
+ ["pvcreate"; "/dev/sda1"];
+ ["pvcreate"; "/dev/sda2"];
+ ["pvcreate"; "/dev/sda3"];
+ ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
+ ["vgcreate"; "VG2"; "/dev/sda3"];
+ ["lvcreate"; "LV1"; "VG1"; "50"];
+ ["lvcreate"; "LV2"; "VG1"; "50"];
+ ["lvcreate"; "LV3"; "VG2"; "50"];
+ ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
+ "list the LVM logical volumes (LVs)",
+ "\
+List all the logical volumes detected. This is the equivalent
+of the L<lvs(8)> command.
+
+This returns a list of the logical volume device names
+(eg. C</dev/VolGroup00/LogVol00>).
+
+See also C<guestfs_lvs_full>.");
+
+ ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
+ [], (* XXX how to test? *)
+ "list the LVM physical volumes (PVs)",
+ "\
+List all the physical volumes detected. This is the equivalent
+of the L<pvs(8)> command. The \"full\" version includes all fields.");
+
+ ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
+ [], (* XXX how to test? *)
+ "list the LVM volume groups (VGs)",
+ "\
+List all the volumes groups detected. This is the equivalent
+of the L<vgs(8)> command. The \"full\" version includes all fields.");
+
+ ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
+ [], (* XXX how to test? *)
+ "list the LVM logical volumes (LVs)",
+ "\
+List all the logical volumes detected. This is the equivalent
+of the L<lvs(8)> command. The \"full\" version includes all fields.");
+
+ ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
+ [InitISOFS, Always, TestOutputList (
+ [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
+ InitISOFS, Always, TestOutputList (
+ [["read_lines"; "/empty"]], [])],
+ "read file as lines",
+ "\
+Return the contents of the file named C<path>.
+
+The file contents are returned as a list of lines. Trailing
+C<LF> and C<CRLF> character sequences are I<not> returned.
+
+Note that this function cannot correctly handle binary files
+(specifically, files containing C<\\0> character which is treated
+as end of line). For those you need to use the C<guestfs_read_file>
+function which has a more complex interface.");
+
+ ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
+ [], (* XXX Augeas code needs tests. *)
+ "create a new Augeas handle",
+ "\
+Create a new Augeas handle for editing configuration files.
+If there was any previous Augeas handle associated with this
+guestfs session, then it is closed.
+
+You must call this before using any other C<guestfs_aug_*>
+commands.
+
+C<root> is the filesystem root. C<root> must not be NULL,
+use C</> instead.
+
+The flags are the same as the flags defined in
+E<lt>augeas.hE<gt>, the logical I<or> of the following
+integers:
+
+=over 4
+
+=item C<AUG_SAVE_BACKUP> = 1
+
+Keep the original file with a C<.augsave> extension.
+
+=item C<AUG_SAVE_NEWFILE> = 2
+
+Save changes into a file with extension C<.augnew>, and
+do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
+
+=item C<AUG_TYPE_CHECK> = 4
+
+Typecheck lenses (can be expensive).
+
+=item C<AUG_NO_STDINC> = 8
+
+Do not use standard load path for modules.
+
+=item C<AUG_SAVE_NOOP> = 16
+
+Make save a no-op, just record what would have been changed.
+
+=item C<AUG_NO_LOAD> = 32
+
+Do not load the tree in C<guestfs_aug_init>.
+
+=back
+
+To close the handle, you can call C<guestfs_aug_close>.
+
+To find out more about Augeas, see L<http://augeas.net/>.");
+
+ ("aug_close", (RErr, []), 26, [Optional "augeas"],
+ [], (* XXX Augeas code needs tests. *)
+ "close the current Augeas handle",
+ "\
+Close the current Augeas handle and free up any resources
+used by it. After calling this, you have to call
+C<guestfs_aug_init> again before you can use any other
+Augeas functions.");
+
+ ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
+ [], (* XXX Augeas code needs tests. *)
+ "define an Augeas variable",
+ "\
+Defines an Augeas variable C<name> whose value is the result
+of evaluating C<expr>. If C<expr> is NULL, then C<name> is
+undefined.
+
+On success this returns the number of nodes in C<expr>, or
+C<0> if C<expr> evaluates to something which is not a nodeset.");
+
+ ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
+ [], (* XXX Augeas code needs tests. *)
+ "define an Augeas node",
+ "\
+Defines a variable C<name> whose value is the result of
+evaluating C<expr>.
+
+If C<expr> evaluates to an empty nodeset, a node is created,
+equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
+C<name> will be the nodeset containing that single node.
+
+On success this returns a pair containing the
+number of nodes in the nodeset, and a boolean flag
+if a node was created.");
+
+ ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
+ [], (* XXX Augeas code needs tests. *)
+ "look up the value of an Augeas path",
+ "\
+Look up the value associated with C<path>. If C<path>
+matches exactly one node, the C<value> is returned.");
+
+ ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
+ [], (* XXX Augeas code needs tests. *)
+ "set Augeas path to value",
+ "\
+Set the value associated with C<path> to C<val>.
+
+In the Augeas API, it is possible to clear a node by setting
+the value to NULL. Due to an oversight in the libguestfs API
+you cannot do that with this call. Instead you must use the
+C<guestfs_aug_clear> call.");
+
+ ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
+ [], (* XXX Augeas code needs tests. *)
+ "insert a sibling Augeas node",
+ "\
+Create a new sibling C<label> for C<path>, inserting it into
+the tree before or after C<path> (depending on the boolean
+flag C<before>).
+
+C<path> must match exactly one existing node in the tree, and
+C<label> must be a label, ie. not contain C</>, C<*> or end
+with a bracketed index C<[N]>.");
+
+ ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
+ [], (* XXX Augeas code needs tests. *)
+ "remove an Augeas path",
+ "\
+Remove C<path> and all of its children.
+
+On success this returns the number of entries which were removed.");
+
+ ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
+ [], (* XXX Augeas code needs tests. *)
+ "move Augeas node",
+ "\
+Move the node C<src> to C<dest>. C<src> must match exactly
+one node. C<dest> is overwritten if it exists.");
+
+ ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
+ [], (* XXX Augeas code needs tests. *)
+ "return Augeas nodes which match augpath",
+ "\
+Returns a list of paths which match the path expression C<path>.
+The returned paths are sufficiently qualified so that they match
+exactly one node in the current tree.");
+
+ ("aug_save", (RErr, []), 25, [Optional "augeas"],
+ [], (* XXX Augeas code needs tests. *)
+ "write all pending Augeas changes to disk",
+ "\
+This writes all pending changes to disk.
+
+The flags which were passed to C<guestfs_aug_init> affect exactly
+how files are saved.");
+
+ ("aug_load", (RErr, []), 27, [Optional "augeas"],
+ [], (* XXX Augeas code needs tests. *)
+ "load files into the tree",
+ "\
+Load files into the tree.
+
+See C<aug_load> in the Augeas documentation for the full gory
+details.");
+
+ ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
+ [], (* XXX Augeas code needs tests. *)
+ "list Augeas nodes under augpath",
+ "\
+This is just a shortcut for listing C<guestfs_aug_match>
+C<path/*> and sorting the resulting nodes into alphabetical order.");
+
+ ("rm", (RErr, [Pathname "path"]), 29, [],
+ [InitBasicFS, Always, TestRun
+ [["touch"; "/new"];
+ ["rm"; "/new"]];
+ InitBasicFS, Always, TestLastFail
+ [["rm"; "/new"]];
+ InitBasicFS, Always, TestLastFail
+ [["mkdir"; "/new"];
+ ["rm"; "/new"]]],
+ "remove a file",
+ "\
+Remove the single file C<path>.");
+
+ ("rmdir", (RErr, [Pathname "path"]), 30, [],
+ [InitBasicFS, Always, TestRun
+ [["mkdir"; "/new"];
+ ["rmdir"; "/new"]];
+ InitBasicFS, Always, TestLastFail
+ [["rmdir"; "/new"]];
+ InitBasicFS, Always, TestLastFail
+ [["touch"; "/new"];
+ ["rmdir"; "/new"]]],
+ "remove a directory",
+ "\
+Remove the single directory C<path>.");
+
+ ("rm_rf", (RErr, [Pathname "path"]), 31, [],
+ [InitBasicFS, Always, TestOutputFalse
+ [["mkdir"; "/new"];
+ ["mkdir"; "/new/foo"];
+ ["touch"; "/new/foo/bar"];
+ ["rm_rf"; "/new"];
+ ["exists"; "/new"]]],
+ "remove a file or directory recursively",
+ "\
+Remove the file or directory C<path>, recursively removing the
+contents if its a directory. This is like the C<rm -rf> shell
+command.");
+
+ ("mkdir", (RErr, [Pathname "path"]), 32, [],
+ [InitBasicFS, Always, TestOutputTrue
+ [["mkdir"; "/new"];
+ ["is_dir"; "/new"]];
+ InitBasicFS, Always, TestLastFail
+ [["mkdir"; "/new/foo/bar"]]],
+ "create a directory",
+ "\
+Create a directory named C<path>.");
+
+ ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
+ [InitBasicFS, Always, TestOutputTrue
+ [["mkdir_p"; "/new/foo/bar"];
+ ["is_dir"; "/new/foo/bar"]];
+ InitBasicFS, Always, TestOutputTrue
+ [["mkdir_p"; "/new/foo/bar"];
+ ["is_dir"; "/new/foo"]];
+ InitBasicFS, Always, TestOutputTrue
+ [["mkdir_p"; "/new/foo/bar"];
+ ["is_dir"; "/new"]];
+ (* Regression tests for RHBZ#503133: *)
+ InitBasicFS, Always, TestRun
+ [["mkdir"; "/new"];
+ ["mkdir_p"; "/new"]];
+ InitBasicFS, Always, TestLastFail
+ [["touch"; "/new"];
+ ["mkdir_p"; "/new"]]],
+ "create a directory and parents",
+ "\
+Create a directory named C<path>, creating any parent directories
+as necessary. This is like the C<mkdir -p> shell command.");
+
+ ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
+ [], (* XXX Need stat command to test *)
+ "change file mode",
+ "\
+Change the mode (permissions) of C<path> to C<mode>. Only
+numeric modes are supported.
+
+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>.
+
+The mode actually set is affected by the umask.");
+
+ ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
+ [], (* XXX Need stat command to test *)
+ "change file owner and group",
+ "\
+Change the file owner to C<owner> and group to C<group>.
+
+Only numeric uid and gid are supported. If you want to use
+names, you will need to locate and parse the password file
+yourself (Augeas support makes this relatively easy).");
+
+ ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
+ [InitISOFS, Always, TestOutputTrue (
+ [["exists"; "/empty"]]);
+ InitISOFS, Always, TestOutputTrue (
+ [["exists"; "/directory"]])],
+ "test if file or directory exists",
+ "\
+This returns C<true> if and only if there is a file, directory
+(or anything) with the given C<path> name.
+
+See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
+
+ ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
+ [InitISOFS, Always, TestOutputTrue (
+ [["is_file"; "/known-1"]]);
+ InitISOFS, Always, TestOutputFalse (
+ [["is_file"; "/directory"]])],
+ "test if file exists",
+ "\
+This returns C<true> if and only if there is a file
+with the given C<path> name. Note that it returns false for
+other objects like directories.
+
+See also C<guestfs_stat>.");
+
+ ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
+ [InitISOFS, Always, TestOutputFalse (
+ [["is_dir"; "/known-3"]]);
+ InitISOFS, Always, TestOutputTrue (
+ [["is_dir"; "/directory"]])],
+ "test if file exists",
+ "\
+This returns C<true> if and only if there is a directory
+with the given C<path> name. Note that it returns false for
+other objects like files.
+
+See also C<guestfs_stat>.");
+
+ ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
+ [InitEmpty, Always, TestOutputListOfDevices (
+ [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
+ ["pvcreate"; "/dev/sda1"];
+ ["pvcreate"; "/dev/sda2"];
+ ["pvcreate"; "/dev/sda3"];
+ ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
+ "create an LVM physical volume",
+ "\
+This creates an LVM physical volume on the named C<device>,
+where C<device> should usually be a partition name such
+as C</dev/sda1>.");
+
+ ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
+ [InitEmpty, Always, TestOutputList (
+ [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
+ ["pvcreate"; "/dev/sda1"];
+ ["pvcreate"; "/dev/sda2"];
+ ["pvcreate"; "/dev/sda3"];
+ ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
+ ["vgcreate"; "VG2"; "/dev/sda3"];
+ ["vgs"]], ["VG1"; "VG2"])],
+ "create an LVM volume group",
+ "\
+This creates an LVM volume group called C<volgroup>
+from the non-empty list of physical volumes C<physvols>.");
+
+ ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
+ [InitEmpty, Always, TestOutputList (
+ [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
+ ["pvcreate"; "/dev/sda1"];
+ ["pvcreate"; "/dev/sda2"];
+ ["pvcreate"; "/dev/sda3"];
+ ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
+ ["vgcreate"; "VG2"; "/dev/sda3"];
+ ["lvcreate"; "LV1"; "VG1"; "50"];
+ ["lvcreate"; "LV2"; "VG1"; "50"];
+ ["lvcreate"; "LV3"; "VG2"; "50"];
+ ["lvcreate"; "LV4"; "VG2"; "50"];
+ ["lvcreate"; "LV5"; "VG2"; "50"];
+ ["lvs"]],
+ ["/dev/VG1/LV1"; "/dev/VG1/LV2";
+ "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
+ "create an LVM logical volume",
+ "\
+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, [],
+ [InitEmpty, Always, TestOutput (
+ [["part_disk"; "/dev/sda"; "mbr"];
+ ["mkfs"; "ext2"; "/dev/sda1"];
+ ["mount_options"; ""; "/dev/sda1"; "/"];
+ ["write"; "/new"; "new file contents"];
+ ["cat"; "/new"]], "new file contents")],
+ "make a filesystem",
+ "\
+This creates a filesystem on C<device> (usually a partition
+or LVM logical volume). The filesystem type is C<fstype>, for
+example C<ext3>.");
+
+ ("sfdisk", (RErr, [Device "device";
+ Int "cyls"; Int "heads"; Int "sectors";
+ StringList "lines"]), 43, [DangerWillRobinson],
+ [],
+ "create partitions on a block device",
+ "\
+This is a direct interface to the L<sfdisk(8)> program for creating
+partitions on block devices.
+
+C<device> should be a block device, for example C</dev/sda>.
+
+C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
+and sectors on the device, which are passed directly to sfdisk as
+the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
+of these, then the corresponding parameter is omitted. Usually for
+'large' disks, you can just pass C<0> for these, but for small
+(floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
+out the right geometry and you will need to tell it.
+
+C<lines> is a list of lines that we feed to C<sfdisk>. For more
+information refer to the L<sfdisk(8)> manpage.
+
+To create a single partition occupying the whole disk, you would
+pass C<lines> as a single element list, when the single element being
+the string C<,> (comma).
+
+See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
+C<guestfs_part_init>");
+
+ ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning; DeprecatedBy "write"],
+ (* Regression test for RHBZ#597135. *)
+ [InitBasicFS, Always, TestLastFail
+ [["write_file"; "/new"; "abc"; "10000"]]],
+ "create a file",
+ "\
+This call creates a file called C<path>. The contents of the
+file is the string C<content> (which can contain any 8 bit data),
+with length C<size>.
+
+As a special case, if C<size> is C<0>
+then the length is calculated using C<strlen> (so in this case
+the content cannot contain embedded ASCII NULs).
+
+I<NB.> Owing to a bug, writing content containing ASCII NUL
+characters does I<not> work, even if the length is specified.");
+
+ ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
+ [InitEmpty, Always, TestOutputListOfDevices (
+ [["part_disk"; "/dev/sda"; "mbr"];
+ ["mkfs"; "ext2"; "/dev/sda1"];
+ ["mount_options"; ""; "/dev/sda1"; "/"];
+ ["mounts"]], ["/dev/sda1"]);
+ InitEmpty, Always, TestOutputList (
+ [["part_disk"; "/dev/sda"; "mbr"];
+ ["mkfs"; "ext2"; "/dev/sda1"];
+ ["mount_options"; ""; "/dev/sda1"; "/"];
+ ["umount"; "/"];
+ ["mounts"]], [])],
+ "unmount a filesystem",
+ "\
+This unmounts the given filesystem. The filesystem may be
+specified either by its mountpoint (path) or the device which
+contains the filesystem.");
+
+ ("mounts", (RStringList "devices", []), 46, [],
+ [InitBasicFS, Always, TestOutputListOfDevices (
+ [["mounts"]], ["/dev/sda1"])],
+ "show mounted filesystems",
+ "\
+This returns the list of currently mounted filesystems. It returns
+the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
+
+Some internal mounts are not shown.
+
+See also: C<guestfs_mountpoints>");
+
+ ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
+ [InitBasicFS, Always, TestOutputList (
+ [["umount_all"];
+ ["mounts"]], []);
+ (* check that umount_all can unmount nested mounts correctly: *)
+ InitEmpty, Always, TestOutputList (
+ [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
+ ["mkfs"; "ext2"; "/dev/sda1"];
+ ["mkfs"; "ext2"; "/dev/sda2"];
+ ["mkfs"; "ext2"; "/dev/sda3"];
+ ["mount_options"; ""; "/dev/sda1"; "/"];
+ ["mkdir"; "/mp1"];
+ ["mount_options"; ""; "/dev/sda2"; "/mp1"];
+ ["mkdir"; "/mp1/mp2"];
+ ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
+ ["mkdir"; "/mp1/mp2/mp3"];
+ ["umount_all"];
+ ["mounts"]], [])],
+ "unmount all filesystems",
+ "\
+This unmounts all mounted filesystems.
+
+Some internal mounts are not unmounted by this call.");
+
+ ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
+ [],
+ "remove all LVM LVs, VGs and PVs",
+ "\
+This command removes all LVM logical volumes, volume groups
+and physical volumes.");
+
+ ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
+ [InitISOFS, Always, TestOutput (
+ [["file"; "/empty"]], "empty");
+ InitISOFS, Always, TestOutput (
+ [["file"; "/known-1"]], "ASCII text");
+ InitISOFS, Always, TestLastFail (
+ [["file"; "/notexists"]]);
+ InitISOFS, Always, TestOutput (
+ [["file"; "/abssymlink"]], "symbolic link");
+ InitISOFS, Always, TestOutput (
+ [["file"; "/directory"]], "directory")],
+ "determine file type",
+ "\
+This call uses the standard L<file(1)> command to determine
+the type or contents of the file.
+
+This call will also transparently look inside various types
+of compressed file.
+
+The exact command which runs is C<file -zb path>. Note in
+particular that the filename is not prepended to the output
+(the C<-b> option).
+
+This command can also be used on C</dev/> devices
+(and partitions, LV names). You can for example use this
+to determine if a device contains a filesystem, although
+it's usually better to use C<guestfs_vfs_type>.
+
+If the C<path> does not begin with C</dev/> then
+this command only works for the content of regular files.
+For other file types (directory, symbolic link etc) it
+will just return the string C<directory> etc.");
+
+ ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
+ [InitBasicFS, Always, TestOutput (
+ [["upload"; "test-command"; "/test-command"];
+ ["chmod"; "0o755"; "/test-command"];
+ ["command"; "/test-command 1"]], "Result1");
+ InitBasicFS, Always, TestOutput (
+ [["upload"; "test-command"; "/test-command"];
+ ["chmod"; "0o755"; "/test-command"];
+ ["command"; "/test-command 2"]], "Result2\n");
+ InitBasicFS, Always, TestOutput (
+ [["upload"; "test-command"; "/test-command"];
+ ["chmod"; "0o755"; "/test-command"];
+ ["command"; "/test-command 3"]], "\nResult3");
+ InitBasicFS, Always, TestOutput (
+ [["upload"; "test-command"; "/test-command"];
+ ["chmod"; "0o755"; "/test-command"];
+ ["command"; "/test-command 4"]], "\nResult4\n");
+ InitBasicFS, Always, TestOutput (
+ [["upload"; "test-command"; "/test-command"];
+ ["chmod"; "0o755"; "/test-command"];
+ ["command"; "/test-command 5"]], "\nResult5\n\n");
+ InitBasicFS, Always, TestOutput (
+ [["upload"; "test-command"; "/test-command"];
+ ["chmod"; "0o755"; "/test-command"];
+ ["command"; "/test-command 6"]], "\n\nResult6\n\n");
+ InitBasicFS, Always, TestOutput (
+ [["upload"; "test-command"; "/test-command"];
+ ["chmod"; "0o755"; "/test-command"];
+ ["command"; "/test-command 7"]], "");
+ InitBasicFS, Always, TestOutput (
+ [["upload"; "test-command"; "/test-command"];
+ ["chmod"; "0o755"; "/test-command"];
+ ["command"; "/test-command 8"]], "\n");
+ InitBasicFS, Always, TestOutput (
+ [["upload"; "test-command"; "/test-command"];
+ ["chmod"; "0o755"; "/test-command"];
+ ["command"; "/test-command 9"]], "\n\n");
+ InitBasicFS, Always, TestOutput (
+ [["upload"; "test-command"; "/test-command"];
+ ["chmod"; "0o755"; "/test-command"];
+ ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
+ InitBasicFS, Always, TestOutput (
+ [["upload"; "test-command"; "/test-command"];
+ ["chmod"; "0o755"; "/test-command"];
+ ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
+ InitBasicFS, Always, TestLastFail (
+ [["upload"; "test-command"; "/test-command"];
+ ["chmod"; "0o755"; "/test-command"];
+ ["command"; "/test-command"]])],
+ "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). Note that
+the command runs directly, and is I<not> invoked via
+the shell (see C<guestfs_sh>).
+
+The return value is anything printed to I<stdout> by
+the command.
+
+If the command returns a non-zero exit status, then
+this function returns an error message. The error message
+string is the content of I<stderr> from the command.
+
+The C<$PATH> environment variable will contain at least
+C</usr/bin> and C</bin>. 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, [ProtocolLimitWarning],
+ [InitBasicFS, Always, TestOutputList (
+ [["upload"; "test-command"; "/test-command"];
+ ["chmod"; "0o755"; "/test-command"];
+ ["command_lines"; "/test-command 1"]], ["Result1"]);
+ InitBasicFS, Always, TestOutputList (
+ [["upload"; "test-command"; "/test-command"];
+ ["chmod"; "0o755"; "/test-command"];
+ ["command_lines"; "/test-command 2"]], ["Result2"]);
+ InitBasicFS, Always, TestOutputList (
+ [["upload"; "test-command"; "/test-command"];
+ ["chmod"; "0o755"; "/test-command"];
+ ["command_lines"; "/test-command 3"]], ["";"Result3"]);
+ InitBasicFS, Always, TestOutputList (
+ [["upload"; "test-command"; "/test-command"];
+ ["chmod"; "0o755"; "/test-command"];
+ ["command_lines"; "/test-command 4"]], ["";"Result4"]);
+ InitBasicFS, Always, TestOutputList (
+ [["upload"; "test-command"; "/test-command"];
+ ["chmod"; "0o755"; "/test-command"];
+ ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
+ InitBasicFS, Always, TestOutputList (
+ [["upload"; "test-command"; "/test-command"];
+ ["chmod"; "0o755"; "/test-command"];
+ ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
+ InitBasicFS, Always, TestOutputList (
+ [["upload"; "test-command"; "/test-command"];
+ ["chmod"; "0o755"; "/test-command"];
+ ["command_lines"; "/test-command 7"]], []);
+ InitBasicFS, Always, TestOutputList (
+ [["upload"; "test-command"; "/test-command"];
+ ["chmod"; "0o755"; "/test-command"];
+ ["command_lines"; "/test-command 8"]], [""]);
+ InitBasicFS, Always, TestOutputList (
+ [["upload"; "test-command"; "/test-command"];
+ ["chmod"; "0o755"; "/test-command"];
+ ["command_lines"; "/test-command 9"]], ["";""]);
+ InitBasicFS, Always, TestOutputList (
+ [["upload"; "test-command"; "/test-command"];
+ ["chmod"; "0o755"; "/test-command"];
+ ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
+ InitBasicFS, Always, TestOutputList (
+ [["upload"; "test-command"; "/test-command"];
+ ["chmod"; "0o755"; "/test-command"];
+ ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
+ "run a command, returning lines",
+ "\
+This is the same as C<guestfs_command>, but splits the
+result into a list of lines.
+
+See also: C<guestfs_sh_lines>");
+
+ ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
+ [InitISOFS, Always, TestOutputStruct (
+ [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
+ "get file information",
+ "\
+Returns file information for the given C<path>.
+
+This is the same as the C<stat(2)> system call.");
+
+ ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
+ [InitISOFS, Always, TestOutputStruct (
+ [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
+ "get file information for a symbolic link",
+ "\
+Returns file information for the given C<path>.
+
+This is the same as C<guestfs_stat> except that if C<path>
+is a symbolic link, then the link is stat-ed, not the file it
+refers to.
+
+This is the same as the C<lstat(2)> system call.");
+
+ ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
+ [InitISOFS, Always, TestOutputStruct (
+ [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
+ "get file system statistics",
+ "\
+Returns file system statistics for any mounted file system.
+C<path> 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<statvfs(2)> system call.");
+
+ ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
+ [], (* XXX test *)
+ "get ext2/ext3/ext4 superblock details",
+ "\
+This returns the contents of the ext2, ext3 or ext4 filesystem
+superblock on C<device>.
+
+It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
+manpage for more details. The list of fields returned isn't
+clearly defined, and depends on both the version of C<tune2fs>
+that libguestfs was built against, and the filesystem itself.");
+
+ ("blockdev_setro", (RErr, [Device "device"]), 56, [],
+ [InitEmpty, Always, TestOutputTrue (
+ [["blockdev_setro"; "/dev/sda"];
+ ["blockdev_getro"; "/dev/sda"]])],
+ "set block device to read-only",
+ "\
+Sets the block device named C<device> to read-only.
+
+This uses the L<blockdev(8)> command.");
+
+ ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
+ [InitEmpty, Always, TestOutputFalse (
+ [["blockdev_setrw"; "/dev/sda"];
+ ["blockdev_getro"; "/dev/sda"]])],
+ "set block device to read-write",
+ "\
+Sets the block device named C<device> to read-write.
+
+This uses the L<blockdev(8)> command.");
+
+ ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
+ [InitEmpty, Always, 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<blockdev(8)> command.");
+
+ ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
+ [InitEmpty, Always, 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<guestfs_blockdev_getsz>
+for that).
+
+This uses the L<blockdev(8)> command.");
+
+ ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
+ [InitEmpty, Always, 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<size in blocks> and
+I<filesystem block size>).
+
+This uses the L<blockdev(8)> command.");
+
+ ("blockdev_setbsz", (RErr, [Device "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<size in blocks> and
+I<filesystem block size>).
+
+This uses the L<blockdev(8)> command.");
+
+ ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
+ [InitEmpty, Always, 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<guestfs_blockdev_getss> for the real sector size of
+the device, and C<guestfs_blockdev_getsize64> for the more
+useful I<size in bytes>.
+
+This uses the L<blockdev(8)> command.");
+
+ ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
+ [InitEmpty, Always, 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<guestfs_blockdev_getsz>.
+
+This uses the L<blockdev(8)> command.");
+
+ ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
+ [InitEmpty, Always, TestRun
+ [["blockdev_flushbufs"; "/dev/sda"]]],
+ "flush device buffers",
+ "\
+This tells the kernel to flush internal buffers associated
+with C<device>.
+
+This uses the L<blockdev(8)> command.");
+
+ ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
+ [InitEmpty, Always, TestRun
+ [["blockdev_rereadpt"; "/dev/sda"]]],
+ "reread partition table",
+ "\
+Reread the partition table on C<device>.
+
+This uses the L<blockdev(8)> command.");
+
+ ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
+ [InitBasicFS, Always, TestOutput (
+ (* Pick a file from cwd which isn't likely to change. *)
+ [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
+ ["checksum"; "md5"; "/COPYING.LIB"]],
+ Digest.to_hex (Digest.file "COPYING.LIB"))],
+ "upload a file from the local machine",
+ "\
+Upload local file C<filename> to C<remotefilename> on the
+filesystem.
+
+C<filename> can also be a named pipe.
+
+See also C<guestfs_download>.");
+
+ ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [Progress],
+ [InitBasicFS, Always, 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"]],
+ Digest.to_hex (Digest.file "COPYING.LIB"))],
+ "download a file to the local machine",
+ "\
+Download file C<remotefilename> and save it as C<filename>
+on the local machine.
+
+C<filename> can also be a named pipe.
+
+See also C<guestfs_upload>, C<guestfs_cat>.");
+
+ ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
+ [InitISOFS, Always, TestOutput (
+ [["checksum"; "crc"; "/known-3"]], "2891671662");
+ InitISOFS, Always, TestLastFail (
+ [["checksum"; "crc"; "/notexists"]]);
+ InitISOFS, Always, TestOutput (
+ [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
+ InitISOFS, Always, TestOutput (
+ [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
+ InitISOFS, Always, TestOutput (
+ [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
+ InitISOFS, Always, TestOutput (
+ [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
+ InitISOFS, Always, TestOutput (
+ [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
+ InitISOFS, Always, TestOutput (
+ [["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
+file named C<path>.
+
+The type of checksum to compute is given by the C<csumtype>
+parameter which must have one of the following values:
+
+=over 4
+
+=item C<crc>
+
+Compute the cyclic redundancy check (CRC) specified by POSIX
+for the C<cksum> command.
+
+=item C<md5>
+
+Compute the MD5 hash (using the C<md5sum> program).
+
+=item C<sha1>
+
+Compute the SHA1 hash (using the C<sha1sum> program).
+
+=item C<sha224>
+
+Compute the SHA224 hash (using the C<sha224sum> program).
+
+=item C<sha256>
+
+Compute the SHA256 hash (using the C<sha256sum> program).
+
+=item C<sha384>
+
+Compute the SHA384 hash (using the C<sha384sum> program).
+
+=item C<sha512>
+
+Compute the SHA512 hash (using the C<sha512sum> program).
+
+=back
+
+The checksum is returned as a printable string.
+
+To get the checksum for a device, use C<guestfs_checksum_device>.
+
+To get the checksums for many files, use C<guestfs_checksums_out>.");
+
+ ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
+ [InitBasicFS, Always, TestOutput (
+ [["tar_in"; "../images/helloworld.tar"; "/"];
+ ["cat"; "/hello"]], "hello\n")],
+ "unpack tarfile to directory",
+ "\
+This command uploads and unpacks local file C<tarfile> (an
+I<uncompressed> tar file) into C<directory>.
+
+To upload a compressed tarball, use C<guestfs_tgz_in>
+or C<guestfs_txz_in>.");
+
+ ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
+ [],
+ "pack directory into tarfile",
+ "\
+This command packs the contents of C<directory> and downloads
+it to local file C<tarfile>.
+
+To download a compressed tarball, use C<guestfs_tgz_out>
+or C<guestfs_txz_out>.");
+
+ ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
+ [InitBasicFS, Always, TestOutput (
+ [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
+ ["cat"; "/hello"]], "hello\n")],
+ "unpack compressed tarball to directory",
+ "\
+This command uploads and unpacks local file C<tarball> (a
+I<gzip compressed> tar file) into C<directory>.
+
+To upload an uncompressed tarball, use C<guestfs_tar_in>.");
+
+ ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
+ [],
+ "pack directory into compressed tarball",
+ "\
+This command packs the contents of C<directory> and downloads
+it to local file C<tarball>.
+
+To download an uncompressed tarball, use C<guestfs_tar_out>.");
+
+ ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
+ [InitBasicFS, Always, TestLastFail (
+ [["umount"; "/"];
+ ["mount_ro"; "/dev/sda1"; "/"];
+ ["touch"; "/new"]]);
+ InitBasicFS, Always, TestOutput (
+ [["write"; "/new"; "data"];
+ ["umount"; "/"];
+ ["mount_ro"; "/dev/sda1"; "/"];
+ ["cat"; "/new"]], "data")],
+ "mount a guest disk, read-only",
+ "\
+This is the same as the C<guestfs_mount> command, but it
+mounts the filesystem with the read-only (I<-o ro>) flag.");
+
+ ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
+ [],
+ "mount a guest disk with mount options",
+ "\
+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.
+
+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 a guest disk with mount options and vfstype",
+ "\
+This is the same as the C<guestfs_mount> command, but it
+allows you to set both the mount options and the vfstype
+as for the L<mount(8)> I<-o> and I<-t> flags.");
+
+ ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
+ [],
+ "debugging and internals",
+ "\
+The C<guestfs_debug> command exposes some internals of
+C<guestfsd> (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<daemon/debug.c> in the libguestfs source
+to find out what you can do.");
+
+ ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
+ [InitEmpty, Always, TestOutputList (
+ [["part_disk"; "/dev/sda"; "mbr"];
+ ["pvcreate"; "/dev/sda1"];
+ ["vgcreate"; "VG"; "/dev/sda1"];
+ ["lvcreate"; "LV1"; "VG"; "50"];
+ ["lvcreate"; "LV2"; "VG"; "50"];
+ ["lvremove"; "/dev/VG/LV1"];
+ ["lvs"]], ["/dev/VG/LV2"]);
+ InitEmpty, Always, TestOutputList (
+ [["part_disk"; "/dev/sda"; "mbr"];
+ ["pvcreate"; "/dev/sda1"];
+ ["vgcreate"; "VG"; "/dev/sda1"];
+ ["lvcreate"; "LV1"; "VG"; "50"];
+ ["lvcreate"; "LV2"; "VG"; "50"];
+ ["lvremove"; "/dev/VG"];
+ ["lvs"]], []);
+ InitEmpty, Always, TestOutputList (
+ [["part_disk"; "/dev/sda"; "mbr"];
+ ["pvcreate"; "/dev/sda1"];
+ ["vgcreate"; "VG"; "/dev/sda1"];
+ ["lvcreate"; "LV1"; "VG"; "50"];
+ ["lvcreate"; "LV2"; "VG"; "50"];
+ ["lvremove"; "/dev/VG"];
+ ["vgs"]], ["VG"])],
+ "remove an LVM logical volume",
+ "\
+Remove an LVM logical volume C<device>, where C<device> is
+the path to the LV, such as C</dev/VG/LV>.
+
+You can also remove all LVs in a volume group by specifying
+the VG name, C</dev/VG>.");
+
+ ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
+ [InitEmpty, Always, TestOutputList (
+ [["part_disk"; "/dev/sda"; "mbr"];
+ ["pvcreate"; "/dev/sda1"];
+ ["vgcreate"; "VG"; "/dev/sda1"];
+ ["lvcreate"; "LV1"; "VG"; "50"];
+ ["lvcreate"; "LV2"; "VG"; "50"];
+ ["vgremove"; "VG"];
+ ["lvs"]], []);
+ InitEmpty, Always, TestOutputList (
+ [["part_disk"; "/dev/sda"; "mbr"];
+ ["pvcreate"; "/dev/sda1"];
+ ["vgcreate"; "VG"; "/dev/sda1"];
+ ["lvcreate"; "LV1"; "VG"; "50"];
+ ["lvcreate"; "LV2"; "VG"; "50"];
+ ["vgremove"; "VG"];
+ ["vgs"]], [])],
+ "remove an LVM volume group",
+ "\
+Remove an LVM volume group C<vgname>, (for example C<VG>).
+
+This also forcibly removes all logical volumes in the volume
+group (if any).");
+
+ ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
+ [InitEmpty, Always, TestOutputListOfDevices (
+ [["part_disk"; "/dev/sda"; "mbr"];
+ ["pvcreate"; "/dev/sda1"];
+ ["vgcreate"; "VG"; "/dev/sda1"];
+ ["lvcreate"; "LV1"; "VG"; "50"];
+ ["lvcreate"; "LV2"; "VG"; "50"];
+ ["vgremove"; "VG"];
+ ["pvremove"; "/dev/sda1"];
+ ["lvs"]], []);
+ InitEmpty, Always, TestOutputListOfDevices (
+ [["part_disk"; "/dev/sda"; "mbr"];
+ ["pvcreate"; "/dev/sda1"];
+ ["vgcreate"; "VG"; "/dev/sda1"];
+ ["lvcreate"; "LV1"; "VG"; "50"];
+ ["lvcreate"; "LV2"; "VG"; "50"];
+ ["vgremove"; "VG"];
+ ["pvremove"; "/dev/sda1"];
+ ["vgs"]], []);
+ InitEmpty, Always, TestOutputListOfDevices (
+ [["part_disk"; "/dev/sda"; "mbr"];
+ ["pvcreate"; "/dev/sda1"];
+ ["vgcreate"; "VG"; "/dev/sda1"];
+ ["lvcreate"; "LV1"; "VG"; "50"];
+ ["lvcreate"; "LV2"; "VG"; "50"];
+ ["vgremove"; "VG"];
+ ["pvremove"; "/dev/sda1"];
+ ["pvs"]], [])],
+ "remove an LVM physical volume",
+ "\
+This wipes a physical volume C<device> so that LVM will no longer
+recognise it.
+
+The implementation uses the C<pvremove> command which refuses to
+wipe physical volumes that contain any volume groups, so you have
+to remove those first.");
+
+ ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
+ [InitBasicFS, Always, 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<device> to C<label>. Filesystem labels are limited to
+16 characters.
+
+You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
+to return the existing label on a filesystem.");
+
+ ("get_e2label", (RString "label", [Device "device"]), 81, [DeprecatedBy "vfs_label"],
+ [],
+ "get the ext2/3/4 filesystem label",
+ "\
+This returns the ext2/3/4 filesystem label of the filesystem on
+C<device>.");
+
+ ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
+ (let uuid = uuidgen () in
+ [InitBasicFS, Always, TestOutput (
+ [["set_e2uuid"; "/dev/sda1"; uuid];
+ ["get_e2uuid"; "/dev/sda1"]], uuid);
+ InitBasicFS, Always, TestOutput (
+ [["set_e2uuid"; "/dev/sda1"; "clear"];
+ ["get_e2uuid"; "/dev/sda1"]], "");
+ (* We can't predict what UUIDs will be, so just check the commands run. *)
+ InitBasicFS, Always, TestRun (
+ [["set_e2uuid"; "/dev/sda1"; "random"]]);
+ InitBasicFS, Always, TestRun (
+ [["set_e2uuid"; "/dev/sda1"; "time"]])]),
+ "set the ext2/3/4 filesystem UUID",
+ "\
+This sets the ext2/3/4 filesystem UUID of the filesystem on
+C<device> to C<uuid>. The format of the UUID and alternatives
+such as C<clear>, C<random> and C<time> are described in the
+L<tune2fs(8)> manpage.
+
+You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
+to return the existing UUID of a filesystem.");
+
+ ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [DeprecatedBy "vfs_uuid"],
+ (* Regression test for RHBZ#597112. *)
+ (let uuid = uuidgen () in
+ [InitBasicFS, Always, TestOutput (
+ [["mke2journal"; "1024"; "/dev/sdb"];
+ ["set_e2uuid"; "/dev/sdb"; uuid];
+ ["get_e2uuid"; "/dev/sdb"]], uuid)]),
+ "get the ext2/3/4 filesystem UUID",
+ "\
+This returns the ext2/3/4 filesystem UUID of the filesystem on
+C<device>.");
+
+ ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
+ [InitBasicFS, Always, TestOutputInt (
+ [["umount"; "/dev/sda1"];
+ ["fsck"; "ext2"; "/dev/sda1"]], 0);
+ InitBasicFS, Always, TestOutputInt (
+ [["umount"; "/dev/sda1"];
+ ["zero"; "/dev/sda1"];
+ ["fsck"; "ext2"; "/dev/sda1"]], 8)],
+ "run the filesystem checker",
+ "\
+This runs the filesystem checker (fsck) on C<device> which
+should have filesystem type C<fstype>.
+
+The returned integer is the status. See L<fsck(8)> for the
+list of status codes from C<fsck>.
+
+Notes:
+
+=over 4
+
+=item *
+
+Multiple status codes can be summed together.
+
+=item *
+
+A non-zero return code can mean \"success\", for example if
+errors have been corrected on the filesystem.
+
+=item *
+
+Checking or repairing NTFS volumes is not supported
+(by linux-ntfs).
+
+=back
+
+This command is entirely equivalent to running C<fsck -a -t fstype device>.");
+
+ ("zero", (RErr, [Device "device"]), 85, [Progress],
+ [InitBasicFS, Always, TestOutput (
+ [["umount"; "/dev/sda1"];
+ ["zero"; "/dev/sda1"];
+ ["file"; "/dev/sda1"]], "data")],
+ "write zeroes to the device",
+ "\
+This command writes zeroes over the first few blocks of C<device>.
+
+How many blocks are zeroed isn't specified (but it's I<not> enough
+to securely wipe the device). It should be sufficient to remove
+any partition tables, filesystem superblocks and so on.
+
+See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
+
+ ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
+ (* See:
+ * https://bugzilla.redhat.com/show_bug.cgi?id=484986
+ * https://bugzilla.redhat.com/show_bug.cgi?id=479760
+ *)
+ [InitBasicFS, Always, TestOutputTrue (
+ [["mkdir_p"; "/boot/grub"];
+ ["write"; "/boot/grub/device.map"; "(hd0) /dev/vda"];
+ ["grub_install"; "/"; "/dev/vda"];
+ ["is_dir"; "/boot"]])],
+ "install GRUB",
+ "\
+This command installs GRUB (the Grand Unified Bootloader) on
+C<device>, with the root directory being C<root>.
+
+Note: If grub-install reports the error
+\"No suitable drive was found in the generated device map.\"
+it may be that you need to create a C</boot/grub/device.map>
+file first that contains the mapping between grub device names
+and Linux device names. It is usually sufficient to create
+a file containing:
+
+ (hd0) /dev/vda
+
+replacing C</dev/vda> with the name of the installation device.");
+
+ ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
+ [InitBasicFS, Always, TestOutput (
+ [["write"; "/old"; "file content"];
+ ["cp"; "/old"; "/new"];
+ ["cat"; "/new"]], "file content");
+ InitBasicFS, Always, TestOutputTrue (
+ [["write"; "/old"; "file content"];
+ ["cp"; "/old"; "/new"];
+ ["is_file"; "/old"]]);
+ InitBasicFS, Always, TestOutput (
+ [["write"; "/old"; "file content"];
+ ["mkdir"; "/dir"];
+ ["cp"; "/old"; "/dir/new"];
+ ["cat"; "/dir/new"]], "file content")],
+ "copy a file",
+ "\
+This copies a file from C<src> to C<dest> where C<dest> is
+either a destination filename or destination directory.");
+
+ ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
+ [InitBasicFS, Always, TestOutput (
+ [["mkdir"; "/olddir"];
+ ["mkdir"; "/newdir"];
+ ["write"; "/olddir/file"; "file content"];
+ ["cp_a"; "/olddir"; "/newdir"];
+ ["cat"; "/newdir/olddir/file"]], "file content")],
+ "copy a file or directory recursively",
+ "\
+This copies a file or directory from C<src> to C<dest>
+recursively using the C<cp -a> command.");
+
+ ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
+ [InitBasicFS, Always, TestOutput (
+ [["write"; "/old"; "file content"];
+ ["mv"; "/old"; "/new"];
+ ["cat"; "/new"]], "file content");
+ InitBasicFS, Always, TestOutputFalse (
+ [["write"; "/old"; "file content"];
+ ["mv"; "/old"; "/new"];
+ ["is_file"; "/old"]])],
+ "move a file",
+ "\
+This moves a file from C<src> to C<dest> where C<dest> is
+either a destination filename or destination directory.");
+
+ ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
+ [InitEmpty, Always, TestRun (
+ [["drop_caches"; "3"]])],
+ "drop kernel page cache, dentries and inodes",
+ "\
+This instructs the guest kernel to drop its page cache,
+and/or dentries and inode caches. The parameter C<whattodrop>
+tells the kernel what precisely to drop, see
+L<http://linux-mm.org/Drop_Caches>
+
+Setting C<whattodrop> to 3 should drop everything.
+
+This automatically calls L<sync(2)> before the operation,
+so that the maximum guest memory is freed.");
+
+ ("dmesg", (RString "kmsgs", []), 91, [],
+ [InitEmpty, Always, TestRun (
+ [["dmesg"]])],
+ "return kernel messages",
+ "\
+This returns the kernel messages (C<dmesg> output) from
+the guest kernel. This is sometimes useful for extended
+debugging of problems.
+
+Another way to get the same information is to enable
+verbose messages with C<guestfs_set_verbose> or by setting
+the environment variable C<LIBGUESTFS_DEBUG=1> before
+running the program.");
+
+ ("ping_daemon", (RErr, []), 92, [],
+ [InitEmpty, Always, TestRun (
+ [["ping_daemon"]])],
+ "ping the guest daemon",
+ "\
+This is a test probe into the guestfs daemon running inside
+the qemu subprocess. Calling this function checks that the
+daemon responds to the ping message, without affecting the daemon
+or attached block device(s) in any other way.");
+
+ ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
+ [InitBasicFS, Always, TestOutputTrue (
+ [["write"; "/file1"; "contents of a file"];
+ ["cp"; "/file1"; "/file2"];
+ ["equal"; "/file1"; "/file2"]]);
+ InitBasicFS, Always, TestOutputFalse (
+ [["write"; "/file1"; "contents of a file"];
+ ["write"; "/file2"; "contents of another file"];
+ ["equal"; "/file1"; "/file2"]]);
+ InitBasicFS, Always, TestLastFail (
+ [["equal"; "/file1"; "/file2"]])],
+ "test if two files have equal contents",
+ "\
+This compares the two files C<file1> and C<file2> and returns
+true if their content is exactly equal, or false otherwise.
+
+The external L<cmp(1)> program is used for the comparison.");
+
+ ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutputList (
+ [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
+ InitISOFS, Always, TestOutputList (
+ [["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<strings(1)> command on a file and returns
+the list of printable strings found.");
+
+ ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutputList (
+ [["strings_e"; "b"; "/known-5"]], []);
+ InitBasicFS, Always, TestOutputList (
+ [["write"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"];
+ ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
+ "print the printable strings in a file",
+ "\
+This is like the C<guestfs_strings> command, but allows you to
+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
+
+Single 8-bit-byte characters.
+
+=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.");
+
+ ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutput (
+ [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
+ (* Test for RHBZ#501888c2 regression which caused large hexdump
+ * commands to segfault.
+ *)
+ InitISOFS, Always, TestRun (
+ [["hexdump"; "/100krandom"]]);
+ (* Test for RHBZ#579608, absolute symbolic links. *)
+ InitISOFS, Always, TestRun (
+ [["hexdump"; "/abssymlink"]])],
+ "dump a file in hexadecimal",
+ "\
+This runs C<hexdump -C> on the given C<path>. The result is
+the human-readable, canonical hex dump of the file.");
+
+ ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
+ [InitNone, Always, TestOutput (
+ [["part_disk"; "/dev/sda"; "mbr"];
+ ["mkfs"; "ext3"; "/dev/sda1"];
+ ["mount_options"; ""; "/dev/sda1"; "/"];
+ ["write"; "/new"; "test file"];
+ ["umount"; "/dev/sda1"];
+ ["zerofree"; "/dev/sda1"];
+ ["mount_options"; ""; "/dev/sda1"; "/"];
+ ["cat"; "/new"]], "test file")],
+ "zero unused inodes and disk blocks on ext2/3 filesystem",
+ "\
+This runs the I<zerofree> program on C<device>. This program
+claims to zero unused inodes and disk blocks on an ext2/3
+filesystem, thus making it possible to compress the filesystem
+more effectively.
+
+You should B<not> run this program if the filesystem is
+mounted.
+
+It is possible that using this program can damage the filesystem
+or data on the filesystem.");
+
+ ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
+ [],
+ "resize an LVM physical volume",
+ "\
+This resizes (expands or shrinks) an existing LVM physical
+volume to match the new size of the underlying device.");
+
+ ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
+ Int "cyls"; Int "heads"; Int "sectors";
+ String "line"]), 99, [DangerWillRobinson],
+ [],
+ "modify a single partition on a block device",
+ "\
+This runs L<sfdisk(8)> option to modify just the single
+partition C<n> (note: C<n> counts from 1).
+
+For other parameters, see C<guestfs_sfdisk>. You should usually
+pass C<0> for the cyls/heads/sectors parameters.
+
+See also: C<guestfs_part_add>");
+
+ ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
+ [],
+ "display the partition table",
+ "\
+This displays the partition table on C<device>, in the
+human-readable output of the L<sfdisk(8)> command. It is
+not intended to be parsed.
+
+See also: C<guestfs_part_list>");
+
+ ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
+ [],
+ "display the kernel geometry",
+ "\
+This displays the kernel's idea of the geometry of C<device>.
+
+The result is in human-readable format, and not designed to
+be parsed.");
+
+ ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
+ [],
+ "display the disk geometry from the partition table",
+ "\
+This displays the disk geometry of C<device> read from the
+partition table. Especially in the case where the underlying
+block device has been resized, this can be different from the
+kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
+
+The result is in human-readable format, and not designed to
+be parsed.");
+
+ ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
+ [],
+ "activate or deactivate all volume groups",
+ "\
+This command activates or (if C<activate> is false) deactivates
+all logical volumes in all volume groups.
+If activated, then they are made known to the
+kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
+then those devices disappear.
+
+This command is the same as running C<vgchange -a y|n>");
+
+ ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
+ [],
+ "activate or deactivate some volume groups",
+ "\
+This command activates or (if C<activate> is false) deactivates
+all logical volumes in the listed volume groups C<volgroups>.
+If activated, then they are made known to the
+kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
+then those devices disappear.
+
+This command is the same as running C<vgchange -a y|n volgroups...>
+
+Note that if C<volgroups> is an empty list then B<all> volume groups
+are activated or deactivated.");
+
+ ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
+ [InitNone, Always, TestOutput (
+ [["part_disk"; "/dev/sda"; "mbr"];
+ ["pvcreate"; "/dev/sda1"];
+ ["vgcreate"; "VG"; "/dev/sda1"];
+ ["lvcreate"; "LV"; "VG"; "10"];
+ ["mkfs"; "ext2"; "/dev/VG/LV"];
+ ["mount_options"; ""; "/dev/VG/LV"; "/"];
+ ["write"; "/new"; "test content"];
+ ["umount"; "/"];
+ ["lvresize"; "/dev/VG/LV"; "20"];
+ ["e2fsck_f"; "/dev/VG/LV"];
+ ["resize2fs"; "/dev/VG/LV"];
+ ["mount_options"; ""; "/dev/VG/LV"; "/"];
+ ["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
+volume to C<mbytes>. When reducing, data in the reduced part
+is lost.");
+
+ ("resize2fs", (RErr, [Device "device"]), 106, [],
+ [], (* lvresize tests this *)
+ "resize an ext2, ext3 or ext4 filesystem",
+ "\
+This resizes an ext2, ext3 or ext4 filesystem to match the size of
+the underlying device.
+
+I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
+on the C<device> before calling this command. For unknown reasons
+C<resize2fs> sometimes gives an error about this and sometimes not.
+In any case, it is always safe to call C<guestfs_e2fsck_f> before
+calling this function.");
+
+ ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
+ [InitBasicFS, Always, TestOutputList (
+ [["find"; "/"]], ["lost+found"]);
+ InitBasicFS, Always, TestOutputList (
+ [["touch"; "/a"];
+ ["mkdir"; "/b"];
+ ["touch"; "/b/c"];
+ ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
+ InitBasicFS, Always, TestOutputList (
+ [["mkdir_p"; "/a/b/c"];
+ ["touch"; "/a/b/c/d"];
+ ["find"; "/a/b/"]], ["c"; "c/d"])],
+ "find all files and directories",
+ "\
+This command lists out all files and directories, recursively,
+starting at C<directory>. It is essentially equivalent to
+running the shell command C<find directory -print> but some
+post-processing happens on the output, described below.
+
+This returns a list of strings I<without any prefix>. Thus
+if the directory structure was:
+
+ /tmp/a
+ /tmp/b
+ /tmp/c/d
+
+then the returned list from C<guestfs_find> C</tmp> would be
+4 elements:
+
+ a
+ b
+ c
+ c/d
+
+If C<directory> is not a directory, then this command returns
+an error.
+
+The returned list is sorted.
+
+See also C<guestfs_find0>.");
+
+ ("e2fsck_f", (RErr, [Device "device"]), 108, [],
+ [], (* lvresize tests this *)
+ "check an ext2/ext3 filesystem",
+ "\
+This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
+filesystem checker on C<device>, noninteractively (C<-p>),
+even if the filesystem appears to be clean (C<-f>).
+
+This command is only needed because of C<guestfs_resize2fs>
+(q.v.). Normally you should use C<guestfs_fsck>.");
+
+ ("sleep", (RErr, [Int "secs"]), 109, [],
+ [InitNone, Always, TestRun (
+ [["sleep"; "1"]])],
+ "sleep for some seconds",
+ "\
+Sleep for C<secs> seconds.");
+
+ ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
+ [InitNone, Always, TestOutputInt (
+ [["part_disk"; "/dev/sda"; "mbr"];
+ ["mkfs"; "ntfs"; "/dev/sda1"];
+ ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
+ InitNone, Always, TestOutputInt (
+ [["part_disk"; "/dev/sda"; "mbr"];
+ ["mkfs"; "ext2"; "/dev/sda1"];
+ ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
+ "probe NTFS volume",
+ "\
+This command runs the L<ntfs-3g.probe(8)> command which probes
+an NTFS C<device> for mountability. (Not all NTFS volumes can
+be mounted read-write, and some cannot be mounted at all).
+
+C<rw> is a boolean flag. Set it to true if you want to test
+if the volume can be mounted read-write. Set it to false if
+you want to test if the volume can be mounted read-only.
+
+The return value is an integer which C<0> if the operation
+would succeed, or some non-zero value documented in the
+L<ntfs-3g.probe(8)> manual page.");
+
+ ("sh", (RString "output", [String "command"]), 111, [],
+ [], (* XXX needs tests *)
+ "run a command via the shell",
+ "\
+This call runs a command from the guest filesystem via the
+guest's C</bin/sh>.
+
+This is like C<guestfs_command>, but passes the command to:
+
+ /bin/sh -c \"command\"
+
+Depending on the guest's shell, this usually results in
+wildcards being expanded, shell expressions being interpolated
+and so on.
+
+All the provisos about C<guestfs_command> apply to this call.");
+
+ ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
+ [], (* XXX needs tests *)
+ "run a command via the shell returning lines",
+ "\
+This is the same as C<guestfs_sh>, but splits the result
+into a list of lines.
+
+See also: C<guestfs_command_lines>");
+
+ ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
+ (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
+ * code in stubs.c, since all valid glob patterns must start with "/".
+ * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
+ *)
+ [InitBasicFS, Always, TestOutputList (
+ [["mkdir_p"; "/a/b/c"];
+ ["touch"; "/a/b/c/d"];
+ ["touch"; "/a/b/c/e"];
+ ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
+ InitBasicFS, Always, TestOutputList (
+ [["mkdir_p"; "/a/b/c"];
+ ["touch"; "/a/b/c/d"];
+ ["touch"; "/a/b/c/e"];
+ ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
+ InitBasicFS, Always, TestOutputList (
+ [["mkdir_p"; "/a/b/c"];
+ ["touch"; "/a/b/c/d"];
+ ["touch"; "/a/b/c/e"];
+ ["glob_expand"; "/a/*/x/*"]], [])],
+ "expand a wildcard path",
+ "\
+This command searches for all the pathnames matching
+C<pattern> according to the wildcard expansion rules
+used by the shell.
+
+If no paths match, then this returns an empty list
+(note: not an error).
+
+It is just a wrapper around the C L<glob(3)> function
+with flags C<GLOB_MARK|GLOB_BRACE>.
+See that manual page for more details.");
+
+ ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
+ [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
+ [["scrub_device"; "/dev/sdc"]])],
+ "scrub (securely wipe) a device",
+ "\
+This command writes patterns over C<device> to make data retrieval
+more difficult.
+
+It is an interface to the L<scrub(1)> program. See that
+manual page for more details.");
+
+ ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
+ [InitBasicFS, Always, TestRun (
+ [["write"; "/file"; "content"];
+ ["scrub_file"; "/file"]])],
+ "scrub (securely wipe) a file",
+ "\
+This command writes patterns over a file to make data retrieval
+more difficult.
+
+The file is I<removed> after scrubbing.
+
+It is an interface to the L<scrub(1)> program. See that
+manual page for more details.");
+
+ ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
+ [], (* XXX needs testing *)
+ "scrub (securely wipe) free space",
+ "\
+This command creates the directory C<dir> and then fills it
+with files until the filesystem is full, and scrubs the files
+as for C<guestfs_scrub_file>, and deletes them.
+The intention is to scrub any free space on the partition
+containing C<dir>.
+
+It is an interface to the L<scrub(1)> program. See that
+manual page for more details.");
+
+ ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
+ [InitBasicFS, Always, TestRun (
+ [["mkdir"; "/tmp"];
+ ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
+ "create a temporary directory",
+ "\
+This command creates a temporary directory. The
+C<template> parameter should be a full pathname for the
+temporary directory name with the final six characters being
+\"XXXXXX\".
+
+For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
+the second one being suitable for Windows filesystems.
+
+The name of the temporary directory that was created
+is returned.
+
+The temporary directory is created with mode 0700
+and is owned by root.
+
+The caller is responsible for deleting the temporary
+directory and its contents after use.
+
+See also: L<mkdtemp(3)>");
+
+ ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
+ [InitISOFS, Always, TestOutputInt (
+ [["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
+C<wc -l> external command.");
+
+ ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
+ [InitISOFS, Always, TestOutputInt (
+ [["wc_w"; "/10klines"]], 10000)],
+ "count words in a file",
+ "\
+This command counts the words in a file, using the
+C<wc -w> external command.");
+
+ ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
+ [InitISOFS, Always, TestOutputInt (
+ [["wc_c"; "/100kallspaces"]], 102400)],
+ "count characters in a file",
+ "\
+This command counts the characters in a file, using the
+C<wc -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"]);
+ (* 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
+a list of strings.");
+
+ ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutputList (
+ [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
+ InitISOFS, Always, TestOutputList (
+ [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
+ InitISOFS, Always, TestOutputList (
+ [["head_n"; "0"; "/10klines"]], [])],
+ "return first N lines of a file",
+ "\
+If the parameter C<nrlines> is a positive number, this returns the first
+C<nrlines> lines of the file C<path>.
+
+If the parameter C<nrlines> is a negative number, this returns lines
+from the file C<path>, excluding the last C<nrlines> lines.
+
+If the parameter C<nrlines> is zero, this returns an empty list.");
+
+ ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutputList (
+ [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
+ "return last 10 lines of a file",
+ "\
+This command returns up to the last 10 lines of a file as
+a list of strings.");
+
+ ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutputList (
+ [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
+ InitISOFS, Always, TestOutputList (
+ [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
+ InitISOFS, Always, TestOutputList (
+ [["tail_n"; "0"; "/10klines"]], [])],
+ "return last N lines of a file",
+ "\
+If the parameter C<nrlines> is a positive number, this returns the last
+C<nrlines> lines of the file C<path>.
+
+If the parameter C<nrlines> is a negative number, this returns lines
+from the file C<path>, starting with the C<-nrlines>th line.
+
+If the parameter C<nrlines> is zero, this returns an empty list.");
+
+ ("df", (RString "output", []), 125, [],
+ [], (* XXX Tricky to test because it depends on the exact format
+ * of the 'df' command and other imponderables.
+ *)
+ "report file system disk space usage",