+ g->last_errnum = errnum;
+}
+
+/* Warning are printed unconditionally. We try to make these rare.
+ * Generally speaking, a warning should either be an error, or if it's
+ * not important for end users then it should be a debug message.
+ */
+void
+guestfs___warning (guestfs_h *g, const char *fs, ...)
+{
+ va_list args;
+ char *msg, *msg2;
+ int len;
+
+ va_start (args, fs);
+ len = vasprintf (&msg, fs, args);
+ va_end (args);
+
+ if (len < 0) return;
+
+ len = asprintf (&msg2, _("warning: %s"), msg);
+ free (msg);
+
+ if (len < 0) return;
+
+ guestfs___call_callbacks_message (g, GUESTFS_EVENT_LIBRARY, msg2, len);
+
+ free (msg2);
+}
+
+/* Debug messages. */
+void
+guestfs___debug (guestfs_h *g, const char *fs, ...)
+{
+ va_list args;
+ char *msg;
+ int len;
+
+ /* The cpp macro "debug" has already checked that g->verbose is true
+ * before calling this function, but we check it again just in case
+ * anyone calls this function directly.
+ */
+ if (!g->verbose)
+ return;
+
+ va_start (args, fs);
+ len = vasprintf (&msg, fs, args);
+ va_end (args);
+
+ if (len < 0) return;
+
+ guestfs___call_callbacks_message (g, GUESTFS_EVENT_LIBRARY, msg, len);
+}
+
+/* Call trace messages. These are enabled by setting g->trace, and
+ * calls to this function should only happen from the generated code
+ * in src/actions.c
+ */
+void
+guestfs___trace (guestfs_h *g, const char *fs, ...)
+{
+ va_list args;
+ char *msg;
+ int len;
+
+ va_start (args, fs);
+ len = vasprintf (&msg, fs, args);
+ va_end (args);
+
+ if (len < 0) return;
+
+ guestfs___call_callbacks_message (g, GUESTFS_EVENT_TRACE, msg, len);
+
+ free (msg);