Test for "version" command should be InitNone.
[libguestfs.git] / src / generator.ml
index d94ec14..fc320fa 100755 (executable)
@@ -84,6 +84,16 @@ and ret =
      * inefficient.  Keys should be unique.  NULLs are not permitted.
      *)
   | RHashtable of string
+(* Not implemented:
+    (* "RBufferOut" is handled almost exactly like RString, but
+     * it allows the string to contain arbitrary 8 bit data including
+     * ASCII NUL.  In the C API this causes an implicit extra parameter
+     * to be added of type <size_t *size_r>.  Other programming languages
+     * support strings with arbitrary 8 bit data.  At the RPC layer
+     * we have to use the opaque<> type instead of string<>.
+     *)
+  | RBufferOut of string
+*)
 
 and args = argt list   (* Function parameters, guestfs handle is implicit. *)
 
@@ -110,6 +120,18 @@ and argt =
      *)
   | FileIn of string
   | FileOut of string
+(* Not implemented:
+    (* Opaque buffer which can contain arbitrary 8 bit data.
+     * In the C API, this is expressed as <char *, int> pair.
+     * Most other languages have a string type which can contain
+     * ASCII NUL.  We use whatever type is appropriate for each
+     * language.
+     * Buffers are limited by the total message size.  To transfer
+     * large blocks of data, use FileIn/FileOut parameters instead.
+     * To return an arbitrary buffer, use RBufferOut.
+     *)
+  | BufferIn of string
+*)
 
 type flags =
   | ProtocolLimitWarning  (* display warning about protocol size limits *)
@@ -636,6 +658,36 @@ qemu subprocess, then this will return an error.
 
 This is an internal call used for debugging and testing.");
 
+  ("version", (RStruct ("version", "version"), []), -1, [],
+   [InitNone, Always, TestOutputStruct (
+      [["version"]], [CompareWithInt ("major", 1)])],
+   "get the library version number",
+   "\
+Return the libguestfs version number that the program is linked
+against.
+
+Note that because of dynamic linking this is not necessarily
+the version of libguestfs that you compiled against.  You can
+compile the program, and then at runtime dynamically link
+against a completely different C<libguestfs.so> library.
+
+This call was added in version C<1.0.58>.  In previous
+versions of libguestfs there was no way to get the version
+number.  From C code you can use ELF weak linking tricks to find out if
+this symbol exists (if it doesn't, then it's an earlier version).
+
+The call returns a structure with four elements.  The first
+three (C<major>, C<minor> and C<release>) are numbers and
+correspond to the usual version triplet.  The fourth element
+(C<extra>) is a string and is normally empty, but may be
+used for distro-specific information.
+
+To construct the original version string:
+C<$major.$minor.$release$extra>
+
+I<Note:> Don't use this call to test for availability
+of features.  Distro backports makes this unreliable.");
+
 ]
 
 (* daemon_functions are any functions which cause some action
@@ -2928,6 +2980,14 @@ let structs = [
     "ftyp", FChar;
     "name", FString;
   ];
+
+  (* Version numbers. *)
+  "version", [
+    "major", FInt64;
+    "minor", FInt64;
+    "release", FInt64;
+    "extra", FString;
+  ];
 ] (* end of structs *)
 
 (* Ugh, Java has to be different ..
@@ -2940,7 +3000,8 @@ let java_structs = [
   "lvm_lv", "LV";
   "stat", "Stat";
   "statvfs", "StatVFS";
-  "dirent", "Dirent"
+  "dirent", "Dirent";
+  "version", "Version";
 ]
 
 (* Used for testing language bindings. *)
@@ -4582,7 +4643,11 @@ static int %s (void)
 
 and generate_one_test_body name i test_name init test =
   (match init with
-   | InitNone
+   | InitNone (* XXX at some point, InitNone and InitEmpty became
+              * folded together as the same thing.  Really we should
+              * make InitNone do nothing at all, but the tests may
+              * need to be checked to make sure this is OK.
+              *)
    | InitEmpty ->
        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
        List.iter (generate_test_command_call test_name)
@@ -6048,30 +6113,33 @@ and generate_perl_struct_code typ cols name style n do_cleanups =
   do_cleanups ();
   pr "      if (%s == NULL)\n" n;
   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
-  pr "      EXTEND (SP, %d);\n" (List.length cols);
+  pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
   List.iter (
-    function
-    | name, FString ->
-       pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
-         n name
-    | name, FUUID ->
-       pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
-         n name
-    | name, (FBytes|FUInt64) ->
-       pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
-         n name
-    | name, FInt64 ->
-       pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
-         n name
-    | name, (FInt32|FUInt32) ->
-       pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
-         n name
-    | name, FChar ->
-       pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
-         n name
-    | name, FOptPercent ->
-       pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
-         n name
+    fun ((name, _) as col) ->
+      pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
+
+      match col with
+      | name, FString ->
+         pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
+           n name
+      | name, FUUID ->
+         pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
+           n name
+      | name, (FBytes|FUInt64) ->
+         pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
+           n name
+      | name, FInt64 ->
+         pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
+           n name
+      | name, (FInt32|FUInt32) ->
+         pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
+           n name
+      | name, FChar ->
+         pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
+           n name
+      | name, FOptPercent ->
+         pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
+           n name
   ) cols;
   pr "      free (%s);\n" n