update generator to emit each RESOLVE_DEVICE call
[libguestfs.git] / src / generator.ml
index 94dc268..f10d6b0 100755 (executable)
@@ -134,6 +134,7 @@ and args = argt list        (* Function parameters, guestfs handle is implicit. *)
      *)
 and argt =
   | String of string   (* const char *name, cannot be NULL *)
+  | Device of string   (* /dev device name, cannot be NULL *)
   | OptString of string        (* const char *name, may be NULL *)
   | StringList of string(* list of strings (each string cannot be NULL) *)
   | Bool of string     (* boolean *)
@@ -301,6 +302,12 @@ and test_init =
     (* 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.
@@ -448,6 +455,8 @@ image).
 
 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
@@ -755,6 +764,31 @@ C<$major.$minor.$release$extra>
 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)>.");
+
 ]
 
 (* daemon_functions are any functions which cause some action
@@ -1619,8 +1653,7 @@ 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);
-                           CompareWithInt ("bsize", 131072)])],
+      [["statvfs"; "/"]], [CompareWithInt ("namemax", 256)])],
    "get file system statistics",
    "\
 Returns file system statistics for any mounted file system.
@@ -1629,7 +1662,7 @@ C<path> should be a file or directory in the 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",
    "\
@@ -1756,7 +1789,8 @@ This uses the L<blockdev(8)> command.");
    [InitBasicFS, Always, TestOutput (
       (* Pick a file from cwd which isn't likely to change. *)
       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
-       ["checksum"; "md5"; "/COPYING.LIB"]], "e3eda01d9815f8d24aae2dbd89b68b06")],
+       ["checksum"; "md5"; "/COPYING.LIB"]],
+        Digest.to_hex (Digest.file "COPYING.LIB"))],
    "upload a file from the local machine",
    "\
 Upload local file C<filename> to C<remotefilename> on the
@@ -1772,7 +1806,8 @@ See also C<guestfs_download>.");
       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
        ["upload"; "testdownload.tmp"; "/upload"];
-       ["checksum"; "md5"; "/upload"]], "e3eda01d9815f8d24aae2dbd89b68b06")],
+       ["checksum"; "md5"; "/upload"]],
+        Digest.to_hex (Digest.file "COPYING.LIB"))],
    "download a file to the local machine",
    "\
 Download file C<remotefilename> and save it as C<filename>
@@ -3206,10 +3241,10 @@ 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"]])],
+   [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
@@ -3257,17 +3292,17 @@ This command disables the libguestfs appliance 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 (
@@ -3395,6 +3430,24 @@ This closes the inotify handle which was previously
 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>");
+
 ]
 
 let all_functions = non_daemon_functions @ daemon_functions
@@ -3719,7 +3772,7 @@ let mapi f xs =
   loop 0 xs
 
 let name_of_argt = function
-  | String n | OptString n | StringList n | Bool n | Int n
+  | Device n | String n | OptString n | StringList n | Bool n | Int n
   | FileIn n | FileOut n -> n
 
 let java_name_of_struct typ =
@@ -4106,7 +4159,7 @@ and generate_xdr () =
            pr "struct %s_args {\n" name;
            List.iter (
              function
-             | String n -> pr "  string %s<>;\n" n
+             | Device n | String n -> pr "  string %s<>;\n" n
              | OptString n -> pr "  str *%s;\n" n
              | StringList n -> pr "  str %s<>;\n" n
              | Bool n -> pr "  bool %s;\n" n
@@ -4467,7 +4520,7 @@ check_state (guestfs_h *g, const char *caller)
        | args ->
            List.iter (
              function
-             | String n ->
+             | Device n | String n ->
                  pr "  args.%s = (char *) %s;\n" n n
              | OptString n ->
                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
@@ -4676,7 +4729,7 @@ and generate_daemon_actions () =
                 * allow device name translation.  This is safe because
                 * we can modify the string (passed from RPC).
                 *)
-             | String n
+             | Device n | String n
              | OptString n -> pr "  char *%s;\n" n
              | StringList n -> pr "  char **%s;\n" n
              | Bool n -> pr "  int %s;\n" n
@@ -4697,6 +4750,9 @@ and generate_daemon_actions () =
            pr "  }\n";
            List.iter (
              function
+             | Device n ->
+                 pr "  %s = args.%s;\n" n n;
+                 pr "  RESOLVE_DEVICE (%s, goto done);" n;
              | String n -> pr "  %s = args.%s;\n" n n
              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
              | StringList n ->
@@ -5317,6 +5373,13 @@ and generate_one_test_body name i test_name init test =
          [["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)
@@ -5594,6 +5657,7 @@ and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
       List.iter (
         function
         | OptString n, "NULL" -> ()
+        | Device n, arg
         | String n, arg
         | OptString n, arg ->
             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
@@ -5641,6 +5705,7 @@ and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
       List.iter (
         function
         | OptString _, "NULL" -> pr ", NULL"
+        | Device n, _
         | String n, _
         | OptString n, _ ->
             pr ", %s" n
@@ -5889,6 +5954,7 @@ and generate_fish_cmds () =
       );
       List.iter (
         function
+        | Device n
         | String n
         | OptString n
         | FileIn n
@@ -5909,7 +5975,7 @@ and generate_fish_cmds () =
       iteri (
         fun i ->
           function
-          | String name -> pr "  %s = argv[%d];\n" name i
+          | Device name | String name -> pr "  %s = argv[%d];\n" name i
           | OptString name ->
               pr "  %s = strcmp (argv[%d], \"\") != 0 ? argv[%d] : NULL;\n"
                 name i i
@@ -6142,7 +6208,7 @@ and generate_fish_actions_pod () =
       pr " %s" name;
       List.iter (
         function
-        | String n -> pr " %s" n
+        | Device n | String n -> pr " %s" n
         | OptString n -> pr " %s" n
         | StringList n -> pr " '%s ...'" n
         | Bool _ -> pr " true|false"
@@ -6208,6 +6274,7 @@ and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
     in
     List.iter (
       function
+      | Device n
       | String n
       | OptString n ->
           next ();
@@ -6470,6 +6537,7 @@ copy_table (char * const * argv)
 
       List.iter (
         function
+        | Device n
         | String n
         | FileIn n
         | FileOut n ->
@@ -6522,7 +6590,8 @@ copy_table (char * const * argv)
         function
         | StringList n ->
             pr "  ocaml_guestfs_free_strings (%s);\n" n;
-        | String _ | OptString _ | Bool _ | Int _ | FileIn _ | FileOut _ -> ()
+        | Device _ | String _ | OptString _ | Bool _ | Int _
+        | FileIn _ | FileOut _ -> ()
       ) (snd style);
 
       pr "  if (r == %s)\n" error_code;
@@ -6605,7 +6674,7 @@ and generate_ocaml_prototype ?(is_external = false) name style =
   pr "%s : t -> " name;
   List.iter (
     function
-    | String _ | FileIn _ | FileOut _ -> pr "string -> "
+    | Device _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
     | OptString _ -> pr "string option -> "
     | StringList _ -> pr "string array -> "
     | Bool _ -> pr "bool -> "
@@ -6750,7 +6819,7 @@ DESTROY (g)
       iteri (
         fun i ->
           function
-          | String n | FileIn n | FileOut n -> pr "      char *%s;\n" n
+          | Device 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
@@ -6765,7 +6834,7 @@ DESTROY (g)
       let do_cleanups () =
         List.iter (
           function
-          | String _ | OptString _ | Bool _ | Int _
+          | Device _ | String _ | OptString _ | Bool _ | Int _
           | FileIn _ | FileOut _ -> ()
           | StringList n -> pr "      free (%s);\n" n
         ) (snd style)
@@ -7137,7 +7206,8 @@ and generate_perl_prototype name style =
       if !comma then pr ", ";
       comma := true;
       match arg with
-      | String n | OptString n | Bool n | Int n | FileIn n | FileOut n ->
+      | Device n | String n
+      | OptString n | Bool n | Int n | FileIn n | FileOut n ->
           pr "$%s" n
       | StringList n ->
           pr "\\@%s" n
@@ -7384,7 +7454,7 @@ py_guestfs_close (PyObject *self, PyObject *args)
 
       List.iter (
         function
-        | String n | FileIn n | FileOut n -> pr "  const char *%s;\n" n
+        | Device n | String n | FileIn n | FileOut n -> pr "  const char *%s;\n" n
         | OptString n -> pr "  const char *%s;\n" n
         | StringList n ->
             pr "  PyObject *py_%s;\n" n;
@@ -7399,7 +7469,7 @@ py_guestfs_close (PyObject *self, PyObject *args)
       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
       List.iter (
         function
-        | String _ | FileIn _ | FileOut _ -> pr "s"
+        | Device _ | String _ | FileIn _ | FileOut _ -> pr "s"
         | OptString _ -> pr "z"
         | StringList _ -> pr "O"
         | Bool _ -> pr "i" (* XXX Python has booleans? *)
@@ -7409,7 +7479,7 @@ py_guestfs_close (PyObject *self, PyObject *args)
       pr "                         &py_g";
       List.iter (
         function
-        | String n | FileIn n | FileOut n -> pr ", &%s" n
+        | Device n | String n | FileIn n | FileOut n -> pr ", &%s" n
         | OptString n -> pr ", &%s" n
         | StringList n -> pr ", &py_%s" n
         | Bool n -> pr ", &%s" n
@@ -7422,7 +7492,8 @@ py_guestfs_close (PyObject *self, PyObject *args)
       pr "  g = get_handle (py_g);\n";
       List.iter (
         function
-        | String _ | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
+        | Device _ | String _
+        | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
         | StringList n ->
             pr "  %s = get_string_list (py_%s);\n" n n;
             pr "  if (!%s) return NULL;\n" n
@@ -7436,7 +7507,8 @@ py_guestfs_close (PyObject *self, PyObject *args)
 
       List.iter (
         function
-        | String _ | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
+        | Device _ | String _
+        | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
         | StringList n ->
             pr "  free (%s);\n" n
       ) (snd style);
@@ -7744,7 +7816,7 @@ static VALUE ruby_guestfs_close (VALUE gv)
 
       List.iter (
         function
-        | String n | FileIn n | FileOut n ->
+        | Device 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;
@@ -7796,7 +7868,8 @@ static VALUE ruby_guestfs_close (VALUE gv)
 
       List.iter (
         function
-        | String _ | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
+        | Device _ | String _
+        | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
         | StringList n ->
             pr "  free (%s);\n" n
       ) (snd style);
@@ -8106,6 +8179,7 @@ and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
       needs_comma := true;
 
       match arg with
+      | Device n
       | String n
       | OptString n
       | FileIn n
@@ -8223,6 +8297,7 @@ Java_com_redhat_et_libguestfs_GuestFS__1close
       pr "  (JNIEnv *env, jobject obj, jlong jg";
       List.iter (
         function
+        | Device n
         | String n
         | OptString n
         | FileIn n
@@ -8274,6 +8349,7 @@ Java_com_redhat_et_libguestfs_GuestFS__1close
             "NULL", "NULL" in
       List.iter (
         function
+        | Device n
         | String n
         | OptString n
         | FileIn n
@@ -8302,6 +8378,7 @@ Java_com_redhat_et_libguestfs_GuestFS__1close
       (* Get the parameters. *)
       List.iter (
         function
+        | Device n
         | String n
         | FileIn n
         | FileOut n ->
@@ -8333,6 +8410,7 @@ Java_com_redhat_et_libguestfs_GuestFS__1close
       (* Release the parameters. *)
       List.iter (
         function
+        | Device n
         | String n
         | FileIn n
         | FileOut n ->
@@ -8490,6 +8568,16 @@ and generate_java_struct_list_return typ jtyp cols =
   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;
 
@@ -8597,7 +8685,7 @@ last_error h = do
           function
           | FileIn n
           | FileOut n
-          | String n -> pr "withCString %s $ \\%s -> " n n
+          | Device 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 _ -> ()
@@ -8608,7 +8696,8 @@ last_error h = do
             function
             | Bool n -> sprintf "(fromBool %s)" n
             | Int n -> sprintf "(fromIntegral %s)" n
-            | FileIn n | FileOut n | String n | OptString n | StringList n -> n
+            | FileIn n | FileOut n
+            | Device n | String n | OptString n | StringList n -> n
           ) (snd style) in
         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
           (String.concat " " ("p" :: args));
@@ -8658,7 +8747,7 @@ and generate_haskell_prototype ~handle ?(hs = false) style =
   List.iter (
     fun arg ->
       (match arg with
-       | String _ -> pr "%s" string
+       | Device _ | String _ -> pr "%s" string
        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
        | StringList _ -> if hs then pr "[String]" else pr "Ptr CString"
        | Bool _ -> pr "%s" bool
@@ -8733,6 +8822,7 @@ print_strings (char * const* const argv)
     pr "{\n";
     List.iter (
       function
+      | Device n
       | String n
       | FileIn n
       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
@@ -9247,12 +9337,7 @@ Run it from the top source directory using the command
   ) 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