Only tested on ARM (!) so far, but if someone can test them on x86{,64} that'd be great.
Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming blog: http://rwmj.wordpress.com Fedora now supports 80 OCaml packages (the OPEN alternative to F#)
From 387616241206c2b6e3a1bbaedd84cb3b586975d9 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" <rjo...@redhat.com> Date: Fri, 4 Jan 2013 12:33:48 +0900 Subject: [PATCH 1/7] Update copyright dates for 2013. On generated files in git and README. --- README | 2 +- gobject/Makefile.inc | 2 +- java/Makefile.inc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README b/README index 1196e0f..6a5692f 100644 --- a/README +++ b/README @@ -346,7 +346,7 @@ attention to the qemu command line and kernel output. Copyright and license information ---------------------------------------------------------------------- -Copyright (C) 2009-2012 Red Hat Inc. +Copyright (C) 2009-2013 Red Hat Inc. The library is distributed under the LGPLv2+. The programs are distributed under the GPLv2+. Please see the files COPYING and diff --git a/gobject/Makefile.inc b/gobject/Makefile.inc index 8708994..25c383e 100644 --- a/gobject/Makefile.inc +++ b/gobject/Makefile.inc @@ -3,7 +3,7 @@ # generator/ *.ml # ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. # -# Copyright (C) 2009-2012 Red Hat Inc. +# Copyright (C) 2009-2013 Red Hat Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/java/Makefile.inc b/java/Makefile.inc index 9dd39de..985be59 100644 --- a/java/Makefile.inc +++ b/java/Makefile.inc @@ -3,7 +3,7 @@ # generator/ *.ml # ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. # -# Copyright (C) 2009-2012 Red Hat Inc. +# Copyright (C) 2009-2013 Red Hat Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by -- 1.7.11.7
From 33f9dd68b244d3d8c6afb9032413626ff62beda9 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" <rjo...@redhat.com> Date: Wed, 9 Jan 2013 12:28:23 +0900 Subject: [PATCH 2/7] Refresh README file. --- README | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/README b/README index 6a5692f..28db6c5 100644 --- a/README +++ b/README @@ -166,12 +166,12 @@ To build the Perl tools: Building ---------------------------------------------------------------------- -Then make the daemon, library and root filesystem: +Build the daemon, library and root filesystem: ./configure make -Finally run the tests: +Run the tests: make check @@ -189,6 +189,10 @@ some libvirt guests installed, that these guests' disks are accessible by the current user, and these tests may fail for other reasons which are not necessarily because of real problems. + make help + +lists all 'make' targets. + If everything works, you can install the library and tools by running this command as root: @@ -292,7 +296,7 @@ distributions. Non-Linux ports are trickier, but we will accept patches if they aren't too invasive. The main porting issues are with the dependencies needed to build the -appliance. You will need to port the febootstrap first +appliance. You will need to port febootstrap first (http://people.redhat.com/~rjones/febootstrap/). -- 1.7.11.7
From da00e6e1b0645e69431a2161aeebb4f18a01f3a0 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" <rjo...@redhat.com> Date: Mon, 7 Jan 2013 06:46:09 +0900 Subject: [PATCH 3/7] java: Tidy up javadoc. --- generator/java.ml | 16 ++++++++++++++-- java/com/redhat/et/libguestfs/LibGuestFSException.java | 4 +++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/generator/java.ml b/generator/java.ml index c83bf80..270ad44 100644 --- a/generator/java.ml +++ b/generator/java.ml @@ -40,7 +40,19 @@ import java.util.HashMap; import java.util.Map; /** - * The GuestFS object is a libguestfs handle. + * Libguestfs handle. + * <p> + * The <code>GuestFS</code> object corresponds to a libguestfs handle. + * <p> + * Note that the main documentation for the libguestfs API is in + * the following man pages: + * <p> + * <ol> + * <li> <a href=\"http://libguestfs.org/guestfs-java.3.html\"><code>guestfs-java(3)</code></a> and </li> + * <li> <a href=\"http://libguestfs.org/guestfs.3.html\"><code>guestfs(3)</code></a>. </li> + * </ol> + * <p> + * This javadoc is <b>not</b> a good introduction to using libguestfs. * * @author rjones */ @@ -384,7 +396,7 @@ and generate_java_struct jtyp cols () = package com.redhat.et.libguestfs; /** - * Libguestfs %s structure. + * %s structure. * * @author rjones * @see GuestFS diff --git a/java/com/redhat/et/libguestfs/LibGuestFSException.java b/java/com/redhat/et/libguestfs/LibGuestFSException.java index c7bcc05..7b5a27f 100644 --- a/java/com/redhat/et/libguestfs/LibGuestFSException.java +++ b/java/com/redhat/et/libguestfs/LibGuestFSException.java @@ -1,5 +1,5 @@ /* libguestfs Java bindings - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009-2013 Red Hat Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,6 +19,8 @@ package com.redhat.et.libguestfs; /** + * Libguestfs error class. + * <p> * This exception is thrown when some error occurs when using the * libguestfs library. The error message is always a simple * printable string. -- 1.7.11.7
From f3eabd6c849f39380f698433e1cac95fd0627189 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" <rjo...@redhat.com> Date: Mon, 7 Jan 2013 23:41:46 +0900 Subject: [PATCH 4/7] java: Change synopsis in man page to show use of add_drive. --- java/examples/guestfs-java.pod | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/java/examples/guestfs-java.pod b/java/examples/guestfs-java.pod index 0795c86..6e032b4 100644 --- a/java/examples/guestfs-java.pod +++ b/java/examples/guestfs-java.pod @@ -9,7 +9,13 @@ guestfs-java - How to use libguestfs from Java import com.redhat.et.libguestfs.*; GuestFS g = new GuestFS (); - g.add_drive_opts ("disk.img"); + g.add_drive ("disk.img", + new HashMap<String,Object>() { + { + put ("readonly", Boolean.TRUE); + put ("format", "raw"); + } + }); g.launch (); =head1 DESCRIPTION -- 1.7.11.7
From e18e3674b53dce63a88f58387ad5109c6b780716 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" <rjo...@redhat.com> Date: Tue, 8 Jan 2013 11:29:31 +0900 Subject: [PATCH 5/7] java: Use defined constants for flags in call to guestfs_create_flags. --- generator/java.ml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/generator/java.ml b/generator/java.ml index 270ad44..1879f50 100644 --- a/generator/java.ml +++ b/generator/java.ml @@ -67,6 +67,10 @@ public class GuestFS { */ long g; + /* guestfs_create_flags values defined in <guestfs.h> */ + private static int CREATE_NO_ENVIRONMENT = 1; + private static int CREATE_NO_CLOSE_ON_EXIT = 2; + /** * Create a libguestfs handle, setting flags. * @@ -82,11 +86,11 @@ public class GuestFS { if (optargs != null) _optobj = optargs.get (\"environment\"); if (_optobj != null && !((Boolean) _optobj).booleanValue()) - flags |= 1; + flags |= CREATE_NO_ENVIRONMENT; if (optargs != null) _optobj = optargs.get (\"close_on_exit\"); if (_optobj != null && !((Boolean) _optobj).booleanValue()) - flags |= 2; + flags |= CREATE_NO_CLOSE_ON_EXIT; g = _create (flags); } @@ -100,6 +104,7 @@ public class GuestFS { { g = _create (0); } + private native long _create (int flags) throws LibGuestFSException; /** -- 1.7.11.7
From 4b9c9401aac30054333af891f9630a59b63d474a Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" <rjo...@redhat.com> Date: Fri, 4 Jan 2013 05:07:16 +0900 Subject: [PATCH 6/7] java: Implement the event API. --- generator/java.ml | 302 ++++++++++++++++++++++- generator/main.ml | 3 +- java/Makefile.am | 6 +- java/com/redhat/et/libguestfs/EventCallback.java | 33 +++ java/examples/guestfs-java.pod | 30 +++ java/t/GuestFS400Events.java | 95 +++++++ 6 files changed, 465 insertions(+), 4 deletions(-) create mode 100644 java/com/redhat/et/libguestfs/EventCallback.java create mode 100644 java/t/GuestFS400Events.java diff --git a/generator/java.ml b/generator/java.ml index 1879f50..9ef09ad 100644 --- a/generator/java.ml +++ b/generator/java.ml @@ -1,5 +1,5 @@ (* libguestfs - * Copyright (C) 2009-2012 Red Hat Inc. + * Copyright (C) 2009-2013 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,6 +27,7 @@ open Docstrings open Optgroups open Actions open Structs +open Events open C (* Generate Java bindings GuestFS.java file. *) @@ -133,6 +134,117 @@ public class GuestFS { "; + (* Events. *) + pr " // Event bitmasks.\n\n"; + List.iter ( + fun (name, bitmask) -> + pr " /**\n"; + pr " * Event '%s'.\n" name; + pr " *\n"; + pr " * @see #set_event_callback\n"; + pr " */\n"; + pr " public static final long EVENT_%s = 0x%x;\n" (String.uppercase name) bitmask; + pr "\n"; + ) events; + + pr " /** Bitmask of all events. */\n"; + pr " public static final long EVENT_ALL = 0x%x;\n" ((1 lsl List.length events) - 1); + pr "\n"; + + pr " /** Utility function to turn an event number or bitmask into a string. */\n"; + pr " public static String eventToString (long events)\n"; + pr " {\n"; + pr " if (events == 0)\n"; + pr " return \"\";\n"; + pr "\n"; + pr " String ret = \"\";\n"; + pr "\n"; + List.iter ( + fun (name, bitmask) -> + pr " if ((events & EVENT_%s) != 0) {\n" (String.uppercase name); + pr " ret = ret + \"|EVENT_%s\";\n" (String.uppercase name); + pr " events &= ~0x%x;\n" bitmask; + pr " }\n"; + ) events; + pr "\n"; + pr " if (events != 0)\n"; + pr " ret = events + ret;\n"; + pr " else\n"; + pr " ret = ret.substring (1);\n"; + pr "\n"; + pr " return ret;\n"; + pr " }\n"; + + pr " + /** + * Set an event handler. + * <p> + * Set an event handler (<code>callback</code>) which is called when any + * event from the set (<code>events</code>) is raised by the API. + * <code>events</code> is one or more <code>EVENT_*</code> constants, + * bitwise ORed together. + * <p> + * When an event happens, the callback object's <code>event</code> method + * is invoked like this: + * <pre> + * callback.event (event, // the specific event which fired (long) + * eh, // the event handle (int) + * buffer, // event data (String) + * array // event data (long[]) + * ); + * </pre> + * Note that you can pass arbitrary data from the main program to the + * callback by putting it into your {@link EventCallback callback object}, + * then accessing it in the callback via <code>this</code>. + * <p> + * This function returns an event handle which may be used to delete + * the event. Note that event handlers are deleted automatically when + * the libguestfs handle is closed. + * + * @throws LibGuestFSException + * @see The section \"EVENTS\" in the guestfs(3) manual + * @see #delete_event_callback + */ + public int set_event_callback (EventCallback callback, long events) + throws LibGuestFSException + { + if (g == 0) + throw new LibGuestFSException (\"set_event_callback: handle is closed\"); + + return _set_event_callback (g, callback, events); + } + + private native int _set_event_callback (long g, EventCallback callback, + long events) + throws LibGuestFSException; + + /** + * Delete an event handler. + * <p> + * Delete a previously registered event handler. The 'eh' parameter is + * the event handle returned from a previous call to + * {@link #set_event_callback set_event_callback}. + * <p> + * Note that event handlers are deleted automatically when the + * libguestfs handle is closed. + * + * @throws LibGuestFSException + * @see #set_event_callback + */ + public void delete_event_callback (int eh) + throws LibGuestFSException + { + if (g == 0) + throw new LibGuestFSException (\"delete_event_callback: handle is closed\"); + + _delete_event_callback (g, eh); + } + + private native void _delete_event_callback (long g, int eh); + +"; + + (* Methods. *) List.iter ( fun ({ name = name; style = (ret, args, optargs as style); in_docs = in_docs; shortdesc = shortdesc; @@ -433,10 +545,25 @@ and generate_java_c () = #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <inttypes.h> #include \"com_redhat_et_libguestfs_GuestFS.h\" #include \"guestfs.h\" +/* This is the opaque data passed between _set_event_callback and + * the C wrapper which calls the Java event callback. + * + * NB: The 'callback' in the following struct is registered as a global + * reference. It must be freed along with the struct. + */ +struct callback_data { + JavaVM *jvm; // JVM + jobject callback; // object supporting EventCallback interface + jmethodID method; // callback.event method +}; + +static struct callback_data **get_all_event_callbacks (guestfs_h *g, size_t *len_rtn); + /* Note that this function returns. The exception is not thrown * until after the wrapper function returns. */ @@ -469,7 +596,180 @@ Java_com_redhat_et_libguestfs_GuestFS__1close (JNIEnv *env, jobject obj, jlong jg) { guestfs_h *g = (guestfs_h *) (long) jg; + size_t len, i; + struct callback_data **data; + + /* There is a nasty, difficult to solve case here where the + * user deletes events in one of the callbacks that we are + * about to invoke, resulting in a double-free. XXX + */ + data = get_all_event_callbacks (g, &len); + guestfs_close (g); + + for (i = 0; i < len; ++i) { + (*env)->DeleteGlobalRef (env, data[i]->callback); + free (data[i]); + } + free (data); +} + +/* See EventCallback interface. */ +#define METHOD_NAME \"event\" +#define METHOD_SIGNATURE \"(JILjava/lang/String;[J)V\" + +static void +guestfs_java_callback (guestfs_h *g, + void *opaque, + uint64_t event, + int event_handle, + int flags, + const char *buf, size_t buf_len, + const uint64_t *array, size_t array_len) +{ + struct callback_data *data = opaque; + JavaVM *jvm = data->jvm; + JNIEnv *env; + int r; + jstring jbuf; + jlongArray jarray; + size_t i; + jlong jl; + + /* Get the Java environment. See: + * http://stackoverflow.com/questions/12900695/how-to-obtain-jni-interface-pointer-jnienv-for-asynchronous-calls + */ + r = (*jvm)->GetEnv (jvm, (void **) &env, JNI_VERSION_1_6); + if (r != JNI_OK) { + switch (r) { + case JNI_EDETACHED: + /* This can happen when the close event is generated during an atexit + * cleanup. The JVM has probably been destroyed so I doubt it is + * safe to run Java code at this point. + */ + fprintf (stderr, \"%%s: event %%\" PRIu64 \" (eh %%d) ignored because the thread is not attached to the JVM. This can happen when libguestfs handles are cleaned up at program exit after the JVM has been destroyed.\\n\", + __func__, event, event_handle); + return; + + default: + fprintf (stderr, \"%%s: jvm->GetEnv failed! (JNI_* error code = %%d)\\n\", + __func__, r); + return; + } + } + + /* Convert the buffer and array to Java objects. */ + jbuf = (*env)->NewStringUTF (env, buf); // XXX size + + jarray = (*env)->NewLongArray (env, array_len); + for (i = 0; i < array_len; ++i) { + jl = array[i]; + (*env)->SetLongArrayRegion (env, jarray, i, 1, &jl); + } + + /* Call the event method. If it throws an exception, all we can do is + * print it on stderr. + */ + (*env)->ExceptionClear (env); + (*env)->CallVoidMethod (env, data->callback, data->method, + (jlong) event, (jint) event_handle, + jbuf, jarray); + if ((*env)->ExceptionOccurred (env)) { + (*env)->ExceptionDescribe (env); + (*env)->ExceptionClear (env); + } +} + +JNIEXPORT jint JNICALL +Java_com_redhat_et_libguestfs_GuestFS__1set_1event_1callback + (JNIEnv *env, jobject obj, jlong jg, jobject jcallback, jlong jevents) +{ + guestfs_h *g = (guestfs_h *) (long) jg; + int r; + struct callback_data *data; + jclass callback_class; + jmethodID method; + char key[64]; + + callback_class = (*env)->GetObjectClass (env, jcallback); + method = (*env)->GetMethodID (env, callback_class, METHOD_NAME, METHOD_SIGNATURE); + if (method == 0) { + throw_exception (env, \"GuestFS.set_event_callback: callback class does not implement the EventCallback interface\"); + return -1; + } + + data = guestfs___safe_malloc (g, sizeof *data); + (*env)->GetJavaVM (env, &data->jvm); + data->method = method; + + r = guestfs_set_event_callback (g, guestfs_java_callback, + (uint64_t) jevents, 0, data); + if (r == -1) { + free (data); + throw_exception (env, guestfs_last_error (g)); + return -1; + } + + /* Register jcallback as a global reference so the GC won't free it. */ + data->callback = (*env)->NewGlobalRef (env, jcallback); + + /* Store 'data' in the handle, so we can free it at some point. */ + snprintf (key, sizeof key, \"_java_event_%%d\", r); + guestfs_set_private (g, key, data); + + return (jint) r; +} + +JNIEXPORT void JNICALL +Java_com_redhat_et_libguestfs_GuestFS__1delete_1event_1callback + (JNIEnv *env, jobject obj, jlong jg, jint eh) +{ + guestfs_h *g = (guestfs_h *) (long) jg; + char key[64]; + struct callback_data *data; + + snprintf (key, sizeof key, \"_java_event_%%d\", eh); + + data = guestfs_get_private (g, key); + if (data) { + (*env)->DeleteGlobalRef (env, data->callback); + free (data); + guestfs_set_private (g, key, NULL); + guestfs_delete_event_callback (g, eh); + } +} + +static struct callback_data ** +get_all_event_callbacks (guestfs_h *g, size_t *len_rtn) +{ + struct callback_data **r; + size_t i; + const char *key; + struct callback_data *data; + + /* Count the length of the array that will be needed. */ + *len_rtn = 0; + data = guestfs_first_private (g, &key); + while (data != NULL) { + if (strncmp (key, \"_java_event_\", strlen (\"_java_event_\")) == 0) + (*len_rtn)++; + data = guestfs_next_private (g, &key); + } + + /* Copy them into the return array. */ + r = guestfs___safe_malloc (g, sizeof (struct callback_data *) * (*len_rtn)); + + i = 0; + data = guestfs_first_private (g, &key); + while (data != NULL) { + if (strncmp (key, \"_java_event_\", strlen (\"_java_event_\")) == 0) { + r[i] = data; + i++; + } + data = guestfs_next_private (g, &key); + } + + return r; } "; diff --git a/generator/main.ml b/generator/main.ml index 618052b..69ebe05 100644 --- a/generator/main.ml +++ b/generator/main.ml @@ -138,7 +138,8 @@ Run it from the top source directory using the command output_to filename (generate_java_struct jtyp cols) ) structs; delete_except_generated - ~skip:["java/com/redhat/et/libguestfs/LibGuestFSException.java"] + ~skip:["java/com/redhat/et/libguestfs/LibGuestFSException.java"; + "java/com/redhat/et/libguestfs/EventCallback.java"] "java/com/redhat/et/libguestfs/*.java"; output_to "java/Makefile.inc" generate_java_makefile_inc; diff --git a/java/Makefile.am b/java/Makefile.am index b655ae9..449f40b 100644 --- a/java/Makefile.am +++ b/java/Makefile.am @@ -1,5 +1,5 @@ # libguestfs Java bindings -# Copyright (C) 2009-2012 Red Hat Inc. +# Copyright (C) 2009-2013 Red Hat Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -33,13 +33,15 @@ include $(srcdir)/Makefile.inc java_sources = \ $(java_built_sources) \ + com/redhat/et/libguestfs/EventCallback.java \ com/redhat/et/libguestfs/LibGuestFSException.java java_tests = \ Bindtests.java \ t/GuestFS005Load.java \ t/GuestFS010Basic.java \ - t/GuestFS080OptArgs.java + t/GuestFS080OptArgs.java \ + t/GuestFS400Events.java EXTRA_DIST = \ $(java_sources) \ diff --git a/java/com/redhat/et/libguestfs/EventCallback.java b/java/com/redhat/et/libguestfs/EventCallback.java new file mode 100644 index 0000000..a5e84e1 --- /dev/null +++ b/java/com/redhat/et/libguestfs/EventCallback.java @@ -0,0 +1,33 @@ +/* libguestfs Java bindings + * Copyright (C) 2009-2013 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package com.redhat.et.libguestfs; + +/** + * Event callback interface. + * <p> + * This is the interface for event callbacks. See the + * {@link GuestFS#set_event_callback set_event_callback method} + * for details. + * + * @author rjones + * @see GuestFS + */ +public interface EventCallback { + public void event (long event, int eh, String buffer, long[] array); +} diff --git a/java/examples/guestfs-java.pod b/java/examples/guestfs-java.pod index 6e032b4..c777e05 100644 --- a/java/examples/guestfs-java.pod +++ b/java/examples/guestfs-java.pod @@ -40,6 +40,36 @@ is the error message (a C<String>). Calling any method on a closed handle raises the same exception. +=head2 EVENTS + +The L<libguestfs event API|guestfs(3)/EVENTS> is fully supported from +Java. Create a class which implements the C<EventCallback> interface, +create an instance of this class, and then call the C<GuestFS#set_event_callback> +method to register this instance. The C<event> method of the class is +called when libguestfs generates an event. + +For example, this will print all trace events: + + GuestFS g = new GuestFS (); + g.set_trace (true); + g.set_event_callback ( + new EventCallback () { + public void event (long event, int eh, + String buffer, long[] array) { + System.out.println (GuestFS.eventToString (event) + + ": " + buffer); + } + }, + GuestFS.EVENT_TRACE); + g.add_drive_ro ("disk.img"); + // etc. + +The output looks similar to this: + + EVENT_TRACE: add_drive_ro "disk.img" + EVENT_TRACE: add_drive_ro = 0 + // etc. + =head1 EXAMPLE 1: CREATE A DISK IMAGE @EXAMPLE1@ diff --git a/java/t/GuestFS400Events.java b/java/t/GuestFS400Events.java new file mode 100644 index 0000000..98236d8 --- /dev/null +++ b/java/t/GuestFS400Events.java @@ -0,0 +1,95 @@ +/* libguestfs Java bindings + * Copyright (C) 2013 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import java.io.*; +import java.util.HashMap; +import com.redhat.et.libguestfs.*; + +public class GuestFS400Events +{ + static class PrintEvent implements EventCallback + { + public void event (long event, int eh, String buffer, long[] array) + { + String msg = "event=" + GuestFS.eventToString (event) + " " + + "eh=" + eh + " "; + + if (buffer != null) + msg += "buffer='" + buffer + "' "; + + if (array.length > 0) { + msg += "array[" + array.length + "]={"; + for (int i = 0; i < array.length; ++i) + msg += " " + array[i]; + msg += " }"; + } + + System.out.println ("java event logged: " + msg); + } + } + + static class CloseInvoked extends PrintEvent + { + private int close_invoked = 0; + + public void event (long event, int eh, String buffer, long[] array) + { + super.event (event, eh, buffer, array); + close_invoked++; + } + + public int getCloseInvoked () + { + return close_invoked; + } + } + + public static void main (String[] argv) + { + try { + GuestFS g = new GuestFS (); + + // Grab all messages into an event handler that just + // prints each event. + g.set_event_callback (new PrintEvent (), + GuestFS.EVENT_APPLIANCE|GuestFS.EVENT_LIBRARY| + GuestFS.EVENT_TRACE); + + // Check that the close event is invoked. + CloseInvoked ci = new CloseInvoked (); + g.set_event_callback (ci, GuestFS.EVENT_CLOSE); + + // Now make sure we see some messages. + g.set_trace (true); + g.set_verbose (true); + + // Do some stuff. + g.add_drive_ro ("/dev/null"); + g.set_autosync (true); + + // Close the handle. + assert ci.getCloseInvoked() == 0; + g.close (); + assert ci.getCloseInvoked() == 1; + } + catch (Exception exn) { + System.err.println (exn); + System.exit (1); + } + } +} -- 1.7.11.7
From 9586488a34d5d99f7d98b597d4d5aeda61943c1d Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" <rjo...@redhat.com> Date: Thu, 10 Jan 2013 06:25:30 +0900 Subject: [PATCH 7/7] podwrapper: Refresh podwrapper man page. This also adds a rule so you can do: make podwrapper.1 if you want to read the documentation as a man page. --- .gitignore | 1 + Makefile.am | 11 ++++++++++ podwrapper.pl.in | 63 ++++++++++++++++++++++++++++++++++++-------------------- 3 files changed, 53 insertions(+), 22 deletions(-) diff --git a/.gitignore b/.gitignore index 7f8c892..394e20a 100644 --- a/.gitignore +++ b/.gitignore @@ -320,6 +320,7 @@ Makefile.in /po-docs/po4a.conf /po-docs/*/*.pod /po-docs/*/stamp-update-po +/podwrapper.1 /podwrapper.pl /po/*.gmo /python/bindtests.py diff --git a/Makefile.am b/Makefile.am index d8b6590..42052c0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -288,11 +288,22 @@ stamp-guestfs-release-notes.pod: guestfs-release-notes.pod $< touch $@ +# NB. podwrapper is an internal tool, so the man page mustn't be installed. +noinst_MANS = podwrapper.1 +podwrapper.1: podwrapper.pl + $(PODWRAPPER) \ + --section 1 \ + --man $@-t \ + --license GPLv2+ \ + $< + mv $@-t $@ + # Make clean. CLEANFILES = \ html/*.html \ pod2htm?.tmp \ + podwrapper.1 \ qemu-wrapper.sh \ stamp-guestfs-release-notes.pod diff --git a/podwrapper.pl.in b/podwrapper.pl.in index 46c71f2..3998782 100755 --- a/podwrapper.pl.in +++ b/podwrapper.pl.in @@ -32,27 +32,37 @@ use File::Basename; =head1 NAME -podwrapper.pl - Generate various output formats from POD input files +podwrapper.pl - Generate libguestfs documentation from POD input files =head1 SYNOPSIS + man_MANS = virt-foo.1 + virt-foo.1 $(top_builddir)/html/virt-foo.1.html: stamp-virt-foo.pod + stamp-virt-foo.pod: virt-foo.pod - $(PODWRAPPER) --man virt-foo.1 --html virt-foo.1.html $< - touch $@ + $(PODWRAPPER) \ + --section 1 \ + --man virt-foo.1 \ + --html $(top_builddir)/html/virt-foo.1.html \ + --license GPLv2+ \ + $< + touch $@ + + CLEANFILES += stamp-virt-foo.pod =head1 DESCRIPTION -podwrapper is a Perl script that generates various output formats +podwrapper.pl is a Perl script that generates various output formats from POD input files that libguestfs uses for most documentation. -You should specify an input file, and one or more output formats. -For example: +You must specify one input file, and one or more output formats. The +output options are I<--man>, I<--html> and I<--text> (see below). - podwrapper.pl virt-foo.pod --man virt-foo.1 +In C<Makefile.am> files, use a variation of the boilerplate shown in +the L</SYNOPSIS> section above. -will turn C<virt-foo.pod> into a man page C<virt-foo.1>. The output -options are I<--man>, I<--html> and I<--text> (see below). +For information about the POD format, see L<perlpod(1)>. =head1 OPTIONS @@ -70,7 +80,7 @@ Display brief help. my $html; -=item B<--html=output.html> +=item B<--html output.html> Write a web page to C<output.html>. If this option is not given, then no web page output is produced. @@ -79,7 +89,7 @@ given, then no web page output is produced. my @inserts; -=item B<--insert=filename:__PATTERN__> +=item B<--insert filename:__PATTERN__> In the input file, replace the literal text C<__PATTERN__> with the replacement file C<filename>. You can give this option multiple @@ -95,7 +105,11 @@ patterns, in fact you can use any string as the pattern. my @licenses; -=item B<--license=GPLv2+|LGPLv2+|examples> +=item B<--license GPLv2+> + +=item B<--license LGPLv2+> + +=item B<--license examples> Add the given license to the end of the man page. This parameter is required. The parameter may be given multiple times (eg. for @@ -105,16 +119,16 @@ mixed content). my $man; -=item B<--man=output.n> +=item B<--man output.n> -Write a man page to C<output.n>. If this option is not -given, then no man page output is produced. +Write a man page to C<output.n> (C<n> is the manual section number). +If this option is not given, then no man page output is produced. =cut my $name; -=item B<--name=name> +=item B<--name name> Set the name of the man page. If not set, defaults to the basename of the input file. @@ -123,7 +137,7 @@ of the input file. my $section; -=item B<--section=N> +=item B<--section N> Set the section of the man page (a number such as C<1> for command line utilities or C<3> for C API documentation). If @@ -143,7 +157,7 @@ subdirectory. my $text; -=item B<--text=output.txt> +=item B<--text output.txt> Write a text file to C<output.txt>. If this option is not given, then no text output is produced. @@ -152,7 +166,7 @@ given, then no text output is produced. my @verbatims; -=item B<--verbatim=filename:@PATTERN@> +=item B<--verbatim filename:__PATTERN__> In the input file, replace the literal text C<__PATTERN__> with the replacement file C<filename>. You can give this option multiple @@ -529,11 +543,16 @@ sub read_verbatim_file $r; } +=head1 SEE ALSO + +L<perlpod(1)>, +L<Pod::Simple(3pm)>, +libguestfs.git/README. + =head1 AUTHOR Richard W.M. Jones. -=head1 SEE ALSO +=head1 COPYRIGHT -libguestfs.git/README, -L<Pod::Simple> +Copyright (C) 2012-2013 Red Hat Inc. -- 1.7.11.7
_______________________________________________ Libguestfs mailing list Libguestfs@redhat.com https://www.redhat.com/mailman/listinfo/libguestfs