*)
and argt =
| String of string (* const char *name, cannot be NULL *)
+ | Device of string (* /dev device name, cannot be NULL *)
+ | Pathname of string (* file name, cannot be NULL *)
+ | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
| OptString of string (* const char *name, may be NULL *)
| StringList of string(* list of strings (each string cannot be NULL) *)
+ | DeviceList of string(* list of Device names (each cannot be NULL) *)
| Bool of string (* boolean *)
| Int of string (* int (smallish ints, signed, <= 31 bits) *)
+ | Int64 of string (* any 64 bit int *)
(* 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.
*
* Note that the test environment has 3 block devices, of size 500MB,
* 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
- * a fourth squashfs block device with some known files on it (/dev/sdd).
+ * a fourth ISO block device with some known files on it (/dev/sdd).
*
* Note for partitioning purposes, the 500MB device has 1015 cylinders.
* Number of cylinders was 63 for IDE emulated disks with precisely
* the same size. How exactly this is calculated is a mystery.
*
- * The squashfs block device (/dev/sdd) comes from images/test.sqsh.
+ * The ISO block device (/dev/sdd) comes from images/test.iso.
*
* To be able to run the tests in a reasonable amount of time,
* the virtual machine and block devices are reused between tests.
(* Block devices are empty and no filesystems are mounted. *)
| InitEmpty
+ (* /dev/sda contains a single partition /dev/sda1, with random
+ * content. /dev/sdb and /dev/sdc may have random content.
+ * No LVM.
+ *)
+ | InitPartition
+
(* /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.
*)
| InitBasicFSonLVM
- (* /dev/sdd (the squashfs, see images/ directory in source)
+ (* /dev/sdd (the ISO, see images/ directory in source)
* is mounted on /
*)
- | InitSquashFS
+ | InitISOFS
(* Sequence of commands for testing. *)
and seq = cmd list
* Apart from that, long descriptions are just perldoc paragraphs.
*)
+(* Generate a random UUID (used in tests). *)
+let uuidgen () =
+ let chan = Unix.open_process_in "uuidgen" in
+ let uuid = input_line chan in
+ (match Unix.close_process_in chan with
+ | Unix.WEXITED 0 -> ()
+ | Unix.WEXITED _ ->
+ failwith "uuidgen: process exited with non-zero status"
+ | Unix.WSIGNALED _ | Unix.WSTOPPED _ ->
+ failwith "uuidgen: process signalled or stopped by signal"
+ );
+ uuid
+
(* These test functions are used in the language binding tests. *)
let test_all_args = [
StringList "strlist";
Bool "b";
Int "integer";
+ Int64 "integer64";
FileIn "filein";
FileOut "fileout";
]
("wait_ready", (RErr, []), -1, [NotInFish],
[],
- "wait until the qemu subprocess launches",
+ "wait until the qemu subprocess launches (no op)",
"\
-Internally libguestfs is implemented by running a virtual machine
-using L<qemu(1)>.
+This function is a no op.
+
+In versions of the API E<lt> 1.0.71 you had to call this function
+just after calling C<guestfs_launch> to wait for the launch
+to complete. However this is no longer necessary because
+C<guestfs_launch> now does the waiting.
-You should call this after C<guestfs_launch> to wait for the launch
-to complete.");
+If you see any calls to this function in code then you can just
+remove them, unless you want to retain compatibility with older
+versions of the API.");
("kill_subprocess", (RErr, []), -1, [],
[],
This is equivalent to the qemu parameter
C<-drive file=filename,cache=off,if=...>.
+C<cache=off> is omitted in cases where it is not supported by
+the underlying filesystem.
Note that this call checks for the existence of C<filename>. This
stops you from specifying other types of drive which are supported
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_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
[],
"set the search path",
"\
For more information on states, see L<guestfs(3)>.");
- ("set_busy", (RErr, []), -1, [NotInFish],
- [],
- "set state to busy",
- "\
-This sets the state to C<BUSY>. This is only used when implementing
-actions using the low-level API.
-
-For more information on states, see L<guestfs(3)>.");
-
- ("set_ready", (RErr, []), -1, [NotInFish],
- [],
- "set state to ready",
- "\
-This sets the state to C<READY>. This is only used when implementing
-actions using the low-level API.
-
-For more information on states, see L<guestfs(3)>.");
-
- ("end_busy", (RErr, []), -1, [NotInFish],
- [],
- "leave the busy state",
- "\
-This sets the state to C<READY>, or if in C<CONFIG> then it leaves the
-state as is. This is only used when implementing
-actions using the low-level API.
-
-For more information on states, see L<guestfs(3)>.");
-
("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
[InitNone, Always, TestOutputInt (
[["set_memsize"; "500"];
I<Note:> Don't use this call to test for availability
of features. Distro backports makes this unreliable.");
+ ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
+ [InitNone, Always, TestOutputTrue (
+ [["set_selinux"; "true"];
+ ["get_selinux"]])],
+ "set SELinux enabled or disabled at appliance boot",
+ "\
+This sets the selinux flag that is passed to the appliance
+at boot time. The default is C<selinux=0> (disabled).
+
+Note that if SELinux is enabled, it is always in
+Permissive mode (C<enforcing=0>).
+
+For more information on the architecture of libguestfs,
+see L<guestfs(3)>.");
+
+ ("get_selinux", (RBool "selinux", []), -1, [],
+ [],
+ "get SELinux enabled flag",
+ "\
+This returns the current setting of the selinux flag which
+is passed to the appliance at boot time. See C<guestfs_set_selinux>.
+
+For more information on the architecture of libguestfs,
+see L<guestfs(3)>.");
+
+ ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
+ [InitNone, Always, TestOutputFalse (
+ [["set_trace"; "false"];
+ ["get_trace"]])],
+ "enable or disable command traces",
+ "\
+If the command trace flag is set to 1, then commands are
+printed on stdout before they are executed in a format
+which is very similar to the one used by guestfish. In
+other words, you can run a program with this enabled, and
+you will get out a script which you can feed to guestfish
+to perform the same set of actions.
+
+If you want to trace C API calls into libguestfs (and
+other libraries) then possibly a better way is to use
+the external ltrace(1) command.
+
+Command traces are disabled unless the environment variable
+C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
+
+ ("get_trace", (RBool "trace", []), -1, [],
+ [],
+ "get command trace enabled flag",
+ "\
+Return the command trace flag.");
+
+ ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
+ [InitNone, Always, TestOutputFalse (
+ [["set_direct"; "false"];
+ ["get_direct"]])],
+ "enable or disable direct appliance mode",
+ "\
+If the direct appliance mode flag is enabled, then stdin and
+stdout are passed directly through to the appliance once it
+is launched.
+
+One consequence of this is that log messages aren't caught
+by the library and handled by C<guestfs_set_log_message_callback>,
+but go straight to stdout.
+
+You probably don't want to use this unless you know what you
+are doing.
+
+The default is disabled.");
+
+ ("get_direct", (RBool "direct", []), -1, [],
+ [],
+ "get direct appliance mode flag",
+ "\
+Return the direct appliance mode flag.");
+
]
(* daemon_functions are any functions which cause some action
*)
let daemon_functions = [
- ("mount", (RErr, [String "device"; String "mountpoint"]), 1, [],
+ ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
[InitEmpty, Always, TestOutput (
[["sfdiskM"; "/dev/sda"; ","];
["mkfs"; "ext2"; "/dev/sda1"];
You should always call this if you have modified a disk image, before
closing the handle.");
- ("touch", (RErr, [String "path"]), 3, [],
+ ("touch", (RErr, [Pathname "path"]), 3, [],
[InitBasicFS, Always, TestOutputTrue (
[["touch"; "/new"];
["exists"; "/new"]])],
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],
- [InitSquashFS, Always, TestOutput (
+ ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutput (
[["cat"; "/known-2"]], "abcdef\n")],
"list the contents of a file",
"\
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", [String "directory"]), 5, [],
+ ("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.
*)
This command is mostly useful for interactive sessions. It
is I<not> intended that you try to parse the output string.");
- ("ls", (RStringList "listing", [String "directory"]), 6, [],
+ ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
[InitBasicFS, Always, TestOutputList (
[["touch"; "/new"];
["touch"; "/newer"];
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", [String "path"]), 15, [],
- [InitSquashFS, Always, TestOutputList (
+ ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
+ [InitISOFS, Always, TestOutputList (
[["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
- InitSquashFS, Always, TestOutputList (
+ InitISOFS, Always, TestOutputList (
[["read_lines"; "/empty"]], [])],
"read file as lines",
"\
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, [String "root"; Int "flags"]), 16, [],
+ ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [],
[], (* XXX Augeas code needs tests. *)
"create a new Augeas handle",
"\
number of nodes in the nodeset, and a boolean flag
if a node was created.");
- ("aug_get", (RString "val", [String "path"]), 19, [],
+ ("aug_get", (RString "val", [String "augpath"]), 19, [],
[], (* 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 "path"; String "val"]), 20, [],
+ ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [],
[], (* XXX Augeas code needs tests. *)
"set Augeas path to value",
"\
Set the value associated with C<path> to C<value>.");
- ("aug_insert", (RErr, [String "path"; String "label"; Bool "before"]), 21, [],
+ ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [],
[], (* XXX Augeas code needs tests. *)
"insert a sibling Augeas node",
"\
C<label> must be a label, ie. not contain C</>, C<*> or end
with a bracketed index C<[N]>.");
- ("aug_rm", (RInt "nrnodes", [String "path"]), 22, [],
+ ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [],
[], (* XXX Augeas code needs tests. *)
"remove an Augeas path",
"\
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 "path"]), 24, [],
+ ("aug_match", (RStringList "matches", [String "augpath"]), 24, [],
[], (* XXX Augeas code needs tests. *)
- "return Augeas nodes which match path",
+ "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
See C<aug_load> in the Augeas documentation for the full gory
details.");
- ("aug_ls", (RStringList "matches", [String "path"]), 28, [],
+ ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [],
[], (* XXX Augeas code needs tests. *)
- "list Augeas nodes under a path",
+ "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, [String "path"]), 29, [],
+ ("rm", (RErr, [Pathname "path"]), 29, [],
[InitBasicFS, Always, TestRun
[["touch"; "/new"];
["rm"; "/new"]];
"\
Remove the single file C<path>.");
- ("rmdir", (RErr, [String "path"]), 30, [],
+ ("rmdir", (RErr, [Pathname "path"]), 30, [],
[InitBasicFS, Always, TestRun
[["mkdir"; "/new"];
["rmdir"; "/new"]];
"\
Remove the single directory C<path>.");
- ("rm_rf", (RErr, [String "path"]), 31, [],
+ ("rm_rf", (RErr, [Pathname "path"]), 31, [],
[InitBasicFS, Always, TestOutputFalse
[["mkdir"; "/new"];
["mkdir"; "/new/foo"];
contents if its a directory. This is like the C<rm -rf> shell
command.");
- ("mkdir", (RErr, [String "path"]), 32, [],
+ ("mkdir", (RErr, [Pathname "path"]), 32, [],
[InitBasicFS, Always, TestOutputTrue
[["mkdir"; "/new"];
["is_dir"; "/new"]];
"\
Create a directory named C<path>.");
- ("mkdir_p", (RErr, [String "path"]), 33, [],
+ ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
[InitBasicFS, Always, TestOutputTrue
[["mkdir_p"; "/new/foo/bar"];
["is_dir"; "/new/foo/bar"]];
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"; String "path"]), 34, [],
+ ("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.");
- ("chown", (RErr, [Int "owner"; Int "group"; String "path"]), 35, [],
+ ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
[], (* XXX Need stat command to test *)
"change file owner and group",
"\
names, you will need to locate and parse the password file
yourself (Augeas support makes this relatively easy).");
- ("exists", (RBool "existsflag", [String "path"]), 36, [],
- [InitSquashFS, Always, TestOutputTrue (
+ ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
+ [InitISOFS, Always, TestOutputTrue (
[["exists"; "/empty"]]);
- InitSquashFS, Always, TestOutputTrue (
+ InitISOFS, Always, TestOutputTrue (
[["exists"; "/directory"]])],
"test if file or directory exists",
"\
See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
- ("is_file", (RBool "fileflag", [String "path"]), 37, [],
- [InitSquashFS, Always, TestOutputTrue (
+ ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
+ [InitISOFS, Always, TestOutputTrue (
[["is_file"; "/known-1"]]);
- InitSquashFS, Always, TestOutputFalse (
+ InitISOFS, Always, TestOutputFalse (
[["is_file"; "/directory"]])],
"test if file exists",
"\
See also C<guestfs_stat>.");
- ("is_dir", (RBool "dirflag", [String "path"]), 38, [],
- [InitSquashFS, Always, TestOutputFalse (
+ ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
+ [InitISOFS, Always, TestOutputFalse (
[["is_dir"; "/known-3"]]);
- InitSquashFS, Always, TestOutputTrue (
+ InitISOFS, Always, TestOutputTrue (
[["is_dir"; "/directory"]])],
"test if file exists",
"\
See also C<guestfs_stat>.");
- ("pvcreate", (RErr, [String "device"]), 39, [],
+ ("pvcreate", (RErr, [Device "device"]), 39, [],
[InitEmpty, Always, TestOutputListOfDevices (
[["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
["pvcreate"; "/dev/sda1"];
where C<device> should usually be a partition name such
as C</dev/sda1>.");
- ("vgcreate", (RErr, [String "volgroup"; StringList "physvols"]), 40, [],
+ ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [],
[InitEmpty, Always, TestOutputList (
[["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
["pvcreate"; "/dev/sda1"];
This creates an LVM volume group called C<logvol>
on the volume group C<volgroup>, with C<size> megabytes.");
- ("mkfs", (RErr, [String "fstype"; String "device"]), 42, [],
+ ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
[InitEmpty, Always, TestOutput (
[["sfdiskM"; "/dev/sda"; ","];
["mkfs"; "ext2"; "/dev/sda1"];
or LVM logical volume). The filesystem type is C<fstype>, for
example C<ext3>.");
- ("sfdisk", (RErr, [String "device";
+ ("sfdisk", (RErr, [Device "device";
Int "cyls"; Int "heads"; Int "sectors";
StringList "lines"]), 43, [DangerWillRobinson],
[],
See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>");
- ("write_file", (RErr, [String "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
+ ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
[InitBasicFS, Always, TestOutput (
[["write_file"; "/new"; "new file contents"; "0"];
["cat"; "/new"]], "new file contents");
This command removes all LVM logical volumes, volume groups
and physical volumes.");
- ("file", (RString "description", [String "path"]), 49, [],
- [InitSquashFS, Always, TestOutput (
+ ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
+ [InitISOFS, Always, TestOutput (
[["file"; "/empty"]], "empty");
- InitSquashFS, Always, TestOutput (
+ InitISOFS, Always, TestOutput (
[["file"; "/known-1"]], "ASCII text");
- InitSquashFS, Always, TestLastFail (
+ InitISOFS, Always, TestLastFail (
[["file"; "/notexists"]])],
"determine file type",
"\
See also: C<guestfs_sh_lines>");
- ("stat", (RStruct ("statbuf", "stat"), [String "path"]), 52, [],
- [InitSquashFS, Always, TestOutputStruct (
+ ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
+ [InitISOFS, Always, TestOutputStruct (
[["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
"get file information",
"\
This is the same as the C<stat(2)> system call.");
- ("lstat", (RStruct ("statbuf", "stat"), [String "path"]), 53, [],
- [InitSquashFS, Always, TestOutputStruct (
+ ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
+ [InitISOFS, Always, TestOutputStruct (
[["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
"get file information for a symbolic link",
"\
This is the same as the C<lstat(2)> system call.");
- ("statvfs", (RStruct ("statbuf", "statvfs"), [String "path"]), 54, [],
- [InitSquashFS, Always, TestOutputStruct (
- [["statvfs"; "/"]], [CompareWithInt ("namemax", 256)])],
+ ("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.
This is the same as the C<statvfs(2)> system call.");
- ("tune2fs_l", (RHashtable "superblock", [String "device"]), 55, [],
+ ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
[], (* XXX test *)
"get ext2/ext3/ext4 superblock details",
"\
clearly defined, and depends on both the version of C<tune2fs>
that libguestfs was built against, and the filesystem itself.");
- ("blockdev_setro", (RErr, [String "device"]), 56, [],
+ ("blockdev_setro", (RErr, [Device "device"]), 56, [],
[InitEmpty, Always, TestOutputTrue (
[["blockdev_setro"; "/dev/sda"];
["blockdev_getro"; "/dev/sda"]])],
This uses the L<blockdev(8)> command.");
- ("blockdev_setrw", (RErr, [String "device"]), 57, [],
+ ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
[InitEmpty, Always, TestOutputFalse (
[["blockdev_setrw"; "/dev/sda"];
["blockdev_getro"; "/dev/sda"]])],
This uses the L<blockdev(8)> command.");
- ("blockdev_getro", (RBool "ro", [String "device"]), 58, [],
+ ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
[InitEmpty, Always, TestOutputTrue (
[["blockdev_setro"; "/dev/sda"];
["blockdev_getro"; "/dev/sda"]])],
This uses the L<blockdev(8)> command.");
- ("blockdev_getss", (RInt "sectorsize", [String "device"]), 59, [],
+ ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
[InitEmpty, Always, TestOutputInt (
[["blockdev_getss"; "/dev/sda"]], 512)],
"get sectorsize of block device",
This uses the L<blockdev(8)> command.");
- ("blockdev_getbsz", (RInt "blocksize", [String "device"]), 60, [],
+ ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
[InitEmpty, Always, TestOutputInt (
[["blockdev_getbsz"; "/dev/sda"]], 4096)],
"get blocksize of block device",
This uses the L<blockdev(8)> command.");
- ("blockdev_setbsz", (RErr, [String "device"; Int "blocksize"]), 61, [],
+ ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
[], (* XXX test *)
"set blocksize of block device",
"\
This uses the L<blockdev(8)> command.");
- ("blockdev_getsz", (RInt64 "sizeinsectors", [String "device"]), 62, [],
+ ("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 uses the L<blockdev(8)> command.");
- ("blockdev_getsize64", (RInt64 "sizeinbytes", [String "device"]), 63, [],
+ ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
[InitEmpty, Always, TestOutputInt (
[["blockdev_getsize64"; "/dev/sda"]], 524288000)],
"get total size of device in bytes",
This uses the L<blockdev(8)> command.");
- ("blockdev_flushbufs", (RErr, [String "device"]), 64, [],
+ ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
[InitEmpty, Always, TestRun
[["blockdev_flushbufs"; "/dev/sda"]]],
"flush device buffers",
This uses the L<blockdev(8)> command.");
- ("blockdev_rereadpt", (RErr, [String "device"]), 65, [],
+ ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
[InitEmpty, Always, TestRun
[["blockdev_rereadpt"; "/dev/sda"]]],
"reread partition table",
See also C<guestfs_download>.");
- ("download", (RErr, [String "remotefilename"; FileOut "filename"]), 67, [],
+ ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
[InitBasicFS, Always, TestOutput (
(* Pick a file from cwd which isn't likely to change. *)
[["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
See also C<guestfs_upload>, C<guestfs_cat>.");
- ("checksum", (RString "checksum", [String "csumtype"; String "path"]), 68, [],
- [InitSquashFS, Always, TestOutput (
+ ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
+ [InitISOFS, Always, TestOutput (
[["checksum"; "crc"; "/known-3"]], "2891671662");
- InitSquashFS, Always, TestLastFail (
+ InitISOFS, Always, TestLastFail (
[["checksum"; "crc"; "/notexists"]]);
- InitSquashFS, Always, TestOutput (
+ InitISOFS, Always, TestOutput (
[["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
- InitSquashFS, Always, TestOutput (
+ InitISOFS, Always, TestOutput (
[["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
- InitSquashFS, Always, TestOutput (
+ InitISOFS, Always, TestOutput (
[["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
- InitSquashFS, Always, TestOutput (
+ InitISOFS, Always, TestOutput (
[["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
- InitSquashFS, Always, TestOutput (
+ InitISOFS, Always, TestOutput (
[["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
- InitSquashFS, Always, TestOutput (
+ InitISOFS, Always, TestOutput (
[["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
"compute MD5, SHAx or CRC checksum of file",
"\
To upload an uncompressed tarball, use C<guestfs_tar_in>.");
- ("tgz_out", (RErr, [String "directory"; FileOut "tarball"]), 72, [],
+ ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
[],
"pack directory into compressed tarball",
"\
To download an uncompressed tarball, use C<guestfs_tar_out>.");
- ("mount_ro", (RErr, [String "device"; String "mountpoint"]), 73, [],
+ ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
[InitBasicFS, Always, TestLastFail (
[["umount"; "/"];
["mount_ro"; "/dev/sda1"; "/"];
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"; String "device"; String "mountpoint"]), 74, [],
+ ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
[],
"mount a guest disk with mount options",
"\
allows you to set the mount options as for the
L<mount(8)> I<-o> flag.");
- ("mount_vfs", (RErr, [String "options"; String "vfstype"; String "device"; String "mountpoint"]), 75, [],
+ ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
[],
"mount a guest disk with mount options and vfstype",
"\
to look at the file C<daemon/debug.c> in the libguestfs source
to find out what you can do.");
- ("lvremove", (RErr, [String "device"]), 77, [],
+ ("lvremove", (RErr, [Device "device"]), 77, [],
[InitEmpty, Always, TestOutputList (
[["sfdiskM"; "/dev/sda"; ","];
["pvcreate"; "/dev/sda1"];
This also forcibly removes all logical volumes in the volume
group (if any).");
- ("pvremove", (RErr, [String "device"]), 79, [],
+ ("pvremove", (RErr, [Device "device"]), 79, [],
[InitEmpty, Always, TestOutputListOfDevices (
[["sfdiskM"; "/dev/sda"; ","];
["pvcreate"; "/dev/sda1"];
wipe physical volumes that contain any volume groups, so you have
to remove those first.");
- ("set_e2label", (RErr, [String "device"; String "label"]), 80, [],
+ ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
[InitBasicFS, Always, TestOutput (
[["set_e2label"; "/dev/sda1"; "testlabel"];
["get_e2label"; "/dev/sda1"]], "testlabel")],
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", [String "device"]), 81, [],
+ ("get_e2label", (RString "label", [Device "device"]), 81, [],
[],
"get the ext2/3/4 filesystem label",
"\
This returns the ext2/3/4 filesystem label of the filesystem on
C<device>.");
- ("set_e2uuid", (RErr, [String "device"; String "uuid"]), 82, [],
- [InitBasicFS, Always, TestOutput (
- [["set_e2uuid"; "/dev/sda1"; "a3a61220-882b-4f61-89f4-cf24dcc7297d"];
- ["get_e2uuid"; "/dev/sda1"]], "a3a61220-882b-4f61-89f4-cf24dcc7297d");
- 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_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
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", [String "device"]), 83, [],
+ ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
[],
"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"; String "device"]), 84, [],
+ ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
[InitBasicFS, Always, TestOutputInt (
[["umount"; "/dev/sda1"];
["fsck"; "ext2"; "/dev/sda1"]], 0);
This command is entirely equivalent to running C<fsck -a -t fstype device>.");
- ("zero", (RErr, [String "device"]), 85, [],
+ ("zero", (RErr, [Device "device"]), 85, [],
[InitBasicFS, Always, TestOutput (
[["umount"; "/dev/sda1"];
["zero"; "/dev/sda1"];
See also: C<guestfs_scrub_device>.");
- ("grub_install", (RErr, [String "root"; String "device"]), 86, [],
+ ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
(* Test disabled because grub-install incompatible with virtio-blk driver.
* See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
*)
This command installs GRUB (the Grand Unified Bootloader) on
C<device>, with the root directory being C<root>.");
- ("cp", (RErr, [String "src"; String "dest"]), 87, [],
+ ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
[InitBasicFS, Always, TestOutput (
[["write_file"; "/old"; "file content"; "0"];
["cp"; "/old"; "/new"];
This copies a file from C<src> to C<dest> where C<dest> is
either a destination filename or destination directory.");
- ("cp_a", (RErr, [String "src"; String "dest"]), 88, [],
+ ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
[InitBasicFS, Always, TestOutput (
[["mkdir"; "/olddir"];
["mkdir"; "/newdir"];
This copies a file or directory from C<src> to C<dest>
recursively using the C<cp -a> command.");
- ("mv", (RErr, [String "src"; String "dest"]), 89, [],
+ ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
[InitBasicFS, Always, TestOutput (
[["write_file"; "/old"; "file content"; "0"];
["mv"; "/old"; "/new"];
daemon responds to the ping message, without affecting the daemon
or attached block device(s) in any other way.");
- ("equal", (RBool "equality", [String "file1"; String "file2"]), 93, [],
+ ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
[InitBasicFS, Always, TestOutputTrue (
[["write_file"; "/file1"; "contents of a file"; "0"];
["cp"; "/file1"; "/file2"];
The external L<cmp(1)> program is used for the comparison.");
- ("strings", (RStringList "stringsout", [String "path"]), 94, [ProtocolLimitWarning],
- [InitSquashFS, Always, TestOutputList (
+ ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutputList (
[["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
- InitSquashFS, Always, TestOutputList (
+ InitISOFS, Always, TestOutputList (
[["strings"; "/empty"]], [])],
"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"; String "path"]), 95, [ProtocolLimitWarning],
- [InitSquashFS, Always, TestOutputList (
+ ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutputList (
[["strings_e"; "b"; "/known-5"]], []);
InitBasicFS, Disabled, TestOutputList (
[["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
The returned strings are transcoded to UTF-8.");
- ("hexdump", (RString "dump", [String "path"]), 96, [ProtocolLimitWarning],
- [InitSquashFS, Always, TestOutput (
+ ("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.
*)
- InitSquashFS, Always, TestRun (
+ InitISOFS, Always, TestRun (
[["hexdump"; "/100krandom"]])],
"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, [String "device"]), 97, [],
+ ("zerofree", (RErr, [Device "device"]), 97, [],
[InitNone, Always, TestOutput (
[["sfdiskM"; "/dev/sda"; ","];
["mkfs"; "ext3"; "/dev/sda1"];
It is possible that using this program can damage the filesystem
or data on the filesystem.");
- ("pvresize", (RErr, [String "device"]), 98, [],
+ ("pvresize", (RErr, [Device "device"]), 98, [],
[],
"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, [String "device"; Int "partnum";
+ ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
Int "cyls"; Int "heads"; Int "sectors";
String "line"]), 99, [DangerWillRobinson],
[],
For other parameters, see C<guestfs_sfdisk>. You should usually
pass C<0> for the cyls/heads/sectors parameters.");
- ("sfdisk_l", (RString "partitions", [String "device"]), 100, [],
+ ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
[],
"display the partition table",
"\
human-readable output of the L<sfdisk(8)> command. It is
not intended to be parsed.");
- ("sfdisk_kernel_geometry", (RString "partitions", [String "device"]), 101, [],
+ ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
[],
"display the kernel geometry",
"\
The result is in human-readable format, and not designed to
be parsed.");
- ("sfdisk_disk_geometry", (RString "partitions", [String "device"]), 102, [],
+ ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
[],
"display the disk geometry from the partition table",
"\
Note that if C<volgroups> is an empty list then B<all> volume groups
are activated or deactivated.");
- ("lvresize", (RErr, [String "device"; Int "mbytes"]), 105, [],
+ ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [],
[InitNone, Always, TestOutput (
[["sfdiskM"; "/dev/sda"; ","];
["pvcreate"; "/dev/sda1"];
volume to C<mbytes>. When reducing, data in the reduced part
is lost.");
- ("resize2fs", (RErr, [String "device"]), 106, [],
+ ("resize2fs", (RErr, [Device "device"]), 106, [],
[], (* lvresize tests this *)
"resize an ext2/ext3 filesystem",
"\
In any case, it is always safe to call C<guestfs_e2fsck_f> before
calling this function.");
- ("find", (RStringList "names", [String "directory"]), 107, [],
+ ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
[InitBasicFS, Always, TestOutputList (
[["find"; "/"]], ["lost+found"]);
InitBasicFS, Always, TestOutputList (
If C<directory> is not a directory, then this command returns
an error.
-The returned list is sorted.");
+The returned list is sorted.
- ("e2fsck_f", (RErr, [String "device"]), 108, [],
+See also C<guestfs_find0>.");
+
+ ("e2fsck_f", (RErr, [Device "device"]), 108, [],
[], (* lvresize tests this *)
"check an ext2/ext3 filesystem",
"\
"\
Sleep for C<secs> seconds.");
- ("ntfs_3g_probe", (RInt "status", [Bool "rw"; String "device"]), 110, [],
+ ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [],
[InitNone, Always, TestOutputInt (
[["sfdiskM"; "/dev/sda"; ","];
["mkfs"; "ntfs"; "/dev/sda1"];
See also: C<guestfs_command_lines>");
- ("glob_expand", (RStringList "paths", [String "pattern"]), 113, [],
+ ("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"];
with flags C<GLOB_MARK|GLOB_BRACE>.
See that manual page for more details.");
- ("scrub_device", (RErr, [String "device"]), 114, [DangerWillRobinson],
+ ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson],
[InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
[["scrub_device"; "/dev/sdc"]])],
"scrub (securely wipe) a device",
It is an interface to the L<scrub(1)> program. See that
manual page for more details.");
- ("scrub_file", (RErr, [String "file"]), 115, [],
+ ("scrub_file", (RErr, [Pathname "file"]), 115, [],
[InitBasicFS, Always, TestRun (
[["write_file"; "/file"; "content"; "0"];
["scrub_file"; "/file"]])],
It is an interface to the L<scrub(1)> program. See that
manual page for more details.");
- ("scrub_freespace", (RErr, [String "dir"]), 116, [],
+ ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [],
[], (* XXX needs testing *)
"scrub (securely wipe) free space",
"\
It is an interface to the L<scrub(1)> program. See that
manual page for more details.");
- ("mkdtemp", (RString "dir", [String "template"]), 117, [],
+ ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
[InitBasicFS, Always, TestRun (
[["mkdir"; "/tmp"];
["mkdtemp"; "/tmp/tmpXXXXXX"]])],
See also: L<mkdtemp(3)>");
- ("wc_l", (RInt "lines", [String "path"]), 118, [],
- [InitSquashFS, Always, TestOutputInt (
+ ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
+ [InitISOFS, Always, TestOutputInt (
[["wc_l"; "/10klines"]], 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", [String "path"]), 119, [],
- [InitSquashFS, Always, TestOutputInt (
+ ("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", [String "path"]), 120, [],
- [InitSquashFS, Always, TestOutputInt (
+ ("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", [String "path"]), 121, [ProtocolLimitWarning],
- [InitSquashFS, Always, TestOutputList (
+ ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutputList (
[["head"; "/10klines"]], ["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"; String "path"]), 122, [ProtocolLimitWarning],
- [InitSquashFS, Always, TestOutputList (
+ ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutputList (
[["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
- InitSquashFS, Always, TestOutputList (
+ InitISOFS, Always, TestOutputList (
[["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
- InitSquashFS, Always, TestOutputList (
+ InitISOFS, Always, TestOutputList (
[["head_n"; "0"; "/10klines"]], [])],
"return first N lines of a file",
"\
If the parameter C<nrlines> is zero, this returns an empty list.");
- ("tail", (RStringList "lines", [String "path"]), 123, [ProtocolLimitWarning],
- [InitSquashFS, Always, TestOutputList (
+ ("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"; String "path"]), 124, [ProtocolLimitWarning],
- [InitSquashFS, Always, TestOutputList (
+ ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutputList (
[["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
- InitSquashFS, Always, TestOutputList (
+ InitISOFS, Always, TestOutputList (
[["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
- InitSquashFS, Always, TestOutputList (
+ InitISOFS, Always, TestOutputList (
[["tail_n"; "0"; "/10klines"]], [])],
"return last N lines of a file",
"\
is I<not> intended that you try to parse the output string.
Use C<statvfs> from programs.");
- ("du", (RInt64 "sizekb", [String "path"]), 127, [],
- [InitSquashFS, Always, TestOutputInt (
- [["du"; "/directory"]], 0 (* squashfs doesn't have blocks *))],
+ ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
+ [InitISOFS, Always, TestOutputInt (
+ [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
"estimate file space usage",
"\
This command runs the C<du -s> command to estimate file space
The result is the estimated size in I<kilobytes>
(ie. units of 1024 bytes).");
- ("initrd_list", (RStringList "filenames", [String "path"]), 128, [],
- [InitSquashFS, Always, TestOutputList (
+ ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
+ [InitISOFS, Always, TestOutputList (
[["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
"list files in an initrd",
"\
filesystem as initrd. We I<only> support the newer initramfs
format (compressed cpio files).");
- ("mount_loop", (RErr, [String "file"; String "mountpoint"]), 129, [],
+ ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
[],
"mount a file using the loop device",
"\
in a file) on a mount point. It is entirely equivalent to
the command C<mount -o loop file mountpoint>.");
- ("mkswap", (RErr, [String "device"]), 130, [],
+ ("mkswap", (RErr, [Device "device"]), 130, [],
[InitEmpty, Always, TestRun (
[["sfdiskM"; "/dev/sda"; ","];
["mkswap"; "/dev/sda1"]])],
"\
Create a swap partition on C<device>.");
- ("mkswap_L", (RErr, [String "label"; String "device"]), 131, [],
+ ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
[InitEmpty, Always, TestRun (
[["sfdiskM"; "/dev/sda"; ","];
["mkswap_L"; "hello"; "/dev/sda1"]])],
(eg. C</dev/sda>), just to a partition. This appears to be
a limitation of the kernel or swap tools.");
- ("mkswap_U", (RErr, [String "uuid"; String "device"]), 132, [],
- [InitEmpty, Always, TestRun (
- [["sfdiskM"; "/dev/sda"; ","];
- ["mkswap_U"; "a3a61220-882b-4f61-89f4-cf24dcc7297d"; "/dev/sda1"]])],
+ ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [],
+ (let uuid = uuidgen () in
+ [InitEmpty, Always, TestRun (
+ [["sfdiskM"; "/dev/sda"; ","];
+ ["mkswap_U"; uuid; "/dev/sda1"]])]),
"create a swap partition with an explicit UUID",
"\
Create a swap partition on C<device> with UUID C<uuid>.");
- ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; String "path"]), 133, [],
+ ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [],
[InitBasicFS, Always, TestOutputStruct (
[["mknod"; "0o10777"; "0"; "0"; "/node"];
(* NB: default umask 022 means 0777 -> 0755 in these tests *)
device major and minor numbers, only used when creating block
and character special devices.");
- ("mkfifo", (RErr, [Int "mode"; String "path"]), 134, [],
+ ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [],
[InitBasicFS, Always, TestOutputStruct (
[["mkfifo"; "0o777"; "/node"];
["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
mode C<mode>. It is just a convenient wrapper around
C<guestfs_mknod>.");
- ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; String "path"]), 135, [],
+ ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [],
[InitBasicFS, Always, TestOutputStruct (
[["mknod_b"; "0o777"; "99"; "66"; "/node"];
["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
mode C<mode> and device major/minor C<devmajor> and C<devminor>.
It is just a convenient wrapper around C<guestfs_mknod>.");
- ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; String "path"]), 136, [],
+ ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [],
[InitBasicFS, Always, TestOutputStruct (
[["mknod_c"; "0o777"; "99"; "66"; "/node"];
["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
This call returns the previous umask.");
- ("readdir", (RStructList ("entries", "dirent"), [String "dir"]), 138, [],
+ ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
[],
"read directories entries",
"\
get a simple list of names, use C<guestfs_ls>. To get a printable
directory for human consumption, use C<guestfs_ll>.");
- ("sfdiskM", (RErr, [String "device"; StringList "lines"]), 139, [DangerWillRobinson],
+ ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
[],
"create partitions on a block device",
"\
See also C<guestfs_sfdisk> and the L<sfdisk(8)> manpage.");
- ("zfile", (RString "description", [String "method"; String "path"]), 140, [DeprecatedBy "file"],
+ ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
[],
"determine file type inside a compressed file",
"\
Since 1.0.63, use C<guestfs_file> instead which can now
process compressed files.");
- ("getxattrs", (RStructList ("xattrs", "xattr"), [String "path"]), 141, [],
+ ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [],
[],
"list extended attributes of a file or directory",
"\
See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
- ("lgetxattrs", (RStructList ("xattrs", "xattr"), [String "path"]), 142, [],
+ ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [],
[],
"list extended attributes of a file or directory",
"\
("setxattr", (RErr, [String "xattr";
String "val"; Int "vallen"; (* will be BufferIn *)
- String "path"]), 143, [],
+ Pathname "path"]), 143, [],
[],
"set extended attribute of a file or directory",
"\
("lsetxattr", (RErr, [String "xattr";
String "val"; Int "vallen"; (* will be BufferIn *)
- String "path"]), 144, [],
+ Pathname "path"]), 144, [],
[],
"set extended attribute of a file or directory",
"\
is a symbolic link, then it sets an extended attribute
of the link itself.");
- ("removexattr", (RErr, [String "xattr"; String "path"]), 145, [],
+ ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [],
[],
"remove extended attribute of a file or directory",
"\
See also: C<guestfs_lremovexattr>, L<attr(5)>.");
- ("lremovexattr", (RErr, [String "xattr"; String "path"]), 146, [],
+ ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [],
[],
"remove extended attribute of a file or directory",
"\
a list of devices. This one returns a hash table (map) of
device name to directory where the device is mounted.");
- ("mkmountpoint", (RErr, [String "path"]), 148, [],
+ ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
+ (* This is a special case: while you would expect a parameter
+ * of type "Pathname", that doesn't work, because it implies
+ * NEED_ROOT in the generated calling code in stubs.c, and
+ * this function cannot use NEED_ROOT.
+ *)
[],
"create a mountpoint",
"\
The inner filesystem is now unpacked under the /ext3 mountpoint.");
- ("rmmountpoint", (RErr, [String "path"]), 149, [],
+ ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
[],
"remove a mountpoint",
"\
with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
for full details.");
- ("read_file", (RBufferOut "content", [String "path"]), 150, [ProtocolLimitWarning],
- [InitSquashFS, Always, TestOutputBuffer (
+ ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutputBuffer (
[["read_file"; "/known-4"]], "abc\ndef\nghi")],
"read a file",
"\
However unlike C<guestfs_download>, this function is limited
in the total size of file that can be handled.");
- ("grep", (RStringList "lines", [String "regex"; String "path"]), 151, [ProtocolLimitWarning],
- [InitSquashFS, Always, TestOutputList (
+ ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutputList (
[["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
- InitSquashFS, Always, TestOutputList (
+ InitISOFS, Always, TestOutputList (
[["grep"; "nomatch"; "/test-grep.txt"]], [])],
"return lines matching a pattern",
"\
This calls the external C<grep> program and returns the
matching lines.");
- ("egrep", (RStringList "lines", [String "regex"; String "path"]), 152, [ProtocolLimitWarning],
- [InitSquashFS, Always, TestOutputList (
+ ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutputList (
[["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
"return lines matching a pattern",
"\
This calls the external C<egrep> program and returns the
matching lines.");
- ("fgrep", (RStringList "lines", [String "pattern"; String "path"]), 153, [ProtocolLimitWarning],
- [InitSquashFS, Always, TestOutputList (
+ ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutputList (
[["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
"return lines matching a pattern",
"\
This calls the external C<fgrep> program and returns the
matching lines.");
- ("grepi", (RStringList "lines", [String "regex"; String "path"]), 154, [ProtocolLimitWarning],
- [InitSquashFS, Always, TestOutputList (
+ ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutputList (
[["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
"return lines matching a pattern",
"\
This calls the external C<grep -i> program and returns the
matching lines.");
- ("egrepi", (RStringList "lines", [String "regex"; String "path"]), 155, [ProtocolLimitWarning],
- [InitSquashFS, Always, TestOutputList (
+ ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutputList (
[["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
"return lines matching a pattern",
"\
This calls the external C<egrep -i> program and returns the
matching lines.");
- ("fgrepi", (RStringList "lines", [String "pattern"; String "path"]), 156, [ProtocolLimitWarning],
- [InitSquashFS, Always, TestOutputList (
+ ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutputList (
[["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
"return lines matching a pattern",
"\
This calls the external C<fgrep -i> program and returns the
matching lines.");
- ("zgrep", (RStringList "lines", [String "regex"; String "path"]), 157, [ProtocolLimitWarning],
- [InitSquashFS, Always, TestOutputList (
+ ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutputList (
[["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
"return lines matching a pattern",
"\
This calls the external C<zgrep> program and returns the
matching lines.");
- ("zegrep", (RStringList "lines", [String "regex"; String "path"]), 158, [ProtocolLimitWarning],
- [InitSquashFS, Always, TestOutputList (
+ ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutputList (
[["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
"return lines matching a pattern",
"\
This calls the external C<zegrep> program and returns the
matching lines.");
- ("zfgrep", (RStringList "lines", [String "pattern"; String "path"]), 159, [ProtocolLimitWarning],
- [InitSquashFS, Always, TestOutputList (
+ ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutputList (
[["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
"return lines matching a pattern",
"\
This calls the external C<zfgrep> program and returns the
matching lines.");
- ("zgrepi", (RStringList "lines", [String "regex"; String "path"]), 160, [ProtocolLimitWarning],
- [InitSquashFS, Always, TestOutputList (
+ ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutputList (
[["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
"return lines matching a pattern",
"\
This calls the external C<zgrep -i> program and returns the
matching lines.");
- ("zegrepi", (RStringList "lines", [String "regex"; String "path"]), 161, [ProtocolLimitWarning],
- [InitSquashFS, Always, TestOutputList (
+ ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutputList (
[["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
"return lines matching a pattern",
"\
This calls the external C<zegrep -i> program and returns the
matching lines.");
- ("zfgrepi", (RStringList "lines", [String "pattern"; String "path"]), 162, [ProtocolLimitWarning],
- [InitSquashFS, Always, TestOutputList (
+ ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutputList (
[["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
"return lines matching a pattern",
"\
This calls the external C<zfgrep -i> program and returns the
matching lines.");
- ("realpath", (RString "rpath", [String "path"]), 163, [],
- [InitSquashFS, Always, TestOutput (
+ ("realpath", (RString "rpath", [Pathname "path"]), 163, [],
+ [InitISOFS, Always, TestOutput (
[["realpath"; "/../directory"]], "/directory")],
"canonicalized absolute pathname",
"\
Return the canonicalized absolute pathname of C<path>. The
returned path has no C<.>, C<..> or symbolic link path elements.");
- ("ln", (RErr, [String "target"; String "linkname"]), 164, [],
+ ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
[InitBasicFS, Always, TestOutputStruct (
[["touch"; "/a"];
["ln"; "/a"; "/b"];
"\
This command creates a hard link using the C<ln> command.");
- ("ln_f", (RErr, [String "target"; String "linkname"]), 165, [],
+ ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
[InitBasicFS, Always, TestOutputStruct (
[["touch"; "/a"];
["touch"; "/b"];
This command creates a hard link using the C<ln -f> command.
The C<-f> option removes the link (C<linkname>) if it exists already.");
- ("ln_s", (RErr, [String "target"; String "linkname"]), 166, [],
+ ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
[InitBasicFS, Always, TestOutputStruct (
[["touch"; "/a"];
["ln_s"; "a"; "/b"];
"\
This command creates a symbolic link using the C<ln -s> command.");
- ("ln_sf", (RErr, [String "target"; String "linkname"]), 167, [],
+ ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
[InitBasicFS, Always, TestOutput (
[["mkdir_p"; "/a/b"];
["touch"; "/a/b/c"];
This command creates a symbolic link using the C<ln -sf> command,
The C<-f> option removes the link (C<linkname>) if it exists already.");
- ("readlink", (RString "link", [String "path"]), 168, [],
+ ("readlink", (RString "link", [Pathname "path"]), 168, [],
[] (* XXX tested above *),
"read the target of a symbolic link",
"\
This command reads the target of a symbolic link.");
- ("fallocate", (RErr, [String "path"; Int "len"]), 169, [],
+ ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
[InitBasicFS, Always, TestOutputStruct (
[["fallocate"; "/a"; "1000000"];
["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
C<alloc> command which allocates a file in the host and
attaches it as a device.");
- ("swapon_device", (RErr, [String "device"]), 170, [],
- [InitNone, Always, TestRun (
- [["mkswap"; "/dev/sdb"];
- ["swapon_device"; "/dev/sdb"];
- ["swapoff_device"; "/dev/sdb"]])],
+ ("swapon_device", (RErr, [Device "device"]), 170, [],
+ [InitPartition, Always, TestRun (
+ [["mkswap"; "/dev/sda1"];
+ ["swapon_device"; "/dev/sda1"];
+ ["swapoff_device"; "/dev/sda1"]])],
"enable swap on device",
"\
This command enables the libguestfs appliance to use the
information about the host to the guest this way. Instead,
attach a new host device to the guest and swap on that.");
- ("swapoff_device", (RErr, [String "device"]), 171, [],
+ ("swapoff_device", (RErr, [Device "device"]), 171, [],
[], (* XXX tested by swapon_device *)
"disable swap on device",
"\
device or partition named C<device>.
See C<guestfs_swapon_device>.");
- ("swapon_file", (RErr, [String "file"]), 172, [],
+ ("swapon_file", (RErr, [Pathname "file"]), 172, [],
[InitBasicFS, Always, TestRun (
[["fallocate"; "/swap"; "8388608"];
["mkswap_file"; "/swap"];
This command enables swap to a file.
See C<guestfs_swapon_device> for other notes.");
- ("swapoff_file", (RErr, [String "file"]), 173, [],
+ ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
[], (* XXX tested by swapon_file *)
"disable swap on file",
"\
["swapoff_label"; "swapit"];
["zero"; "/dev/sdb"];
["blockdev_rereadpt"; "/dev/sdb"]])],
- "enable swap on labelled swap partition",
+ "enable swap on labeled swap partition",
"\
-This command enables swap to a labelled swap partition.
+This command enables swap to a labeled swap partition.
See C<guestfs_swapon_device> for other notes.");
("swapoff_label", (RErr, [String "label"]), 175, [],
[], (* XXX tested by swapon_label *)
- "disable swap on labelled swap partition",
+ "disable swap on labeled swap partition",
"\
This command disables the libguestfs appliance swap on
-labelled swap partition.");
+labeled swap partition.");
("swapon_uuid", (RErr, [String "uuid"]), 176, [],
- [InitEmpty, Always, TestRun (
- [["mkswap_U"; "a3a61220-882b-4f61-89f4-cf24dcc7297d"; "/dev/sdb"];
- ["swapon_uuid"; "a3a61220-882b-4f61-89f4-cf24dcc7297d"];
- ["swapoff_uuid"; "a3a61220-882b-4f61-89f4-cf24dcc7297d"]])],
+ (let uuid = uuidgen () in
+ [InitEmpty, Always, TestRun (
+ [["mkswap_U"; uuid; "/dev/sdb"];
+ ["swapon_uuid"; uuid];
+ ["swapoff_uuid"; uuid]])]),
"enable swap on swap partition by UUID",
"\
This command enables swap to a swap partition with the given UUID.
This command disables the libguestfs appliance swap partition
with the given UUID.");
- ("mkswap_file", (RErr, [String "path"]), 178, [],
+ ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
[InitBasicFS, Always, TestRun (
[["fallocate"; "/swap"; "8388608"];
["mkswap_file"; "/swap"]])],
file. To create the file itself, use something like C<guestfs_fallocate>.");
("inotify_init", (RErr, [Int "maxevents"]), 179, [],
- [InitSquashFS, Always, TestRun (
+ [InitISOFS, Always, TestRun (
[["inotify_init"; "0"]])],
"create an inotify handle",
"\
via libguestfs. Note that there is one global inotify handle
per libguestfs instance.");
- ("inotify_add_watch", (RInt64 "wd", [String "path"; Int "mask"]), 180, [],
+ ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [],
[InitBasicFS, Always, TestOutputList (
[["inotify_init"; "0"];
["inotify_add_watch"; "/"; "1073741823"];
opened by inotify_init. It removes all watches, throws
away any pending events, and deallocates all resources.");
+ ("setcon", (RErr, [String "context"]), 185, [],
+ [],
+ "set SELinux security context",
+ "\
+This sets the SELinux security context of the daemon
+to the string C<context>.
+
+See the documentation about SELINUX in L<guestfs(3)>.");
+
+ ("getcon", (RString "context", []), 186, [],
+ [],
+ "get SELinux security context",
+ "\
+This gets the SELinux security context of the daemon.
+
+See the documentation about SELINUX in L<guestfs(3)>,
+and C<guestfs_setcon>");
+
+ ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
+ [InitEmpty, Always, TestOutput (
+ [["sfdiskM"; "/dev/sda"; ","];
+ ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
+ ["mount"; "/dev/sda1"; "/"];
+ ["write_file"; "/new"; "new file contents"; "0"];
+ ["cat"; "/new"]], "new file contents")],
+ "make a filesystem with block size",
+ "\
+This call is similar to C<guestfs_mkfs>, but it allows you to
+control the block size of the resulting filesystem. Supported
+block sizes depend on the filesystem type, but typically they
+are C<1024>, C<2048> or C<4096> only.");
+
+ ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
+ [InitEmpty, Always, TestOutput (
+ [["sfdiskM"; "/dev/sda"; ",100 ,"];
+ ["mke2journal"; "4096"; "/dev/sda1"];
+ ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
+ ["mount"; "/dev/sda2"; "/"];
+ ["write_file"; "/new"; "new file contents"; "0"];
+ ["cat"; "/new"]], "new file contents")],
+ "make ext2/3/4 external journal",
+ "\
+This creates an ext2 external journal on C<device>. It is equivalent
+to the command:
+
+ mke2fs -O journal_dev -b blocksize device");
+
+ ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
+ [InitEmpty, Always, TestOutput (
+ [["sfdiskM"; "/dev/sda"; ",100 ,"];
+ ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
+ ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
+ ["mount"; "/dev/sda2"; "/"];
+ ["write_file"; "/new"; "new file contents"; "0"];
+ ["cat"; "/new"]], "new file contents")],
+ "make ext2/3/4 external journal with label",
+ "\
+This creates an ext2 external journal on C<device> with label C<label>.");
+
+ ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [],
+ (let uuid = uuidgen () in
+ [InitEmpty, Always, TestOutput (
+ [["sfdiskM"; "/dev/sda"; ",100 ,"];
+ ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
+ ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
+ ["mount"; "/dev/sda2"; "/"];
+ ["write_file"; "/new"; "new file contents"; "0"];
+ ["cat"; "/new"]], "new file contents")]),
+ "make ext2/3/4 external journal with UUID",
+ "\
+This creates an ext2 external journal on C<device> with UUID C<uuid>.");
+
+ ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
+ [],
+ "make ext2/3/4 filesystem with external journal",
+ "\
+This creates an ext2/3/4 filesystem on C<device> with
+an external journal on C<journal>. It is equivalent
+to the command:
+
+ mke2fs -t fstype -b blocksize -J device=<journal> <device>
+
+See also C<guestfs_mke2journal>.");
+
+ ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
+ [],
+ "make ext2/3/4 filesystem with external journal",
+ "\
+This creates an ext2/3/4 filesystem on C<device> with
+an external journal on the journal labeled C<label>.
+
+See also C<guestfs_mke2journal_L>.");
+
+ ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [],
+ [],
+ "make ext2/3/4 filesystem with external journal",
+ "\
+This creates an ext2/3/4 filesystem on C<device> with
+an external journal on the journal with UUID C<uuid>.
+
+See also C<guestfs_mke2journal_U>.");
+
+ ("modprobe", (RErr, [String "modulename"]), 194, [],
+ [InitNone, Always, TestRun [["modprobe"; "fat"]]],
+ "load a kernel module",
+ "\
+This loads a kernel module in the appliance.
+
+The kernel module must have been whitelisted when libguestfs
+was built (see C<appliance/kmod.whitelist.in> in the source).");
+
+ ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
+ [InitNone, Always, TestOutput (
+ [["echo_daemon"; "This is a test"]], "This is a test"
+ )],
+ "echo arguments back to the client",
+ "\
+This command concatenate the list of C<words> passed with single spaces between
+them and returns the resulting string.
+
+You can use this command to test the connection through to the daemon.
+
+See also C<guestfs_ping_daemon>.");
+
+ ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
+ [], (* There is a regression test for this. *)
+ "find all files and directories, returning NUL-separated list",
+ "\
+This command lists out all files and directories, recursively,
+starting at C<directory>, placing the resulting list in the
+external file called C<files>.
+
+This command works the same way as C<guestfs_find> with the
+following exceptions:
+
+=over 4
+
+=item *
+
+The resulting list is written to an external file.
+
+=item *
+
+Items (filenames) in the result are separated
+by C<\\0> characters. See L<find(1)> option I<-print0>.
+
+=item *
+
+This command is not limited in the number of names that it
+can return.
+
+=item *
+
+The result list is not sorted.
+
+=back");
+
+ ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
+ [InitISOFS, Always, TestOutput (
+ [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
+ InitISOFS, Always, TestOutput (
+ [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
+ InitISOFS, Always, TestOutput (
+ [["case_sensitive_path"; "/Known-1"]], "/known-1");
+ InitISOFS, Always, TestLastFail (
+ [["case_sensitive_path"; "/Known-1/"]]);
+ InitBasicFS, Always, TestOutput (
+ [["mkdir"; "/a"];
+ ["mkdir"; "/a/bbb"];
+ ["touch"; "/a/bbb/c"];
+ ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
+ InitBasicFS, Always, TestOutput (
+ [["mkdir"; "/a"];
+ ["mkdir"; "/a/bbb"];
+ ["touch"; "/a/bbb/c"];
+ ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
+ InitBasicFS, Always, TestLastFail (
+ [["mkdir"; "/a"];
+ ["mkdir"; "/a/bbb"];
+ ["touch"; "/a/bbb/c"];
+ ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
+ "return true path on case-insensitive filesystem",
+ "\
+This can be used to resolve case insensitive paths on
+a filesystem which is case sensitive. The use case is
+to resolve paths which you have read from Windows configuration
+files or the Windows Registry, to the true path.
+
+The command handles a peculiarity of the Linux ntfs-3g
+filesystem driver (and probably others), which is that although
+the underlying filesystem is case-insensitive, the driver
+exports the filesystem to Linux as case-sensitive.
+
+One consequence of this is that special directories such
+as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
+(or other things) depending on the precise details of how
+they were created. In Windows itself this would not be
+a problem.
+
+Bug or feature? You decide:
+L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
+
+This function resolves the true case of each element in the
+path and returns the case-sensitive path.
+
+Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
+might return C<\"/WINDOWS/system32\"> (the exact return value
+would depend on details of how the directories were originally
+created under Windows).
+
+I<Note>:
+This function does not handle drive names, backslashes etc.
+
+See also C<guestfs_realpath>.");
+
+ ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
+ [InitBasicFS, Always, TestOutput (
+ [["vfs_type"; "/dev/sda1"]], "ext2")],
+ "get the Linux VFS type corresponding to a mounted device",
+ "\
+This command gets the block device type corresponding to
+a mounted device called C<device>.
+
+Usually the result is the name of the Linux VFS module that
+is used to mount this device (probably determined automatically
+if you used the C<guestfs_mount> call).");
+
+ ("truncate", (RErr, [Pathname "path"]), 199, [],
+ [InitBasicFS, Always, TestOutputStruct (
+ [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
+ ["truncate"; "/test"];
+ ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
+ "truncate a file to zero size",
+ "\
+This command truncates C<path> to a zero-length file. The
+file must exist already.");
+
+ ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
+ [InitBasicFS, Always, TestOutputStruct (
+ [["touch"; "/test"];
+ ["truncate_size"; "/test"; "1000"];
+ ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
+ "truncate a file to a particular size",
+ "\
+This command truncates C<path> to size C<size> bytes. The file
+must exist already. If the file is smaller than C<size> then
+the file is extended to the required size with null bytes.");
+
+ ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
+ [InitBasicFS, Always, TestOutputStruct (
+ [["touch"; "/test"];
+ ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
+ ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
+ "set timestamp of a file with nanosecond precision",
+ "\
+This command sets the timestamps of a file with nanosecond
+precision.
+
+C<atsecs, atnsecs> are the last access time (atime) in secs and
+nanoseconds from the epoch.
+
+C<mtsecs, mtnsecs> are the last modification time (mtime) in
+secs and nanoseconds from the epoch.
+
+If the C<*nsecs> field contains the special value C<-1> then
+the corresponding timestamp is set to the current time. (The
+C<*secs> field is ignored in this case).
+
+If the C<*nsecs> field contains the special value C<-2> then
+the corresponding timestamp is left unchanged. (The
+C<*secs> field is ignored in this case).");
+
+ ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
+ [InitBasicFS, Always, TestOutputStruct (
+ [["mkdir_mode"; "/test"; "0o111"];
+ ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
+ "create a directory with a particular mode",
+ "\
+This command creates a directory, setting the initial permissions
+of the directory to C<mode>. See also C<guestfs_mkdir>.");
+
+ ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
+ [], (* XXX *)
+ "change file owner and group",
+ "\
+Change the file owner to C<owner> and group to C<group>.
+This is like C<guestfs_chown> but if C<path> is a symlink then
+the link itself is changed, not the target.
+
+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).");
+
+ ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
+ [], (* XXX *)
+ "lstat on multiple files",
+ "\
+This call allows you to perform the C<guestfs_lstat> operation
+on multiple files, where all files are in the directory C<path>.
+C<names> is the list of files from this directory.
+
+On return you get a list of stat structs, with a one-to-one
+correspondence to the C<names> list. If any name did not exist
+or could not be lstat'd, then the C<ino> field of that structure
+is set to C<-1>.
+
+This call is intended for programs that want to efficiently
+list a directory contents without making many round-trips.
+See also C<guestfs_lxattrlist> for a similarly efficient call
+for getting extended attributes. Very long directory listings
+might cause the protocol message size to be exceeded, causing
+this call to fail. The caller must split up such requests
+into smaller groups of names.");
+
+ ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [],
+ [], (* XXX *)
+ "lgetxattr on multiple files",
+ "\
+This call allows you to get the extended attributes
+of multiple files, where all files are in the directory C<path>.
+C<names> is the list of files from this directory.
+
+On return you get a flat list of xattr structs which must be
+interpreted sequentially. The first xattr struct always has a zero-length
+C<attrname>. C<attrval> in this struct is zero-length
+to indicate there was an error doing C<lgetxattr> for this
+file, I<or> is a C string which is a decimal number
+(the number of following attributes for this file, which could
+be C<\"0\">). Then after the first xattr struct are the
+zero or more attributes for the first named file.
+This repeats for the second and subsequent files.
+
+This call is intended for programs that want to efficiently
+list a directory contents without making many round-trips.
+See also C<guestfs_lstatlist> for a similarly efficient call
+for getting standard stats. Very long directory listings
+might cause the protocol message size to be exceeded, causing
+this call to fail. The caller must split up such requests
+into smaller groups of names.");
+
+ ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
+ [], (* XXX *)
+ "readlink on multiple files",
+ "\
+This call allows you to do a C<readlink> operation
+on multiple files, where all files are in the directory C<path>.
+C<names> is the list of files from this directory.
+
+On return you get a list of strings, with a one-to-one
+correspondence to the C<names> list. Each string is the
+value of the symbol link.
+
+If the C<readlink(2)> operation fails on any name, then
+the corresponding result string is the empty string C<\"\">.
+However the whole operation is completed even if there
+were C<readlink(2)> errors, and so you can call this
+function with names where you don't know if they are
+symbolic links already (albeit slightly less efficient).
+
+This call is intended for programs that want to efficiently
+list a directory contents without making many round-trips.
+Very long directory listings might cause the protocol
+message size to be exceeded, causing
+this call to fail. The caller must split up such requests
+into smaller groups of names.");
+
+ ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
+ [InitISOFS, Always, TestOutputBuffer (
+ [["pread"; "/known-4"; "1"; "3"]], "\n")],
+ "read part of a file",
+ "\
+This command lets you read part of a file. It reads C<count>
+bytes of the file, starting at C<offset>, from file C<path>.
+
+This may read fewer bytes than requested. For further details
+see the L<pread(2)> system call.");
+
]
let all_functions = non_daemon_functions @ daemon_functions
"inotify_event", "INotifyEvent";
]
+(* What structs are actually returned. *)
+type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
+
+(* Returns a list of RStruct/RStructList structs that are returned
+ * by any function. Each element of returned list is a pair:
+ *
+ * (structname, RStructOnly)
+ * == there exists function which returns RStruct (_, structname)
+ * (structname, RStructListOnly)
+ * == there exists function which returns RStructList (_, structname)
+ * (structname, RStructAndList)
+ * == there are functions returning both RStruct (_, structname)
+ * and RStructList (_, structname)
+ *)
+let rstructs_used_by functions =
+ (* ||| is a "logical OR" for rstructs_used_t *)
+ let (|||) a b =
+ match a, b with
+ | RStructAndList, _
+ | _, RStructAndList -> RStructAndList
+ | RStructOnly, RStructListOnly
+ | RStructListOnly, RStructOnly -> RStructAndList
+ | RStructOnly, RStructOnly -> RStructOnly
+ | RStructListOnly, RStructListOnly -> RStructListOnly
+ in
+
+ let h = Hashtbl.create 13 in
+
+ (* if elem->oldv exists, update entry using ||| operator,
+ * else just add elem->newv to the hash
+ *)
+ let update elem newv =
+ try let oldv = Hashtbl.find h elem in
+ Hashtbl.replace h elem (newv ||| oldv)
+ with Not_found -> Hashtbl.add h elem newv
+ in
+
+ List.iter (
+ fun (_, style, _, _, _, _, _) ->
+ match fst style with
+ | RStruct (_, structname) -> update structname RStructOnly
+ | RStructList (_, structname) -> update structname RStructListOnly
+ | _ -> ()
+ ) functions;
+
+ (* return key->values as a list of (key,value) *)
+ Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
+
(* Used for testing language bindings. *)
type callt =
| CallString of string
| CallOptString of string option
| CallStringList of string list
| CallInt of int
+ | CallInt64 of int64
| CallBool of bool
(* Used to memoize the result of pod2text. *)
v
with
_ -> Hashtbl.create 13
+let pod2text_memo_updated () =
+ let chan = open_out pod2text_memo_filename in
+ output_value chan pod2text_memo;
+ close_out chan
(* Useful functions.
* Note we don't want to use any external OCaml libraries which
loop 0 xs
let name_of_argt = function
- | String n | OptString n | StringList n | Bool n | Int n
+ | Pathname n | Device n | Dev_or_Path n | String n | OptString n
+ | StringList n | DeviceList n | Bool n | Int n | Int64 n
| FileIn n | FileOut n -> n
let java_name_of_struct typ =
if n = "i" || n = "n" then
failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
if n = "argv" || n = "args" then
- failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name
+ failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
+
+ (* List Haskell, OCaml and C keywords here.
+ * http://www.haskell.org/haskellwiki/Keywords
+ * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
+ * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
+ * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
+ * |perl -pe 's/(.+)/"$1";/'|fmt -70
+ * Omitting _-containing words, since they're handled above.
+ * Omitting the OCaml reserved word, "val", is ok,
+ * and saves us from renaming several parameters.
+ *)
+ let reserved = [
+ "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
+ "char"; "class"; "const"; "constraint"; "continue"; "data";
+ "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
+ "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
+ "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
+ "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
+ "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
+ "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
+ "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
+ "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
+ "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
+ "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
+ "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
+ "volatile"; "when"; "where"; "while";
+ ] in
+ if List.mem n reserved then
+ failwithf "%s has param/ret using reserved word %s" name n;
in
(match fst style with
pr "struct %s_args {\n" name;
List.iter (
function
- | String n -> pr " string %s<>;\n" n
+ | Pathname n | Device n | Dev_or_Path n | String n ->
+ pr " string %s<>;\n" n
| OptString n -> pr " str *%s;\n" n
- | StringList n -> pr " str %s<>;\n" n
+ | StringList n | DeviceList n -> pr " str %s<>;\n" n
| Bool n -> pr " bool %s;\n" n
| Int n -> pr " int %s;\n" n
+ | Int64 n -> pr " hyper %s;\n" n
| FileIn _ | FileOut _ -> ()
) args;
pr "};\n\n"
name style
) all_functions
+(* Generate the guestfs-internal-actions.h file. *)
+and generate_internal_actions_h () =
+ generate_header CStyle LGPLv2;
+ List.iter (
+ fun (shortname, style, _, _, _, _, _) ->
+ let name = "guestfs__" ^ shortname in
+ generate_prototype ~single_line:true ~newline:true ~handle:"handle"
+ name style
+ ) non_daemon_functions
+
(* Generate the client-side dispatch stubs. *)
and generate_client_actions () =
generate_header CStyle LGPLv2;
pr "\
#include <stdio.h>
#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
#include \"guestfs.h\"
+#include \"guestfs-internal-actions.h\"
#include \"guestfs_protocol.h\"
#define error guestfs_error
-#define perrorf guestfs_perrorf
-#define safe_malloc guestfs_safe_malloc
+//#define perrorf guestfs_perrorf
+//#define safe_malloc guestfs_safe_malloc
#define safe_realloc guestfs_safe_realloc
-#define safe_strdup guestfs_safe_strdup
+//#define safe_strdup guestfs_safe_strdup
#define safe_memdup guestfs_safe_memdup
/* Check the return message from a call for validity. */
static int
check_reply_header (guestfs_h *g,
const struct guestfs_message_header *hdr,
- int proc_nr, int serial)
+ unsigned int proc_nr, unsigned int serial)
{
if (hdr->prog != GUESTFS_PROGRAM) {
error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
static int
check_state (guestfs_h *g, const char *caller)
{
- if (!guestfs_is_ready (g)) {
- if (guestfs_is_config (g))
+ if (!guestfs__is_ready (g)) {
+ if (guestfs__is_config (g) || guestfs__is_launching (g))
error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
caller);
- else if (guestfs_is_launching (g))
- error (g, \"%%s: call wait_ready() before using this function\",
- caller);
else
error (g, \"%%s called from the wrong state, %%d != READY\",
- caller, guestfs_get_state (g));
+ caller, guestfs__get_state (g));
return -1;
}
return 0;
";
- (* Client-side stubs for each function. *)
+ (* Generate code to generate guestfish call traces. *)
+ let trace_call shortname style =
+ pr " if (guestfs__get_trace (g)) {\n";
+
+ let needs_i =
+ List.exists (function
+ | StringList _ | DeviceList _ -> true
+ | _ -> false) (snd style) in
+ if needs_i then (
+ pr " int i;\n";
+ pr "\n"
+ );
+
+ pr " printf (\"%s\");\n" shortname;
+ List.iter (
+ function
+ | String n (* strings *)
+ | Device n
+ | Pathname n
+ | Dev_or_Path n
+ | FileIn n
+ | FileOut n ->
+ (* guestfish doesn't support string escaping, so neither do we *)
+ pr " printf (\" \\\"%%s\\\"\", %s);\n" n
+ | OptString n -> (* string option *)
+ pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
+ pr " else printf (\" null\");\n"
+ | StringList n
+ | DeviceList n -> (* string list *)
+ pr " putchar (' ');\n";
+ pr " putchar ('\"');\n";
+ pr " for (i = 0; %s[i]; ++i) {\n" n;
+ pr " if (i > 0) putchar (' ');\n";
+ pr " fputs (%s[i], stdout);\n" n;
+ pr " }\n";
+ pr " putchar ('\"');\n";
+ | Bool n -> (* boolean *)
+ pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
+ | Int n -> (* int *)
+ pr " printf (\" %%d\", %s);\n" n
+ | Int64 n ->
+ pr " printf (\" %%\" PRIi64, %s);\n" n
+ ) (snd style);
+ pr " putchar ('\\n');\n";
+ pr " }\n";
+ pr "\n";
+ in
+
+ (* For non-daemon functions, generate a wrapper around each function. *)
List.iter (
fun (shortname, style, _, _, _, _, _) ->
let name = "guestfs_" ^ shortname in
- (* Generate the context struct which stores the high-level
- * state between callback functions.
- *)
- pr "struct %s_ctx {\n" shortname;
- pr " /* This flag is set by the callbacks, so we know we've done\n";
- pr " * the callbacks as expected, and in the right sequence.\n";
- pr " * 0 = not called, 1 = reply_cb called.\n";
- pr " */\n";
- pr " int cb_sequence;\n";
- pr " struct guestfs_message_header hdr;\n";
- pr " struct guestfs_message_error err;\n";
- (match fst style with
- | RErr -> ()
- | RConstString _ | RConstOptString _ ->
- failwithf "RConstString|RConstOptString cannot be used by daemon functions"
- | RInt _ | RInt64 _
- | RBool _ | RString _ | RStringList _
- | RStruct _ | RStructList _
- | RHashtable _ | RBufferOut _ ->
- pr " struct %s_ret ret;\n" name
- );
- pr "};\n";
- pr "\n";
-
- (* Generate the reply callback function. *)
- pr "static void %s_reply_cb (guestfs_h *g, void *data, XDR *xdr)\n" shortname;
+ generate_prototype ~extern:false ~semicolon:false ~newline:true
+ ~handle:"g" name style;
pr "{\n";
- pr " guestfs_main_loop *ml = guestfs_get_main_loop (g);\n";
- pr " struct %s_ctx *ctx = (struct %s_ctx *) data;\n" shortname shortname;
- pr "\n";
- pr " /* This should definitely not happen. */\n";
- pr " if (ctx->cb_sequence != 0) {\n";
- pr " ctx->cb_sequence = 9999;\n";
- pr " error (g, \"%%s: internal error: reply callback called twice\", \"%s\");\n" name;
- pr " return;\n";
- pr " }\n";
- pr "\n";
- pr " ml->main_loop_quit (ml, g);\n";
- pr "\n";
- pr " if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {\n";
- pr " error (g, \"%%s: failed to parse reply header\", \"%s\");\n" name;
- pr " return;\n";
- pr " }\n";
- pr " if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {\n";
- pr " if (!xdr_guestfs_message_error (xdr, &ctx->err)) {\n";
- pr " error (g, \"%%s: failed to parse reply error\", \"%s\");\n"
- name;
- pr " return;\n";
- pr " }\n";
- pr " goto done;\n";
- pr " }\n";
-
- (match fst style with
- | RErr -> ()
- | RConstString _ | RConstOptString _ ->
- failwithf "RConstString|RConstOptString cannot be used by daemon functions"
- | RInt _ | RInt64 _
- | RBool _ | RString _ | RStringList _
- | RStruct _ | RStructList _
- | RHashtable _ | RBufferOut _ ->
- pr " if (!xdr_%s_ret (xdr, &ctx->ret)) {\n" name;
- pr " error (g, \"%%s: failed to parse reply\", \"%s\");\n" name;
- pr " return;\n";
- pr " }\n";
- );
+ trace_call shortname style;
+ pr " return guestfs__%s " shortname;
+ generate_c_call_args ~handle:"g" style;
+ pr ";\n";
+ pr "}\n";
+ pr "\n"
+ ) non_daemon_functions;
- pr " done:\n";
- pr " ctx->cb_sequence = 1;\n";
- pr "}\n\n";
+ (* Client-side stubs for each function. *)
+ List.iter (
+ fun (shortname, style, _, _, _, _, _) ->
+ let name = "guestfs_" ^ shortname in
(* Generate the action stub. *)
generate_prototype ~extern:false ~semicolon:false ~newline:true
| _ -> pr " struct %s_args args;\n" name
);
- pr " struct %s_ctx ctx;\n" shortname;
- pr " guestfs_main_loop *ml = guestfs_get_main_loop (g);\n";
+ pr " guestfs_message_header hdr;\n";
+ pr " guestfs_message_error err;\n";
+ let has_ret =
+ match fst style with
+ | RErr -> false
+ | RConstString _ | RConstOptString _ ->
+ failwithf "RConstString|RConstOptString cannot be used by daemon functions"
+ | RInt _ | RInt64 _
+ | RBool _ | RString _ | RStringList _
+ | RStruct _ | RStructList _
+ | RHashtable _ | RBufferOut _ ->
+ pr " struct %s_ret ret;\n" name;
+ true in
+
pr " int serial;\n";
+ pr " int r;\n";
pr "\n";
+ trace_call shortname style;
pr " if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
- pr " guestfs_set_busy (g);\n";
- pr "\n";
- pr " memset (&ctx, 0, sizeof ctx);\n";
+ pr " guestfs___set_busy (g);\n";
pr "\n";
(* Send the main header and arguments. *)
(match snd style with
| [] ->
- pr " serial = guestfs__send_sync (g, GUESTFS_PROC_%s, NULL, NULL);\n"
+ pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
(String.uppercase shortname)
| args ->
List.iter (
function
- | String n ->
+ | Pathname n | Device n | Dev_or_Path n | String n ->
pr " args.%s = (char *) %s;\n" n n
| OptString n ->
pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
- | StringList n ->
+ | StringList n | DeviceList n ->
pr " args.%s.%s_val = (char **) %s;\n" n n n;
pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
| Bool n ->
pr " args.%s = %s;\n" n n
| Int n ->
pr " args.%s = %s;\n" n n
+ | Int64 n ->
+ pr " args.%s = %s;\n" n n
| FileIn _ | FileOut _ -> ()
) args;
- pr " serial = guestfs__send_sync (g, GUESTFS_PROC_%s,\n"
+ pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
(String.uppercase shortname);
pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
name;
);
pr " if (serial == -1) {\n";
- pr " guestfs_end_busy (g);\n";
+ pr " guestfs___end_busy (g);\n";
pr " return %s;\n" error_code;
pr " }\n";
pr "\n";
List.iter (
function
| FileIn n ->
- pr " {\n";
- pr " int r;\n";
- pr "\n";
- pr " r = guestfs__send_file_sync (g, %s);\n" n;
- pr " if (r == -1) {\n";
- pr " guestfs_end_busy (g);\n";
- pr " return %s;\n" error_code;
- pr " }\n";
- pr " if (r == -2) /* daemon cancelled */\n";
- pr " goto read_reply;\n";
- need_read_reply_label := true;
+ pr " r = guestfs___send_file (g, %s);\n" n;
+ pr " if (r == -1) {\n";
+ pr " guestfs___end_busy (g);\n";
+ pr " return %s;\n" error_code;
pr " }\n";
+ pr " if (r == -2) /* daemon cancelled */\n";
+ pr " goto read_reply;\n";
+ need_read_reply_label := true;
pr "\n";
| _ -> ()
) (snd style);
(* Wait for the reply from the remote end. *)
if !need_read_reply_label then pr " read_reply:\n";
- pr " guestfs__switch_to_receiving (g);\n";
- pr " ctx.cb_sequence = 0;\n";
- pr " guestfs_set_reply_callback (g, %s_reply_cb, &ctx);\n" shortname;
- pr " (void) ml->main_loop_run (ml, g);\n";
- pr " guestfs_set_reply_callback (g, NULL, NULL);\n";
- pr " if (ctx.cb_sequence != 1) {\n";
- pr " error (g, \"%%s reply failed, see earlier error messages\", \"%s\");\n" name;
- pr " guestfs_end_busy (g);\n";
+ pr " memset (&hdr, 0, sizeof hdr);\n";
+ pr " memset (&err, 0, sizeof err);\n";
+ if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
+ pr "\n";
+ pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
+ if not has_ret then
+ pr "NULL, NULL"
+ else
+ pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
+ pr ");\n";
+
+ pr " if (r == -1) {\n";
+ pr " guestfs___end_busy (g);\n";
pr " return %s;\n" error_code;
pr " }\n";
pr "\n";
- pr " if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
+ pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
(String.uppercase shortname);
- pr " guestfs_end_busy (g);\n";
+ pr " guestfs___end_busy (g);\n";
pr " return %s;\n" error_code;
pr " }\n";
pr "\n";
- pr " if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {\n";
- pr " error (g, \"%%s\", ctx.err.error_message);\n";
- pr " free (ctx.err.error_message);\n";
- pr " guestfs_end_busy (g);\n";
+ pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
+ pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
+ pr " free (err.error_message);\n";
+ pr " guestfs___end_busy (g);\n";
pr " return %s;\n" error_code;
pr " }\n";
pr "\n";
List.iter (
function
| FileOut n ->
- pr " if (guestfs__receive_file_sync (g, %s) == -1) {\n" n;
- pr " guestfs_end_busy (g);\n";
+ pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
+ pr " guestfs___end_busy (g);\n";
pr " return %s;\n" error_code;
pr " }\n";
pr "\n";
| _ -> ()
) (snd style);
- pr " guestfs_end_busy (g);\n";
+ pr " guestfs___end_busy (g);\n";
(match fst style with
| RErr -> pr " return 0;\n"
| RInt n | RInt64 n | RBool n ->
- pr " return ctx.ret.%s;\n" n
+ pr " return ret.%s;\n" n
| RConstString _ | RConstOptString _ ->
failwithf "RConstString|RConstOptString cannot be used by daemon functions"
| RString n ->
- pr " return ctx.ret.%s; /* caller will free */\n" n
+ pr " return ret.%s; /* caller will free */\n" n
| RStringList n | RHashtable n ->
pr " /* caller will free this, but we need to add a NULL entry */\n";
- pr " ctx.ret.%s.%s_val =\n" n n;
- pr " safe_realloc (g, ctx.ret.%s.%s_val,\n" n n;
- pr " sizeof (char *) * (ctx.ret.%s.%s_len + 1));\n"
+ pr " ret.%s.%s_val =\n" n n;
+ pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
+ pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
n n;
- pr " ctx.ret.%s.%s_val[ctx.ret.%s.%s_len] = NULL;\n" n n n n;
- pr " return ctx.ret.%s.%s_val;\n" n n
+ pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
+ pr " return ret.%s.%s_val;\n" n n
| RStruct (n, _) ->
pr " /* caller will free this */\n";
- pr " return safe_memdup (g, &ctx.ret.%s, sizeof (ctx.ret.%s));\n" n n
+ pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
| RStructList (n, _) ->
pr " /* caller will free this */\n";
- pr " return safe_memdup (g, &ctx.ret.%s, sizeof (ctx.ret.%s));\n" n n
+ pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
| RBufferOut n ->
- pr " *size_r = ctx.ret.%s.%s_len;\n" n n;
- pr " return ctx.ret.%s.%s_val; /* caller will free */\n" n n
+ pr " *size_r = ret.%s.%s_len;\n" n n;
+ pr " return ret.%s.%s_val; /* caller will free */\n" n n
);
pr "}\n\n"
pr "#include <stdlib.h>\n";
pr "#include <string.h>\n";
pr "#include <inttypes.h>\n";
- pr "#include <ctype.h>\n";
pr "#include <rpc/types.h>\n";
pr "#include <rpc/xdr.h>\n";
pr "\n";
pr "#include \"daemon.h\"\n";
+ pr "#include \"c-ctype.h\"\n";
pr "#include \"../src/guestfs_protocol.h\"\n";
pr "#include \"actions.h\"\n";
pr "\n";
pr " struct guestfs_%s_args args;\n" name;
List.iter (
function
- (* Note we allow the string to be writable, in order to
- * allow device name translation. This is safe because
- * we can modify the string (passed from RPC).
- *)
- | String n
+ | Device n | Dev_or_Path n
+ | Pathname n
+ | String n -> ()
| OptString n -> pr " char *%s;\n" n
- | StringList n -> pr " char **%s;\n" n
+ | StringList n | DeviceList n -> pr " char **%s;\n" n
| Bool n -> pr " int %s;\n" n
| Int n -> pr " int %s;\n" n
+ | Int64 n -> pr " int64_t %s;\n" n
| FileIn _ | FileOut _ -> ()
) args
);
pr " reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
pr " return;\n";
pr " }\n";
+ let pr_args n =
+ pr " char *%s = args.%s;\n" n n
+ in
+ let pr_list_handling_code n =
+ pr " %s = realloc (args.%s.%s_val,\n" n n n;
+ pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
+ pr " if (%s == NULL) {\n" n;
+ pr " reply_with_perror (\"realloc\");\n";
+ pr " goto done;\n";
+ pr " }\n";
+ pr " %s[args.%s.%s_len] = NULL;\n" n n n;
+ pr " args.%s.%s_val = %s;\n" n n n;
+ in
List.iter (
function
- | String n -> pr " %s = args.%s;\n" n n
+ | Pathname n ->
+ pr_args n;
+ pr " ABS_PATH (%s, goto done);\n" n;
+ | Device n ->
+ pr_args n;
+ pr " RESOLVE_DEVICE (%s, goto done);\n" n;
+ | Dev_or_Path n ->
+ pr_args n;
+ pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
+ | String n -> pr_args n
| OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
| StringList n ->
- pr " %s = realloc (args.%s.%s_val,\n" n n n;
- pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
- pr " if (%s == NULL) {\n" n;
- pr " reply_with_perror (\"realloc\");\n";
- pr " goto done;\n";
+ pr_list_handling_code n;
+ | DeviceList n ->
+ pr_list_handling_code n;
+ pr " /* Ensure that each is a device,\n";
+ pr " * and perform device name translation. */\n";
+ pr " { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
+ pr " RESOLVE_DEVICE (physvols[pvi], goto done);\n";
pr " }\n";
- pr " %s[args.%s.%s_len] = NULL;\n" n n n;
- pr " args.%s.%s_val = %s;\n" n n n;
| Bool n -> pr " %s = args.%s;\n" n n
| Int n -> pr " %s = args.%s;\n" n n
+ | Int64 n -> pr " %s = args.%s;\n" n n
| FileIn _ | FileOut _ -> ()
) args;
pr "\n"
);
+
+ (* this is used at least for do_equal *)
+ if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
+ (* Emit NEED_ROOT just once, even when there are two or
+ more Pathname args *)
+ pr " NEED_ROOT (goto done);\n";
+ );
+
(* Don't want to call the impl with any FileIn or FileOut
* parameters, since these go "outside" the RPC protocol.
*)
pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
pr " return -1;\n";
pr " }\n";
- pr " if (!*str || isspace (*str)) {\n";
+ pr " if (!*str || c_isspace (*str)) {\n";
pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
pr " return -1;\n";
pr " }\n";
pr " pend++;\n";
pr " }\n";
pr "\n";
- pr " while (*p && isspace (*p)) /* Skip any leading whitespace. */\n";
+ pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
pr " p++;\n";
pr "\n";
pr " if (!*p) { /* Empty line? Skip it. */\n";
fprintf (stderr, \"%%s\\n\", msg);
}
-static void print_strings (char * const * const argv)
+/* FIXME: nearly identical code appears in fish.c */
+static void print_strings (char *const *argv)
{
int argc;
}
/*
-static void print_table (char * const * const argv)
+static void print_table (char const *const *argv)
{
int i;
int main (int argc, char *argv[])
{
char c = 0;
- int failed = 0;
+ unsigned long int n_failed = 0;
const char *filename;
int fd;
int nr_tests, test_num = 0;
exit (1);
}
- if (guestfs_add_drive_ro (g, \"../images/test.sqsh\") == -1) {
- printf (\"guestfs_add_drive_ro ../images/test.sqsh FAILED\\n\");
+ if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
+ printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
exit (1);
}
/* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
alarm (600);
- if (guestfs_wait_ready (g) == -1) {
- printf (\"guestfs_wait_ready FAILED\\n\");
- exit (1);
- }
-
/* Cancel previous alarm. */
alarm (0);
pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
pr " if (%s () == -1) {\n" test_name;
pr " printf (\"%s FAILED\\n\");\n" test_name;
- pr " failed++;\n";
+ pr " n_failed++;\n";
pr " }\n";
) test_names;
pr "\n";
pr " unlink (\"test3.img\");\n";
pr "\n";
- pr " if (failed > 0) {\n";
- pr " printf (\"***** %%d / %%d tests FAILED *****\\n\", failed, nr_tests);\n";
+ pr " if (n_failed > 0) {\n";
+ pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
pr " exit (1);\n";
pr " }\n";
pr "\n";
[["blockdev_setrw"; "/dev/sda"];
["umount_all"];
["lvm_remove_all"]]
+ | InitPartition ->
+ pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
+ List.iter (generate_test_command_call test_name)
+ [["blockdev_setrw"; "/dev/sda"];
+ ["umount_all"];
+ ["lvm_remove_all"];
+ ["sfdiskM"; "/dev/sda"; ","]]
| InitBasicFS ->
pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
List.iter (generate_test_command_call test_name)
["lvcreate"; "LV"; "VG"; "8"];
["mkfs"; "ext2"; "/dev/VG/LV"];
["mount"; "/dev/VG/LV"; "/"]]
- | InitSquashFS ->
- pr " /* InitSquashFS for %s */\n" test_name;
+ | InitISOFS ->
+ pr " /* InitISOFS for %s */\n" test_name;
List.iter (generate_test_command_call test_name)
[["blockdev_setrw"; "/dev/sda"];
["umount_all"];
["lvm_remove_all"];
- ["mount_vfs"; "ro"; "squashfs"; "/dev/sdd"; "/"]]
+ ["mount_ro"; "/dev/sdd"; "/"]]
);
let get_seq_last = function
List.iter (
function
| OptString n, "NULL" -> ()
+ | Pathname n, arg
+ | Device n, arg
+ | Dev_or_Path n, arg
| String n, arg
| OptString n, arg ->
pr " const char *%s = \"%s\";\n" n (c_quote arg);
| Int _, _
+ | Int64 _, _
| Bool _, _
| FileIn _, _ | FileOut _, _ -> ()
- | StringList n, arg ->
+ | StringList n, arg | DeviceList n, arg ->
let strs = string_split " " arg in
iteri (
fun i str ->
pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
) strs;
- pr " const char *%s[] = {\n" n;
+ pr " const char *const %s[] = {\n" n;
iteri (
fun i _ -> pr " %s_%d,\n" n i
) strs;
List.iter (
function
| OptString _, "NULL" -> pr ", NULL"
+ | Pathname n, _
+ | Device n, _ | Dev_or_Path n, _
| String n, _
| OptString n, _ ->
pr ", %s" n
| FileIn _, arg | FileOut _, arg ->
pr ", \"%s\"" (c_quote arg)
- | StringList n, _ ->
- pr ", %s" n
+ | StringList n, _ | DeviceList n, _ ->
+ pr ", (char **) %s" n
| Int _, arg ->
let i =
try int_of_string arg
with Failure "int_of_string" ->
failwithf "%s: expecting an int, but got '%s'" test_name arg in
pr ", %d" i
+ | Int64 _, arg ->
+ let i =
+ try Int64.of_string arg
+ with Failure "int_of_string" ->
+ failwithf "%s: expecting an int64, but got '%s'" test_name arg in
+ pr ", %Ld" i
| Bool _, arg ->
let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
) (List.combine (snd style) args);
pr "#include <stdlib.h>\n";
pr "#include <string.h>\n";
pr "#include <inttypes.h>\n";
- pr "#include <ctype.h>\n";
pr "\n";
pr "#include <guestfs.h>\n";
+ pr "#include \"c-ctype.h\"\n";
pr "#include \"fish.h\"\n";
pr "\n";
pr "}\n";
pr "\n";
+ let emit_print_list_function typ =
+ pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
+ typ typ typ;
+ pr "{\n";
+ pr " unsigned int i;\n";
+ pr "\n";
+ pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
+ pr " printf (\"[%%d] = {\\n\", i);\n";
+ pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
+ pr " printf (\"}\\n\");\n";
+ pr " }\n";
+ pr "}\n";
+ pr "\n";
+ in
+
(* print_* functions *)
List.iter (
fun (typ, cols) ->
pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
pr "{\n";
if needs_i then (
- pr " int i;\n";
+ pr " unsigned int i;\n";
pr "\n"
);
List.iter (
| name, FString ->
pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
| name, FUUID ->
- pr " printf (\"%s: \");\n" name;
+ pr " printf (\"%%s%s: \", indent);\n" name;
pr " for (i = 0; i < 32; ++i)\n";
- pr " printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
+ pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
pr " printf (\"\\n\");\n"
| name, FBuffer ->
pr " printf (\"%%s%s: \", indent);\n" name;
pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
- pr " if (isprint (%s->%s[i]))\n" typ name;
- pr " printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
+ pr " if (c_isprint (%s->%s[i]))\n" typ name;
+ pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
pr " else\n";
- pr " printf (\"%%s\\\\x%%02x\", indent, %s->%s[i]);\n" typ name;
+ pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
pr " printf (\"\\n\");\n"
| name, (FUInt64|FBytes) ->
pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
) cols;
pr "}\n";
pr "\n";
- pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
- pr "{\n";
- pr " print_%s_indent (%s, \"\");\n" typ typ;
- pr "}\n";
- pr "\n";
- pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
- typ typ typ;
- pr "{\n";
- pr " int i;\n";
- pr "\n";
- pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
- pr " printf (\"[%%d] = {\\n\", i);\n";
- pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
- pr " printf (\"}\\n\");\n";
- pr " }\n";
- pr "}\n";
- pr "\n";
) structs;
+ (* Emit a print_TYPE_list function definition only if that function is used. *)
+ List.iter (
+ function
+ | typ, (RStructListOnly | RStructAndList) ->
+ (* generate the function for typ *)
+ emit_print_list_function typ
+ | typ, _ -> () (* empty *)
+ ) (rstructs_used_by all_functions);
+
+ (* Emit a print_TYPE function definition only if that function is used. *)
+ List.iter (
+ function
+ | typ, (RStructOnly | RStructAndList) ->
+ pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
+ pr "{\n";
+ pr " print_%s_indent (%s, \"\");\n" typ typ;
+ pr "}\n";
+ pr "\n";
+ | typ, _ -> () (* empty *)
+ ) (rstructs_used_by all_functions);
+
(* run_<action> actions *)
List.iter (
fun (name, style, _, flags, _, _, _) ->
);
List.iter (
function
+ | Device n
| String n
| OptString n
| FileIn n
| FileOut n -> pr " const char *%s;\n" n
- | StringList n -> pr " char **%s;\n" n
+ | Pathname n
+ | Dev_or_Path n -> pr " char *%s;\n" n
+ | StringList n | DeviceList n -> pr " char **%s;\n" n
| Bool n -> pr " int %s;\n" n
| Int n -> pr " int %s;\n" n
+ | Int64 n -> pr " int64_t %s;\n" n
) (snd style);
(* Check and convert parameters. *)
iteri (
fun i ->
function
- | String name -> pr " %s = argv[%d];\n" name i
+ | Device name
+ | String name ->
+ pr " %s = argv[%d];\n" name i
+ | Pathname name
+ | Dev_or_Path name ->
+ pr " %s = resolve_win_path (argv[%d]);\n" name i;
+ pr " if (%s == NULL) return -1;\n" name
| OptString name ->
pr " %s = strcmp (argv[%d], \"\") != 0 ? argv[%d] : NULL;\n"
name i i
| FileOut name ->
pr " %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdout\";\n"
name i i
- | StringList name ->
- pr " %s = parse_string_list (argv[%d]);\n" name i
+ | StringList name | DeviceList name ->
+ pr " %s = parse_string_list (argv[%d]);\n" name i;
+ pr " if (%s == NULL) return -1;\n" name;
| Bool name ->
pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
| Int name ->
pr " %s = atoi (argv[%d]);\n" name i
+ | Int64 name ->
+ pr " %s = atoll (argv[%d]);\n" name i
) (snd style);
(* Call C API function. *)
generate_c_call_args ~handle:"g" style;
pr ";\n";
+ List.iter (
+ function
+ | Device name | String name
+ | OptString name | FileIn name | FileOut name | Bool name
+ | Int name | Int64 name -> ()
+ | Pathname name | Dev_or_Path name ->
+ pr " free (%s);\n" name
+ | StringList name | DeviceList name ->
+ pr " free_strings (%s);\n" name
+ ) (snd style);
+
(* Check return value for errors and display command results. *)
(match fst style with
| RErr -> pr " return r;\n"
pr " %s" name;
List.iter (
function
- | String n -> pr " %s" n
+ | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
| OptString n -> pr " %s" n
- | StringList n -> pr " '%s ...'" n
+ | StringList n | DeviceList n -> pr " '%s ...'" n
| Bool _ -> pr " true|false"
| Int n -> pr " %s" n
+ | Int64 n -> pr " %s" n
| FileIn n | FileOut n -> pr " (%s|-)" n
) (snd style);
pr "\n";
in
List.iter (
function
+ | Pathname n
+ | Device n | Dev_or_Path n
| String n
| OptString n ->
next ();
- if not in_daemon then pr "const char *%s" n
- else pr "char *%s" n
- | StringList n ->
+ pr "const char *%s" n
+ | StringList n | DeviceList n ->
next ();
- if not in_daemon then pr "char * const* const %s" n
- else pr "char **%s" n
+ pr "char *const *%s" n
| Bool n -> next (); pr "int %s" n
| Int n -> next (); pr "int %s" n
+ | Int64 n -> next (); pr "int64_t %s" n
| FileIn n
| FileOut n ->
if not in_daemon then (next (); pr "const char *%s" n)
";
(* Struct copy functions. *)
+
+ let emit_ocaml_copy_list_function typ =
+ pr "static CAMLprim value\n";
+ pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
+ pr "{\n";
+ pr " CAMLparam0 ();\n";
+ pr " CAMLlocal2 (rv, v);\n";
+ pr " unsigned int i;\n";
+ pr "\n";
+ pr " if (%ss->len == 0)\n" typ;
+ pr " CAMLreturn (Atom (0));\n";
+ pr " else {\n";
+ pr " rv = caml_alloc (%ss->len, 0);\n" typ;
+ pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
+ pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
+ pr " caml_modify (&Field (rv, i), v);\n";
+ pr " }\n";
+ pr " CAMLreturn (rv);\n";
+ pr " }\n";
+ pr "}\n";
+ pr "\n";
+ in
+
List.iter (
fun (typ, cols) ->
let has_optpercent_col =
pr " CAMLreturn (rv);\n";
pr "}\n";
pr "\n";
-
- pr "static CAMLprim value\n";
- pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n"
- typ typ typ;
- pr "{\n";
- pr " CAMLparam0 ();\n";
- pr " CAMLlocal2 (rv, v);\n";
- pr " int i;\n";
- pr "\n";
- pr " if (%ss->len == 0)\n" typ;
- pr " CAMLreturn (Atom (0));\n";
- pr " else {\n";
- pr " rv = caml_alloc (%ss->len, 0);\n" typ;
- pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
- pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
- pr " caml_modify (&Field (rv, i), v);\n";
- pr " }\n";
- pr " CAMLreturn (rv);\n";
- pr " }\n";
- pr "}\n";
- pr "\n";
) structs;
+ (* Emit a copy_TYPE_list function definition only if that function is used. *)
+ List.iter (
+ function
+ | typ, (RStructListOnly | RStructAndList) ->
+ (* generate the function for typ *)
+ emit_ocaml_copy_list_function typ
+ | typ, _ -> () (* empty *)
+ ) (rstructs_used_by all_functions);
+
(* The wrappers. *)
List.iter (
fun (name, style, _, _, _, _, _) ->
let needs_extra_vs =
match fst style with RConstOptString _ -> true | _ -> false in
+ pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
+ pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
+ List.iter (pr ", value %s") (List.tl params); pr ");\n";
+
pr "CAMLprim value\n";
pr "ocaml_guestfs_%s (value %s" name (List.hd params);
List.iter (pr ", value %s") (List.tl params);
List.iter (
function
+ | Pathname n
+ | Device n | Dev_or_Path n
| String n
| FileIn n
| FileOut n ->
pr " const char *%s =\n" n;
pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
n n
- | StringList n ->
+ | StringList n | DeviceList n ->
pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
| Bool n ->
pr " int %s = Bool_val (%sv);\n" n n
| Int n ->
pr " int %s = Int_val (%sv);\n" n n
+ | Int64 n ->
+ pr " int64_t %s = Int64_val (%sv);\n" n n
) (snd style);
let error_code =
match fst style with
List.iter (
function
- | StringList n ->
+ | StringList n | DeviceList n ->
pr " ocaml_guestfs_free_strings (%s);\n" n;
- | String _ | OptString _ | Bool _ | Int _ | FileIn _ | FileOut _ -> ()
+ | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
+ | Bool _ | Int _ | Int64 _
+ | FileIn _ | FileOut _ -> ()
) (snd style);
pr " if (r == %s)\n" error_code;
pr "\n";
if List.length params > 5 then (
+ pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
+ pr "CAMLprim value ";
+ pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
pr "CAMLprim value\n";
pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
pr "{\n";
pr "%s : t -> " name;
List.iter (
function
- | String _ | FileIn _ | FileOut _ -> pr "string -> "
+ | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
| OptString _ -> pr "string option -> "
- | StringList _ -> pr "string array -> "
+ | StringList _ | DeviceList _ -> pr "string array -> "
| Bool _ -> pr "bool -> "
| Int _ -> pr "int -> "
+ | Int64 _ -> pr "int64 -> "
) (snd style);
(match fst style with
| RErr -> pr "unit" (* all errors are turned into exceptions *)
iteri (
fun i ->
function
- | String n | FileIn n | FileOut n -> pr " char *%s;\n" n
+ | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
+ pr " char *%s;\n" n
| OptString n ->
(* http://www.perlmonks.org/?node_id=554277
* Note that the implicit handle argument means we have
* to add 1 to the ST(x) operator.
*)
pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
- | StringList n -> pr " char **%s;\n" n
+ | StringList n | DeviceList n -> pr " char **%s;\n" n
| Bool n -> pr " int %s;\n" n
| Int n -> pr " int %s;\n" n
+ | Int64 n -> pr " int64_t %s;\n" n
) (snd style);
let do_cleanups () =
List.iter (
function
- | String _ | OptString _ | Bool _ | Int _
+ | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
+ | Bool _ | Int _ | Int64 _
| FileIn _ | FileOut _ -> ()
- | StringList n -> pr " free (%s);\n" n
+ | StringList n | DeviceList n -> pr " free (%s);\n" n
) (snd style)
in
my $h = Sys::Guestfs->new ();
$h->add_drive ('guest.img');
$h->launch ();
- $h->wait_ready ();
$h->mount ('/dev/sda1', '/');
$h->touch ('/hello');
$h->sync ();
if !comma then pr ", ";
comma := true;
match arg with
- | String n | OptString n | Bool n | Int n | FileIn n | FileOut n ->
+ | Pathname n | Device n | Dev_or_Path n | String n
+ | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
pr "$%s" n
- | StringList n ->
+ | StringList n | DeviceList n ->
pr "\\@%s" n
) (snd style);
pr ");"
generate_header CStyle LGPLv2;
pr "\
+#include <Python.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
-#include <Python.h>
-
#include \"guestfs.h\"
typedef struct {
}
/* This list should be freed (but not the strings) after use. */
-static const char **
+static char **
get_string_list (PyObject *obj)
{
int i, len;
- const char **r;
+ char **r;
assert (obj);
";
+ let emit_put_list_function typ =
+ pr "static PyObject *\n";
+ pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
+ pr "{\n";
+ pr " PyObject *list;\n";
+ pr " int i;\n";
+ pr "\n";
+ pr " list = PyList_New (%ss->len);\n" typ;
+ pr " for (i = 0; i < %ss->len; ++i)\n" typ;
+ pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
+ pr " return list;\n";
+ pr "};\n";
+ pr "\n"
+ in
+
(* Structures, turned into Python dictionaries. *)
List.iter (
fun (typ, cols) ->
typ name;
pr " else {\n";
pr " Py_INCREF (Py_None);\n";
- pr " PyDict_SetItemString (dict, \"%s\", Py_None);" name;
+ pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
pr " }\n"
| name, FChar ->
pr " PyDict_SetItemString (dict, \"%s\",\n" name;
pr "};\n";
pr "\n";
- pr "static PyObject *\n";
- pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
- pr "{\n";
- pr " PyObject *list;\n";
- pr " int i;\n";
- pr "\n";
- pr " list = PyList_New (%ss->len);\n" typ;
- pr " for (i = 0; i < %ss->len; ++i)\n" typ;
- pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
- pr " return list;\n";
- pr "};\n";
- pr "\n"
) structs;
+ (* Emit a put_TYPE_list function definition only if that function is used. *)
+ List.iter (
+ function
+ | typ, (RStructListOnly | RStructAndList) ->
+ (* generate the function for typ *)
+ emit_put_list_function typ
+ | typ, _ -> () (* empty *)
+ ) (rstructs_used_by all_functions);
+
(* Python wrapper functions. *)
List.iter (
fun (name, style, _, _, _, _, _) ->
List.iter (
function
- | String n | FileIn n | FileOut n -> pr " const char *%s;\n" n
+ | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
+ pr " const char *%s;\n" n
| OptString n -> pr " const char *%s;\n" n
- | StringList n ->
+ | StringList n | DeviceList n ->
pr " PyObject *py_%s;\n" n;
- pr " const char **%s;\n" n
+ pr " char **%s;\n" n
| Bool n -> pr " int %s;\n" n
| Int n -> pr " int %s;\n" n
+ | Int64 n -> pr " long long %s;\n" n
) (snd style);
pr "\n";
pr " if (!PyArg_ParseTuple (args, (char *) \"O";
List.iter (
function
- | String _ | FileIn _ | FileOut _ -> pr "s"
+ | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
| OptString _ -> pr "z"
- | StringList _ -> pr "O"
+ | StringList _ | DeviceList _ -> pr "O"
| Bool _ -> pr "i" (* XXX Python has booleans? *)
| Int _ -> pr "i"
+ | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
+ * emulate C's int/long/long long in Python?
+ *)
) (snd style);
pr ":guestfs_%s\",\n" name;
pr " &py_g";
List.iter (
function
- | String n | FileIn n | FileOut n -> pr ", &%s" n
+ | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
| OptString n -> pr ", &%s" n
- | StringList n -> pr ", &py_%s" n
+ | StringList n | DeviceList n -> pr ", &py_%s" n
| Bool n -> pr ", &%s" n
| Int n -> pr ", &%s" n
+ | Int64 n -> pr ", &%s" n
) (snd style);
pr "))\n";
pr " g = get_handle (py_g);\n";
List.iter (
function
- | String _ | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
- | StringList n ->
+ | Pathname _ | Device _ | Dev_or_Path _ | String _
+ | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
+ | StringList n | DeviceList n ->
pr " %s = get_string_list (py_%s);\n" n n;
pr " if (!%s) return NULL;\n" n
) (snd style);
List.iter (
function
- | String _ | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
- | StringList n ->
+ | Pathname _ | Device _ | Dev_or_Path _ | String _
+ | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
+ | StringList n | DeviceList n ->
pr " free (%s);\n" n
) (snd style);
g = guestfs.GuestFS ()
g.add_drive (\"guest.img\")
g.launch ()
-g.wait_ready ()
parts = g.list_partitions ()
The guestfs module provides a Python binding to the libguestfs API
# Launch the qemu subprocess and wait for it to become ready:
g.launch ()
-g.wait_ready ()
# Now you can issue commands, for example:
logvols = g.lvs ()
failwithf "pod2text: process signalled or stopped by signal %d" i
);
Hashtbl.add pod2text_memo key lines;
- let chan = open_out pod2text_memo_filename in
- output_value chan pod2text_memo;
- close_out chan;
+ pod2text_memo_updated ();
lines
(* Generate ruby bindings. *)
List.iter (
function
- | String n | FileIn n | FileOut n ->
+ | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
pr " Check_Type (%sv, T_STRING);\n" n;
pr " const char *%s = StringValueCStr (%sv);\n" n n;
pr " if (!%s)\n" n;
pr " \"%s\", \"%s\");\n" n name
| OptString n ->
pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
- | StringList n ->
+ | StringList n | DeviceList n ->
pr " char **%s;\n" n;
pr " Check_Type (%sv, T_ARRAY);\n" n;
pr " {\n";
pr " int %s = RTEST (%sv);\n" n n
| Int n ->
pr " int %s = NUM2INT (%sv);\n" n n
+ | Int64 n ->
+ pr " long long %s = NUM2LL (%sv);\n" n n
) (snd style);
pr "\n";
List.iter (
function
- | String _ | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
- | StringList n ->
+ | Pathname _ | Device _ | Dev_or_Path _ | String _
+ | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
+ | StringList n | DeviceList n ->
pr " free (%s);\n" n
) (snd style);
needs_comma := true;
match arg with
+ | Pathname n
+ | Device n | Dev_or_Path n
| String n
| OptString n
| FileIn n
| FileOut n ->
pr "String %s" n
- | StringList n ->
+ | StringList n | DeviceList n ->
pr "String[] %s" n
| Bool n ->
pr "boolean %s" n
| Int n ->
pr "int %s" n
+ | Int64 n ->
+ pr "long %s" n
) (snd style);
pr ")\n";
pr " (JNIEnv *env, jobject obj, jlong jg";
List.iter (
function
+ | Pathname n
+ | Device n | Dev_or_Path n
| String n
| OptString n
| FileIn n
| FileOut n ->
pr ", jstring j%s" n
- | StringList n ->
+ | StringList n | DeviceList n ->
pr ", jobjectArray j%s" n
| Bool n ->
pr ", jboolean j%s" n
| Int n ->
pr ", jint j%s" n
+ | Int64 n ->
+ pr ", jlong j%s" n
) (snd style);
pr ")\n";
pr "{\n";
"NULL", "NULL" in
List.iter (
function
+ | Pathname n
+ | Device n | Dev_or_Path n
| String n
| OptString n
| FileIn n
| FileOut n ->
pr " const char *%s;\n" n
- | StringList n ->
+ | StringList n | DeviceList n ->
pr " int %s_len;\n" n;
pr " const char **%s;\n" n
| Bool n
| Int n ->
pr " int %s;\n" n
+ | Int64 n ->
+ pr " int64_t %s;\n" n
) (snd style);
let needs_i =
| RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
| RConstOptString _
| RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
- List.exists (function StringList _ -> true | _ -> false) (snd style) in
+ List.exists (function
+ | StringList _ -> true
+ | DeviceList _ -> true
+ | _ -> false) (snd style) in
if needs_i then
pr " int i;\n";
(* Get the parameters. *)
List.iter (
function
+ | Pathname n
+ | Device n | Dev_or_Path n
| String n
| FileIn n
| FileOut n ->
* a NULL parameter.
*)
pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
- | StringList n ->
+ | StringList n | DeviceList n ->
pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
pr " for (i = 0; i < %s_len; ++i) {\n" n;
pr " }\n";
pr " %s[%s_len] = NULL;\n" n n;
| Bool n
- | Int n ->
+ | Int n
+ | Int64 n ->
pr " %s = j%s;\n" n n
) (snd style);
(* Release the parameters. *)
List.iter (
function
+ | Pathname n
+ | Device n | Dev_or_Path n
| String n
| FileIn n
| FileOut n ->
| OptString n ->
pr " if (j%s)\n" n;
pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
- | StringList n ->
+ | StringList n | DeviceList n ->
pr " for (i = 0; i < %s_len; ++i) {\n" n;
pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
n;
pr " }\n";
pr " free (%s);\n" n
| Bool n
- | Int n -> ()
+ | Int n
+ | Int64 n -> ()
) (snd style);
(* Check for errors. *)
pr " guestfs_free_%s_list (r);\n" typ;
pr " return jr;\n"
+and generate_java_makefile_inc () =
+ generate_header HashStyle GPLv2;
+
+ pr "java_built_sources = \\\n";
+ List.iter (
+ fun (typ, jtyp) ->
+ pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
+ ) java_structs;
+ pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
+
and generate_haskell_hs () =
generate_header HaskellStyle LGPLv2;
function
| FileIn n
| FileOut n
- | String n -> pr "withCString %s $ \\%s -> " n n
+ | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
| OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
- | StringList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
- | Bool _ | Int _ -> ()
+ | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
+ | Bool _ | Int _ | Int64 _ -> ()
) (snd style);
(* Convert integer arguments. *)
let args =
function
| Bool n -> sprintf "(fromBool %s)" n
| Int n -> sprintf "(fromIntegral %s)" n
- | FileIn n | FileOut n | String n | OptString n | StringList n -> n
+ | Int64 n -> sprintf "(fromIntegral %s)" n
+ | FileIn n | FileOut n
+ | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
) (snd style) in
pr "withForeignPtr h (\\p -> c_%s %s)\n" name
(String.concat " " ("p" :: args));
List.iter (
fun arg ->
(match arg with
- | String _ -> pr "%s" string
+ | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
| OptString _ -> if hs then pr "Maybe String" else pr "CString"
- | StringList _ -> if hs then pr "[String]" else pr "Ptr CString"
+ | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
| Bool _ -> pr "%s" bool
| Int _ -> pr "%s" int
+ | Int64 _ -> pr "%s" int
| FileIn _ -> pr "%s" string
| FileOut _ -> pr "%s" string
);
#include <string.h>
#include \"guestfs.h\"
+#include \"guestfs-internal-actions.h\"
#include \"guestfs_protocol.h\"
#define error guestfs_error
#define safe_malloc guestfs_safe_malloc
static void
-print_strings (char * const* const argv)
+print_strings (char *const *argv)
{
int argc;
let () =
let (name, style, _, _, _, _, _) = test0 in
generate_prototype ~extern:false ~semicolon:false ~newline:true
- ~handle:"g" ~prefix:"guestfs_" name style;
+ ~handle:"g" ~prefix:"guestfs__" name style;
pr "{\n";
List.iter (
function
+ | Pathname n
+ | Device n | Dev_or_Path n
| String n
| FileIn n
| FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
| OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
- | StringList n -> pr " print_strings (%s);\n" n
+ | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
| Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
| Int n -> pr " printf (\"%%d\\n\", %s);\n" n
+ | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
) (snd style);
pr " /* Java changes stdout line buffering so we need this: */\n";
pr " fflush (stdout);\n";
if String.sub name (String.length name - 3) 3 <> "err" then (
pr "/* Test normal return. */\n";
generate_prototype ~extern:false ~semicolon:false ~newline:true
- ~handle:"g" ~prefix:"guestfs_" name style;
+ ~handle:"g" ~prefix:"guestfs__" name style;
pr "{\n";
(match fst style with
| RErr ->
) else (
pr "/* Test error return. */\n";
generate_prototype ~extern:false ~semicolon:false ~newline:true
- ~handle:"g" ~prefix:"guestfs_" name style;
+ ~handle:"g" ~prefix:"guestfs__" name style;
pr "{\n";
pr " error (g, \"error\");\n";
(match fst style with
"[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
| CallInt i when i >= 0 -> string_of_int i
| CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
+ | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
+ | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
| CallBool b -> string_of_bool b
) args
)
| CallStringList xs ->
"[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
| CallInt i -> string_of_int i
+ | CallInt64 i -> Int64.to_string i
| CallBool b -> if b then "1" else "0"
) args
)
| CallStringList xs ->
"[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
| CallInt i -> string_of_int i
+ | CallInt64 i -> Int64.to_string i
| CallBool b -> if b then "1" else "0"
) args
)
| CallStringList xs ->
"[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
| CallInt i -> string_of_int i
+ | CallInt64 i -> Int64.to_string i
| CallBool b -> string_of_bool b
) args
)
"new String[]{" ^
String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
| CallInt i -> string_of_int i
+ | CallInt64 i -> Int64.to_string i
| CallBool b -> string_of_bool b
) args
)
"[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
| CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
| CallInt i -> string_of_int i
+ | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
+ | CallInt64 i -> Int64.to_string i
| CallBool true -> "True"
| CallBool false -> "False"
) args
and generate_lang_bindtests call =
call "test0" [CallString "abc"; CallOptString (Some "def");
CallStringList []; CallBool false;
- CallInt 0; CallString "123"; CallString "456"];
+ CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
call "test0" [CallString "abc"; CallOptString None;
CallStringList []; CallBool false;
- CallInt 0; CallString "123"; CallString "456"];
+ CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
call "test0" [CallString ""; CallOptString (Some "def");
CallStringList []; CallBool false;
- CallInt 0; CallString "123"; CallString "456"];
+ CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
call "test0" [CallString ""; CallOptString (Some "");
CallStringList []; CallBool false;
- CallInt 0; CallString "123"; CallString "456"];
+ CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
call "test0" [CallString "abc"; CallOptString (Some "def");
CallStringList ["1"]; CallBool false;
- CallInt 0; CallString "123"; CallString "456"];
+ CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
call "test0" [CallString "abc"; CallOptString (Some "def");
CallStringList ["1"; "2"]; CallBool false;
- CallInt 0; CallString "123"; CallString "456"];
+ CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
call "test0" [CallString "abc"; CallOptString (Some "def");
CallStringList ["1"]; CallBool true;
- CallInt 0; CallString "123"; CallString "456"];
+ CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
call "test0" [CallString "abc"; CallOptString (Some "def");
CallStringList ["1"]; CallBool false;
- CallInt (-1); CallString "123"; CallString "456"];
+ CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
call "test0" [CallString "abc"; CallOptString (Some "def");
CallStringList ["1"]; CallBool false;
- CallInt (-2); CallString "123"; CallString "456"];
+ CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
call "test0" [CallString "abc"; CallOptString (Some "def");
CallStringList ["1"]; CallBool false;
- CallInt 1; CallString "123"; CallString "456"];
+ CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
call "test0" [CallString "abc"; CallOptString (Some "def");
CallStringList ["1"]; CallBool false;
- CallInt 2; CallString "123"; CallString "456"];
+ CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
call "test0" [CallString "abc"; CallOptString (Some "def");
CallStringList ["1"]; CallBool false;
- CallInt 4095; CallString "123"; CallString "456"];
+ CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
call "test0" [CallString "abc"; CallOptString (Some "def");
CallStringList ["1"]; CallBool false;
- CallInt 0; CallString ""; CallString ""]
+ CallInt 0; CallInt64 0L; CallString ""; CallString ""]
(* XXX Add here tests of the return and error functions. *)
generate_actions_h ();
close ();
+ let close = output_to "src/guestfs-internal-actions.h" in
+ generate_internal_actions_h ();
+ close ();
+
let close = output_to "src/guestfs-actions.c" in
generate_client_actions ();
close ();
) java_structs;
let close = output_to "java/Makefile.inc" in
- pr "java_built_sources =";
- List.iter (
- fun (typ, jtyp) ->
- pr " com/redhat/et/libguestfs/%s.java" jtyp;
- ) java_structs;
- pr " com/redhat/et/libguestfs/GuestFS.java\n";
+ generate_java_makefile_inc ();
close ();
let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in