[Libguestfs] [PATCH] Non-daemon actions indirect through generated code

Richard W.M. Jones rjones at redhat.com
Wed Sep 9 11:51:49 UTC 2009


Matt asked me this morning if we could generate guestfish scripts
automatically from running programs like virt-v2v.  Good idea.

This patch however doesn't do this, but it lays the groundwork for it:
In order for us to generate code for any functions which don't go
through the daemon, we need to add an indirection to those calls via
some generated code.  This will allow us to add guestfish tracing at
some point in the future.

If you want to debug calls to libguestfs code, then the easiest thing
to do is to use ltrace(1).  Sample ltrace output is attached.

Rich.

-- 
Richard Jones, Emerging Technologies, Red Hat  http://et.redhat.com/~rjones
virt-p2v converts physical machines to virtual machines.  Boot with a
live CD or over the network (PXE) and turn machines into Xen guests.
http://et.redhat.com/~rjones/virt-p2v
-------------- next part --------------
>From c2411cb88bc535eb1f31cf837aecf586cc36e769 Mon Sep 17 00:00:00 2001
From: Richard Jones <rjones at trick.home.annexia.org>
Date: Wed, 9 Sep 2009 12:34:13 +0100
Subject: [PATCH] Non-daemon actions indirect through generated code.

Previously non-daemon actions were called directly by
user code, eg:

/* Non-generated */
int
guestfs_set_verbose (guestfs_h *g, int v)
{
  g->verbose = !!v;
  return 0;
}

This changes these actions so they go indirectly via
some generated code, eg:

/* Generated */
int guestfs_set_verbose (guestfs_h *g,
		int verbose)
{
  return guestfs__set_verbose (g, verbose);
}

/* Non-generated */
int
guestfs__set_verbose (guestfs_h *g, int v)
{
  g->verbose = !!v;
  return 0;
}

The aim is to have a place in the generated code where
we can add debug or tracing information for these non-
daemon calls.
---
 .gitignore       |    1 +
 src/Makefile.am  |    1 +
 src/generator.ml |   37 ++++++++++++++++++++++++++++--
 src/guestfs.c    |   65 +++++++++++++++++++++++++++--------------------------
 4 files changed, 69 insertions(+), 35 deletions(-)

diff --git a/.gitignore b/.gitignore
index e3137c8..720630a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -178,6 +178,7 @@ ruby/Rakefile
 src/guestfs-actions.c
 src/guestfs-actions.h
 src/guestfs-bindtests.c
+src/guestfs-internal-actions.h
 src/guestfs_protocol.c
 src/guestfs_protocol.h
 src/guestfs_protocol.x
diff --git a/src/Makefile.am b/src/Makefile.am
index e38c336..cd0022d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -46,6 +46,7 @@ BUILT_SOURCES = \
   guestfs-structs.h \
   guestfs-actions.h \
   guestfs-actions.c \
+  guestfs-internal-actions.h \
   guestfs-bindtests.c
 
 # This convenience library is solely to avoid compiler warnings
diff --git a/src/generator.ml b/src/generator.ml
index 2e2b70e..765cb16 100755
--- a/src/generator.ml
+++ b/src/generator.ml
@@ -4548,6 +4548,16 @@ and generate_actions_h () =
         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;
@@ -4557,6 +4567,7 @@ and generate_client_actions () =
 #include <stdlib.h>
 
 #include \"guestfs.h\"
+#include \"guestfs-internal-actions.h\"
 #include \"guestfs_protocol.h\"
 
 #define error guestfs_error
@@ -4619,6 +4630,21 @@ check_state (guestfs_h *g, const char *caller)
 
 ";
 
+  (* For non-daemon functions, generate a wrapper around each function. *)
+  List.iter (
+    fun (shortname, style, _, _, _, _, _) ->
+      let name = "guestfs_" ^ shortname in
+
+      generate_prototype ~extern:false ~semicolon:false ~newline:true
+        ~handle:"g" name style;
+      pr "{\n";
+      pr "  return guestfs__%s " shortname;
+      generate_c_call_args ~handle:"g" style;
+      pr ";\n";
+      pr "}\n";
+      pr "\n"
+  ) non_daemon_functions;
+
   (* Client-side stubs for each function. *)
   List.iter (
     fun (shortname, style, _, _, _, _, _) ->
@@ -9089,6 +9115,7 @@ and generate_bindtests () =
 #include <string.h>
 
 #include \"guestfs.h\"
+#include \"guestfs-internal-actions.h\"
 #include \"guestfs_protocol.h\"
 
 #define error guestfs_error
@@ -9119,7 +9146,7 @@ print_strings (char *const *argv)
   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
@@ -9144,7 +9171,7 @@ print_strings (char *const *argv)
       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 ->
@@ -9210,7 +9237,7 @@ print_strings (char *const *argv)
       ) 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
@@ -9533,6 +9560,10 @@ Run it from the top source directory using the command
   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 ();
diff --git a/src/guestfs.c b/src/guestfs.c
index 20afb63..571205f 100644
--- a/src/guestfs.c
+++ b/src/guestfs.c
@@ -57,6 +57,7 @@
 #endif
 
 #include "guestfs.h"
+#include "guestfs-internal-actions.h"
 #include "guestfs_protocol.h"
 #include "ignore-value.h"
 
@@ -608,33 +609,33 @@ guestfs_get_error_handler (guestfs_h *g, void **data_rtn)
 }
 
 int
-guestfs_set_verbose (guestfs_h *g, int v)
+guestfs__set_verbose (guestfs_h *g, int v)
 {
   g->verbose = !!v;
   return 0;
 }
 
 int
-guestfs_get_verbose (guestfs_h *g)
+guestfs__get_verbose (guestfs_h *g)
 {
   return g->verbose;
 }
 
 int
-guestfs_set_autosync (guestfs_h *g, int a)
+guestfs__set_autosync (guestfs_h *g, int a)
 {
   g->autosync = !!a;
   return 0;
 }
 
 int
-guestfs_get_autosync (guestfs_h *g)
+guestfs__get_autosync (guestfs_h *g)
 {
   return g->autosync;
 }
 
 int
-guestfs_set_path (guestfs_h *g, const char *path)
+guestfs__set_path (guestfs_h *g, const char *path)
 {
   free (g->path);
   g->path = NULL;
@@ -646,13 +647,13 @@ guestfs_set_path (guestfs_h *g, const char *path)
 }
 
 const char *
-guestfs_get_path (guestfs_h *g)
+guestfs__get_path (guestfs_h *g)
 {
   return g->path;
 }
 
 int
-guestfs_set_qemu (guestfs_h *g, const char *qemu)
+guestfs__set_qemu (guestfs_h *g, const char *qemu)
 {
   free (g->qemu);
   g->qemu = NULL;
@@ -662,13 +663,13 @@ guestfs_set_qemu (guestfs_h *g, const char *qemu)
 }
 
 const char *
-guestfs_get_qemu (guestfs_h *g)
+guestfs__get_qemu (guestfs_h *g)
 {
   return g->qemu;
 }
 
 int
-guestfs_set_append (guestfs_h *g, const char *append)
+guestfs__set_append (guestfs_h *g, const char *append)
 {
   free (g->append);
   g->append = NULL;
@@ -678,39 +679,39 @@ guestfs_set_append (guestfs_h *g, const char *append)
 }
 
 const char *
-guestfs_get_append (guestfs_h *g)
+guestfs__get_append (guestfs_h *g)
 {
   return g->append;
 }
 
 int
-guestfs_set_memsize (guestfs_h *g, int memsize)
+guestfs__set_memsize (guestfs_h *g, int memsize)
 {
   g->memsize = memsize;
   return 0;
 }
 
 int
-guestfs_get_memsize (guestfs_h *g)
+guestfs__get_memsize (guestfs_h *g)
 {
   return g->memsize;
 }
 
 int
-guestfs_set_selinux (guestfs_h *g, int selinux)
+guestfs__set_selinux (guestfs_h *g, int selinux)
 {
   g->selinux = selinux;
   return 0;
 }
 
 int
-guestfs_get_selinux (guestfs_h *g)
+guestfs__get_selinux (guestfs_h *g)
 {
   return g->selinux;
 }
 
 int
-guestfs_get_pid (guestfs_h *g)
+guestfs__get_pid (guestfs_h *g)
 {
   if (g->pid > 0)
     return g->pid;
@@ -721,7 +722,7 @@ guestfs_get_pid (guestfs_h *g)
 }
 
 struct guestfs_version *
-guestfs_version (guestfs_h *g)
+guestfs__version (guestfs_h *g)
 {
   struct guestfs_version *r;
 
@@ -763,8 +764,8 @@ add_cmdline (guestfs_h *g, const char *str)
 }
 
 int
-guestfs_config (guestfs_h *g,
-                const char *qemu_param, const char *qemu_value)
+guestfs__config (guestfs_h *g,
+                 const char *qemu_param, const char *qemu_value)
 {
   if (qemu_param[0] != '-') {
     error (g, _("guestfs_config: parameter must begin with '-' character"));
@@ -795,7 +796,7 @@ guestfs_config (guestfs_h *g,
 }
 
 int
-guestfs_add_drive (guestfs_h *g, const char *filename)
+guestfs__add_drive (guestfs_h *g, const char *filename)
 {
   size_t len = strlen (filename) + 64;
   char buf[len];
@@ -834,7 +835,7 @@ guestfs_add_drive (guestfs_h *g, const char *filename)
 }
 
 int
-guestfs_add_drive_ro (guestfs_h *g, const char *filename)
+guestfs__add_drive_ro (guestfs_h *g, const char *filename)
 {
   size_t len = strlen (filename) + 64;
   char buf[len];
@@ -855,7 +856,7 @@ guestfs_add_drive_ro (guestfs_h *g, const char *filename)
 }
 
 int
-guestfs_add_cdrom (guestfs_h *g, const char *filename)
+guestfs__add_cdrom (guestfs_h *g, const char *filename)
 {
   if (strchr (filename, ',') != NULL) {
     error (g, _("filename cannot contain ',' (comma) character"));
@@ -914,7 +915,7 @@ static const char *supermin_hostfiles_name =
   "initramfs." REPO "." host_cpu ".supermin.hostfiles";
 
 int
-guestfs_launch (guestfs_h *g)
+guestfs__launch (guestfs_h *g)
 {
   const char *tmpdir;
   char dir_template[PATH_MAX];
@@ -1506,7 +1507,7 @@ finish_wait_ready (guestfs_h *g, void *vp)
 }
 
 int
-guestfs_wait_ready (guestfs_h *g)
+guestfs__wait_ready (guestfs_h *g)
 {
   int finished = 0, r;
 
@@ -1549,7 +1550,7 @@ guestfs_wait_ready (guestfs_h *g)
 }
 
 int
-guestfs_kill_subprocess (guestfs_h *g)
+guestfs__kill_subprocess (guestfs_h *g)
 {
   if (g->state == CONFIG) {
     error (g, _("no subprocess to kill"));
@@ -1567,37 +1568,37 @@ guestfs_kill_subprocess (guestfs_h *g)
 
 /* Access current state. */
 int
-guestfs_is_config (guestfs_h *g)
+guestfs__is_config (guestfs_h *g)
 {
   return g->state == CONFIG;
 }
 
 int
-guestfs_is_launching (guestfs_h *g)
+guestfs__is_launching (guestfs_h *g)
 {
   return g->state == LAUNCHING;
 }
 
 int
-guestfs_is_ready (guestfs_h *g)
+guestfs__is_ready (guestfs_h *g)
 {
   return g->state == READY;
 }
 
 int
-guestfs_is_busy (guestfs_h *g)
+guestfs__is_busy (guestfs_h *g)
 {
   return g->state == BUSY;
 }
 
 int
-guestfs_get_state (guestfs_h *g)
+guestfs__get_state (guestfs_h *g)
 {
   return g->state;
 }
 
 int
-guestfs_set_ready (guestfs_h *g)
+guestfs__set_ready (guestfs_h *g)
 {
   if (g->state != BUSY) {
     error (g, _("guestfs_set_ready: called when in state %d != BUSY"),
@@ -1609,7 +1610,7 @@ guestfs_set_ready (guestfs_h *g)
 }
 
 int
-guestfs_set_busy (guestfs_h *g)
+guestfs__set_busy (guestfs_h *g)
 {
   if (g->state != READY) {
     error (g, _("guestfs_set_busy: called when in state %d != READY"),
@@ -1621,7 +1622,7 @@ guestfs_set_busy (guestfs_h *g)
 }
 
 int
-guestfs_end_busy (guestfs_h *g)
+guestfs__end_busy (guestfs_h *g)
 {
   switch (g->state)
     {
-- 
1.6.2.5

-------------- next part --------------
__libc_start_main(0x415b80, 6, 0x7fff9ec0e4b8, 0x419380, 0x419370 <unfinished ...>
strrchr("./fish/.libs/lt-guestfish", '/')        = "/lt-guestfish"
__cxa_atexit(0x417b20, 0, 0, 0, 7)               = 0
getenv("HOME")                                   = "/home/rjones"
__snprintf_chk(0x631640, 1024, 1, 1024, 0x42b206) = 23
using_history(0x631657, 0x42b208, 0x631657, 11, 0x42b213) = 0x7ff6c7a839d8
read_history(0x631640, 0x42b208, 0, 11, 0x42b213 <unfinished ...>
malloc(24)                                       = 0x1fa1010
[...]
malloc(23)                                       = 0x1fbc5f0
<... read_history resumed> )                     = 0
sigaction(13, 0x7fff9ec0e300, NULL)              = 0
guestfs_create(13, 0x7fff9ec0de20, 0, -1, 0)     = 0x1fbc610
guestfs_set_autosync(0x1fbc610, 1, 0, 3, 0)      = 0
getenv("LIBGUESTFS_PATH")                        = NULL
guestfs_set_path(0x1fbc610, 0x42c2f0, 0x7fff9ec0f539, 4, 0x42b214) = 0
getopt_long(6, 0x7fff9ec0e4b8, "a:Df:h::im:nrv?Vx", 0x42ca00, 0x7fff9ec0e39c) = -1
strcasecmp("alloc", "help")                      = -7
strcasecmp("alloc", "quit")                      = -16
strcasecmp("alloc", "exit")                      = -4
strcasecmp("alloc", "q")                         = -16
strcasecmp("alloc", "alloc")                     = 0
sscanf(0x7fff9ec0f567, 0x419528, 0x7fff9ec0de40, 0x7fff9ec0de4f, 0) = 2
guestfs_is_config(0x1fbc610, 0, 0x7fff9ec0de50, 0x41952d, 0x7fff9ec0d790) = 1
open("/tmp/test.img", 833, 0666)                 = 3
posix_fallocate(3, 0, 0xa00000, -1, 0x7fff9ec0d790) = 0
close(3)                                         = 0
guestfs_add_drive(0x1fbc610, 0x7fff9ec0f559, 0, -1, 0xa00000) = 0
fflush(0x7ff6c7619780)                           = 0
strcasecmp("run", "help")                        = 10
strcasecmp("run", "quit")                        = 1
strcasecmp("run", "exit")                        = 13
strcasecmp("run", "q")                           = 1
strcasecmp("run", "alloc")                       = 17
strcasecmp("run", "allocate")                    = 17
strcasecmp("run", "echo")                        = 13
strcasecmp("run", "edit")                        = 13
strcasecmp("run", "vi")                          = -4
strcasecmp("run", "emacs")                       = 13
strcasecmp("run", "lcd")                         = 6
strcasecmp("run", "glob")                        = 11
strcasecmp("run", "more")                        = 5
strcasecmp("run", "less")                        = 6
strcasecmp("run", "reopen")                      = 16
strcasecmp("run", "time")                        = -2
strcasecmp("run", "launch")                      = 6
strcasecmp("run", "run")                         = 0
guestfs_is_config(0x1fbc610, 0x4196b3, 0x7ff6c73cad40, 0, 0) = 1
guestfs_launch(0x1fbc610, 0x4196b3, 0x7ff6c73cad40, 0, 0 <unfinished ...>
--- SIGCHLD (Child exited) ---
--- SIGCHLD (Child exited) ---
--- SIGCHLD (Child exited) ---
<... guestfs_launch resumed> )                   = 0
guestfs_wait_ready(0x1fbc610, 9, 0x1fbc890, 72, 0x7ff6c7a93480) = 0
fflush(0x7ff6c7619780)                           = 0
open("/home/rjones/.guestfish", 65, 0644)        = 6
close(6)                                         = 0
append_history(0, 0x631640, 420, -1, 0x7ff6c7eb9700 <unfinished ...>
malloc(24)                                       = 0x1fbc800
<... append_history resumed> )                   = 0
exit(0 <unfinished ...>
--- SIGCHLD (Child exited) ---
--- SIGCHLD (Child exited) ---
__fpending(0x7ff6c7619780, 0, 0x7ff6c761a330, 0x7ff6c761a330, 0x7ff6c761aed0) = 0
ferror(0x7ff6c7619780)                           = 0
fclose(0x7ff6c7619780)                           = 0
__fpending(0x7ff6c7619860, 0, 0x7ff6c761ae10, 0, 0x7ff6c7eb9700) = 0
ferror(0x7ff6c7619860)                           = 0
fclose(0x7ff6c7619860)                           = 0
+++ exited (status 0) +++


More information about the Libguestfs mailing list