(* This script generates a large amount of code and documentation for
* all the daemon actions.
- *
+ *
* To add a new action there are only two files you need to change,
* this one to describe the interface (see the big table of
* 'daemon_functions' below), and daemon/<somefile>.c to write the
* implementation.
- *
+ *
* After editing this file, run it (./src/generator.ml) to regenerate
* all the output files. 'make' will rerun this automatically when
* necessary. Note that if you are using a separate build directory
* you must run generator.ml from the _source_ directory.
- *
+ *
* IMPORTANT: This script should NOT print any warnings. If it prints
* warnings, you should treat them as errors.
*
#load "unix.cma";;
#load "str.cma";;
#directory "+xml-light";;
+#directory "+../pkg-lib/xml-light";; (* for GODI users *)
#load "xml-light.cma";;
open Unix
changes to be committed, although qemu can support this.
This is equivalent to the qemu parameter
-C<-drive file=filename,snapshot=on,if=...>.
+C<-drive file=filename,snapshot=on,readonly=on,if=...>.
C<if=...> is set at compile time by the configuration option
C<./configure --with-drive-if=...>. In the rare case where you
might need to change this at run time, use C<guestfs_add_drive_with_if>
or C<guestfs_add_drive_ro_with_if>.
+C<readonly=on> is only added where qemu supports this option.
+
Note that this call checks for the existence of C<filename>. This
stops you from specifying other types of drive which are supported
by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
You can also override this by setting the C<LIBGUESTFS_QEMU>
environment variable.
-Setting C<qemu> to C<NULL> restores the default qemu binary.");
+Setting C<qemu> to C<NULL> restores the default qemu binary.
+
+Note that you should call this function as early as possible
+after creating the handle. This is because some pre-launch
+operations depend on testing qemu features (by running C<qemu -help>).
+If the qemu binary changes, we don't retest features, and
+so you might see inconsistent results. Using the environment
+variable C<LIBGUESTFS_QEMU> is safest of all since that picks
+the qemu binary at the same time as the handle is created.");
("get_qemu", (RConstString "qemu", []), -1, [],
[InitNone, Always, TestRun (
If the destination is a device, it must be as large or larger
than the source file or device, otherwise the copy will fail.
-This command cannot do partial copies.");
+This command cannot do partial copies (see C<guestfs_copy_size>).");
("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
[InitBasicFS, Always, TestOutputInt (
See also C<guestfs_initrd_list>.");
+ ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
+ [],
+ "get the UUID of a physical volume",
+ "\
+This command returns the UUID of the LVM PV C<device>.");
+
+ ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
+ [],
+ "get the UUID of a volume group",
+ "\
+This command returns the UUID of the LVM VG named C<vgname>.");
+
+ ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
+ [],
+ "get the UUID of a logical volume",
+ "\
+This command returns the UUID of the LVM LV C<device>.");
+
+ ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
+ [],
+ "get the PV UUIDs containing the volume group",
+ "\
+Given a VG called C<vgname>, this returns the UUIDs of all
+the physical volumes that this volume group resides on.
+
+You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
+calls to associate physical volumes and volume groups.
+
+See also C<guestfs_vglvuuids>.");
+
+ ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
+ [],
+ "get the LV UUIDs of all LVs in the volume group",
+ "\
+Given a VG called C<vgname>, this returns the UUIDs of all
+the logical volumes created in this volume group.
+
+You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
+calls to associate logical volumes and volume groups.
+
+See also C<guestfs_vgpvuuids>.");
+
+ ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
+ [InitBasicFS, Always, TestOutputBuffer (
+ [["write_file"; "/src"; "hello, world"; "0"];
+ ["copy_size"; "/src"; "/dest"; "5"];
+ ["read_file"; "/dest"]], "hello")],
+ "copy size bytes from source to destination using dd",
+ "\
+This command copies exactly C<size> bytes from one source device
+or file C<src> to another destination device or file C<dest>.
+
+Note this will fail if the source is too short or if the destination
+is not large enough.");
+
]
let all_functions = non_daemon_functions @ daemon_functions
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
+#include <string.h>
#include <inttypes.h>
#include \"guestfs.h\"
pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
pr "\n";
pr " r = command (&out, &err,\n";
- pr " \"/sbin/lvm\", \"%ss\",\n" typ;
+ pr " \"lvm\", \"%ss\",\n" typ;
pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
pr " if (r == -1) {\n";
exit (EXIT_FAILURE);
}
+ /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
+ alarm (600);
+
if (guestfs_launch (g) == -1) {
printf (\"guestfs_launch FAILED\\n\");
exit (EXIT_FAILURE);
}
- /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
- alarm (600);
-
/* Cancel previous alarm. */
alarm (0);
| Bool _, _
| FileIn _, _ | FileOut _, _ -> ()
| StringList n, "" | DeviceList n, "" ->
- pr " const char *const %s[1] = { NULL };\n" n
+ pr " const char *const %s[1] = { NULL };\n" n
| StringList n, arg | DeviceList n, arg ->
let strs = string_split " " arg in
iteri (
and comment =
"The Int type in the generator is a signed 31 bit int." in
Some (min, max, comment) in
- parse_integer "xstrtol" "long" "int" range name i
+ parse_integer "xstrtoll" "long long" "int" range name i
| Int64 name ->
parse_integer "xstrtoll" "long long" "int64_t" None name i
) (snd style);
#endif /* HAVE_LIBREADLINE */
-char **do_completion (const char *text, int start, int end)
+#ifdef HAVE_RL_COMPLETION_MATCHES
+#define RL_COMPLETION_MATCHES rl_completion_matches
+#else
+#ifdef HAVE_COMPLETION_MATCHES
+#define RL_COMPLETION_MATCHES completion_matches
+#endif
+#endif /* else just fail if we don't have either symbol */
+
+char **
+do_completion (const char *text, int start, int end)
{
char **matches = NULL;
rl_completion_append_character = ' ';
if (start == 0)
- matches = rl_completion_matches (text, generator);
+ matches = RL_COMPLETION_MATCHES (text, generator);
else if (complete_dest_paths)
- matches = rl_completion_matches (text, complete_dest_paths_generator);
+ matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
#endif
return matches;
do_cleanups ();
pr " if (%s == NULL)\n" n;
pr " croak (\"%%s\", guestfs_last_error (g));\n";
- pr " RETVAL = newSVpv (%s, size);\n" n;
+ pr " RETVAL = newSVpvn (%s, size);\n" n;
pr " free (%s);\n" n;
pr " OUTPUT:\n";
pr " RETVAL\n"
pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
name (String.length name) n name
| name, FBuffer ->
- pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
+ pr " (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
name (String.length name) n name n name
| name, (FBytes|FUInt64) ->
pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
n name
| name, FBuffer ->
- pr " PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
+ pr " PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
n name n name
| name, FUUID ->
pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
List.iter (
fun (name, style, _, _, _, shortdesc, _) ->
let rec csharp_return_type () =
- match fst style with
- | RErr -> "void"
- | RBool n -> "bool"
- | RInt n -> "int"
- | RInt64 n -> "long"
- | RConstString n
- | RConstOptString n
- | RString n
- | RBufferOut n -> "string"
- | RStruct (_,n) -> "_" ^ n
- | RHashtable n -> "Hashtable"
- | RStringList n -> "string[]"
- | RStructList (_,n) -> sprintf "_%s[]" n
+ match fst style with
+ | RErr -> "void"
+ | RBool n -> "bool"
+ | RInt n -> "int"
+ | RInt64 n -> "long"
+ | RConstString n
+ | RConstOptString n
+ | RString n
+ | RBufferOut n -> "string"
+ | RStruct (_,n) -> "_" ^ n
+ | RHashtable n -> "Hashtable"
+ | RStringList n -> "string[]"
+ | RStructList (_,n) -> sprintf "_%s[]" n
and c_return_type () =
- match fst style with
- | RErr
- | RBool _
- | RInt _ -> "int"
- | RInt64 _ -> "long"
- | RConstString _
- | RConstOptString _
- | RString _
- | RBufferOut _ -> "string"
- | RStruct (_,n) -> "_" ^ n
- | RHashtable _
- | RStringList _ -> "string[]"
- | RStructList (_,n) -> sprintf "_%s[]" n
-
+ match fst style with
+ | RErr
+ | RBool _
+ | RInt _ -> "int"
+ | RInt64 _ -> "long"
+ | RConstString _
+ | RConstOptString _
+ | RString _
+ | RBufferOut _ -> "string"
+ | RStruct (_,n) -> "_" ^ n
+ | RHashtable _
+ | RStringList _ -> "string[]"
+ | RStructList (_,n) -> sprintf "_%s[]" n
+
and c_error_comparison () =
- match fst style with
- | RErr
- | RBool _
- | RInt _
- | RInt64 _ -> "== -1"
- | RConstString _
- | RConstOptString _
- | RString _
- | RBufferOut _
- | RStruct (_,_)
- | RHashtable _
- | RStringList _
- | RStructList (_,_) -> "== null"
-
+ match fst style with
+ | RErr
+ | RBool _
+ | RInt _
+ | RInt64 _ -> "== -1"
+ | RConstString _
+ | RConstOptString _
+ | RString _
+ | RBufferOut _
+ | RStruct (_,_)
+ | RHashtable _
+ | RStringList _
+ | RStructList (_,_) -> "== null"
+
and generate_extern_prototype () =
- pr " static extern %s guestfs_%s (IntPtr h"
- (c_return_type ()) name;
- List.iter (
- function
- | Pathname n | Device n | Dev_or_Path n | String n | OptString n
- | FileIn n | FileOut n ->
+ pr " static extern %s guestfs_%s (IntPtr h"
+ (c_return_type ()) name;
+ List.iter (
+ function
+ | Pathname n | Device n | Dev_or_Path n | String n | OptString n
+ | FileIn n | FileOut n ->
pr ", [In] string %s" n
- | StringList n | DeviceList n ->
+ | StringList n | DeviceList n ->
pr ", [In] string[] %s" n
- | Bool n ->
- pr ", bool %s" n
- | Int n ->
- pr ", int %s" n
- | Int64 n ->
- pr ", long %s" n
- ) (snd style);
- pr ");\n"
+ | Bool n ->
+ pr ", bool %s" n
+ | Int n ->
+ pr ", int %s" n
+ | Int64 n ->
+ pr ", long %s" n
+ ) (snd style);
+ pr ");\n"
and generate_public_prototype () =
- pr " public %s %s (" (csharp_return_type ()) name;
- let comma = ref false in
- let next () =
- if !comma then pr ", ";
- comma := true
- in
- List.iter (
- function
- | Pathname n | Device n | Dev_or_Path n | String n | OptString n
- | FileIn n | FileOut n ->
+ pr " public %s %s (" (csharp_return_type ()) name;
+ let comma = ref false in
+ let next () =
+ if !comma then pr ", ";
+ comma := true
+ in
+ List.iter (
+ function
+ | Pathname n | Device n | Dev_or_Path n | String n | OptString n
+ | FileIn n | FileOut n ->
next (); pr "string %s" n
- | StringList n | DeviceList n ->
+ | StringList n | DeviceList n ->
next (); pr "string[] %s" n
- | Bool n ->
- next (); pr "bool %s" n
- | Int n ->
- next (); pr "int %s" n
- | Int64 n ->
- next (); pr "long %s" n
- ) (snd style);
- pr ")\n"
+ | Bool n ->
+ next (); pr "bool %s" n
+ | Int n ->
+ next (); pr "int %s" n
+ | Int64 n ->
+ next (); pr "long %s" n
+ ) (snd style);
+ pr ")\n"
and generate_call () =
- pr "guestfs_%s (_handle" name;
- List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
- pr ");\n";
+ pr "guestfs_%s (_handle" name;
+ List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
+ pr ");\n";
in
pr " [DllImport (\"%s\")]\n" library;